Index: /gs3-extensions/gate/trunk/src/org/greenstone/gsdl3/service/GATEServices.java
===================================================================
--- /gs3-extensions/gate/trunk/src/org/greenstone/gsdl3/service/GATEServices.java	(revision 21050)
+++ /gs3-extensions/gate/trunk/src/org/greenstone/gsdl3/service/GATEServices.java	(revision 21050)
@@ -0,0 +1,291 @@
+/*
+ *    GATEServices.java
+ *    Copyright (C) 2002 New Zealand Digital Library, http://www.nzdl.org
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.greenstone.gsdl3.service;
+
+
+// Greenstone classes
+import org.greenstone.gsdl3.util.*;
+
+// GATE classes
+import gate.*;
+import gate.creole.*;
+import gate.gui.*;
+import gate.util.persistence.PersistenceManager;
+
+// XML classes
+import org.w3c.dom.Element; 
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+// General Java classes
+import java.io.File;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+
+/**
+ * <p>Title: GATE Greenstone3 integration</p>
+ * <p>Description: </p>
+ * <p>Copyright: Copyright (c) 2003</p>
+ * <p>Company: University of Waikato</p>
+ * @author unascribed
+ * @version 1.0
+ */
+
+public class GATEServices
+    extends ServiceRack {
+
+    // the services on offer
+    // these strings must match what is found in the properties file
+    protected static final String GATE_TAG_SERVICE = "GateTag";
+
+    protected static final String ANNOTATION_TYPE_PARAM = "annotationType";
+
+    protected Element config_info = null;
+
+    protected CorpusController application;
+
+    protected Corpus corpus;
+
+    protected String[] annotation_types = { "Date", "Location",
+					     "Organization", "Person" };
+    // Address, 
+
+    /** constructor */
+    public GATEServices()
+    {
+    }
+
+
+    /** configure this service */
+    public boolean configure(Element info, Element extra_info)
+    {
+	System.out.println("Configuring GATEServices...");
+	this.config_info = info;
+
+	// set up short_service_info_ - for now just has name and type
+	Element tag_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	tag_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_ENRICH);
+	tag_service.setAttribute(GSXML.NAME_ATT, GATE_TAG_SERVICE);
+	this.short_service_info.appendChild(tag_service);
+
+
+	// Configure GATE for use
+	try {
+	    Gate.init();
+	    Gate.getUserConfig().put(GateConstants.DOCUMENT_ADD_SPACE_ON_UNPACK_FEATURE_NAME,
+				     new Boolean(false));
+
+	    // MainFrame mainFrame = new MainFrame();
+	    // mainFrame.setSize(new java.awt.Dimension(800, 600));
+	    // mainFrame.setVisible(true);
+
+	    // Load the (pre-created) application
+	    URL applicationFileURL = ClassLoader.getSystemResource("gate.app");
+	    File applicationFile = new File(applicationFileURL.getFile());
+	    this.application = (CorpusController) PersistenceManager.loadObjectFromFile(applicationFile);
+
+	    /* Collection processing_resources = application.getPRs();
+	    Iterator pr_iterator = processing_resources.iterator();
+	    while (pr_iterator.hasNext()) {
+		ProcessingResource pr = (ProcessingResource) pr_iterator.next();
+		String pr_name = pr.getName();
+		System.out.println("PR name: " + pr_name);
+		if (pr_name.startsWith("ANNIE POS Tagger")) {
+		    String as_name = ((POSTagger) pr).getInputASName();
+		    System.out.println("AS name: " + as_name);
+		}
+		} */
+
+	    // Create a new corpus
+	    this.corpus = Factory.newCorpus("GSDL3 Corpus");
+	    this.application.setCorpus(this.corpus);
+	}
+	catch (Exception e) {
+	    e.printStackTrace();
+	}
+
+	return true;
+    }
+
+    protected Element getServiceDescription(String service, String lang, String subset) {
+
+	if (!service.equals(GATE_TAG_SERVICE)) {
+	    return null;
+	}
+	Element tag_service = this.doc.createElement(GSXML.SERVICE_ELEM);
+	tag_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_ENRICH);
+	tag_service.setAttribute(GSXML.NAME_ATT, GATE_TAG_SERVICE);
+	if (subset==null || subset.equals(GSXML.DISPLAY_TEXT_ELEM)) {
+	    tag_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, getTextString(service+".name", lang)));
+	    tag_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getTextString(service+".description", lang)));
+	    tag_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_SUBMIT, getTextString(service+".submit", lang)));
+	} 
+	if (subset==null || subset.equals(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER)) {
+	    Element param_list = this.doc.createElement(GSXML.PARAM_ELEM+GSXML.LIST_MODIFIER);
+	    createParameter(ANNOTATION_TYPE_PARAM, param_list, lang);
+	    tag_service.appendChild(param_list);
+	}
+	return tag_service;
+    }
+
+
+    /** creates a new param element and adds it to the param list */
+    protected void createParameter(String name, Element param_list, 
+				   String lang)
+    {
+	Element param = null;
+
+	if (name.equals(ANNOTATION_TYPE_PARAM)) {
+	    int len = this.annotation_types.length;
+	    String[] annotation_type_names = new String[len];
+	    for (int i = 0; i < len; i++) {
+		annotation_type_names[i] = getTextString("param." + name + "." + this.annotation_types[i], lang);
+	    }
+	    
+	    param = GSXML.createParameterDescription(this.doc, name, getTextString("param." + name, lang), GSXML.PARAM_TYPE_ENUM_MULTI, this.annotation_types[0], this.annotation_types, annotation_type_names);
+	    param_list.appendChild(param);
+	}
+	
+    }
+    
+    
+    protected Element processGateTag(Element request)
+    {
+	// System.out.println("(GateTag) Request:\n" + converter_.getPrettyString(request));
+
+	// Create a new (empty) result message
+	Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
+	result.setAttribute(GSXML.FROM_ATT, GATE_TAG_SERVICE);
+	result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
+
+	// 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("Error: GateTag request had no paramList.");
+	    return result;  // Return the empty result
+	}
+
+	// Process the request parameters
+	Set annTypes = new HashSet();
+	Element param = (Element) param_list.getFirstChild();
+	while (param != null) {
+	    // Identify the annotation types desired
+	    if (param.getAttribute(GSXML.NAME_ATT).equals("annotationType")) {
+		String annotation_type = GSXML.getValue(param);
+		String [] types = annotation_type.split(",");
+		for (int i=0; i<types.length; i++) {
+		    annTypes.add(types[i]);
+		}
+	    }
+
+	    param = (Element) param.getNextSibling();
+	}
+
+	// Get the request content 
+      	Element doc_node_list = (Element) GSXML.getChildByTagName(request, GSXML.DOC_NODE_ELEM+GSXML.LIST_MODIFIER);
+	if (doc_node_list == null) {
+	    System.err.println("Error: GateTag request specified no doc nodes.");
+	    return result;  // Return the empty result
+	}
+
+	// Process each document node in the list
+	NodeList doc_nodes = doc_node_list.getChildNodes();
+	for (int i = 0; i < doc_nodes.getLength(); i++) {
+	    Element doc_node = (Element) doc_nodes.item(i);
+	    Element content = (Element) GSXML.getChildByTagName(doc_node, "nodeContent");
+	    Node content_text = (Node) GSXML.getNodeTextNode(content);
+	    String text = content_text.getNodeValue();
+
+	    // GATE needs the text to be a valid HTML file
+	    text = "<html><head></head><body>" + text + "</body></html>";
+	    String annotated_text = processText(text, annTypes);
+
+	    // Remove the surrounding HTML tags
+	    annotated_text = annotated_text.substring(49, annotated_text.length() - 13);
+	    // System.out.println("GATE result:\n" + annotated_text);
+
+	    annotated_text = "<nodeContent>" + annotated_text + "</nodeContent>";
+	    Document annotated_content_doc = this.converter.getDOM(annotated_text);
+	    if (annotated_content_doc != null) {
+		Element annotated_content = annotated_content_doc.getDocumentElement();
+		doc_node.replaceChild(doc_node.getOwnerDocument().importNode(annotated_content, true), content);
+	    } else {
+		System.err.println("GATEServices.processGateTag Error: Couldn't parse annotated text for doc node "+i);
+	    }
+	    
+	}
+
+	result.appendChild(this.doc.importNode(doc_node_list, true));
+	// System.out.println("GateTag result:\n" + converter_.getPrettyString(result));
+	return result;
+    }
+
+
+    public String processText(String text, Set annotationTypesToExport)
+    {
+	try {
+	    // Create a new document containing the text
+	    FeatureMap parameters = Factory.newFeatureMap();
+	    parameters.put("stringContent", text);
+	    parameters.put("markupAware", new Boolean(true));
+	    parameters.put("preserveOriginalContent", new Boolean(true));
+	    parameters.put("collectRepositioningInfo", new Boolean(true));
+	    Document doc = (Document) Factory.createResource("gate.corpora.DocumentImpl",
+							     parameters);
+
+	    // Add it to the corpus
+	    this.corpus.clear();
+	    this.corpus.add(doc);
+
+	    // Process the corpus
+	    this.application.execute();
+
+	    // Extract all the annotations
+	    AnnotationSet annSet = doc.getAnnotations();
+
+	    // Return the desired annotations
+	    AnnotationSet outputAnnotations = annSet.get(annotationTypesToExport);
+	    String result = doc.toXml(outputAnnotations, false);
+	    Factory.deleteResource(doc);
+
+	    // 1. Escape the GATE result
+	    result = GSXML.xmlSafe(result);
+
+	    // 2. Unescape the annotation tags
+	    Iterator setIterator = annotationTypesToExport.iterator();
+	    while (setIterator.hasNext()) {
+		String annotationType = (String) setIterator.next();
+		result = result.replaceAll("&lt;" + annotationType + "&gt;",
+					   "<annotation type=\"" + annotationType + "\">");
+		result = result.replaceAll("&lt;/" + annotationType + "&gt;",
+					   "</annotation>");
+	    }
+
+	    return result;
+	}
+	catch (Exception e) {
+	    e.printStackTrace();
+	    return null;
+	}
+    }
+}
