Index: trunk/gsdl3/src/java/org/greenstone/gsdl3/action/QueryAction.java
===================================================================
--- trunk/gsdl3/src/java/org/greenstone/gsdl3/action/QueryAction.java	(revision 5155)
+++ trunk/gsdl3/src/java/org/greenstone/gsdl3/action/QueryAction.java	(revision 5191)
@@ -29,5 +29,4 @@
 	// create the return message
 	Element result = this.doc.createElement(GSXML.MESSAGE_ELEM);
-	// for now we only have one type of query - subaction not used
 	Element response = basicQuery(request);
 	result.appendChild(this.doc.importNode(response, true));
@@ -36,5 +35,5 @@
     
     /** a generic query handler 
-     * this gets the service description, does the query (just passes all teh 
+     * this gets the service description, does the query (just passes all the 
      * params to the service, then gets the titles for any results 
      */
@@ -112,6 +111,6 @@
 	    return page_response;
 	}
-	Element query_param_list = GSXML.createParameterList(this.doc, service_params);//(Element)this.doc.importNode(cgi_param_list, true);
-	System.out.println("service params are "+this.converter.getString(query_param_list));
+	Element query_param_list = GSXML.createParameterList(this.doc, service_params);
+	///ystem.out.println("service params are "+this.converter.getString(query_param_list));
 	mr_query_request.appendChild(query_param_list);
 
@@ -145,5 +144,8 @@
 	}
 	
-	// do the metadata request
+	// paging of the results is done here - we filter the list to remove unwanted entries before retrieving metadata
+	Element filtered_doc_list = filterDocList(params, service_description, document_list);
+	
+	// do the metadata request on the filtered list
 	Element mr_metadata_message = this.doc.createElement(GSXML.MESSAGE_ELEM);
 	Element mr_metadata_request = this.doc.createElement(GSXML.REQUEST_ELEM);
@@ -164,5 +166,6 @@
 	
 	// add in the doc node list too
-	mr_metadata_request.appendChild(this.doc.importNode(document_list, true));
+	mr_metadata_request.appendChild(filtered_doc_list);
+
 	Element mr_metadata_response = (Element) this.mr.process(mr_metadata_message);	
 	
@@ -177,3 +180,73 @@
 	return page_response;
     }
+
+    /** this filters out some of the doc results for result paging */
+    protected Element filterDocList(HashMap params, Element service_description, Element orig_doc_list) {
+	
+	// check in the service descripiton to see if hitsPerpage is a param
+	Element service_p_list = (Element)GSXML.getChildByTagName(service_description, GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	Element hits_param = GSXML.getNamedElement(service_p_list, GSXML.PARAM_ELEM, GSXML.NAME_ATT, "hitsPerPage");
+	
+	boolean service_paging = false;
+	if (hits_param != null) {
+	    service_paging = true;
+	}
+	if (service_paging) {
+	    // the service is doing the paging, so we want to display all of teh returned docs
+	    return (Element)this.doc.importNode(orig_doc_list, true);
+	}
+	
+	String hits_pp = (String)params.get("hitsPerPage");
+	int hits = 20;
+	if (hits_pp != null && !hits_pp.equals("")) {
+	    try {
+		hits = Integer.parseInt(hits_pp);
+	    } catch (Exception e) {
+		hits=20;
+	    }
+	}
+
+	if (hits == -1) { // all
+	    return (Element)this.doc.importNode(orig_doc_list, true);
+	}
+	NodeList result_docs = orig_doc_list.getElementsByTagName(GSXML.DOC_NODE_ELEM);
+	
+	int num_docs = result_docs.getLength();
+	if (num_docs <= hits) {
+	    // too few docs to do paging
+	    return (Element)this.doc.importNode(orig_doc_list, true);
+	}
+
+	// now we need our own doc list
+	Element result_list = this.doc.createElement(GSXML.DOC_NODE_ELEM + GSXML.LIST_MODIFIER);
+	String start_p = (String)params.get("startPage");
+	int start = 1;
+	if (start_p != null && !start_p.equals("")) {
+	    try {
+		start = Integer.parseInt(start_p);
+	    } catch (Exception e) {
+		start = 1;
+	    }
+	}
+
+	int start_from = (start-1)*hits;
+	int end_at = (start*hits)-1;
+
+	if (start_from > num_docs) {
+	    // something has gone wrong
+	    return result_list;
+	}
+	
+	if (end_at > num_docs) {
+	    end_at = num_docs-1;
+	}
+
+	// now we finally have the docs numbers to use
+	for (int i=start_from; i<=end_at; i++) {
+	    result_list.appendChild(this.doc.importNode(result_docs.item(i), true));
+	}
+
+	return result_list;
+    }
+
 }
