Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/Berry.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/Berry.java	(revision 2225)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/Berry.java	(revision 2225)
@@ -0,0 +1,41 @@
+/*
+ *    Berry.java
+ *    Copyright (C) 2001 New Zealand Digital Library Project
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.nzdl.gsdl.SimpleGraphicalClient;
+
+
+public class Berry extends Object
+{
+       private String berryTitle;
+       //private QueryID 
+	   //time stamp 
+	   // person added 
+
+		 
+   public Berry( String newBerryTitle)
+         {	 
+         berryTitle = newBerryTitle;
+         }
+
+   public String toString ()
+         {
+         return( berryTitle);
+         }
+
+
+} //end Berry class
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/BerryBasketModel.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/BerryBasketModel.java	(revision 2225)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/BerryBasketModel.java	(revision 2225)
@@ -0,0 +1,65 @@
+/*
+ *    BerryBasketModel.java
+ *    Copyright (C) 2001 New Zealand Digital Library Project
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.nzdl.gsdl.SimpleGraphicalClient;
+
+
+import java.util.*;
+import javax.swing.event.*;
+import javax.swing.*;
+import javax.swing.table.*; 
+import java.awt.*;
+
+
+class BerryBasketModel extends AbstractTableModel
+{
+
+ String[] content = {"Doc1", "Doc2", "Doc3"};
+ String[] columnTitles = {"Document", "Person", "Date"};
+ 
+ 
+	public BerryBasketModel()
+	{
+		super();
+	}
+
+	public void add(Berry berry)
+	{
+		System.out.println("adding to BerryBasketModel: "  + berry.toString());	
+		//addElement(berry);
+	}
+
+	
+	public int getColumnCount() { return columnTitles.length; }
+	
+    public int getRowCount() { return content.length;}
+	
+    public Object getValueAt(int row, int col) { 
+	     // get Berry object
+		 // extract document title (say), person, date info from Berry object
+		 // depending on column number
+		 // column reordering shouldn't matter, all
+		 // gets dealt with automatically
+	     return Color.black; 
+	}
+	
+    public String getColumnName(int col) {
+               return columnTitles[col];
+    }
+	
+}
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/BerryBasketPanel.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/BerryBasketPanel.java	(revision 2225)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/BerryBasketPanel.java	(revision 2225)
@@ -0,0 +1,91 @@
+
+/*
+ *    BerryBasketPanel.java
+ *    Copyright (C) 2001 New Zealand Digital Library Project
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.nzdl.gsdl.SimpleGraphicalClient;
+
+
+import javax.swing.*;
+import javax.swing.table.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+
+public class BerryBasketPanel extends JPanel implements Constants
+{
+
+BerryBasketModel berryModel;
+JTable berryTable;
+JList berryList;
+JScrollPane scrollBerryPane;
+
+  public BerryBasketPanel(CSModel csModel) 
+  {
+    super();
+    setLayout( new BorderLayout() );
+	setBorder(BorderFactory.createTitledBorder("BerryBasket"));
+	/* TableModel dataModel = new AbstractTableModel() {
+	     
+	
+          public int getColumnCount() { return columnTitles.length; }
+          public int getRowCount() { return 5;}
+          public Object getValueAt(int row, int col) { return new Integer(row*col); }
+		  public String getColumnName(int col) {
+               return columnTitles[col];
+          }
+
+      }; */
+	 berryModel = new BerryBasketModel();
+     berryTable = new JTable(berryModel);
+ 
+	//berryTable = new JTable(5,2);
+	
+	//berryList = new JList(csModel.getBerryModel()); //  must be vector or array
+	//berryList.setFont(berryFont);
+	//berryList.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
+	//scrollBerryPane = new JScrollPane(berryList);
+	
+	berryTable.setFont(berryFont);
+	berryTable.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
+	
+	berryTable.setDefaultRenderer(Color.class, new BerryCellRenderer());
+	scrollBerryPane = new JScrollPane(berryTable);
+	berryTable.setPreferredScrollableViewportSize(new Dimension(100, 70));
+
+    add(scrollBerryPane, BorderLayout.CENTER);
+  } //end constructor
+
+
+   class BerryCellRenderer extends JLabel implements TableCellRenderer {
+  
+  public Component getTableCellRendererComponent(JTable table,
+                                               Object value,
+                                               boolean isSelected,
+                                               boolean hasFocus,
+                                               int row,
+                                               int column) {
+											   this.setText(value.toString());
+											   return this;
+	} // end getTableCellRendererComponent
+  
+  
+  } //  end BerryCellRenderer
+
+} // end BerryBasketPanel
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/CSFrame.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/CSFrame.java	(revision 2224)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/CSFrame.java	(revision 2225)
@@ -88,6 +88,11 @@
 	searchPanel = new SearchPanel(csModel, this);
 		
+	JPanel centerPanel = new JPanel();
+	QueryHistoryPanel queryHistoryPanel = new QueryHistoryPanel(csModel);
+	centerPanel.add(queryHistoryPanel);
+
 	content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS));	
 	content.add(searchPanel);
