Index: /tags/gsdl3_0/gsdl3/README
===================================================================
--- /tags/gsdl3_0/gsdl3/README	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/README	(revision 3225)
@@ -0,0 +1,172 @@
+initial prototype of gsdl3
+
+only for linux
+
+need to run setup.bash to set CLASSPATH etc
+
+java src code in src/java/org/greenstone/gsdl3 - you need to do a  make, and 
+then a make install in this top directory. - makes all the classes in the 
+subdirectories too.
+
+classes get compiled to src/java/org/greenstone/gsdl/classes, then a jar file
+is made of them all. make install copies this to lib/java
+
+There are two executable classes: Library1 and Library2
+
+both are run by "java org.greenstone.gsdl3.Libraryx <gsdlhome> <sitehome>"
+
+gsdlhome is the base dir for your installation: .../gsdl3
+sitehome is the base dir for the site you are running:
+ for the local library example site, its .../gsdl3/sites/localsite
+ for the distributed soap example site, its .../gsdl3/sites/site1
+
+(imaginative names eh)
+
+There are 3 sites in this prototype example.
+
+sites/localsite is a standalone site, like used by a local library. It has
+no connections to any other sites.
+
+sites/site1 is a site that specifies a SOAP connection to another site: site2
+
+sites/site2 can be run as a local site also.
+
+to run site1, and talk to site2 via SOAP, you need to have apache tomcat installed,running, and serving site2. (see below)
+
+Library1 - just takes straight XML queries and returns the results. see docs/xml/* for examples - not there yet. can use the other library to see how requests are formatted
+basically its like:
+
+<message><request type="describe|query" to="demo/TextQuery" info=""/></message>
+with type="describe", to="", can use serviceList, collectionList and siteList for the info field.
+
+Library2 - still command line based, but has a slightly nicer interface.
+it will prompt you for commands eg
+type of request - describe/query
+collection name
+service name
+info name (at the moment collectionList, serviceList, siteList)
+these can all be left blank except for the first one
+A sample usage thingy:
+
+describe,_,_,_ - returns info from MessageRouter - list of colls, sites, services etc
+
+describe,_,_,collectionList - returns info from MessageRouter - only a list of colls
+
+describe,demo,_,_ - returns info from demo coll - list of services
+
+describe,demo,TextQuery,_ - returns info about the service
+
+Library2 also attempts to use some XSLT transforms to format the resulting xml
+
+********************************************************************
+
+SOAP stuff.
+
+am using jakarta tomcat at this stage to serve the SOAP classes
+-----------------------------------------------------
+set up SOAP Server:
+
+the class SOAPServer is a wrapper around a messagerouter - so can serve 
+the collections
+
+it has a path hard coded in  - need to set this to your appropriate site - 
+for the example sites that I've set up, it should be <GSDL3HOME>/sites/site2
+--------------------------------------------------------------------
+TOMCAT installation:
+
+need to install tomcat and soap:
+
+
+ a tar file is in comms/tomcat directory - not sure where to put this, so made a new directory for it
+
+you need to unzip the tar file.
+
+edit jakarta-tomcat-4.0.1/bin/catalina.sh:
+
+on line 89 add $CP to the CP="...." line ie. CP="$CP:..." - this sets up the 
+class path properly
+
+edit jakarta-tomcat-4.0.1/conf/server.xml
+
+add the following (put proper path for <GSDL3HOME>)
+
+<!-- SOAP Service -->
+<Context path="/soap" docBase="<GSDL3HOME>/comms/soap/soap-2_2/webapps/soap" debug="1" reloadable="true"/>
+
+(there are other Context elements to look at)
+
+---------------------------------------------------------------------
+install soap:
+
+just untar soap-bin-2.2.tar.gz in the comms/soap directory
+--------------------------------------------------------------
+to run tomcat, need to source setup.bash in GSDL3HOME to set up $CP
+
+then cd to comms/tomcat/jakarta-tomcat-4.0.1/bin
+
+run startup.sh
+
+to shut down tomcat, run shutdown.sh
+
+you can access the soap service though the web, at http://localhost:8080/soap
+
+(conf/server.xml is the place to change the port number if needed)
+
+
+Run the admin client
+
+can list, deploy, undeploy soap services
+
+-----------------------------------------------------------------
+to deploy the SOAPServer for site2:
+
+edit the following fields in the deploy form:
+
+ID:  org.greenstone.site2
+Scope: any will do: Request - new instantiation for each request
+		    Session - same instantiation across a session
+		    Application - only uses one instantiation
+
+Methods: process
+
+Java Provider / Provider Class: org.greenstone.gsdl3.SOAPServer
+
+then click deploy.
+hopefully all will be well.
+
+---------------------------------------------------------
+
+shoudl be able to run (from GSDL3HOME directory)
+java org.greenstone.gsdl3.Library2 . ./sites/site1
+
+and have it talk via soap. (assuming you have tomcat running and have deployed
+org.greenstone.site2)
+
+--------------------------------------------------------
+
+debugging soap:
+
+tomcat output goes to jakarta-tomcat-4.0.1/logs/catalina.out
+
+if you recompile the classes, you need to shutdown and restart tomcat to get the new classes.
+
+deployment info is retained between shutdown and start up - dont need to redeploy it each time.
+
+TcpTUnnelGui:
+
+this program allows you to view the actual soap messages
+
+run like:
+
+java org.apache.soap.util.net.TcpTunnelGui 8070 localhost 8080
+
+tomcat uses 8080, and you need to modify the greenstone stuff to talk to port 8070 instead of 8080:
+
+sites/site1 is the site that talks to the SOAPServer for site2
+
+in site1/sitecfg.xml, in the address field, replace 8080 with 8070 when you want to use TcpTunnelGui.
+
+note that 
+http://localhost:8080/soap/servlet/rpcrouter
+
+is the address for talking to the tomcat soap thingy.
Index: /tags/gsdl3_0/gsdl3/setup.bash
===================================================================
--- /tags/gsdl3_0/gsdl3/setup.bash	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/setup.bash	(revision 3225)
@@ -0,0 +1,48 @@
+# if this file is executed, /bin/sh is used, as we don't start with #!
+# this should work under ash, bash, zsh, ksh, sh style shells.
+
+# make sure we are sourced, and not run
+
+if test "$0" != "`echo $0 | sed s/setup\.bash//`" ; then
+# if $0 contains "setup.bash" we've been run... $0 is shellname if sourced.
+# One exception is zsh has an option to set it temporarily to the script name
+  if test -z "$ZSH_NAME" ; then
+  # we aren't using zsh
+  gsdl_not_sourced=true
+  fi
+fi
+
+if test -n "$gsdl_not_sourced" ; then
+  echo "	Error: Make sure you source this script, not execute it. Eg:"
+  echo "		$ source setup.bash"
+  echo "	or"
+  echo "		$ . ./setup.bash"
+  echo "	not"
+  echo "		$ ./setup.bash"
+elif test -n "$GSDL3HOME" ; then
+  echo "Your environment is already set up for Greenstone3!"
+elif test ! -f setup.bash ; then
+  echo "You must source the script from within the Greenstone home directory"
+else
+  GSDL3HOME=`pwd`
+  export GSDL3HOME
+  GSDL3OS=`uname -s | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  # check for running bash under cygwin
+  if test "`echo $GSDL3OS | sed 's/cygwin//'`" != "$GSDL3OS" ;
+  then
+    GSDL3OS=windows
+  fi
+  export GSDL3OS
+
+  PATH=$PATH:$GSDL3HOME/bin/script:$GSDL3HOME/bin/$GSDL3OS
+  export PATH
+  MANPATH=$MANPATH:$GSDL3HOME/doc/man
+  export MANPATH
+  CLASSPATH=$GSDL3HOME/lib/java/gsdl3.jar:$GSDL3HOME/lib/java/xercesImpl.jar:$GSDL3HOME/lib/java/xmlParserAPIs.jar:$GSDL3HOME/lib/java/xindice.jar:$GSDL3HOME/lib/java/jaxp.jar:$GSDL3HOME/lib/java/soap.jar:$GSDL3HOME/lib/java/mail.jar:$GSDL3HOME/lib/java/activation.jar
+  export CLASSPATH
+
+  #tomcat stuff
+  CP=$GSDL3HOME/lib/java/gsdl3.jar:$GSDL3HOME/lib/java/xercesImpl.jar:$GSDL3HOME/lib/java/xmlParserAPIs.jar:$GSDL3HOME/lib/java/xindice.jar:$GSDL3HOME/lib/java/jaxp.jar:$GSDL3HOME/lib/java/soap.jar:$GSDL3HOME/lib/java/mail.jar:$GSDL3HOME/lib/java/activation.jar:/research/kjdon/src/tomcat/jakarta-tomcat-4.0.1/common/lib/servlet.jar
+  echo "Your environment has successfully been set up to run Greenstone3"
+fi
+unset gsdl_not_sourced
Index: /tags/gsdl3_0/gsdl3/sites/localsite/collect/demo/index/buildcfg.xml
===================================================================
--- /tags/gsdl3_0/gsdl3/sites/localsite/collect/demo/index/buildcfg.xml	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/sites/localsite/collect/demo/index/buildcfg.xml	(revision 3225)
@@ -0,0 +1,15 @@
+<buildConfiguration>
+<metadataList>
+<metadata name="numDocs">11</metadata>
+<metadata name="numSections">231</metadata>
+</metadataList>
+<serviceModuleList>
+<serviceModule name="MGGDBMService" type="query">
+<indexList>
+<index name="dtx"/>
+<index name="stt"/>
+</indexList>
+</serviceModule>
+<serviceModule name="PhindService" type="query"/>
+</serviceModuleList>
+</buildConfiguration>
Index: /tags/gsdl3_0/gsdl3/sites/localsite/collect/demo/index/tmp
===================================================================
--- /tags/gsdl3_0/gsdl3/sites/localsite/collect/demo/index/tmp	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/sites/localsite/collect/demo/index/tmp	(revision 3225)
@@ -0,0 +1,1 @@
+<metadata name="metadata"><element name="dc:Title"/><element name="dc:Subject"/></metadata>
Index: /tags/gsdl3_0/gsdl3/sites/localsite/sitecfg.xml
===================================================================
--- /tags/gsdl3_0/gsdl3/sites/localsite/sitecfg.xml	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/sites/localsite/sitecfg.xml	(revision 3225)
@@ -0,0 +1,5 @@
+<config>
+<localSiteName value="org.greenstone.localsite"/>
+<serviceModuleList>
+</serviceModuleList>
+</config>
Index: /tags/gsdl3_0/gsdl3/sites/site1/collect/myfiles/index/buildcfg.xml
===================================================================
--- /tags/gsdl3_0/gsdl3/sites/site1/collect/myfiles/index/buildcfg.xml	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/sites/site1/collect/myfiles/index/buildcfg.xml	(revision 3225)
@@ -0,0 +1,23 @@
+<buildConfiguration>
+<metadataList>
+<metadata name="numDocs">5</metadata>
+<metadata name="numSections">189</metadata>
+</metadataList>
+<serviceModuleList>
+<serviceModule name="MGPPService" type="Query">
+<indexList>
+<index name="mt"/>
+<fieldList>
+<element name="Title"/><element name="Howto"/><element name="text"/>
+</fieldList>
+<levelList>
+<element name="Document"/><element name="Section"/>
+</levelList></indexList>
+<metadataList>
+<metadata name="Title"/><metadata name="Subject"/><metadata name="Howto"/>
+</metadataList>
+</serviceModule>
+</serviceModuleList>
+</buildConfiguration>
+
+
Index: /tags/gsdl3_0/gsdl3/sites/site1/sitecfg.xml
===================================================================
--- /tags/gsdl3_0/gsdl3/sites/site1/sitecfg.xml	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/sites/site1/sitecfg.xml	(revision 3225)
@@ -0,0 +1,6 @@
+<config>
+<localSiteName value="org.greenstone.site1"/>
+<siteList>
+<site name="org.greenstone.site2" address="http://localhost:8080/soap/servlet/rpcrouter" type="soap"/>
+</siteList>
+</config>
Index: /tags/gsdl3_0/gsdl3/sites/site2/collect/fao/index/buildcfg.xml
===================================================================
--- /tags/gsdl3_0/gsdl3/sites/site2/collect/fao/index/buildcfg.xml	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/sites/site2/collect/fao/index/buildcfg.xml	(revision 3225)
@@ -0,0 +1,18 @@
+<buildConfiguration>
+<metadataList>
+<metadata name="numDocs">321</metadata>
+<metadata name="numSections">5532</metadata>
+<metadata name="Title">Food and Agriculture</metadata>
+<metadata name="Description">A demo colleciton</metadata>
+<metadata name="Metadata"><element name="dc:Title"/><element name="dc:Subject"/></metadata>
+</metadataList>
+<serviceModuleList>
+<serviceModule name="MGGDBMService" type="query">
+<indexList>
+<index name="dtx"/>
+<index name="stt"/>
+<index name="stx"/>
+</indexList>
+</serviceModule>
+</serviceModuleList>
+</buildConfiguration>
Index: /tags/gsdl3_0/gsdl3/sites/site2/sitecfg.xml
===================================================================
--- /tags/gsdl3_0/gsdl3/sites/site2/sitecfg.xml	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/sites/site2/sitecfg.xml	(revision 3225)
@@ -0,0 +1,5 @@
+<config>
+<localSiteName value="org.greenstone.site2"/>
+<serviceModuleList>
+</serviceModuleList>
+</config>
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/Library1.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/Library1.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/Library1.java	(revision 3225)
@@ -0,0 +1,50 @@
+package org.greenstone.gsdl3;
+
+import org.greenstone.gsdl3.core.*;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/** sample command line interface to gsdl3 site
+ *
+ * enter XML queries at the prompt
+ */
+final public class Library1 {
+
+    public static void main(String args[]) {
+
+	if (args.length != 2) {
+	    System.out.println("Usage: Library1 <gsdl3home> <sitehome>");
+	    System.exit(1);
+	}
+	String gsdl_home = args[0]; // dont use yet
+	String site_home = args[1];
+
+	MessageRouter mr = new MessageRouter();
+	mr.setSiteHome(site_home);
+	mr.configure();
+	
+	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+	String query=null;
+	String result=null;
+	while (true) {
+	    System.out.println("Please enter an XML query all on one line, or 'exit' to quit");
+	    try {
+		query = br.readLine();
+	    } catch (Exception e) {
+		System.err.println("Library1 exception:"+e.getMessage());
+	    }
+	    if (query.startsWith("exit")) {
+		System.exit(1);
+	    }
+	    System.out.println("\nProcessing query");
+	    
+	    result = mr.process(query);
+
+	    System.out.println("Result:\n"+result+"\n");
+
+
+	}
+       
+    }
+}
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/Library2.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/Library2.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/Library2.java	(revision 3225)
@@ -0,0 +1,116 @@
+package org.greenstone.gsdl3;
+
+import org.greenstone.gsdl3.core.*;
+import org.greenstone.gsdl3.util.*;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.File;
+import java.io.IOException;
+final public class Library2 {
+
+    public static void main(String args[]) {
+
+	if (args.length != 2) {
+	    System.out.println("Usage: Library2 <gsdl3home> <sitehome>");
+	    System.exit(1);
+	}
+	String gsdl_home = args[0]; 
+	String transform_home = GSFile.xmlTransformDir(gsdl_home);
+	String site_home = args[1];
+	
+	MessageRouter mr = new MessageRouter();
+	mr.setSiteHome(site_home);
+	mr.configure();
+	
+	// for doing xslt transforms
+	XMLTransformer transformer = new XMLTransformer();
+
+	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+	String query=null;
+	String request=null;
+	String result=null;
+	String collect=null;
+	String service=null;
+	String info=null;
+	while (true) {
+	    System.out.println("Please enter a  query type (choose from: describe, query) or 'exit' to quit");
+	    try {
+		query = br.readLine();
+		query.trim();
+		
+		if (query.startsWith("exit")) {
+		    System.exit(1);
+		}
+		if (query.equals("describe")|| query.equals("query")) {
+		    System.out.println("\nPlease enter a collection name (or <enter> for no collection)");
+		    collect = br.readLine();
+		    collect.trim();
+		    System.out.println("\nPlease enter a service name (or <enter> for no service)");
+		    service = br.readLine();
+		    service.trim();
+		    System.out.println("\nPlease enter an info name (or <enter> for no info)");
+		    info = br.readLine();
+		    info.trim();
+		    
+		    request = "<message><request type='"+query+"' to='";
+		    
+		    if (!collect.equals ("")) {
+			request += collect+"/";
+		    }
+		    if (!service.equals("")) {
+			request += service+"/";
+		    }
+		    request += "'";
+		    if (!info.equals("")) {
+			request += " info='"+info+"'";
+		    }
+		    
+		    request += "/></message>";
+		    
+		    System.out.println("Sending message to MessageRouter:\n"+request);
+		    result = mr.process(request);
+		    
+		    System.out.println("Raw Result:\n"+result+"\n");
+		    
+		    // transform the result
+		    
+		    // select a stylesheet
+		    String stylesheet = null;
+		    if (query.equals("describe")) {
+			if (collect.equals("")&&service.equals("")) {
+			    stylesheet = transform_home+File.separatorChar+"home.xsl";
+			} else if (!collect.equals("")) {
+			    stylesheet = transform_home+File.separatorChar+"collect_about.xsl";
+			} else if (!service.equals("")) {
+			    stylesheet = transform_home+File.separatorChar+"service_about.xsl";
+			}
+		    } else if (query.equals("query")) {
+			stylesheet = transform_home+File.separatorChar+"query_result.xsl";
+		    }
+		    if (stylesheet != null) {
+			File style = new File(stylesheet);
+			if (!style.exists()) {
+			    System.err.println("stylesheet doesn't exist");
+			} else {
+			
+			    String transformed_result = transformer.transform(stylesheet, result);
+			    System.out.println("Transformed result:\n"+transformed_result);
+			}
+		    } else {
+			System.out.println("no appropriate stylesheet found");
+		    }
+		} else {
+		    System.out.println("your request was not understood, sorry");
+		}
+		
+	    }  catch (IOException e) {
+		System.err.println("Library2 IO exception:"+e.getMessage());
+	    }
+	    
+	} // while (true
+    }
+    
+}
+
+    
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/Makefile
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/Makefile	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/Makefile	(revision 3225)
@@ -0,0 +1,51 @@
+#############################################################
+#           makefile for Java and JavaCC files ...          #
+#############################################################
+#
+
+# JAVA
+GSDL3HOME=/research/kjdon/gsdl3
+
+JAVALIBDIR=$(GSDL3HOME)/lib/java
+
+JAVASRCDIR=$(GSDL3HOME)/src/java
+
+#the base directory where to put class files
+JAVACLASSDIR=./classes
+
+#name/location of java compiler
+JAVAC=javac
+JAVACOPTIONS= -deprecation -g
+
+#extra java libraries
+JCLASSPATH=$(JAVACLASSDIR):$(JAVALIBDIR)/xercesImpl.jar:$(GSDL3HOME)/lib/java/xmlParserAPIs.jar:$(JAVALIBDIR)/xindice.jar:$(JAVALIBDIR)/soap.jar
+
+#specify main classes + any dynamically loaded ones - ie Services
+# this doesn't recompile properly
+#CLASSES = Library1.class Library2.class SOAPServer.class service/MGPPService.class service/MGGDBMService.class service/PhindService.class
+
+#this way is too slow
+CLASSES = Library1.class Library2.class SOAPServer.class service/MGPPService.class service/MGGDBMService.class service/PhindService.class service/ServiceModule.class comms/Communicator.class comms/SOAPCommunicator.class collection/Collection.class util/GSPath.class util/GSFile.class util/XMLTransformer.class util/XMLConverter.class core/ModuleInterface.class core/MessageRouter.class
+
+#make a .class from a .java
+%.class: %.java
+	$(JAVAC) -d $(JAVACLASSDIR) -sourcepath $(JAVASRCDIR) -classpath $(JCLASSPATH) $(JAVACOPTIONS) $<
+
+
+# this is almost always faster, but can give confusing output- says stuart
+#
+#	$(JAVAC) $(JAVACOPTIONS) -classpath $(JCLASSPATH) *.java
+
+#too slow to compile one by one
+#all: $(CLASSES) 
+all:
+	$(JAVAC) -d $(JAVACLASSDIR) -sourcepath $(JAVASRCDIR) -classpath $(JCLASSPATH) $(JAVACOPTIONS) *.java */*.java
+	jar cf gsdl3.jar -C $(JAVACLASSDIR) org
+
+
+clean: 
+	rm -r $(JAVACLASSDIR)/* gsdl3.jar
+
+install:
+	cp gsdl3.jar $(JAVALIBDIR)/
+
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/SOAPServer.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/SOAPServer.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/SOAPServer.java	(revision 3225)
@@ -0,0 +1,28 @@
+package org.greenstone.gsdl3;
+
+import org.greenstone.gsdl3.core.*;
+import org.w3c.dom.Node;
+
+public class SOAPServer
+    implements ModuleInterface {
+    
+    MessageRouter mr_=null;
+    
+    public SOAPServer() {
+	mr_ = new MessageRouter();
+	String site_home="/research/kjdon/gsdl3/sites/site2";
+	mr_.setSiteHome(site_home);	
+	mr_.configure();
+	}
+    
+    public String process(String xml_in) {
+	return mr_.process(xml_in);
+	
+    }
+
+    /** shouldn't be used, but need this to implement ModuleInterface */
+    public Node process(Node xml_in) {
+	return  mr_.process(xml_in);
+    }
+}
+
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/collection/Collection.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/collection/Collection.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/collection/Collection.java	(revision 3225)
@@ -0,0 +1,228 @@
+package org.greenstone.gsdl3.collection;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.core.*;
+import org.greenstone.gsdl3.service.*;
+
+
+// java XML classes we're using
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList; 
+
+import java.io.File;
+import java.util.HashMap;
+
+/**
+ * Represents a collection in Greenstone.
+ *
+ * Implements ModuleInterface. Contains a list of services supported by the collection, as well as collection metadata
+ *
+ * @see ModuleInterface
+ */
+public class Collection 
+    implements ModuleInterface {
+
+    /** base directory for the site */
+    protected String site_home_ = null;
+
+    /** The name of the collection - this must be the name of the collection 
+     * directory inside collect */
+    protected String collection_name_ = null;
+
+    /** The map of services.
+     *
+     * Maps Services to ServiceModule objects
+     * @see ServiceModule
+     *
+     */
+    protected HashMap service_map_=null;
+
+    /** XML converter for String to DOM and vice versa */
+    protected XMLConverter converter_=null;
+
+    /** container doc for description elements */
+    protected Document doc_ = null;
+    /** list of services */
+    protected Element service_info_ = null;
+    /** list of Metadata */
+    protected Element meta_info_ = null;
+    /** full description */
+    protected Element description_ = null;
+
+    public void setSiteHome(String home) {
+	site_home_ = home;
+    }
+
+    public void setCollectionName(String name) {
+	collection_name_ = name;
+	description_.setAttribute("name", name);
+    }
+
+    public Collection() {
+	service_map_ = new HashMap();
+	converter_ = new XMLConverter();
+	doc_ = converter_.newDOM();
+	description_ = doc_.createElement("collection");
+	service_info_ = doc_.createElement("serviceList");
+	meta_info_ = doc_.createElement("metadataList");
+	
+	
+    }
+	
+    /**
+     * Configures the collection.
+     *
+     * gsdlHome and collectionName must be set before configure is called.
+     *
+     * the file buildcfg.xml is located in gsdlHome/collect/collectionName
+     * collection metadata is obtained, and services loaded.
+     *
+     * @return true/false on success/fail
+     */
+    public boolean configure() {
+	
+	if (site_home_ == null || collection_name_== null) {
+	    System.err.println("site_home_ and collection_name_ must be set before configure called!");
+	    return false;
+	}
+	// read the collection build configuration file
+	File config_file_ = GSFile.collectionBuildConfigFile(site_home_, collection_name_);
+
+	if (!config_file_.exists()) {
+	    System.err.println(config_file_+" does not exist");
+	    System.err.println("couldn't configure collection: "+collection_name_);
+	    return false;
+	}
+
+	try {
+	    
+	    Document doc = converter_.getDOM(config_file_);
+	    
+	    // create all the services
+	    NodeList nodes = doc.getElementsByTagName("serviceModule");
+
+	    // the xml request to send to each serviceModule to query what
+	    // services it provides
+	    Element request = doc_.createElement("request");
+	    request.setAttribute("type", "describe");
+	    request.setAttribute("info", "serviceList");
+
+	    if (nodes.getLength()==0) {
+		System.err.println("Collection configuration error: collection "+collection_name_+" has no services!");
+		return false;
+	    }
+
+	    for(int i=0; i<nodes.getLength(); i++) {
+		Element n = (Element)nodes.item(i);
+		String servicetype = n.getAttribute("name");
+		
+		ServiceModule s = (ServiceModule)Class.forName("org.greenstone.gsdl3.service."+servicetype).newInstance();
+		s.setSiteHome(site_home_);
+		s.setCollectionName(collection_name_);
+		// pass the xml node to the service for configuration
+		s.configure(n);
+
+		// find out the supported service types for this service module
+		Node types = s.process(request);
+		NodeList typenodes = ((Element)types).getElementsByTagName("service");	   
+
+		for (int j=0; j<typenodes.getLength();j++) {
+		    String service = ((Element) typenodes.item(j)).getAttribute("name");	    
+		    service_map_.put(service, s);
+
+		    // also add info to the ServiceInfo XML element
+		    service_info_.appendChild(doc_.importNode(typenodes.item(j), true));
+		}
+		
+	    }
+
+	    // get the metadata - for now just add it to the list
+	    NodeList metanodes = doc.getElementsByTagName("metadata");
+
+	    if (metanodes.getLength()>0) { 	
+		for(int k=0; k<metanodes.getLength(); k++) {
+		    meta_info_.appendChild(doc_.importNode(metanodes.item(k),true));
+		}
+	    }	     
+
+	} catch (Exception e) {
+	    System.out.println("Collection configure exception: "+e.getMessage() + e.getClass() );
+	    e.printStackTrace();
+	    return false;
+	}
+
+	// add elements to description
+	description_.appendChild(service_info_);
+	description_.appendChild(meta_info_);
+	return true;
+    }
+
+
+    /**
+     * Process an XML document - uses Strings 
+     *  just calls process(Node).
+     *
+     * @param in the Document to process - a string
+     * @return the resultant document as a string - contains any error messages
+     * @see String
+     */
+    public String process(String in) {
+
+	Document doc = converter_.getDOM(in);
+	Element e = doc.getDocumentElement();
+	
+	Node res = process(e);
+	return converter_.getString(res);
+	
+    }
+    
+    /** process XML as Node
+     *
+     */
+    public Node process(Node xml_in) {
+
+	// xml_in should always be an Element - should check this
+	Element xml = (Element)xml_in;
+	String to = xml.getAttribute("to");
+
+	// the collection name should be first, check, then remove
+	String col = GSPath.getFirstLink(to);
+	if (col.equals(collection_name_)){
+	    to = GSPath.removeFirstLink(to);
+	    xml.setAttribute("to", to);
+	} else {
+	    System.out.println("Collection error: collection name wrong! was "+col+" should have been "+collection_name_);
+	    return null;
+	}
+
+	if (to.equals("")) { // this command is for me
+	    String type = xml.getAttribute("type");
+	    if (type.equals("describe")) {
+		// create a response with the description inside it
+		Element response = doc_.createElement("response");
+		response.setAttribute("from", collection_name_);
+		response.setAttribute("type", "describe");
+		response.appendChild(description_);
+		return response;
+	    } else {
+		System.out.println("Collection: error, cant handle request:");
+		System.out.println(converter_.getString(xml));
+		return null;
+	    }
+	    
+	} else { // the request is for one of my services
+	    String service = GSPath.getFirstLink(to);
+	    
+	    if (service_map_.containsKey(service)) {
+		return ((ServiceModule)service_map_.get(service)).process(xml);
+	    } else {
+		System.err.println("Collection "+collection_name_+": non-existant service in:\n"+converter_.getString(xml));
+		return null;
+	    }
+
+	}
+    }
+	 
+}
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/comms/Communicator.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/comms/Communicator.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/comms/Communicator.java	(revision 3225)
@@ -0,0 +1,50 @@
+package org.greenstone.gsdl3.comms;
+
+import org.greenstone.gsdl3.core.ModuleInterface;
+import org.greenstone.gsdl3.util.*;
+
+//XML packages
+import org.w3c.dom.Node;
+
+/** Communicator - base class for Modules that talk via some protocol to other modules
+ *
+ */
+abstract public class Communicator
+    implements ModuleInterface {
+
+    /** home directory of local site */
+    protected String site_home_=null;
+    /** name of local site */
+    protected String local_site_name_ = null;
+    /** name of site to connect to */
+    protected String connection_name_=null;
+    /** address of site to connect to */
+    protected String connection_address_=null;
+    /** converter for String to DOM and vice versa */
+    protected XMLConverter converter_= null;
+
+    public Communicator() {
+	converter_ = new XMLConverter();
+    }
+    public void setSiteHome(String home) {
+	site_home_ = home;
+    }
+    public void setSiteName(String name) {
+	local_site_name_ = name;
+    }
+
+    public void setConnectionName(String name) {
+	connection_name_=name;
+    }
+
+    // format of address depends on connection type
+    public void setConnectionAddress(String address){
+	connection_address_ = address;
+    }
+ 
+    abstract public boolean configure(); 
+
+    abstract public String process(String xml_in); 
+
+    abstract public Node process(Node xml_in);
+}
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/comms/SOAPCommunicator.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/comms/SOAPCommunicator.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/comms/SOAPCommunicator.java	(revision 3225)
@@ -0,0 +1,128 @@
+package org.greenstone.gsdl3.comms;
+
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.core.*;
+
+// classes needed for SOAP stuff
+import java.net.URL;
+import java.net.MalformedURLException;
+import java.util.Vector;
+import org.apache.soap.SOAPException;
+import org.apache.soap.Fault;
+import org.apache.soap.Constants;
+import org.apache.soap.rpc.Call;
+import org.apache.soap.rpc.Parameter;
+import org.apache.soap.rpc.Response;
+
+import org.w3c.dom.Node; 
+import org.w3c.dom.NodeList; 
+import org.w3c.dom.Document; 
+import org.w3c.dom.Element; 
+
+public class SOAPCommunicator
+    extends Communicator {
+
+    /** the call object that does the SOAP talking */
+    private Call call_ = null;
+    
+    public SOAPCommunicator() {
+	
+	call_ = new Call();
+	// Set Encoding Style to standard SOAP encoding
+	call_.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
+    }
+    
+    public void setConnectionName(String name) {
+	System.out.println("name="+name);
+	connection_name_ = name;
+	// Set Object URI and Method Name
+	call_.setTargetObjectURI (name);
+	call_.setMethodName ("process"); // everything uses process
+    }
+    
+    public boolean configure() {
+	return true;
+    }
+
+
+    // put this into Communicator??
+    public String process(String in) {
+	// needs to catch SOAPException, MalformedURLException
+	try {
+	    // add the message encloser back on, and edit the to field
+	    Document doc = converter_.getDOM(in);
+	    Document newdoc = converter_.newDOM();
+	    Element top = newdoc.createElement("message");
+	    top.appendChild(newdoc.importNode(doc.getDocumentElement(), true));
+	    //newdoc.appendChild(top);
+	    NodeList requests = top.getElementsByTagName("request");
+	    if (requests.getLength()==0) {
+		// no requests
+		return "";
+	    }
+	    for (int i=0;i<requests.getLength(); i++) {
+		Element e = (Element)requests.item(i);
+		String to = e.getAttribute("to");
+		to = GSPath.removeFirstLink(to); // remove the server name, should check that it is present
+		e.setAttribute("to", to);
+		String from = e.getAttribute("from");
+		from = GSPath.appendLink(from, local_site_name_);
+		e.setAttribute("from", from);
+	    }
+
+	    String converted_request = converter_.getString(top);
+	    System.out.println("converted request = "+converted_request);
+	    //  Set Method Parameters
+	    Parameter param = new Parameter("xml_in", String.class,
+					    converted_request, Constants.NS_URI_SOAP_ENC);
+	    Vector param_list = new Vector ();
+	    param_list.addElement (param);
+	    call_.setParams (param_list);
+	    
+	    //  Set the URL for the Web Service
+	    URL url = new URL(connection_address_);
+	    
+	    // Invoke the Service
+	    Response resp = call_.invoke (url, "");
+	    
+	    // Check for Faults
+	    if (!resp.generatedFault()) {
+	    // Extract Return value
+		Parameter result = resp.getReturnValue ();
+		String res = (String) result.getValue();
+		return res;
+	    }
+	    else {
+		//  Extract Fault Code and String
+		Fault f = resp.getFault();
+		String faultCode = f.getFaultCode();
+		String faultString = f.getFaultString();
+		System.err.println("Fault Occurred (details follow):");
+		System.err.println("Fault Code:  "+faultCode);
+		System.err.println("Fault String:  "+faultString);
+		return new String ("<message>Fault Occurred.  No greeting for you!</message>");
+	    }
+	} catch (SOAPException e) {
+	    System.out.println("SOAP error:"+e.getMessage());
+	    return "";
+	} catch (MalformedURLException e) {
+	    System.out.println("URL error:"+e.getMessage());
+	    return "";
+	}
+    }
+    
+    public Node process(Node xml_in) {
+	String request = converter_.getString(xml_in);
+	String result = process(request);
+	return converter_.getDOM(result).getDocumentElement();
+	
+    }
+}
+
+
+
+
+
+
+
+
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/MGGDBMService.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/MGGDBMService.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/MGGDBMService.java	(revision 3225)
@@ -0,0 +1,105 @@
+package org.greenstone.gsdl3.service;
+
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Text; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList; 
+
+  
+public class MGGDBMService 
+    extends ServiceModule {
+
+    /** passes the request Element to the appropriate service function*/
+    protected Element processService(String name, Element request) {
+	
+	// dont need to check that the service name is  supported for this particular object, because that has been checked by ServiceModule
+	if (name.equals("TextQuery")) {
+	    return processTextQuery(request);
+	} else if (name.equals("DocRetrieve")) {
+	    return processDocRetrieve(request);
+	} else if (name.equals("MetadataRetrieve")) {
+	    return processMetadataRetrieve(request);
+	}
+	
+	System.err.println("MGGDBMService:should never get here. service type wrong:"+name);
+	return null;
+    }
+	
+    public boolean configure(Element info) {
+
+	System.out.println("configuring MGGDBMService");
+
+	Element e = null;
+	// these entries should reflect the build config file - some services may not be available depending on how the colleciton was built.
+	// set up short_service_info_ - for now just has name and type
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "TextQuery");
+	short_service_info_.appendChild(e);
+
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "DocRetrieve");
+	short_service_info_.appendChild(e);
+
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "MetadataRetrieve");
+	short_service_info_.appendChild(e);
+
+
+	// set up service_info_map_ - for now, just has the same elements as above
+	// should have full details about each service incl params lists etc.
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "TextQuery");
+	service_info_map_.put("TextQuery", e);
+	
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "DocRetrieve");
+	service_info_map_.put("DocRetrieve", e);
+	
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "MetadataRetrieve");
+	service_info_map_.put("MetadataRetrieve", e);
+
+	return true;
+    }
+   
+    protected Element processTextQuery(Element request) {
+	Element result = doc_.createElement("response");
+	result.setAttribute("name", "TextQuery");
+	
+	// dummy result
+	Text t = null;
+	t = doc_.createTextNode("Textquery result... ");
+	result.appendChild(t);
+	return result;
+    }
+
+    protected Element processDocRetrieve(Element request) {
+	Element result = doc_.createElement("response");
+	result.setAttribute("name", "DocRetrieve");
+	
+	// dummy result
+	Text t = null;
+	t = doc_.createTextNode("DocRetrieve result... ");
+	result.appendChild(t);
+	return result;
+    }
+
+    protected Element processMetadataRetrieve(Element request) {
+	Element result = doc_.createElement("response");
+	result.setAttribute("name", "MetadataRetrieve");
+	
+	// dummy result
+	Text t = null;
+	t = doc_.createTextNode("MetadataRetrieve result... ");
+	result.appendChild(t);
+	return result;
+    }
+
+}   
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/MGPPService.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/MGPPService.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/MGPPService.java	(revision 3225)
@@ -0,0 +1,131 @@
+package org.greenstone.gsdl3.service;
+
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Text; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.NodeList; 
+
+
+public class MGPPService 
+    extends ServiceModule {
+
+    /** passes the request Element to the appropriate service function*/
+    protected Element processService(String name, Element request) {
+
+	// dont need to check that the service name is  supported for this particular object, because that has been checked by ServiceModule
+	if (name.equals("TextQuery")) {
+	    return processTextQuery(request);
+	} else if(name.equals("FieldQuery")) {
+	    return processFieldQuery(request);
+	} else if (name.equals("DocRetrieve")) {
+	    return processDocRetrieve(request);
+	} else if (name.equals("MetadataRetrieve")) {
+	    return processMetadataRetrieve(request);
+	}
+	
+	System.err.println("MGPPService:should never get here. service type wrong:"+name);
+	return null;
+	
+	
+    }
+    
+
+    public boolean configure(Element info) {
+
+	System.out.println("configuring MGPPService");
+
+	Element e = null;
+	// these entries should reflect the build config file - some services may not be available depending on how the colleciton was built.
+	// set up short_service_info_ - for now just has name and type
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "TextQuery");
+	short_service_info_.appendChild(e);
+
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "FieldQuery");
+	short_service_info_.appendChild(e);
+
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "DocRetrieve");
+	short_service_info_.appendChild(e);
+
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "MetadataRetrieve");
+	short_service_info_.appendChild(e);
+
+	// set up service_info_map_ - for now, just has the same elements as above
+	// should have full details about each service incl params lists etc.
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "TextQuery");
+	service_info_map_.put("TextQuery", e);
+	
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "FieldQuery");
+	service_info_map_.put("FieldQuery", e);
+	
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "DocRetrieve");
+	service_info_map_.put("DocRetrieve", e);
+	
+	e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "MetadataRetrieve");
+	service_info_map_.put("MetadataRetrieve", e);
+	return true;
+    }
+
+    protected Element processTextQuery(Element request) {
+	Element result = doc_.createElement("response");
+	result.setAttribute("name", "TextQuery");
+	
+	// dummy result
+	Text t = null;
+	t = doc_.createTextNode("Textquery result... ");
+	result.appendChild(t);
+	return result;
+    }
+
+    protected Element processFieldQuery(Element request) {
+	Element result = doc_.createElement("response");
+	result.setAttribute("name", "FieldQuery");
+	
+	// dummy result
+	Text t = null;
+	t = doc_.createTextNode("Fieldquery result... ");
+	result.appendChild(t);
+	return result;
+    }
+
+    protected Element processDocRetrieve(Element request) {
+	Element result = doc_.createElement("response");
+	result.setAttribute("name", "DocRetrieve");
+	
+	// dummy result
+	Text t = null;
+	t = doc_.createTextNode("DocRetrieve result... ");
+	result.appendChild(t);
+	return result;
+    }
+
+    protected Element processMetadataRetrieve(Element request) {
+	Element result = doc_.createElement("response");
+	result.setAttribute("name", "MetadataRetrieve");
+	
+	// dummy result
+	Text t = null;
+	t = doc_.createTextNode("MetadataRetrieve result... ");
+	result.appendChild(t);
+	return result;
+    }
+
+}  
+ 
+
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/Makefile
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/Makefile	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/Makefile	(revision 3225)
@@ -0,0 +1,40 @@
+#############################################################
+#           makefile for Java and JavaCC files ...          #
+#############################################################
+#
+
+# JAVA
+GSDL3HOME=/research/kjdon/gsdl3
+JAVALIBDIR=$(GSDL3HOME)/lib/java
+
+
+#the base directory where to put class files
+CLASSDIR=../classes
+
+#name/location of java compiler
+JAVAC=javac
+JAVACOPTIONS= -deprecation -g
+
+#extra java libraries
+JCLASSPATH=$(CLASSDIR):$(JAVALIBDIR)/xerces.jar:$(JAVALIBDIR)/java/xindice.jar
+
+
+CLASSES = ServiceModule.class MGPPService.class MGGDBMService.class PhindService.class
+
+#make a .class from a .java
+%.class: %.java
+	$(JAVAC) -d ../classes -classpath $(JCLASSPATH) $(JAVACOPTIONS) $<
+
+
+# this is almost always faster, but can give confusing output- says stuart
+#
+#	$(JAVAC) $(JAVACOPTIONS) -classpath $(JCLASSPATH) *.java
+
+all: $(CLASSES)
+
+
+clean: 
+	rm -f $$(CLASSES)
+
+
+
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/PhindService.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/PhindService.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/PhindService.java	(revision 3225)
@@ -0,0 +1,59 @@
+package org.greenstone.gsdl3.service;
+
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.Text; 
+
+/** PhindService - the phind phrase browsing service
+ * 
+ */
+public class PhindService 
+    extends ServiceModule {
+
+    
+    protected Element processService(String name, Element request) {
+
+	if (!name.equals("PhindPhraseBrowse")) {
+	    System.err.println("PhindService:you have asked for a non-existant service - "+name+"!");
+	    return null;
+	}
+	// create dummy response
+	Element res = doc_.createElement("response");
+	res.setAttribute("from", "PhindPhraseBrowse");
+	Element data = doc_.createElement("content");
+	Text t = doc_.createTextNode("this is the results for a phind request");
+	data.appendChild(t);
+	
+	res.appendChild(data);
+
+	return res;
+	
+    }
+    /** configure the service module
+     *
+     * @param info a DOM Element containing any config info for the service
+     * @return true if configured
+     */
+    public boolean configure(Element info) {
+
+	System.out.println("configuring PhindService");
+
+	// set up short_service_info_ - for now just has name and type
+	Element e = doc_.createElement("service");
+	e.setAttribute("type", "query");
+	e.setAttribute("name", "PhindPhraseBrowse");
+	short_service_info_.appendChild(e);
+
+	// set up service_info_map_ - we only have one element, and it has
+	// no extra info yet - we are not processing the config info
+	Element f = doc_.createElement("service");
+	f.setAttribute("type", "query");
+	f.setAttribute("name", "PhindPhraseBrowse");
+	service_info_map_.put("PhindPhraseBrowse", f);
+	
+	return true;
+    }
+
+    
+}
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/ServiceModule.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/ServiceModule.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/service/ServiceModule.java	(revision 3225)
@@ -0,0 +1,223 @@
+package org.greenstone.gsdl3.service;
+
+// greenstone classes
+import org.greenstone.gsdl3.util.*;
+import org.greenstone.gsdl3.core.*;
+
+// xml classes
+import org.w3c.dom.Node; 
+import org.w3c.dom.Element; 
+import org.w3c.dom.Document; 
+import org.xml.sax.InputSource;
+import javax.xml.parsers.*;
+import org.apache.xpath.XPathAPI;
+
+// general java classes
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.File;
+import java.util.HashMap;
+
+/**
+ * ServiceModule - abstract base class 
+ *
+ * A ServiceModule provides Services to a collection/system. 
+ * It may provide more than one Service. for eg
+ * MGGDBMServiceModule may support "DocRetrieve", "TextQuery", "MetadataRetrieve" services
+ *
+ */
+public abstract class ServiceModule 
+    implements ModuleInterface
+{
+    /** the absolute address of the site home */
+    protected String site_home_ =null;
+    /** the name of the collection directory that this service belongs to -
+	if any */ 
+    protected String collection_name_ = null;
+
+    /** some services can talk back to the message router */
+    protected ModuleInterface router_ = null;
+
+    /** a converter class to create Documents etc */
+    protected XMLConverter converter_ = null;
+
+    /** XML element for describe requests - the container doc */
+    protected Document doc_ = null;
+
+    /** XML element for describe requests - list of supported services */
+    protected Element short_service_info_ = null;
+
+    /** XML element for describe requests - map of service name to full 
+	description */
+    protected HashMap service_info_map_ = null;
+
+    public void setCollectionName(String coll_name) {
+	collection_name_ = coll_name;
+    }
+    
+    public void setSiteHome(String site_home) {
+	site_home_ = site_home;
+    }
+
+    public void setMessageRouter(ModuleInterface m) {
+       router_ = m;
+    }
+
+    public ServiceModule() {
+	converter_ = new XMLConverter();
+	doc_ = converter_.newDOM();
+	short_service_info_ = doc_.createElement("serviceList");
+	service_info_map_ = new HashMap();
+    }
+    
+    /**
+     * Configure the object. - default method for service modules
+     *
+     * reads either collection (if a collection name has been set), or system 
+     * configuration file, and configures itself
+     * this calls configure(Element) with the XML element node from the config
+     * file.
+     * configure(Element) should be used if the config file has already been 
+     * parsed.  This method will work with any subclass.
+     * 
+     * @return true if configure successful, false otherwise.
+     */
+    public boolean configure(){
+	
+	if (site_home_==null) {
+	    System.err.println("setSiteHome() must be called before configure()");
+	    return false;
+	}
+
+	File config_file=null;
+	if (collection_name_ !=null) {
+	    
+	    config_file = GSFile.collectionBuildConfigFile(site_home_, collection_name_);
+	}
+	else {
+	    config_file = GSFile.siteConfigFile(site_home_);
+	}
+
+	if (config_file.exists() ) {
+	    
+	    Document doc = converter_.getDOM(config_file);
+	    
+	    try {
+		// get the service list and look for own service
+		// Note: XPathAPI is slow apparently
+		String xpath = "//ServiceModule[@name='"+this.getClass().getName()+"']";
+		System.out.println("xpath="+xpath);
+		Node n = XPathAPI.selectSingleNode(doc, xpath);
+		if (n !=null) {
+		    return this.configure((Element)n);
+		}
+	    } catch (Exception e) {
+		System.err.println("ServiceModule configure exception: "+e.getMessage());
+		return false;
+	    }
+	}
+	System.err.println("ServiceModule error: unable to configure ServiceModule " + this.getClass().getName() );
+	return false;
+	
+	
+    } 
+
+    /** The configure method that does the real work
+     *
+     * @param info the XML node <serviceModule name="XXX"/> with name equal
+     * to the class name (of the subclass)
+     *
+     * must initialise short_service_info_ and service_info_map_
+     * @return true if configured ok
+     * must be implemented in subclasses
+     */
+    abstract public boolean configure(Element info); 
+
+    /**
+     * Process an XML document - convenience method that uses Strings rather than Nodes. just calls process(Node).
+     *
+     * @param xml_in the Document to process - a string
+     * @return the resultant document as a string - contains any error messages
+     * @see String
+     */
+    public String process(String xml_in) {
+	
+	Document doc = converter_.getDOM(xml_in);
+	
+	Node res = process(doc);
+	return converter_.getString(res);
+	
+    }
+
+    /** process an XML request in DOM form
+     *
+     * @param xml_in the Element node containing the request
+     * should be <request> or maybe <multipleRequest>?? if more than one 
+     * request coming at once
+     * @return an Element with the result XML
+     * @see Element
+     */
+    public Node process(Node xml_in) {
+
+	// check if request is Element or Document - we want to work 
+	// with an Element
+	Element request=null;
+
+	short node_type = xml_in.getNodeType();
+	if (node_type == Node.DOCUMENT_NODE) {
+	    request = ((Document)xml_in).getDocumentElement();
+	} else if (node_type == Node.ELEMENT_NODE) {
+	    request = (Element)xml_in;
+	} else {
+	    System.err.println("ServiceModule:process error: input should be an Element or Document!");
+	}
+
+	String req = request.getNodeName();
+	if (!req.equals("request")) {
+	    System.err.println("ServiceModule:process - should have been passed a request element, instead was given a "+req+" element!");
+	    return null;
+	}
+
+	String type = request.getAttribute("type");
+	String to = GSPath.getFirstLink(request.getAttribute("to"));
+	String info = request.getAttribute("info");
+	if (type.equals("describe")) { // process here, not by subclass
+	    if (to.equals("")) { // to="", look at info
+		if (info.equals("serviceList")) {
+		    return short_service_info_;
+		} 
+		// else error in info field
+		System.err.println("ServiceModule describe request: error in 'info' field, info='"+info+"'.");
+		return null;
+	    } else { // describe a particular service
+		if (service_info_map_.containsKey(to)) {
+		    return (Element)service_info_map_.get(to);
+		}
+		// else error in to field
+		System.err.println("ServiceModule describe request: error in 'to' field, to='"+to+"'.");
+		return null;
+	    }
+	} else { // other type of request, must be processed by the subclass - 
+	    // send to the service method
+	    if (service_info_map_.containsKey(to)) { 
+		return processService(to, request);
+	    }
+	    else {
+		// else error in to field
+		System.err.println("ServiceModule describe request: error in 'to' field, to='"+to+"'.");
+		return null;
+	    }
+	}
+	
+    }
+
+    /** process method for specific services - must be implemented by all
+     * subclasses
+     * should implement all services supported by the serviceModule except
+     * for describe, which is implemented by this base class
+     *
+     */
+    abstract protected Element processService(String service, Element request);
+
+
+}
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/GSFile.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/GSFile.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/GSFile.java	(revision 3225)
@@ -0,0 +1,49 @@
+package org.greenstone.gsdl3.util;
+
+import java.io.File; 
+
+/**
+ * GSFiles - utility class for Greenstone.
+ *
+ * contains File creation methods.
+ *
+ * @see File
+ */
+public class GSFile {
+
+    /** creates a File for the site config file */
+    static public File siteConfigFile(String site_home) {
+	return new File(site_home + File.separatorChar+"sitecfg.xml");
+
+    }
+
+    /** creates a File for the collection directory  */
+    static public File collectionDirFile(String site_home) {
+	return new File(site_home+File.separatorChar+"collect");
+    }
+    
+    /** creates a File for the collection config file */
+    static public File collectionConfigFile(String site_home, 
+					    String collection_name) {
+	return new File(site_home+File.separatorChar+"collect"+
+			File.separatorChar+collection_name+
+			File.separatorChar+"etc"+
+			File.separatorChar+"collectcfg.xml");
+
+    }
+
+    /** creates a File for the collection build config file */
+    static public File collectionBuildConfigFile(String site_home, 
+						 String collection_name ) {
+	return new File(site_home+File.separatorChar+"collect"+
+			File.separatorChar+collection_name+
+			File.separatorChar+"index"+
+			File.separatorChar+"buildcfg.xml");
+    }
+
+    static public String xmlTransformDir(String gsdl_home) {
+	return gsdl_home+File.separatorChar+"transform";
+    }
+	    
+
+}
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/GSPath.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/GSPath.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/GSPath.java	(revision 3225)
@@ -0,0 +1,69 @@
+package org.greenstone.gsdl3.util;
+
+/**
+ * GSPath - utility class for greenstone
+ *
+ * modifies and examines message address paths and names
+ *
+ */
+
+public class GSPath {
+
+    /** adds new_link to the end of path
+     *
+     * @return the new path
+     */
+    static public String appendLink(String path, String new_link) {
+	if (path.equals("")) {
+	    return new_link;
+	}
+	return path +"/"+new_link;
+    }
+
+    /** adds new_link to the front of path
+     *
+     * @return the new path
+     */
+    static public String prependLink(String path, String new_link) {
+	if (path.equals("")) {
+	    return new_link;
+	}
+	return  new_link+"/"+path;
+    }
+
+    /** returns the first name in the path
+     *
+     */
+    static public String getFirstLink(String path) {
+
+	int i = path.indexOf("/");
+	if (i==0) { // have a '/' on the front
+	    path = path.substring(1);
+	    i= path.indexOf("/");
+	}
+	if (i==-1) { // '/' not found
+	    return path;
+	}
+	
+	return path.substring(0,i);
+    }
+
+    /** removes the first name in the path
+     *
+     * @return the modified path
+     */
+    static public String removeFirstLink(String path) {
+	int i = path.indexOf("/");
+	if (i==0) { // have a '/' on the front
+	    path = path.substring(1);
+	    i= path.indexOf("/");
+	}
+	if (i==-1) { // '/' not found - remove the whole path
+	    return "";
+	}
+	return path.substring(i+1); // remove the '/' char
+    }
+
+}
+
+    
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/Makefile
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/Makefile	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/Makefile	(revision 3225)
@@ -0,0 +1,40 @@
+#############################################################
+#           makefile for Java and JavaCC files ...          #
+#############################################################
+#
+
+# JAVA
+GSDL3HOME=/research/kjdon/gsdl3
+JAVALIBDIR=$(GSDL3HOME)/lib/java
+
+
+#the base directory where to put class files
+CLASSDIR=../classes
+
+#name/location of java compiler
+JAVAC=javac
+JAVACOPTIONS= -deprecation -g
+
+#extra java libraries
+JCLASSPATH=$(CLASSDIR):$(JAVALIBDIR)/xerces.jar:$(JAVALIBDIR)/xindice.jar
+
+
+CLASSES = GSPath.class GSFile.class XMLConverter.class
+
+#make a .class from a .java
+%.class: %.java
+	$(JAVAC) -d ../classes -classpath $(JCLASSPATH) $(JAVACOPTIONS) $<
+
+
+# this is almost always faster, but can give confusing output- says stuart
+#
+#	$(JAVAC) $(JAVACOPTIONS) -classpath $(JCLASSPATH) *.java
+
+all: $(CLASSES)
+
+
+clean: 
+	rm -f $$(CLASSES)
+
+
+
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/XMLConverter.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/XMLConverter.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/XMLConverter.java	(revision 3225)
@@ -0,0 +1,92 @@
+package org.greenstone.gsdl3.util;
+
+// XML classes
+import org.w3c.dom.Document; 
+import org.w3c.dom.Node; 
+import org.xml.sax.InputSource;
+import javax.xml.parsers.*;
+import org.apache.xindice.xml.TextWriter;
+import org.apache.xerces.dom.TextImpl;
+import org.apache.xerces.parsers.DOMParser;
+
+// other java classes
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.File;
+import java.io.FileReader;
+
+/** XMLConverter - utitlity class for greenstone
+ *
+ * parses XML Strings into Documents, converts Nodes to Strings
+ * different parsers have different behaviour - can experiment in here
+ *
+ */
+public class XMLConverter {
+
+    /** JAXP parser factory */
+    protected DocumentBuilderFactory doc_build_fact_=null;
+    /** JAXP parser */
+     protected DocumentBuilder doc_builder_=null;
+
+    /** xerces parser */
+    protected DOMParser parser_ = null;
+
+    public XMLConverter() {
+	try {
+	     doc_build_fact_ = DocumentBuilderFactory.newInstance();
+	    
+	     doc_builder_ = doc_build_fact_.newDocumentBuilder(); 
+	    parser_ = new DOMParser();
+	} catch (Exception e) {
+	    System.out.println("XMLConverter:exception "+e.getMessage());
+	}
+    }
+
+    /** returns a DOM Document */
+    public Document getDOM(String in) {
+	    
+	try {
+	    Reader reader = new StringReader(in);
+	    InputSource xml_source = new InputSource(reader);
+	    
+	    // Document doc = doc_builder_.parse(xml_source);
+	    parser_.parse(xml_source);
+	    Document doc = parser_.getDocument();
+	    return doc;
+
+	} catch (Exception e) {
+	    System.out.println("XMLConverter.getDOM(String): exception "+e.getMessage());
+	}
+	return null;
+    }
+    
+    public Document getDOM(File in) {
+	try {
+	    
+	    Reader reader = new FileReader(in);
+	    InputSource xml_source = new InputSource(reader);
+	    
+	    //Document doc = doc_builder_.parse(xml_source);
+	    parser_.parse(xml_source);
+	    Document doc = parser_.getDocument();
+	    
+	    return doc;
+
+	} catch (Exception e) {
+	    System.out.println("XMLConverter.getDOM(File): exception "+e.getMessage());
+	}
+	return null;
+    }
+
+    /** creates a new empty DOM Document */
+    public Document newDOM() {
+	Document doc = doc_builder_.newDocument();
+	return doc;
+    }
+
+    /** returns the Node as a String */
+    public String getString(Node doc) {
+	TextWriter t = new TextWriter(doc);
+	return t.toString();
+    }
+}
Index: /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java
===================================================================
--- /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/src/java/org/greenstone/gsdl3/util/XMLTransformer.java	(revision 3225)
@@ -0,0 +1,59 @@
+package org.greenstone.gsdl3.util;
+
+// XML classes
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+// other java classes
+import java.io.StringReader;
+import java.io.StringWriter;
+
+/** XMLConverter - utitlity class for greenstone
+ *
+ * parses XML Strings into Documents, converts Nodes to Strings
+ * different parsers have different behaviour - can experiment in here
+ *
+ */
+public class XMLTransformer {
+
+    TransformerFactory t_factory_=null;
+    
+    public XMLTransformer() {
+	try {
+	    t_factory_ = TransformerFactory.newInstance();
+
+	} catch (Exception e) {
+	    System.out.println("XMLTransformer() exception "+e.getMessage());
+	}
+    }
+
+ 
+	
+    public String transform(String stylesheet, String xml_in) {
+	
+	try {
+	    // Use the TransformerFactory to process the stylesheet Source and generate a Transformer.
+	    Transformer transformer = t_factory_.newTransformer(new StreamSource(stylesheet));
+
+	    // Use the Transformer to transform an XML Source and send the output to a Result object.
+	    StringWriter output = new StringWriter();
+
+	    transformer.transform(new StreamSource(new StringReader(xml_in)), new StreamResult(output));
+	    return output.toString();
+	} catch (TransformerConfigurationException e) {
+	    System.err.println("XMLTransformer: couldn't create transformer object");
+	    return "";
+	} catch (TransformerException e) {
+	    System.err.println("XMLTransformer: couldn't transform the source");
+	    return "";
+	}	
+    }
+}
+
+ 
Index: /tags/gsdl3_0/gsdl3/transform/collect_about.xsl
===================================================================
--- /tags/gsdl3_0/gsdl3/transform/collect_about.xsl	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/transform/collect_about.xsl	(revision 3225)
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output method="text"/> 
+ 
+<xsl:template match="//message/response/collection">
+<xsl:value-of select="@name"/>: <xsl:value-of select="metadataList/metadata[@name='Title']"/><xsl:text>
+</xsl:text>
+<xsl:value-of select="metadataList/metadata[@name='Description']"/>
+<xsl:text>
+</xsl:text>
+The collection has <xsl:value-of select="metadataList/metadata[@name='numDocs']"/> documents.
+Metadata available for this collection are:
+<xsl:for-each select="metadataList/metadata[@name='Metadata']/element">
+<xsl:value-of select="@name"/>, 
+</xsl:for-each>
+<xsl:apply-templates select="serviceList"/>
+</xsl:template>
+
+
+<xsl:template match="serviceList">
+the Services available are:
+<xsl:for-each select="service"> 
+***<xsl:value-of select="@name"/>
+</xsl:for-each>
+</xsl:template>
+
+
+</xsl:stylesheet>
Index: /tags/gsdl3_0/gsdl3/transform/home.xsl
===================================================================
--- /tags/gsdl3_0/gsdl3/transform/home.xsl	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/transform/home.xsl	(revision 3225)
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output method="text"/>  
+
+<xsl:template match="/message/response">
+<xsl:apply-templates select="collectionList"/>
+<xsl:apply-templates select="serviceList"/>
+</xsl:template>
+
+
+
+<xsl:template match="collectionList">
+Collections available are:
+<xsl:for-each select="collection"> 
+<xsl:value-of select="@name"/>: <xsl:value-of select="metadata[@name='Title']"/><xsl:text>
+</xsl:text>
+</xsl:for-each>
+</xsl:template> 
+
+<xsl:template match="collection">
+<xsl:value-of select="@name"/>. <xsl:value-of select="metadata[@name='Title']"/>
+</xsl:template>
+
+<xsl:template match="serviceList">
+Services available are:
+
+Transforms:
+<xsl:for-each select="service[@type='transform']"> 
+<xsl:value-of select="@name"/>.
+</xsl:for-each>
+
+Enrichs:
+<xsl:for-each select="service[@type='enrich']"> 
+<xsl:value-of select="@name"/>.
+</xsl:for-each>
+
+Querys:
+<xsl:for-each select="service[@type='query']"> 
+<xsl:value-of select="@name"/>.
+</xsl:for-each>
+
+</xsl:template> 
+
+
+</xsl:stylesheet>  
Index: /tags/gsdl3_0/gsdl3/transform/service_about.xsl
===================================================================
--- /tags/gsdl3_0/gsdl3/transform/service_about.xsl	(revision 3225)
+++ /tags/gsdl3_0/gsdl3/transform/service_about.xsl	(revision 3225)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<xsl:stylesheet version="1.0"
+xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:output method="text"/> 
