Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Retrieve.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Retrieve.java	(revision 4259)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/service/GS2Retrieve.java	(revision 4260)
@@ -33,5 +33,6 @@
 import java.util.StringTokenizer;
 import java.util.Vector;
-
+import java.util.Set;
+import java.util.Iterator;
 
 /** Implements the generic retrieval and classifier services for GS2 
@@ -57,4 +58,17 @@
     private static final String CLASSIFIER_METADATA_SERVICE = "ClassifierBrowseMetadataRetrieve";
     
+    protected static final String STRUCT_PARAM = "structure";
+    protected static final String INFO_PARAM = "info";
+    
+    protected static final String STRUCT_ANCESTORS = "ancestors";
+    protected static final String STRUCT_PARENT = "parent";
+    protected static final String STRUCT_SIBS = "siblings";
+    protected static final String STRUCT_CHILDREN = "children";
+    protected static final String STRUCT_DESCENDS = "descendants";
+
+    protected static final String INFO_NUM_SIBS = "numSiblings";
+    protected static final String INFO_NUM_CHILDREN = "numChildren";
+    protected static final String INFO_SIB_POS = "siblingPosition";
+
     protected static final int DOCUMENT=1;
     protected static final int CLASSIFIER=2;
@@ -297,5 +311,5 @@
 	} else {
 	    node = doc_.createElement(GSXML.DOC_NODE_ELEM);
-	    if (!child && OID.isTop(doc_id)) {
+	    if (/*!child &&*/ OID.isTop(doc_id)) {
 		node.setAttribute(GSXML.NODE_TYPE_ATT, GSXML.NODE_TYPE_ROOT);
 	    } else if (!parent && isLeafNode(doc_id)) {
@@ -417,46 +431,51 @@
 	}
 
+	// the type of info required
+	boolean want_structure = false;
+	boolean want_info = false;
+
+	Vector info_types=new Vector();
 	// The document structure information desired
-	boolean wantAncestors = false;
-	boolean wantParent = false;
-	boolean wantSiblings = false;
-	boolean wantChildren = false;
-	boolean wantDescendants = false;
+	boolean want_ancestors = false;
+	boolean want_parent = false;
+	boolean want_siblings = false;
+	boolean want_children = false;
+	boolean want_descendants = false;
 
 	// Process the request parameters