+	content.add(centerPanel);
 	
 	addWindowListener(new WindowHandler());
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/CSModel.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/CSModel.java	(revision 2224)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/CSModel.java	(revision 2225)
@@ -19,4 +19,5 @@
 package org.nzdl.gsdl.SimpleGraphicalClient;
 
+import java.util.*;
 import java.util.Set;
 import java.util.TreeSet;
@@ -28,4 +29,5 @@
 import org.nzdl.gsdl.service.NzdlService;
 import org.nzdl.gsdl.service.NzdlCollectionInfo;
+
 /**
  * Class 
@@ -43,7 +45,10 @@
 
   Vector collectionList;
+  TreeMap collectionInfoMap;
+    HashMap collectionNameMap;
   String currentCollection;
   ResultModel results;
   NzdlService nzdl;
+  QueryHistoryModel queryHistoryModel;
     
 
@@ -53,4 +58,7 @@
     results = new ResultModel();
     collectionList = new Vector();
+    collectionInfoMap = new TreeMap();
+    collectionNameMap = new HashMap();
+    queryHistoryModel = new QueryHistoryModel();
     currentCollection = "";
     initialiseCollection();
@@ -63,5 +71,7 @@
   }
 
-	
+    public QueryHistoryModel getQueryHistoryModel() {
+	return queryHistoryModel;
+    }
 	
 
@@ -86,68 +96,87 @@
   /* collectionList methods */
 
-  public Vector getCollectionList()
-  {
-    return collectionList;
-  }
+    public Vector getCollectionList() {
+	return new Vector(collectionInfoMap.keySet());
+    }
 
-  public int getCollectionListSize() 
-  {
-    return collectionList.size();
-  }
-	
-  public void addCollection(String collection)
-  {
-    collectionList.add(collection);
-  }
+    public Collection getCollectionAsCollection() {
+	return (Collection)collectionInfoMap;
+    }
 
-  public void setCurrentCollection(String collection )
-  {
-    currentCollection = collection;
-  }
+    public int getCollectionListSize() {
+	return collectionInfoMap.size();
+    }
 
-  public String getCurrentCollection()
-  {
-    return currentCollection;
-  }
+    public NzdlCollectionInfo getCollectionInfo(String collectionName) {
+	return (NzdlCollectionInfo) collectionInfoMap.get(collectionName);
+    }
 
-  public String getFirstCollection()
-  {
-    if (collectionList.size() > 0)
-      return (String)collectionList.get(0);
-    else
-      return "no collections";
-  }
-  /**
-   *
-   */
-  public void initialiseCollection() 
-  {
-    Set collectionSet = nzdl.getCollectionSet(); // set of strings of collection titles
-    TreeSet orderedCollectionSet = new TreeSet(collectionSet);
-    // TreeSet automatically puts strings in alphabetical order
-    System.out.println("Number of collections on the server: " + 
-		       orderedCollectionSet.size());
-    Iterator collectionSetIterator = orderedCollectionSet.iterator();
-    while (collectionSetIterator.hasNext() ) {
-      // object -> String
-      String collectionName = (String)collectionSetIterator.next(); 
-      NzdlCollectionInfo info = nzdl.getCollectionInfo(collectionName);
-      //System.err.println(info);
-      if (info != null && 
-	  info.getBuildDate() != 0) {
-	addCollection(collectionName);
-	System.err.println("Adding " + collectionName + " to collection list...");
-      } // end if
-      else {
-	System.err.println("Collection " + collectionName + " getBuildDate() returned 0");
-      } // end else
-    } // end while	
 
+    public String getLongCollectionName(String collectionName) {
+	return (String) collectionNameMap.get(collectionName);
+    }
+
+
+    public String getCollectionDescription(String collectionName) {
+	Set descSet = nzdl.getMetaData(collectionName, "collection", "collectionextra");
+	if (descSet.size() == 1) 
+	    return (String) descSet.toArray()[0];
+	else
+	    return "collectionName has more than 1 collectionextra entry";
+    }
+
+
+	public void setCurrentCollection(String collection )
+	    {
+		currentCollection = collection;
+	    }
+
+	public String getCurrentCollection()
+	    {
+		return currentCollection;
+	    }
+
+	public String getFirstCollection()
+	    {
+		if (getCollectionListSize() > 0)
+		    return (String)collectionInfoMap.firstKey();
+		else
+		    return "no collections";
+	    }
+	/**
+	 *
+	 */
+	public void initialiseCollection() 
+	    {
+		Set collectionSet = nzdl.getCollectionSet(); // set of strings of collection titles
+		TreeSet orderedCollectionSet = new TreeSet(collectionSet);
+		// TreeSet automatically puts strings in alphabetical order
+		System.out.println("Number of collections on the server: " + 
+				   orderedCollectionSet.size());
+		Iterator collectionSetIterator = orderedCollectionSet.iterator();
+		while (collectionSetIterator.hasNext() ) {
+		    // object -> String
+		    String collectionName = (String)collectionSetIterator.next(); 
+		    NzdlCollectionInfo info = nzdl.getCollectionInfo(collectionName);
+		    if (info != null && 
+			info.getBuildDate() != 0) {
+			collectionInfoMap.put(collectionName, info);
+			String longCollectionName = "";
+			Set n = nzdl.getMetaData(collectionName, "collection", "collectionname");
+			if (n.size() == 1) 
+			    longCollectionName = (String) n.toArray()[0];
+			else 
+			    longCollectionName = collectionName + " has more than 1 collectionname";
+			collectionNameMap.put(collectionName,longCollectionName );
+			System.err.println("Adding " + collectionName + " to collection list...");
+		    } // end if
+		    else {
+			System.err.println("Collection " + collectionName + " getBuildDate() returned 0");
+		    } // end else
+		} // end while	
+		setCurrentCollection(getFirstCollection()); //assume at least one collection
     
-
-    setCurrentCollection(getFirstCollection()); //assume at least one collection
-    
-  }
+	    }
 	
 	
-}
+    }
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/CollectionInfoDialog.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/CollectionInfoDialog.java	(revision 2224)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/CollectionInfoDialog.java	(revision 2225)
@@ -58,68 +58,67 @@
 private NumberFormat numFormat = NumberFormat.getInstance();
 
