Index: trunk/java-client/org/nzdl/gsdl/service/NzdlCrossCollectionWrapper.java
===================================================================
--- trunk/java-client/org/nzdl/gsdl/service/NzdlCrossCollectionWrapper.java	(revision 2285)
+++ trunk/java-client/org/nzdl/gsdl/service/NzdlCrossCollectionWrapper.java	(revision 2285)
@@ -0,0 +1,356 @@
+/*
+ *    NzdlMultiWayWrapper.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.
+ */
+
+//the package we're in
+package org.nzdl.gsdl.service;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Date;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.io.Writer;
+import java.io.FileWriter;
+import org.nzdl.gsdl.corba.gsdlInterface.*;
+import org.nzdl.gsdl.util.NzdlServiceFactory;
+import org.nzdl.gsdl.util.NzdlPreferences;
+
+
+/**
+ * A NzdlCrossCollectionWrapper is a wrapper around one or 
+ * more Collections to make them appear as a single collection.
+ *
+ * NzdlCrossCollectionWrapper assumes that docIDs are unique. 
+ * If they aren't, some _very_ strange things are going to 
+ * happen...
+ *
+ * @author Stuart Yeates  (say1@cs.waikato.ac.nz)
+ * @see org.nzdl.gsdl.service.NzdlCollectionInfo
+ * @version $Revision$
+ */
+public class NzdlCrossCollectionWrapper
+  extends NzdlWrapper {
+
+  Set collectionSet;
+  String collectionName;
+  /** 
+   * The bean constructor ...
+   */
+  public NzdlCrossCollectionWrapper() {
+    super(null);
+  }
+  /** 
+   * The normal constructor
+   */
+  public NzdlCrossCollectionWrapper(NzdlService server, 
+				    Set collectionSet,
+				    String collectionName) {
+    super(server);
+    this.collectionSet = collectionSet;
+    this.collectionName = collectionName;
+  }
+  /** 
+   * The normal constructor
+   */
+  public NzdlCrossCollectionWrapper(NzdlService server, 
+				    String substring) {
+    super(server);
+    
+    Set collections = super.getCollectionSet();
+
+    if (collections.size() == 0) {
+      System.err.println("NzdlCrossCollectionWrapper found no collections.");
+      this.collectionSet = new HashSet();
+      this.collectionName = ":::NoCoLlEcTiOn:::";
+      return;
+    }
+    
+    if (substring == null || substring == "") {
+      this.collectionSet = collections;
+      this.collectionName = "Union Collection";
+      System.err.println("NzdlCrossCollectionWrapper init1 collcount: " 
+			 + collectionSet.size());
+    } else {
+      Set allCollections = collections;
+      Set ourCollections = new HashSet();
+      
+      Iterator iter = collectionSet.iterator();      
+      while(iter.hasNext()) {
+	String coll = (String) iter.next();
+	// handle the case that we've talking via a NzdlMultiWayWrapper
+	String collname = NzdlMultiWayWrapper.findCollection(coll);
+	if (collname.startsWith(substring))
+	  if (collname.indexOf("nuipepa") == -1)
+	    ourCollections.add(coll);
+      }
+      this.collectionSet = ourCollections;
+      this.collectionName = "\"" + substring + "\" Union Collection";
+      System.err.println("NzdlCrossCollectionWrapper init2 collcount: " 
+			 + collectionSet.size());
+    }
+  }
+ 
+  /**
+   * Allow the client to configure a CORBA server.
+   * @param key the parameter to be set.
+   * @param values what that parameter will be set to.
+   */
+  public void configure( String _key, Set _values ) {
+    super.configure(_key, _values);
+  }
+
+  /**
+   * Obtain the set of collection names for a Greenstone library.
+   * @return A set of collection names in string format.
+   */
+  public Set getCollectionSet( ) {
+    System.err.println("in getCollectionSet " + this.collectionName);
+    Set result = super.getCollectionSet();
+    result.add(this.collectionName);
+    System.err.println("getCollectionSet done " + this.collectionName);
+    return result;
+  }
+
+  /**
+   * Check if ORB knows of this collection.
+   * @param name the name of a collecion to be searched for.
+   * @return boolean <TT>true</TT> if collection is found, else <TT>false</TT>.
+   */
+  public boolean hasCollection( String _name ) {
+    if (_name.equalsIgnoreCase(collectionName))
+      return true;
+    else
+      return  super.hasCollection(_name);
+  }
+
+
+  /**
+   * Check if ORB can communicate with of this collection.
+   * @param name the name of a collecion to be pinged.
+   * @return boolean <TT>true</TT> if collection returned ping, else
+   * <TT>false</TT>.
+   */
+  public boolean pingCollection( String _name ) {
+    if (_name.equalsIgnoreCase(collectionName))
+      return true;
+    else 
+      return super.pingCollection(_name);
+  }
+
+  /**
+   * Extract information on this collection into a
+   * {@link NzdlCollectionInfo NzdlCollectionInfo} object
+   * @param name the collection to be retrieved.
+   * @return an instance of
+   * {@link NzdlCollectionInfo NzdlCollectionInfo} containing data on a
+   * collection
+   */
+  public NzdlCollectionInfo getCollectionInfo( String _name ) {
+    if (_name.equalsIgnoreCase(collectionName)) {
+      corbaColInfoResponse fake = new corbaColInfoResponse();
+      
+      Iterator iter = collectionSet.iterator();      
+      while(iter.hasNext()) {
+	String collectionName = (String) iter.next();
+	NzdlCollectionInfo info = super.getCollectionInfo(collectionName);
+	corbaColInfoResponse real = info.getInfo();
+	fake.numDocs += real.numDocs;
+	fake.numWords += real.numWords;
+	fake.numBytes += real.numBytes;
+	fake.isPublic = real.isPublic;
+	fake.isBeta = real.isBeta;
+	fake.ccsCols = real.ccsCols;
+	fake.languages = real.languages;
+	fake.collectionMeta = real.collectionMeta;
+	fake.format = real.format;
+	fake.building = real.building;
+	fake.httpdomain = real.httpdomain;
+	fake.httpprefix = real.httpprefix;
+      }
+      
+      fake.buildDate = 1;
+      
+      return new NzdlCollectionInfo(fake);
+    } else {
+      return super.getCollectionInfo(_name);
+    }
+  }
+  
+  /**
+   * Returns the set of filters for the service object.
+   * @param name the collection name
+   * @return a set of strings that name the filters, for example
+   * BrowseFilter, QueryFilter and NullFilter.
+   */
+  public Set getFilterSet( String _name ) {
+    if (_name.equalsIgnoreCase(collectionName)) {
+      Set results = new HashSet();
+      Iterator iter = collectionSet.iterator();      
+      while(iter.hasNext()) {
+	String collectionName = (String) iter.next();
+	results.addAll(super.getFilterSet(collectionName));
+      }
+      return results;
+    } else {
+      return super.getFilterSet(_name);
+    }
+  }
+
+  /**
+   * @param name the collection name
+   * @return the Set of (name, value) value pairs for all metadata 
+   * associated with a collection  
+   */
+  public Set getMetaTagSet( String _name ) {
+    if (_name.equalsIgnoreCase(collectionName)) {
+      Set results = new HashSet();
+      Iterator iter = collectionSet.iterator();      
+      while(iter.hasNext()) {
+	String collectionName = (String) iter.next();
+	results.addAll(super.getMetaTagSet(collectionName));
+      }
+      return results;
+    } else {
+      return super.getMetaTagSet(_name);
+    }
+  }
+
+  /**
+   * Returns the Greenstone Markup Language (GML) text for a particular
+   * document from a collection.
+   * @param name the name of the collection.
+   * @param docID the document identity string
+   * @return the GML document in the form of a string.
+   */
+  public String getDocument( String _name, String _docID ) {
+    if (_name.equalsIgnoreCase(collectionName)) {
+      String results = new String();
+      Iterator iter = collectionSet.iterator();      
+      while(iter.hasNext()) {
+	String collectionName = (String) iter.next();
+	results = results + super.getDocument(collectionName, _docID);
+      }
+      return results;
+    } else {
+      return super.getDocument(_name,_docID);
+    }
+  }
+
+  /**
+   * Returns the set of value(s) for a metatag from a particular document.
+   * @param name collection name
+   * @param docID the document identifier.
+   * @param metaTag the metatag name such as: Title, Author, Date and Images.
+   * @return The set of value(s) for the requested metatag and document. In
+   * cases such as Title, Author, Date there will probably be only one value
+   * per document.
+   */
+  public Set getMetaData( String _name, String _docID, String _metaTag ) {
+    if (_name.equalsIgnoreCase(collectionName)) {
+      Set results = new HashSet();
+      Iterator iter = collectionSet.iterator();      
+      while(iter.hasNext()) {
+	String collectionName = (String) iter.next();
+	results.addAll(super.getMetaData(collectionName,_docID,_metaTag));
+      }
+      return results;
+    } else {
+      return super.getMetaData(_name,_docID,_metaTag);
+    }
+  }
+
+  /**
+   * Returns a map of value(s) for a metatag from a list of documents.
+   * @param name collection name
+   * @param docIDs a list of document identifier strings.
+   * @param metaTag the metatag name such as: Title, Author, Date and Images.
+   * @return The map of value(s) for the requested metatag and document. In
+   * cases such as Title, Author, Date there will probably be only one value
+   * per document.
+   */
+  public Map getMetaData( String _name, List _docIDs, String _metaTag ) {
+    if (_name.equalsIgnoreCase(collectionName)) {
+      Map results = new HashMap();
+      Iterator iter = collectionSet.iterator();      
+      while(iter.hasNext()) {
+	String collectionName = (String) iter.next();
+	results.putAll(super.getMetaData(collectionName,_docIDs,_metaTag));
+      }
+      return results;
+    } else {
+      return super.getMetaData(_name,_docIDs,_metaTag);
+    }
+  }
+
+
+  corbaTermInfo[] concat(corbaTermInfo[] first, corbaTermInfo[] second) {
+    corbaTermInfo[] result = 
+      new corbaTermInfo[first.length + second.length];
+    for (int i = 0;i<first.length;i++) 
+      result[i] = first[i];
+    for (int i = 0;i<second.length;i++) 
+      result[first.length+ i] = second[i];
+    return result;
+  }
+
+  corbaResultDocInfo[] concat(corbaResultDocInfo[] first, corbaResultDocInfo[] second) {
+    corbaResultDocInfo[] result = 
+      new corbaResultDocInfo[first.length + second.length];
+    for (int i = 0;i<first.length;i++) 
+      result[i] = first[i];
+    for (int i = 0;i<second.length;i++) 
+      result[first.length+ i] = second[i];
+    return result;
+  }
+
+  /**
+   * Services a {@link NzdlRequest NzdlRequest} to a collection and places
+   * the results into a {@link NzdlResponse NzdlResponse} object. <br>
+   * Pre:   Created instances of NzdlRequest and NzdlResponse. <br>
+   * Post: Placed the result data into NzdlResponse object.
+   * @param name the collection name.
+   * @param request an instance of NzdlRequest with query data to be serviced
+   * @param response an instance of NzdlResponse. where the results of
+   * sevciving the query will be placed
+   */
+  public void service( String _name, NzdlRequest _request, 
+		       NzdlResponse _response ) {    
+    if (_name.equalsIgnoreCase(collectionName)) {
+      corbaFilterResponse fake = new corbaFilterResponse();
+      Iterator iter = collectionSet.iterator();      
+      while(iter.hasNext()) {
+	String collectionName = (String) iter.next();
+	NzdlResponse response = new NzdlResponse();
+	super.service(collectionName,_request,response);
+	fake.numDocs = fake.numDocs + response.getResponse().numDocs;
+	fake.termInfo = concat(fake.termInfo,response.getResponse().termInfo);
+	fake.docInfo = concat(fake.docInfo,response.getResponse().docInfo);
+	_response.setResponse(fake);
+      }
+    } else {
+       super.service(_name,_request,_response);
+    }
+  }  
+}