-	Element param = (Element) param_list.getFirstChild();
-	while (param != null) {
-	    if (!param.getNodeName().equals(GSXML.PARAM_ELEM)) {
-		System.err.println("Warning: Non-param in paramList (ignored).");
-	    }
-	    else {
-		// Identify the structure information desired
-		if (param.getAttribute(GSXML.NAME_ATT).equals("structure")) {
-		    String structure = GSXML.getValue(param);
-
-		    // This is NOT locale sensitive
-		    if (structure.compareToIgnoreCase("ancestors") == 0)
-			wantAncestors = true;
-		    else if (structure.compareToIgnoreCase("parent") == 0)
-			wantParent = true;
-		    else if (structure.compareToIgnoreCase("siblings") == 0)
-			wantSiblings = true;
-		    else if (structure.compareToIgnoreCase("children") == 0)
-			wantChildren = true;
-		    else if (structure.compareToIgnoreCase("descendants") == 0)
-			wantDescendants = true;
-		    else
-			System.err.println("Warning: Unknown value \"" + structure + "\".");
-		}
-	    }
-
-	    param = (Element) param.getNextSibling();
+	NodeList params = param_list.getElementsByTagName(GSXML.PARAM_ELEM);
+	for (int i=0; i<params.getLength();i++) {
+	    
+	    Element param = (Element)params.item(i);
+	    String p_name = param.getAttribute(GSXML.NAME_ATT);
+	    String p_value = GSXML.getValue(param);
+	    // Identify the structure information desired
+	    if (p_name.equals(STRUCT_PARAM)) {
+		want_structure = true;
+		
+		// This is NOT locale sensitive
+		if (p_value.equals(STRUCT_ANCESTORS))
+		    want_ancestors = true;
+		else if (p_value.equals(STRUCT_PARENT))
+		    want_parent = true;
+		else if (p_value.equals(STRUCT_SIBS))
+		    want_siblings = true;
+		else if (p_value.equals(STRUCT_CHILDREN))
+		    want_children = true;
+		else if (p_value.equals(STRUCT_DESCENDS))
+		    want_descendants = true;
+		else
+		    System.err.println("Warning: Unknown value \"" + p_value + "\".");
+	    } else if (p_name.equals(INFO_PARAM)) {
+		want_info = true;
+		info_types.add(p_value);
+	    }
 	}
 
 	// Make sure there is no repeated information
-	if (wantAncestors)
-	    wantParent = false;
-	if (wantDescendants)
-	    wantChildren = false;
+	if (want_ancestors)
+	    want_parent = false;
+	if (want_descendants)
+	    want_children = false;
 	
 	
@@ -476,7 +495,8 @@
 	    String doc_id = doc_ids[i];
 	    
-	    
+	    System.out.println("doc_id = "+doc_id);
 	    if (OID.needsTranslating(doc_id)) {
 		doc_id = gdbm_src_.translateOID(doc_id);
+	    System.out.println("translated doc_id = "+doc_id);
 	    }
 
@@ -485,54 +505,71 @@
 	    doc_list.appendChild(doc);
 	    doc.setAttribute(GSXML.NODE_ID_ATT, doc_id);
-	    // all structure info goes into a docNodestructure elem
-	    // classifier elem should be something else???
-	    Element structure_elem = doc_.createElement(GSXML.NODE_STRUCTURE_ELEM);
-	    doc.appendChild(structure_elem);
-
-	    // Add the requested structure information
-	    Element current = createDocNode(doc_id, false, false);
-
-	    //Ancestors: continually add parent nodes until the root is reached
-	    Element top_node = current; // the top node so far
-	    if (wantAncestors) {
-		String current_id = doc_id;
-		while (true) {
-		    Element parent = getParent(current_id);
-		    if (parent == null)
-			break;
-
-		    parent.appendChild(top_node);
-		    current_id = parent.getAttribute(GSXML.NODE_ID_ATT);
-		    top_node = parent;
-		}
-	    }
-	    // Parent: get the parent of the selected node
-	    if (wantParent) {
-		Element parent = getParent(doc_id);
-		if (parent != null) {
-		    parent.appendChild(current);
-		    top_node = parent;
-		}
-	    }
-
-	    // now the top node is the root of the structure
-	    structure_elem.appendChild(top_node);
-	    
-	    //Siblings: get the other descendants of the selected node's parent
-	    if (wantSiblings) {
-		Element parent = (Element)current.getParentNode(); // this may be the structure element if there has been no request for parents or ancestors
-		String parent_id = OID.getParent(doc_id);
-
-		// add siblings, - returns a pointer to the new current node 
-		current = addSiblings(parent, parent_id, doc_id);
-       	    }
-
+
+
+	    if (want_info) {
+
+		Element info_elem = doc_.createElement("nodeStructureInfo");
+		doc.appendChild(info_elem);
+		
+		for (int j=0; j<info_types.size(); j++) {
+		    String info_type = (String)info_types.get(j);
+		    Element inf = getInfo(doc_id, info_type);
+		    if (inf != null) {
+			info_elem.appendChild(inf);
+		    }
+		}
+	    }
+	    if (want_structure) {
+		// all structure info goes into a nodeStructure elem
+		Element structure_elem = doc_.createElement(GSXML.NODE_STRUCTURE_ELEM);
+		doc.appendChild(structure_elem);
+		
+		// Add the requested structure information
+		Element current = createDocNode(doc_id, false, false);
+		
+		//Ancestors: continually add parent nodes until the root is reached
+		Element top_node = current; // the top node so far
+		if (want_ancestors) {
+		    String current_id = doc_id;
+		    while (true) {
+			Element parent = getParent(current_id);
+			if (parent == null)
+			    break;
+			
+			parent.appendChild(top_node);
+			current_id = parent.getAttribute(GSXML.NODE_ID_ATT);
+			top_node = parent;
+		    }
+		}
+		// Parent: get the parent of the selected node
+		if (want_parent) {
+		    Element parent = getParent(doc_id);
+		    if (parent != null) {
+			parent.appendChild(current);
+			top_node = parent;
+		    }
+		}
+
+		
+		// now the top node is the root of the structure
+		structure_elem.appendChild(top_node);
+		
+		//Siblings: get the other descendants of the selected node's parent
+		if (want_siblings) {
+		    Element parent = (Element)current.getParentNode(); // this may be the structure element if there has been no request for parents or ancestors
+		    String parent_id = OID.getParent(doc_id);
+		    
+		    // add siblings, - returns a pointer to the new current node 
+		    current = addSiblings(parent, parent_id, doc_id);
+		}
+		
 	    // Children: get the descendants, but only one level deep
-	    if (wantChildren)
-		addDescendants(current, doc_id, false);
-	    // Descendants: recursively get every descendant of the selected node
-	    if (wantDescendants)
-		addDescendants(current, doc_id, true);
-	}
+		if (want_children)
+		    addDescendants(current, doc_id, false);
+		// Descendants: recursively get every descendant of the selected node
+		if (want_descendants)
+		    addDescendants(current, doc_id, true);
+	    } // if want structure
+	} // for each doc
 	return result;
     }