-CollectionInfoDialog(Frame f, String collectionName, NzdlService nzdl) {
-    super(f, "Collection Information" );
-
-    contentPanel = new JPanel(new GridLayout(0,2, 5, 4));;
-    buttonPanel = new JPanel();
-
-    NzdlCollectionInfo collectionInfo =  nzdl.getCollectionInfo(collectionName);
-    Set n = nzdl.getMetaData(collectionName, "collection", "collectionname");
-      if (n.size() == 1) {
-	fullCollectionName =  (String) n.toArray()[0];
-     }
-    else {
-    System.err.println(collectionName + " has more than 1 collectionname");
-    }
-    n.clear();
-
-    collectionNamePanel = new JPanel();
-    // collectionNamePanel.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
-    collectionNamePanel.add(new JLabel(fullCollectionName));
-
-    contentPanel.add(new JLabel("Short collection name:"));
-    JLabel collectionLabel = new JLabel(collectionName);
-    contentPanel.add(collectionLabel);
-    contentPanel.add(new JLabel("Number of Documents:"));
-
-    long numOfDocs =  collectionInfo.getNumOfDocs();
-    if (numOfDocs == 0) 
-	numOfDocsString = "unknown";
-    else 
-	numOfDocsString = numFormat.format(numOfDocs);
-    contentPanel.add(new JLabel(numOfDocsString));
-    contentPanel.add(new JLabel("Number of Words:"));
-
-    long numOfWords = collectionInfo.getNumOfWords();
-    if (numOfWords == 0) 
-	numOfWordsString = "unknown";
-    else
-	numOfWordsString = numFormat.format(numOfWords);
-    contentPanel.add(new JLabel(numOfWordsString));
-    contentPanel.add(new JLabel("Size:"));
-    long numOfBytes = collectionInfo.getNumOfBytes();
-    contentPanel.add(new JLabel(formatByteSize(numOfBytes)));
-    contentPanel.add(new JLabel("Last built on:"));
-    // waiting for API to return a correct Date object ...
-    Date buildDate = new Date( collectionInfo.getBuildDate()*1000);
-    contentPanel.add(new JLabel(DateFormat.getDateTimeInstance().format(buildDate)));
-    contentPanel.add(new JLabel("Is it Public?"));
-
-    if (collectionInfo.isPublic())
-	publicString = "yes";
-    else
-	publicString = "no";
-    contentPanel.add(new JLabel(publicString));
-    contentPanel.add(new JLabel("Is it beta?"));
-    if (collectionInfo.isBeta())
-	betaString = "yes";
-    else
-	betaString = "no";
-    contentPanel.add(new JLabel(betaString));
-
-    JPanel descPanel = new JPanel();
-    Set descSet = nzdl.getMetaData(collectionName, "collection", "collectionextra");
-    if (descSet.size() == 1) {
-	descString = (String) descSet.toArray()[0];
+    CollectionInfoDialog(Frame f, String collectionName, CSModel csModel) {
+	super(f, "Collection Information" );
+
+	contentPanel = new JPanel(new GridLayout(0,2, 5, 4));;
+	buttonPanel = new JPanel();
+
+	NzdlCollectionInfo collectionInfo =  csModel.getCollectionInfo(collectionName);
+	/*
+	  Set n = nzdl.getMetaData(collectionName, "collection", "collectionname");
+	  if (n.size() == 1) {
+	  fullCollectionName =  (String) n.toArray()[0];
+	  }
+	  else {
+	  System.err.println(collectionName + " has more than 1 collectionname");
+	  }
+	  n.clear();
+	*/
+	collectionNamePanel = new JPanel();
+	// collectionNamePanel.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
+	collectionNamePanel.add(new JLabel(csModel.getLongCollectionName(collectionName)));
+
+	contentPanel.add(new JLabel("Short collection name:"));
+	JLabel collectionLabel = new JLabel(collectionName);
+	contentPanel.add(collectionLabel);
+	contentPanel.add(new JLabel("Number of Documents:"));
+
+	long numOfDocs =  collectionInfo.getNumOfDocs();
+	if (numOfDocs == 0) 
+	    numOfDocsString = "unknown";
+	else 
+	    numOfDocsString = numFormat.format(numOfDocs);
+	contentPanel.add(new JLabel(numOfDocsString));
+	contentPanel.add(new JLabel("Number of Words:"));
+
+	long numOfWords = collectionInfo.getNumOfWords();
+	if (numOfWords == 0) 
+	    numOfWordsString = "unknown";
+	else
+	    numOfWordsString = numFormat.format(numOfWords);
+	contentPanel.add(new JLabel(numOfWordsString));
+	contentPanel.add(new JLabel("Size:"));
+	long numOfBytes = collectionInfo.getNumOfBytes();
+	contentPanel.add(new JLabel(formatByteSize(numOfBytes)));
+	contentPanel.add(new JLabel("Last built on:"));
+	// waiting for API to return a correct Date object ...
+	Date buildDate = new Date( collectionInfo.getBuildDate()*1000);
+	contentPanel.add(new JLabel(DateFormat.getDateTimeInstance().format(buildDate)));
+	contentPanel.add(new JLabel("Is it Public?"));
+
+	if (collectionInfo.isPublic())
+	    publicString = "yes";
+	else
+	    publicString = "no";
+	contentPanel.add(new JLabel(publicString));
+	contentPanel.add(new JLabel("Is it beta?"));
+	if (collectionInfo.isBeta())
+	    betaString = "yes";
+	else
+	    betaString = "no";
+	contentPanel.add(new JLabel(betaString));
+
+	JPanel descPanel = new JPanel();
+	descString = csModel.getCollectionDescription(collectionName);
 	//System.err.println(descString);
 	if (descString.length() > 0) {
@@ -143,27 +142,25 @@
 	    descPanel.add(scrollPane);
 	} // if
-    } // if 
-    descSet.clear();
-
-    okButton = new JButton("Ok");
-    okButton.setPreferredSize(new Dimension(80,20));
-    okButton.addActionListener(this);
-    buttonPanel.add( okButton );
-    getRootPane().setDefaultButton(okButton);
+
+	okButton = new JButton("Ok");
+	okButton.setPreferredSize(new Dimension(80,20));
+	okButton.addActionListener(this);
+	buttonPanel.add( okButton );
+	getRootPane().setDefaultButton(okButton);
     
-    holderPanel = new JPanel();
-    holderPanel.setBorder(BorderFactory.createEmptyBorder(10,10,2,10));
-    holderPanel.setLayout( new BoxLayout(holderPanel, BoxLayout.Y_AXIS));
-    holderPanel.add(collectionNamePanel);
-    holderPanel.add(contentPanel);
-    if (descString.length() > 0) {
-	holderPanel.add(Box.createVerticalStrut(10));
-	holderPanel.add(descPanel); // only if we have a description to show
-    }
-    holderPanel.add(Box.createVerticalStrut(5));
-    holderPanel.add(buttonPanel);
-    getContentPane().add(holderPanel);
-    pack();
-    setVisible(true);
+	holderPanel = new JPanel();
+	holderPanel.setBorder(BorderFactory.createEmptyBorder(10,10,2,10));
+	holderPanel.setLayout( new BoxLayout(holderPanel, BoxLayout.Y_AXIS));
+	holderPanel.add(collectionNamePanel);
+	holderPanel.add(contentPanel);
+	if (descString.length() > 0) {
+	    holderPanel.add(Box.createVerticalStrut(10));
+	    holderPanel.add(descPanel); // only if we have a description to show
+	}
+	holderPanel.add(Box.createVerticalStrut(5));
+	holderPanel.add(buttonPanel);
+	getContentPane().add(holderPanel);
+	pack();
+	setVisible(true);
     } //end CollectionInfoDialog constructor
 
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/Constants.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/Constants.java	(revision 2224)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/Constants.java	(revision 2225)
@@ -64,5 +64,7 @@
     Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
 
-
+    /* Query History Table Column Titles */
+    
+    String[]  QUERY_HISTORY_COLUMN_TITLES = {"Collection", "Terms"};
 
 
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/Query.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/Query.java	(revision 2225)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/Query.java	(revision 2225)
@@ -0,0 +1,46 @@
+
+/*
+ *    Query.java
+ *    Copyright (C) 2001 New Zealand Digital Library Project
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+package org.nzdl.gsdl.SimpleGraphicalClient;
+
+
+import java.io.*;
+
+public class Query extends Object
+{
+
+    /* should be able to return
+       query terms
+    */
+
+
+    private String queryText;
+
+    public Query(String queryString) {	 
+	queryText = queryString;
+    }
+
+    public String toString () {
+	return( queryText);
+    }
+    
+
+} //end Query class
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/QueryHistoryItem.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/QueryHistoryItem.java	(revision 2225)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/QueryHistoryItem.java	(revision 2225)
@@ -0,0 +1,67 @@
+
+/*
+ *    QueryHistoryItem.java
+ *    Copyright (C) 2001 New Zealand Digital Library Project
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+package org.nzdl.gsdl.SimpleGraphicalClient;
+
+import java.io.*;
+import java.util.*;
+
+public class QueryHistoryItem extends Object
+{
+
+    private Date date;
+    private String user; // should be a Person object
+    private Query query;
+    private String collectionName;
+
+	   // time
+	   // person
+	   // etc
+	   
+    public QueryHistoryItem(Query newQuery, Date newDate, String newCollectionName, String newUser) {
+	query = newQuery;
+	date = newDate;
+	user = newUser;
+	collectionName = newCollectionName;
+    }
+
+    public String getCollectionName() {
+	return collectionName;
+    }
+
+    public String getUser() {
+	return user;
+    }
+
+    public Query getQuery() {
+	return query;
+    }
+
+    public Date getDate() {
+	return date;
+    }
+
+    public String toString () {
+	return( user + " " + date + " "  + collectionName +" terms");
+    }
+    
+
+} //end QueryHistoryItem class
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/QueryHistoryModel.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/QueryHistoryModel.java	(revision 2225)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/QueryHistoryModel.java	(revision 2225)
@@ -0,0 +1,83 @@
+/*
+ *    QueryHistoryModel.java
+ *    Copyright (C) 2001 New Zealand Digital Library Project
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+package org.nzdl.gsdl.SimpleGraphicalClient;
+
+import java.util.*;
+import javax.swing.event.*;
+import javax.swing.*;
+import javax.swing.table.*;
+
+class QueryHistoryModel extends AbstractTableModel implements Constants {
+
+    private ArrayList historyItems; 
+
+    public QueryHistoryModel() {
+	super();
+	historyItems = new ArrayList();
+    }
+
+	
+    public void add(QueryHistoryItem queryHistoryItem) {
+	historyItems.add(0,queryHistoryItem); //add at the top!
+	//fireTableDataChanged(); //too general
+	fireTableRowsInserted(0,0);
+    }
+	
+    public int getColumnCount() {
+	return  QUERY_HISTORY_COLUMN_TITLES.length;
+    }
+
+    public int getRowCount() {
+	return historyItems.size();
+    }
+
+    public String getColumnName(int column) {
+	return QUERY_HISTORY_COLUMN_TITLES[column];
+    }
+
+    public Object getValueAt( int row, int column ) {
+	// column resolution is a bit awkward
+	// Collection = 0
+	// Terms = 1
+
+	if (column == 0) return new CollectionName(((QueryHistoryItem)historyItems.get(row)).getCollectionName());
+
+	if (column == 1) return ((QueryHistoryItem)historyItems.get(row)).getQuery();
+	return "row" + row + "col" + column;
+    }
+   
+
+
+    class CollectionName extends Object {
+	String string;
+
+	CollectionName(String newString) {
+	    string = newString;
+	}
+
+	public String toString() {
+	    return string;
+	}
+
+    } // CollectionName
+
+
+} //QueryHistoryModel
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/QueryHistoryPanel.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/QueryHistoryPanel.java	(revision 2225)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/QueryHistoryPanel.java	(revision 2225)
@@ -0,0 +1,86 @@
+/*
+ *    QueryHistoryPanel.java
+ *    Copyright (C) 2001 New Zealand Digital Library Project
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+package org.nzdl.gsdl.SimpleGraphicalClient;
+
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.*;
+import javax.swing.*;
+import javax.swing.border.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+
+
+public class QueryHistoryPanel extends JPanel implements Constants
+{
+
+    QueryHistoryModel personalQueryHistoryModel;
+
+    JTable personalQueryHistoryTable;
+    JTabbedPane tabbedPane;
+    JScrollPane personalScrollQueryPane;
+    TableSorter tableSorter;
+
+    public QueryHistoryPanel(CSModel csModel) {
+	super();
+	setLayout( new BorderLayout() );
+	setBorder(BorderFactory.createTitledBorder("Query History"));
+	
+	personalQueryHistoryModel = csModel.getQueryHistoryModel();
+	tableSorter = new TableSorter(personalQueryHistoryModel);
+	personalQueryHistoryTable = new JTable(tableSorter);
+	tableSorter.addMouseListenerToHeaderInTable(personalQueryHistoryTable);
+
+
+	personalQueryHistoryTable.setDefaultRenderer(QueryHistoryModel.CollectionName.class, new CollectionNameRenderer());
+
+	personalQueryHistoryTable.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
+	personalScrollQueryPane = new JScrollPane(personalQueryHistoryTable);
+	
+	tabbedPane= new JTabbedPane();
+	tabbedPane.addTab("Personal", personalScrollQueryPane);
+	add(tabbedPane, BorderLayout.CENTER);
+    } // end constructor
+
+
+
+class CollectionNameRenderer extends JLabel implements TableCellRenderer {
+  
+  public Component getTableCellRendererComponent(JTable table,
+                                               Object value,
+                                               boolean isSelected,
+                                               boolean hasFocus,
+                                               int row,
+                                               int column) {
+											   this.setText("**" + value.toString());
+											  									   return this;
+	} // end getTableCellRendererComponent
+  
+    
+
+  
+  } //  end CollectionNameRenderer
+
+
+
+
+
+} // QueryHistoryPanel
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/SearchPanel.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/SearchPanel.java	(revision 2224)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/SearchPanel.java	(revision 2225)
@@ -116,9 +116,17 @@
 
     collectionList = new JComboBox(csModel.getCollectionList()){
-	public boolean isFocusTraversable() {
-	  return false;
-	}
-      };
-    collectionInfoButton = new JButton("Info...");
+	       public boolean isFocusTraversable() {
+		return false;
+		}
+    };
+    collectionList.setEditable(false);
+     
+    collectionInfoButton = new JButton("Info...") {
+	    public String getToolTipText(MouseEvent e) {
+		//return "more information on " + collectionList.getSelectedItem();
+		return "More information on " + csModel.getLongCollectionName((String)collectionList.getSelectedItem());
+	    }
+    };
+    ToolTipManager.sharedInstance().registerComponent(collectionInfoButton);
     collectionInfoButton.addActionListener(this);
 
@@ -194,9 +202,9 @@
 
   public void actionPerformed(ActionEvent e) {
+      String collectionName = collectionList.getSelectedItem().toString();
     if (e.getSource() == searchButton ) {
       // cursor not set when RETURN pressed, only when button clicked ?
       windowParent.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
       String queryString = searchTextField.getText();
-      String collectionName = collectionList.getSelectedItem().toString();
       System.err.println("Search started (" + collectionName + "): \"" + queryString + "\" ..." );
       //send query to collection
@@ -240,4 +248,8 @@
 	resultsList.setSelectedIndex(0); // should be under Preference control!
       } // end else
+
+
+      csModel.getQueryHistoryModel().add( new QueryHistoryItem(new Query(queryString), new Date(), collectionName, "user"));
+
       titleMap.clear();
       titleMetaData.clear();
@@ -247,5 +259,5 @@
     else {
 	if (e.getSource() == collectionInfoButton) {
-	    CollectionInfoDialog cid = new CollectionInfoDialog(windowParent, collectionList.getSelectedItem().toString(), nzdl);
+	    CollectionInfoDialog cid = new CollectionInfoDialog(windowParent, collectionName, csModel);
 	}
 	else {
@@ -287,5 +299,5 @@
 	      // treat as HTML
 	      displayAsHTML(sr);
-	      htmlDoc.getImageData(nzdl, result.getCollectionName());
+	      //htmlDoc.getImageData(nzdl, result.getCollectionName());
 	  }
 
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/TableMap.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/TableMap.java	(revision 2225)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/TableMap.java	(revision 2225)
@@ -0,0 +1,69 @@
+/** 
+ * In a chain of data manipulators some behaviour is common. TableMap
+ * provides most of this behavour and can be subclassed by filters
+ * that only need to override a handful of specific methods. TableMap 
+ * implements TableModel by routing all requests to its model, and
+ * TableModelListener by routing all events to its listeners. Inserting 
+ * a TableMap which has not been subclassed into a chain of table filters 
+ * should have no effect.
+ *
+ * @version 1.4 12/17/97
+ * @author Philip Milne */
+
+package org.nzdl.gsdl.SimpleGraphicalClient;
+
+import javax.swing.table.*; 
+import javax.swing.event.TableModelListener; 
+import javax.swing.event.TableModelEvent; 
+
+public class TableMap extends AbstractTableModel 
+                      implements TableModelListener {
+    protected TableModel model; 
+
+    public TableModel getModel() {
+        return model;
+    }
+
+    public void setModel(TableModel model) {
+        this.model = model; 
+        model.addTableModelListener(this); 
+    }
+
+    // By default, implement TableModel by forwarding all messages 
+    // to the model. 
+
+    public Object getValueAt(int aRow, int aColumn) {
+        return model.getValueAt(aRow, aColumn); 
+    }
+        
+    public void setValueAt(Object aValue, int aRow, int aColumn) {
+        model.setValueAt(aValue, aRow, aColumn); 
+    }
+
+    public int getRowCount() {
+        return (model == null) ? 0 : model.getRowCount(); 
+    }
+
+    public int getColumnCount() {
+        return (model == null) ? 0 : model.getColumnCount(); 
+    }
+        
+    public String getColumnName(int aColumn) {
+        return model.getColumnName(aColumn); 
+    }
+
+    public Class getColumnClass(int aColumn) {
+        return model.getColumnClass(aColumn); 
+    }
+        
+    public boolean isCellEditable(int row, int column) { 
+         return model.isCellEditable(row, column); 
+    }
+//
+// Implementation of the TableModelListener interface, 
+//
+    // By default forward all events to all the listeners. 
+    public void tableChanged(TableModelEvent e) {
+        fireTableChanged(e);
+    }
+}
Index: /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/TableSorter.java
===================================================================
--- /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/TableSorter.java	(revision 2225)
+++ /trunk/java-client/org/nzdl/gsdl/SimpleGraphicalClient/TableSorter.java	(revision 2225)
@@ -0,0 +1,313 @@
+/**
+ * A sorter for TableModels. The sorter has a model (conforming to TableModel) 
+ * and itself implements TableModel. TableSorter does not store or copy 
+ * the data in the TableModel, instead it maintains an array of 
+ * integers which it keeps the same size as the number of rows in its 
+ * model. When the model changes it notifies the sorter that something 
+ * has changed eg. "rowsAdded" so that its internal array of integers 
+ * can be reallocated. As requests are made of the sorter (like 
+ * getValueAt(row, col) it redirects them to its model via the mapping 
+ * array. That way the TableSorter appears to hold another copy of the table 
+ * with the rows in a different order. The sorting algorthm used is stable 
+ * which means that it does not move around rows when its comparison 
+ * function returns 0 to denote that they are equivalent. 
+ *
+ * @version 1.5 12/17/97
+ * @author Philip Milne
+ */
+package org.nzdl.gsdl.SimpleGraphicalClient;
+
+
+import java.util.*;
+
+import javax.swing.table.TableModel;
+import javax.swing.event.TableModelEvent;
+
+// Imports for picking up mouse events from the JTable. 
+
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.InputEvent;
+import javax.swing.JTable;
+import javax.swing.table.JTableHeader;
+import javax.swing.table.TableColumnModel;
+
+public class TableSorter extends TableMap {
+    int             indexes[];
+    Vector          sortingColumns = new Vector();
+    boolean         ascending = true;
+    int compares;
+
+    public TableSorter() {
+        indexes = new int[0]; // for consistency
+    }
+
+    public TableSorter(TableModel model) {
+        setModel(model);
+    }
+
+    public void setModel(TableModel model) {
+        super.setModel(model); 
+        reallocateIndexes(); 
+    }
+
+    public int compareRowsByColumn(int row1, int row2, int column) {
+        Class type = model.getColumnClass(column);
+        TableModel data = model;
+
+        // Check for nulls.
+
+        Object o1 = data.getValueAt(row1, column);
+        Object o2 = data.getValueAt(row2, column); 
+
+        // If both values are null, return 0.
+        if (o1 == null && o2 == null) {
+            return 0; 
+        } else if (o1 == null) { // Define null less than everything. 
+            return -1; 
+        } else if (o2 == null) { 
+            return 1; 
+        }
+
+        /*
+         * We copy all returned values from the getValue call in case
+         * an optimised model is reusing one object to return many
+         * values.  The Number subclasses in the JDK are immutable and
+         * so will not be used in this way but other subclasses of
+         * Number might want to do this to save space and avoid
+         * unnecessary heap allocation.
+         */
+
+        if (type.getSuperclass() == java.lang.Number.class) {
+            Number n1 = (Number)data.getValueAt(row1, column);
+            double d1 = n1.doubleValue();
+            Number n2 = (Number)data.getValueAt(row2, column);
+            double d2 = n2.doubleValue();
+
+            if (d1 < d2) {
+                return -1;
+            } else if (d1 > d2) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else if (type == java.util.Date.class) {
+            Date d1 = (Date)data.getValueAt(row1, column);
+            long n1 = d1.getTime();
+            Date d2 = (Date)data.getValueAt(row2, column);
+            long n2 = d2.getTime();
+
+            if (n1 < n2) {
+                return -1;
+            } else if (n1 > n2) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else if (type == String.class) {
+            String s1 = (String)data.getValueAt(row1, column);
+            String s2    = (String)data.getValueAt(row2, column);
+            int result = s1.compareTo(s2);
+
+            if (result < 0) {
+                return -1;
+            } else if (result > 0) {
+                return 1;
+            } else {
+                return 0;
+            }
+        } else if (type == Boolean.class) {
+            Boolean bool1 = (Boolean)data.getValueAt(row1, column);
+            boolean b1 = bool1.booleanValue();
+            Boolean bool2 = (Boolean)data.getValueAt(row2, column);
+            boolean b2 = bool2.booleanValue();
+
+            if (b1 == b2) {
+                return 0;
+            } else if (b1) { // Define false < true
+                return 1;
+            } else {
+                return -1;
+            }
+        } else {
+            Object v1 = data.getValueAt(row1, column);
+            String s1 = v1.toString();
+            Object v2 = data.getValueAt(row2, column);
+            String s2 = v2.toString();
+            int result = s1.compareTo(s2);
+
+            if (result < 0) {
+                return -1;
+            } else if (result > 0) {
+                return 1;
+            } else {
+        	return 0;
+            }
+        }
+    }
+
+    public int compare(int row1, int row2) {
+        compares++;
+        for (int level = 0; level < sortingColumns.size(); level++) {
+            Integer column = (Integer)sortingColumns.elementAt(level);
+            int result = compareRowsByColumn(row1, row2, column.intValue());
+            if (result != 0) {
+                return ascending ? result : -result;
+            }
+        }
+        return 0;
+    }
+
+    public void reallocateIndexes() {
+        int rowCount = model.getRowCount();
+
+        // Set up a new array of indexes with the right number of elements
+        // for the new data model.
+        indexes = new int[rowCount];
+
+        // Initialise with the identity mapping.
+        for (int row = 0; row < rowCount; row++) {
+            indexes[row] = row;
+        }
+    }
+
+    public void tableChanged(TableModelEvent e) {
+        //System.out.println("Sorter: tableChanged"); 
+        reallocateIndexes();
+
+        super.tableChanged(e);
+    }
+
+    public void checkModel() {
+        if (indexes.length != model.getRowCount()) {
+            System.err.println("Sorter not informed of a change in model.");
+        }
+    }
+
+    public void sort(Object sender) {
+        checkModel();
+
+        compares = 0;
+        // n2sort();
+        // qsort(0, indexes.length-1);
+        shuttlesort((int[])indexes.clone(), indexes, 0, indexes.length);
+        //System.out.println("Compares: "+compares);
+    }
+
+    public void n2sort() {
+        for (int i = 0; i < getRowCount(); i++) {
+            for (int j = i+1; j < getRowCount(); j++) {
+                if (compare(indexes[i], indexes[j]) == -1) {
+                    swap(i, j);
+                }
+            }
+        }
+    }
+
+    // This is a home-grown implementation which we have not had time
+    // to research - it may perform poorly in some circumstances. It
+    // requires twice the space of an in-place algorithm and makes
+    // NlogN assigments shuttling the values between the two
+    // arrays. The number of compares appears to vary between N-1 and
+    // NlogN depending on the initial order but the main reason for
+    // using it here is that, unlike qsort, it is stable.
+    public void shuttlesort(int from[], int to[], int low, int high) {
+        if (high - low < 2) {
+            return;
+        }
+        int middle = (low + high)/2;
+        shuttlesort(to, from, low, middle);
+        shuttlesort(to, from, middle, high);
+
+        int p = low;
+        int q = middle;
+
+        /* This is an optional short-cut; at each recursive call,
+        check to see if the elements in this subset are already
+        ordered.  If so, no further comparisons are needed; the
+        sub-array can just be copied.  The array must be copied rather
+        than assigned otherwise sister calls in the recursion might
+        get out of sinc.  When the number of elements is three they
+        are partitioned so that the first set, [low, mid), has one
+        element and and the second, [mid, high), has two. We skip the
+        optimisation when the number of elements is three or less as
+        the first compare in the normal merge will produce the same
+        sequence of steps. This optimisation seems to be worthwhile
+        for partially ordered lists but some analysis is needed to
+        find out how the performance drops to Nlog(N) as the initial
+        order diminishes - it may drop very quickly.  */
+
+        if (high - low >= 4 && compare(from[middle-1], from[middle]) <= 0) {
+            for (int i = low; i < high; i++) {
+                to[i] = from[i];
+            }
+            return;
+        }
+
+        // A normal merge. 
+
+        for (int i = low; i < high; i++) {
+            if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) {
+                to[i] = from[p++];
+            }
+            else {
+                to[i] = from[q++];
+            }
+        }
+    }
+
+    public void swap(int i, int j) {
+        int tmp = indexes[i];
+        indexes[i] = indexes[j];
+        indexes[j] = tmp;
+    }
+
+    // The mapping only affects the contents of the data rows.
+    // Pass all requests to these rows through the mapping array: "indexes".
+
+    public Object getValueAt(int aRow, int aColumn) {
+        checkModel();
+        return model.getValueAt(indexes[aRow], aColumn);
+    }
+
+    public void setValueAt(Object aValue, int aRow, int aColumn) {
+        checkModel();
+        model.setValueAt(aValue, indexes[aRow], aColumn);
+    }
+
+    public void sortByColumn(int column) {
+        sortByColumn(column, true);
+    }
+
+    public void sortByColumn(int column, boolean ascending) {
+        this.ascending = ascending;
+        sortingColumns.removeAllElements();
+        sortingColumns.addElement(new Integer(column));
+        sort(this);
+        super.tableChanged(new TableModelEvent(this)); 
+    }
+
+    // There is no-where else to put this. 
+    // Add a mouse listener to the Table to trigger a table sort 
+    // when a column heading is clicked in the JTable. 
+    public void addMouseListenerToHeaderInTable(JTable table) { 
+        final TableSorter sorter = this; 
+        final JTable tableView = table; 
+        tableView.setColumnSelectionAllowed(false); 
+        MouseAdapter listMouseListener = new MouseAdapter() {
+            public void mouseClicked(MouseEvent e) {
+                TableColumnModel columnModel = tableView.getColumnModel();
+                int viewColumn = columnModel.getColumnIndexAtX(e.getX()); 
+                int column = tableView.convertColumnIndexToModel(viewColumn); 
+                if (e.getClickCount() == 1 && column != -1) {
+                    //System.out.println("Sorting ..."); 
+                    int shiftPressed = e.getModifiers()&InputEvent.SHIFT_MASK; 
+                    boolean ascending = (shiftPressed == 0); 
+                    sorter.sortByColumn(column, ascending); 
+                }
+            }
+        };
+        JTableHeader th = tableView.getTableHeader(); 
+        th.addMouseListener(listMouseListener); 
+    }
+}
