Index: branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java
===================================================================
--- branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java	(revision 9814)
+++ branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractDocumentRetrieve.java	(revision 9815)
@@ -23,4 +23,5 @@
 // Greenstone classes
 //import org.greenstone.gdbm.*;
+import org.greenstone.gsdl3.core.GSException;
 import org.greenstone.gsdl3.util.GSXML;
 import org.greenstone.gsdl3.util.GSPath;
@@ -165,6 +166,6 @@
 	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
 	if (param_list == null) {
-	    System.err.println("AbstractDocumentRetrieve, DocumentMetadataRetrieve Error: missing paramList.\n");
-	    return result;  // Return the empty result
+	    GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: missing "+ GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+	    return result;  
 	}
 
@@ -190,23 +191,35 @@
 	}
 	
-	Element node_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
-	result.appendChild(node_list);
-	
+	// check that there has been some metadata specified
+	if (!all_metadata && metadata_names_list.size()==0) {
+	    GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: no metadata names found in the "+ GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+	    return result;  
+	}
+
 	// Get the documents
 	Element request_node_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
 	if (request_node_list == null) {
-	    System.err.println("Error: DocumentMetadataRetrieve request had no "+GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	    GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: missing " +GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
  	    return result;
  	}
 	
-	NodeList request_nodes = request_node_list.getChildNodes();
+	// copy the request doc node list to the response
+	Element response_node_list = (Element) this.doc.importNode(request_node_list, true);
+	result.appendChild(response_node_list);
+	
+	// use the copied list so that we add the metadata into the copy
+	// are we just adding metadata for the top level nodes? or can we accept a hierarchy here???
+	NodeList request_nodes = GSXML.getChildrenByTagName(response_node_list, GSXML.DOC_NODE_ELEM);
+	if (request_nodes.getLength()==0) {
+	    GSXML.addError(this.doc, result, "DocumentMetadataRetrieve: no "+GSXML.DOC_NODE_ELEM +" found in the "+ GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+ 	    return result;
+ 	}
+	
+	// Whew, now we have checked (almost) all the syntax of the request, now we can process it.
+	
 	for (int i = 0; i < request_nodes.getLength(); i++) {
 	    Element request_node = (Element) request_nodes.item(i);
 	    String node_id = request_node.getAttribute(GSXML.NODE_ID_ATT);
 	    
-	    // Add the document to the results list
-	    Element new_node = (Element)this.doc.importNode(request_node, false);
-	    node_list.appendChild(new_node);
-
 	    if (external_id) {
 		// can we have .pr etc extensions with external ids?
@@ -219,7 +232,14 @@
 		continue;
 	    }
-	    
-	    Element metadata_list = getMetadataList(node_id, all_metadata, metadata_names_list);
-	    new_node.appendChild(metadata_list);
+	    try {
+		Element metadata_list = getMetadataList(node_id, all_metadata, metadata_names_list);
+		request_node.appendChild(metadata_list);
+	    } catch (GSException e) {		
+		GSXML.addError(this.doc, result, e.getMessage(), e.getType());
+		if (e.getType().equals(GSXML.ERROR_TYPE_SYSTEM)) {
+		    // there is no point trying any others
+		    return result;
+		}
+	    }
 	}
 	
@@ -240,16 +260,30 @@
 
 	String lang = request.getAttribute(GSXML.LANG_ATT);
-	Element query_doc_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
-	if (query_doc_list == null) {
-	    System.err.println("AbstractDocumentRetrieve Error: DocumentStructureRetrieve request specified no doc nodes.\n");
-	    return result;
-	}
 
 	// Get the parameters of the request
 	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
 	if (param_list == null) {
-	    System.err.println("AbstractDocumentRetrieve Error: DocumentStructureRetrieve request had no paramList.");
-	    return result;  // Return the empty result
-	}
+	    GSXML.addError(this.doc, result, "DocumentStructureRetrieve: missing "+ GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+	    return result;  
+	}
+	
+	// get the documents of the request
+	Element query_doc_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (query_doc_list == null) {
+	    GSXML.addError(this.doc, result, "DocumentStructureRetrieve: missing " +GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+ 	    return result;
+ 	}
+	
+	// copy the doc_list to the response
+	Element response_node_list = (Element) this.doc.importNode(query_doc_list, true);
+	result.appendChild(response_node_list);
+	
+	// check that we have some doc nodes specified
+	NodeList node_list = GSXML.getChildrenByTagName(response_node_list, GSXML.DOC_NODE_ELEM);
+	if (node_list.getLength()==0) {
+	    GSXML.addError(this.doc, result, "DocumentStructureRetrieve: no "+GSXML.DOC_NODE_ELEM +" found in the "+ GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER, GSXML.ERROR_TYPE_SYNTAX);
+ 	    return result;
+ 	}
+
 	Element extid_param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, EXTID_PARAM);
 	boolean external_id = false;
@@ -308,19 +342,8 @@
 	if (want_descendants)
 	    want_children = false;
-	
-	// the document list to hold the results
-	Element doc_list = this.doc.createElement(GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
-	result.appendChild(doc_list);
-	
-	// Get the documents
-	String[] doc_ids = GSXML.getAttributeValuesFromList(query_doc_list, 
-							    GSXML.NODE_ID_ATT);
-	for (int i = 0; i < doc_ids.length; i++) {
-	    // Add the document to the list
-	    Element doc = this.doc.createElement(GSXML.DOC_NODE_ELEM);
-	    doc_list.appendChild(doc);
-	    
-	    String doc_id = doc_ids[i];
-	    doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
+
+	for (int i=0; i < node_list.getLength(); i++) {
+	    Element doc = (Element) node_list.item(i);
+	    String doc_id = doc.getAttribute(GSXML.NODE_ID_ATT);
 	    if (external_id) {
 		doc_id = translateExternalId(doc_id);
@@ -433,5 +456,5 @@
 	}
 
-	// Get the parameters of the request - no parameters at this stage
+	// Get the parameters of the request
   	Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
 	Element extid_param = GSXML.getNamedElement(param_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, EXTID_PARAM);
@@ -473,7 +496,12 @@
 		continue;
 	    }
-	    
-	    Element node_content = getNodeContent(doc_id);
-	    doc.appendChild(node_content);
+	    try {
+		Element node_content = getNodeContent(doc_id);
+		doc.appendChild(node_content);
+	    } catch (GSException e) {
+		GSXML.addError(this.doc, result, e.getMessage());
+		return result;
+		
+	    }
 	}
 	return result;
@@ -594,10 +622,17 @@
     }
 
-    /** if id ends in .fc, .pc etc, then translate it to the correct id */
-    abstract protected String translateId(String id);
+    /** if id ends in .fc, .pc etc, then translate it to the correct id 
+     * default implementation: just remove the suffix */
+    protected String translateId(String id) {
+	return id.substring(0,id.length());
+    }
     
     /** if an id is not a greenstone id (an external id) then translate 
-	it to a greenstone one*/
-    abstract protected String translateExternalId(String id);
+     * it to a greenstone one 
+     * default implementation: return the id */
+    protected String translateExternalId(String id) {
+	return id;
+    }
+
     /** returns the document type of the doc that the specified node 
 	belongs to. should be one of 
@@ -605,13 +640,28 @@
 	GSXML.DOC_TYPE_PAGED, 
 	GSXML.DOC_TYPE_HIERARCHY
+	default implementation: return DOC_TYPE_SIMPLE
     */
-    abstract protected String getDocType(String node_id);
-
-    /** returns the id of the root node of the document containing node node_id. . may be the same as node_id */
-    abstract protected String getRootId(String node_id);
-    /** returns a list of the child ids in order, null if no children */
-    abstract protected ArrayList getChildrenIds(String node_id);
-    /** returns the node id of the parent node, null if no parent */
-    abstract protected String getParentId(String node_id);
+    protected String getDocType(String node_id) {
+	return GSXML.DOC_TYPE_SIMPLE;
+    }
+	
+
+    /** returns the id of the root node of the document containing 
+     * node node_id. may be the same as node_id 
+     * default implemntation: return node_id
+    */
+    protected String getRootId(String node_id) {
+	return node_id;
+    }
+    /** returns a list of the child ids in order, null if no children 
+     * default implementation: return null */
+    protected ArrayList getChildrenIds(String node_id) {
+	return null;
+    }
+    /** returns the node id of the parent node, null if no parent 
+     * default implementation: return null */
+    protected String getParentId(String node_id) {
+	return null;
+    }
 
     /** get the metadata for the doc node doc_id
@@ -621,10 +671,11 @@
     abstract protected Element getMetadataList(String doc_id, 
 					       boolean all_metadata, 
-					       ArrayList metadata_names);
+					       ArrayList metadata_names) throws GSException;
     /** returns the content of a node
-     * shoudl return a nodeContent element:
+     * should return a nodeContent element:
      * <nodeContent>text content or other elements</nodeContent>
+     * can return 
      */
-    abstract protected Element getNodeContent(String doc_id);
+    abstract protected Element getNodeContent(String doc_id) throws GSException;
 
     /** returns the structural information asked for.
Index: branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java
===================================================================
--- branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java	(revision 9814)
+++ branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS2DocumentRetrieve.java	(revision 9815)
@@ -20,4 +20,5 @@
 
 // Greenstone classes
+import org.greenstone.gsdl3.core.GSException;
 import org.greenstone.gsdl3.util.GSXML;
 import org.greenstone.gsdl3.util.GSFile;
@@ -146,5 +147,6 @@
     // assumes only one value per metadata
     protected Element getMetadataList(String node_id, boolean all_metadata,
-				      ArrayList metadata_names) {
+				      ArrayList metadata_names)  
+	throws GSException {
 	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
 	DBInfo info = this.gdbm_src.getInfo(node_id);
@@ -281,5 +283,5 @@
      * <nodeContent>text content or other elements</nodeContent>
      */
-    abstract protected Element getNodeContent(String doc_id);
+    abstract protected Element getNodeContent(String doc_id) throws GSException;
 
     protected String getMetadata(String node_id, DBInfo info, 
Index: branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS3DocumentRetrieve.java
===================================================================
--- branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS3DocumentRetrieve.java	(revision 9814)
+++ branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractGS3DocumentRetrieve.java	(revision 9815)
@@ -20,4 +20,5 @@
 
 // Greenstone classes
+import org.greenstone.gsdl3.core.GSException;
 import org.greenstone.gsdl3.util.GSXML;
 import org.greenstone.gsdl3.util.GSFile;
@@ -109,11 +110,4 @@
     }
     
-    /** if an id is not a greenstone id (an external id) then translate 
-	it to a greenstone one*/
-    protected String translateExternalId(String node_id){
-	// dont have this yet
-	return node_id;
-    }
-
     /** returns the id of the root node of the document containing node node_id. . may be the same as node_id */
     protected String getRootId(String node_id) {
@@ -150,5 +144,6 @@
     // assumes only one value per metadata
     protected Element getMetadataList(String node_id, boolean all_metadata,
-				      ArrayList metadata_names) {
+				      ArrayList metadata_names)   
+	throws GSException {
 	Element metadata_list = this.doc.createElement(GSXML.METADATA_ELEM+GSXML.LIST_MODIFIER);
 
@@ -215,5 +210,5 @@
      * <nodeContent>text content or other elements</nodeContent>
      */
-    abstract protected Element getNodeContent(String doc_id);
+    abstract protected Element getNodeContent(String doc_id) throws GSException;
 
 }   
Index: branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractMGSearch.java
===================================================================
--- branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractMGSearch.java	(revision 9814)
+++ branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/AbstractMGSearch.java	(revision 9815)
@@ -201,4 +201,9 @@
 	this.mg_src.runQuery(basedir, textdir, query);
 	MGQueryResult mqr = this.mg_src.getQueryResult();
+	if (mqr.isClear()) {
+	    // something has gone wrong
+	    GSXML.addError(this.doc, result, "Couldn't query the mg database", GSXML.ERROR_TYPE_SYSTEM);
+	    return result;
+	}
 	long totalDocs = mqr.getTotalDocs();
 
Index: branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGPPRetrieve.java
===================================================================
--- branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGPPRetrieve.java	(revision 9814)
+++ branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGPPRetrieve.java	(revision 9815)
@@ -21,4 +21,5 @@
 // Greenstone classes
 import org.greenstone.mgpp.*;
+import org.greenstone.gsdl3.core.GSException;
 import org.greenstone.gsdl3.util.GSFile;
 import org.greenstone.gsdl3.util.GSXML;
@@ -79,5 +80,5 @@
      * <nodeContent>text content or other elements</nodeContent>
      */
-    protected Element getNodeContent(String doc_id) {
+    protected Element getNodeContent(String doc_id) throws GSException {
 	String lang = "en"; //  ********** 
 	long doc_num = this.gdbm_src.OID2Docnum(doc_id);
Index: branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGRetrieve.java
===================================================================
--- branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGRetrieve.java	(revision 9814)
+++ branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS2MGRetrieve.java	(revision 9815)
@@ -21,4 +21,5 @@
 // Greenstone classes
 import org.greenstone.mg.*;
+import org.greenstone.gsdl3.core.GSException;
 import org.greenstone.gsdl3.util.GSFile;
 import org.greenstone.gsdl3.util.GSXML;
@@ -80,5 +81,5 @@
      * <nodeContent>text content or other elements</nodeContent>
      */
-    protected Element getNodeContent(String doc_id) {
+    protected Element getNodeContent(String doc_id) throws GSException {
 	String lang = "en"; //  ********** 
 	long doc_num = this.gdbm_src.OID2Docnum(doc_id);
Index: branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS3MGPPRetrieve.java
===================================================================
--- branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS3MGPPRetrieve.java	(revision 9814)
+++ branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS3MGPPRetrieve.java	(revision 9815)
@@ -21,4 +21,5 @@
 // Greenstone classes
 import org.greenstone.mgpp.*;
+import org.greenstone.gsdl3.core.GSException;
 import org.greenstone.gsdl3.util.GSFile;
 import org.greenstone.gsdl3.util.GSXML;
@@ -80,5 +81,5 @@
      * <nodeContent>text content or other elements</nodeContent>
      */
-    protected Element getNodeContent(String doc_id) {
+    protected Element getNodeContent(String doc_id) throws GSException {
 	if (GS3OID.isDocTop(doc_id) && database.isHierarchicalDocument(doc_id)) {
 	    // if we have a whole doc id, and the document is hierarchical,
Index: branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS3MGRetrieve.java
===================================================================
--- branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS3MGRetrieve.java	(revision 9814)
+++ branches/ant-install-branch/gsdl3/src/java/org/greenstone/gsdl3/service/GS3MGRetrieve.java	(revision 9815)
@@ -21,4 +21,5 @@
 // Greenstone classes
 import org.greenstone.mg.*;
+import org.greenstone.gsdl3.core.GSException;
 import org.greenstone.gsdl3.util.GSFile;
 import org.greenstone.gsdl3.util.GSXML;
@@ -86,5 +87,5 @@
      * <nodeContent>text content or other elements</nodeContent>
      */
-    protected Element getNodeContent(String doc_id) {
+    protected Element getNodeContent(String doc_id) throws GSException {
 
 	if (GS3OID.isDocTop(doc_id) && database.isHierarchicalDocument(doc_id)) {
@@ -111,5 +112,6 @@
 	} catch (Exception e) {
 	    System.out.println("exception happended with mg_src.getDocument()");
-	    doc_content = "this is the content for section hash id "+ doc_id+", mg doc num "+doc_int+"\n";
+	    throw new GSException("Couldn't get document content for id: "+ doc_int+"\n"+e.getMessage());
+	    //doc_content = "this is the content for section hash id "+ doc_id+", mg doc num "+doc_int+"\n";
 	}
 	