@@ -576,5 +613,5 @@
 	// The metadata information required
 	Vector metadata_list = new Vector();
-	
+	boolean all_metadata = false;
 	// Process the request parameters
 	Element param = (Element) param_list.getFirstChild();
@@ -583,4 +620,8 @@
 	    if (param.getAttribute(GSXML.NAME_ATT).equals("metadata")) {
 		String metadata = GSXML.getValue(param);
+		if (metadata.equals("all")) {
+		    all_metadata = true;
+		    break;
+		}
 		metadata_list.add(metadata);
 	    }
@@ -590,5 +631,5 @@
 	Element node_list = doc_.createElement(node_name+GSXML.LIST_MODIFIER);
 	result.appendChild(node_list);
-
+	
 	// Get the documents
 	Element request_node_list = (Element) GSXML.getChildByTagName(request, node_name+GSXML.LIST_MODIFIER);
@@ -615,8 +656,26 @@
 	    new_node.appendChild(node_meta_list);
 	    DBInfo info = gdbm_src_.getInfo(node_id);
-	    for (int m = 0; m < metadata_list.size(); m++) {
-		String metadata = (String) metadata_list.get(m);
-		String value = info.getInfo(metadata);
-		GSXML.addMetadata(doc_, node_meta_list, metadata, value);
+	    if (info == null) {// I have had a case where it is null!
+		continue;
+	    }
+	    System.out.println("found the info");
+	    if (all_metadata) {
+		System.out.println("trying to get all the metadata");
+		// return everything out of the database
+		Set keys = info.getKeys();
+		Iterator it = keys.iterator();
+		while(it.hasNext()) {
+		    String key = (String)it.next();
+		    System.out.println("getting metadata "+key);
+		    String value = info.getInfo(key);
+		    GSXML.addMetadata(doc_, node_meta_list, key, value);
+		}
+	    } else { // just get the selected ones
+		
+		for (int m = 0; m < metadata_list.size(); m++) {
+		    String metadata = (String) metadata_list.get(m);
+		    String value = info.getInfo(metadata);
+		    GSXML.addMetadata(doc_, node_meta_list, metadata, value);
+		}
 	    }
 	}
@@ -641,3 +700,53 @@
 	return doc_content;
     }
+
+    protected Element getInfo(String doc_id, String info_type) {
+
+	String value="";
+	if (info_type.equals(INFO_NUM_SIBS)) {
+	    String parent_id = OID.getParent(doc_id);
+	    if (parent_id.equals(doc_id)) {
+		value="0";
+	    } else {
+		value = String.valueOf(getNumChildren(parent_id));
+	    }
+	} else if (info_type.equals(INFO_NUM_CHILDREN)) {
+	    value = String.valueOf(getNumChildren(doc_id));
+	} else if (info_type.equals(INFO_SIB_POS)) {
+	    String parent_id = OID.getParent(doc_id);
+	    if (parent_id.equals(doc_id)) {
+		value="-1";
+	    } else {
+		DBInfo info = gdbm_src_.getInfo(parent_id);
+		String contains = info.getInfo("contains");
+		contains = contains.replaceAll("\"", parent_id);
+		String [] children = contains.split(";");
+		for (int i=0;i<children.length;i++) {
+		    String child_id = children[i];
+		    System.out.println("child="+child_id+" doc="+doc_id);
+		    if (child_id.equals(doc_id)) {
+			value = String.valueOf(i+1); // make it from 1 to length
+			break;
+		    }
+		}
+	    }
+	} else {
+	    return null;
+	}
+	Element info_elem = doc_.createElement("info");
+	info_elem.setAttribute(GSXML.NAME_ATT, info_type);
+	info_elem.setAttribute(GSXML.VALUE_ATT, value);
+	return info_elem;
+    }
+
+    protected int getNumChildren(String doc_id) {
+	DBInfo info = gdbm_src_.getInfo(doc_id);
+	String contains = info.getInfo("contains");
+	if (contains.equals("")) {
+	    return 0;
+	}
+	String [] children = contains.split(";");
+	return children.length;
+    }
+    
 }   
