[MOBY-guts] biomoby commit
Martin Senger
senger at dev.open-bio.org
Wed Dec 3 12:22:21 UTC 2008
senger
Wed Dec 3 07:22:21 EST 2008
Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/client
In directory dev.open-bio.org:/tmp/cvs-serv12031/S/client
Modified Files:
CentralImpl.java
Log Message:
revert to 1.57
moby-live/Java/src/main/org/biomoby/client CentralImpl.java,1.59,1.60
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralImpl.java,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -r1.59 -r1.60
--- /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralImpl.java 2008/12/03 12:09:40 1.59
+++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralImpl.java 2008/12/03 12:22:21 1.60
@@ -1,2139 +1,2139 @@
-// CentralImpl.java
-// A default client to the Moby Central service.
-//
-// senger at ebi.ac.uk
-// February 2003
-//
-
-package org.biomoby.client;
-
-import org.biomoby.registry.meta.Registry;
-import org.biomoby.shared.Central;
-import org.biomoby.shared.MobyData;
-import org.biomoby.shared.MobyDataType;
-import org.biomoby.shared.MobyException;
-import org.biomoby.shared.MobyNamespace;
-import org.biomoby.shared.MobyPrimaryDataSet;
-import org.biomoby.shared.MobyPrimaryDataSimple;
-import org.biomoby.shared.MobyRelationship;
-import org.biomoby.shared.MobySecondaryData;
-import org.biomoby.shared.MobyService;
-import org.biomoby.shared.MobyServiceType;
-import org.biomoby.shared.NoSuccessException;
-import org.biomoby.shared.PendingCurationException;
-import org.biomoby.shared.MobyResourceRef;
-import org.biomoby.shared.Utils;
-
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.namespace.QName;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import org.apache.axis.AxisFault;
-import org.apache.axis.client.Call;
-import org.apache.axis.client.Service;
-import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
-import org.apache.commons.httpclient.Header;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpException;
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.methods.HeadMethod;
-import org.apache.commons.httpclient.params.HttpMethodParams;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.LineNumberReader;
-import java.io.PrintStream;
-import java.io.InputStream;
-import java.lang.reflect.Constructor;
-import java.net.HttpURLConnection;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Vector;
-import java.util.TreeMap;
-import java.util.Comparator;
-import java.util.zip.GZIPInputStream;
-import java.util.logging.*;
-
-/**
- * A default implementation of the
- * interface {@link org.biomoby.shared.Central Central}
- * allowing access to a Moby registry.
- *<p>
- * This class is supposed to be used by all other clients that wish
- * to communicate with the Moby Registry, but do not want to know
- * about all XML details that are necessary for talking with the Moby Central
- * directly. This is an example of a client program:
- *<pre>
- * import org.biomoby.shared.Central;
- * import org.biomoby.shared.MobyException;
- * import org.biomoby.client.CentralImpl;
- * import java.util.Map;
- * import java.util.Iterator;
- *
- * public class Test {
- *
- * public static void main (String[] args)
- * throws MobyException {
- *
- * Central worker = new CentralImpl();
- * Map authorities = worker.getServiceNamesByAuthority();
- *
- * for (Iterator it = authorities.entrySet().iterator(); it.hasNext(); ) {
- * Map.Entry entry = (Map.Entry)it.next();
- * System.out.println (entry.getKey());
- * String[] names = (String[])entry.getValue();
- * for (int i = 0; i < names.length; i++)
- * System.out.println ("\t" + names[i]);
- * }
- * }
- * }
- *</pre>
- *
- * @author <A HREF="mailto:senger at ebi.ac.uk">Martin Senger</A>
- * @version $Id$
- */
-
-public class CentralImpl
- implements Central, SimpleCache {
-
- private URL endpoint;
- private String uri;
- protected boolean debug = false;
-
- /** Common central used to if getDefaultCentral() is called */
- protected static Map<String,CentralImpl> defaultCentrals = new HashMap<String,CentralImpl>();
-
- /** Default location (endpoint) of a Moby registry. */
- public static final String DEFAULT_ENDPOINT = "http://moby.ucalgary.ca/moby/MOBY-Central.pl";
-
- /** Default namespace used by the contacted Moby registry. */
- public static final String DEFAULT_NAMESPACE = "http://moby.ucalgary.ca/MOBY/Central";
-
- /**
- * The META-INF resource file that will be checked to determine what
- * default class should be instantiated in order to create a Central Implementation
- * when getDefaultCentral() is called.
- */
- public static final String CENTRAL_IMPL_RESOURCE_NAME = "org.biomoby.shared.CentralDefaultImpl";
- /** The class to use for getDefaultCentral if all else fails */
- public static final String DEFAULT_CENTRAL_IMPL_CLASSNAME = "org.biomoby.client.CentralDigestCachedImpl";
- private static Logger logger = Logger.getLogger("org.biomoby.client.CentralImpl");
-
- /**
- * Thread local that gives each thread its own
- * DocumentBuilderFactory (since it is not thread-safe). Code taken
- * from Apache's JaxpUtils.
- */
- public static ThreadLocal DOCUMENT_BUILDER_FACTORIES = new ThreadLocal() {
- protected synchronized Object initialValue() {
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- dbf.setNamespaceAware (true);
- return dbf;
- }
- };
-
-
- /*************************************************************************
- * Default constructor. It connects to a default Moby registry
- * (as defined in {@link #DEFAULT_ENDPOINT}) using a default namespace
- * (as defined int {@link #DEFAULT_NAMESPACE}).
- *************************************************************************/
- public CentralImpl()
- throws MobyException {
- this (DEFAULT_ENDPOINT, DEFAULT_NAMESPACE);
- }
-
- /*************************************************************************
- * Constructor allowing to specify which Moby Registry to use.
- *
- * @throws MobyException if 'endpoint' is not a valid URL, or if no
- * DOM parser is available
- *************************************************************************/
- public CentralImpl (String endpoint)
- throws MobyException {
- this (endpoint, DEFAULT_NAMESPACE);
- }
-
- /*************************************************************************
- * Constructor allowing to specify which Moby Registry and what
- * namespace to use. If any of the parameters is null, its default
- * value is used instead.
- *<p>
- * @throws MobyException if 'endpoint' is not a valid URL, or if no
- * DOM parser was found
- *************************************************************************/
- public CentralImpl (String endpoint, String namespace)
- throws MobyException {
-
- if (endpoint == null || "".equals (endpoint.trim()))
- endpoint = DEFAULT_ENDPOINT;
- if (namespace == null || "".equals (namespace.trim()))
- namespace = DEFAULT_NAMESPACE;
-
- try {
- this.endpoint = new URL (endpoint);
- } catch (MalformedURLException e) {
- throw new MobyException ("Bad URL: " + endpoint);
- }
- this.uri = namespace;
-
- cache = new Hashtable<String,Object>();
- useCache = true;
- }
-
- /*************************************************************************
- * Loads a DOM Document from an InputStream. Uses thread-safe
- * mechanism.
- *************************************************************************/
- public static Document loadDocument (InputStream input)
- throws MobyException {
- try {
- DocumentBuilderFactory dbf
- = (DocumentBuilderFactory)DOCUMENT_BUILDER_FACTORIES.get();
- DocumentBuilder db = dbf.newDocumentBuilder();
- return (db.parse (input));
- } catch (Exception e) {
- throw new MobyException ("Problem with reading XML input: " + e.toString(), e);
- }
- }
-
- /*************************************************************************
- * Call 'method' with 'parameters' and return its result.
- *************************************************************************/
- protected Object doCall (String method, Object[] parameters)
- throws MobyException {
-
- Call call = null;
- try {
- Service service = new Service();
- call = (Call) service.createCall();
- call.setTargetEndpointAddress (endpoint);
- call.setTimeout (new Integer (0));
-
- call.setSOAPActionURI (uri + "#" + method);
-
- if (debug) {
- System.err.println ("METHOD CALL: " + method);
- System.err.println ("------------");
- if (parameters.length > 0)
- System.err.println (parameters[0] + "\n");
- System.err.println ("------------\n");
-
- Object result = call.invoke (uri, method, parameters);
-
- System.err.println ("METHOD RETURN:");
- System.err.println ("------------");
- if (result != null)
- System.err.println (result + "\n");
- System.err.println ("------------\n");
-
- return resultToString (result);
-
- } else {
- return resultToString (call.invoke (uri, method, parameters));
- }
-
- } catch (AxisFault e) {
- throw new MobyException
- (formatFault (e,
- endpoint.toString(),
- (call == null ? null : call.getOperationName())),
- e);
-// (endpoint.toString()+(call == null ? "" : call.getOperationName()), e);
-
- } catch (Exception e) {
- throw new MobyException (e.toString(), e);
-// e.printStackTrace();
- }
- }
-
-
- /**************************************************************************
- * Parse the given XML sniplet to find tag 'success'. If it has value '1'
- * look further for tag 'id' and return it back (or return an empty string
- * if ID is not there). Otherwise raise an exception with the 'culprit'
- * and with the message from the tag 'message'. <p>
- *
- * The return value is a two-element long array. The first element
- * is the ID (given by BioMobe registry), and the second element
- * is RDF corresponding with the registered object (BioMoby
- * returns this only for service instances, so for other objects
- * this will be null). <p>
- *
- * This is how the XML is supposed to look:
- * <MOBYRegistration>
- * <success> <!-- 1 | 0 | -1 --> </success>
- * <id> <!-- some id number for your registration --> </id>
- * <message> <![CDATA[message here]]> </message>
- * <RDF> <!-- RDF of your service instance here (if applicable) --> </RDF>
- * </MOBYRegistration>
- *
- * Success takes the value "1" to indicate success, "0" to
- * indicate failure, and "-1" to indicate "Pending Curation".
- *************************************************************************/
- protected String[] checkRegistration (String xml, Object culprit)
- throws MobyException, NoSuccessException, PendingCurationException {
-
- String id = "", success = "0", message = "", rdf = "";
-
- // parse returned XML
- Document document = loadDocument (new ByteArrayInputStream (xml.getBytes()));
- Element root = document.getDocumentElement();
-
- NodeList children = root.getChildNodes();
- for (int i = 0; i < children.getLength(); i++) {
- if (children.item (i).getNodeType() != Node.ELEMENT_NODE)
- continue;
- Element elem = (Element)children.item (i);
- if (elem.getNodeName().equals ("id")) {
- if (elem.getFirstChild() != null)
- id = elem.getFirstChild().getNodeValue();
- } else if (elem.getNodeName().equals("success")) {
- if (elem.getFirstChild() != null)
- success = elem.getFirstChild().getNodeValue();
- } else if (elem.getNodeName().equals ("message")) {
- if (elem.getFirstChild() != null)
- message = elem.getFirstChild().getNodeValue();
- } else if (elem.getNodeName().equals ("RDF")) {
- if (elem.getFirstChild() != null)
- rdf = elem.getFirstChild().getNodeValue();
- }
- }
-
- if (success.equals ("0"))
- throw new NoSuccessException (message, culprit);
- else if (success.equals ("-1"))
- throw new PendingCurationException();
- return new String[] { id, rdf };
- }
-
- /**************************************************************************
- * Return a piece of XML created from the definitions representing input
- * data types and their usage in the given service. Only data considered
- * primary are included. Note that the main job of converting to XML is
- * done by instances of MobyPrimaryData.
- *
- * The returned XML looks like this:
- * <Input>
- * <!-- zero or more Primary (Simple and/or Complex) articles -->
- * </Input>
- *************************************************************************/
- protected String buildPrimaryInputTag (MobyService service) {
- StringBuffer buf = new StringBuffer();
- MobyData[] primaryInputs = service.getPrimaryInputs();
- buf.append ("<Input>\n");
- for (int i = 0; i < primaryInputs.length; i++)
- buf.append (primaryInputs[i].toXML());
- buf.append ("</Input>\n");
- return new String (buf);
- }
-
- /**************************************************************************
- * Return a piece of XML created from the definitions representing input
- * data types and their usage in the given service. Only data considered
- * secondary are included. Note that the main job of converting to XML is
- * done by instances of MobySecondaryData.
- *
- * The returned XML looks like this:
- * <secondaryArticles>
- * <!-- zero or more INPUT Secondary articles -->
- * </secondaryArticles>
- *************************************************************************/
- protected String buildSecondaryInputTag (MobyService service) {
- StringBuffer buf = new StringBuffer();
- MobyData[] secInputs = service.getSecondaryInputs();
- buf.append ("<secondaryArticles>\n");
- for (int i = 0; i < secInputs.length; i++) {
- buf.append (secInputs[i].toXML());
- }
- buf.append ("</secondaryArticles>\n");
- return new String (buf);
- }
-
- /**************************************************************************
- * Return a piece of XML created from the definitions representing output
- * data types and their usage in the given service. Only data considered
- * primary are included. Note that the main job of converting to XML is
- * done by instances of MobyPrimaryData.
- *
- * The returned XML looks like this:
- * <Output>
- * <!-- zero or more Primary (Simple and/or Complex) articles -->
- * </Output>
- *
- *************************************************************************/
- protected String buildOutputTag (MobyService service) {
- StringBuffer buf = new StringBuffer();
- MobyData[] primaryOutputs = service.getPrimaryOutputs();
- buf.append ("<Output>\n");
- for (int i = 0; i < primaryOutputs.length; i++)
- buf.append (primaryOutputs[i].toXML());
- buf.append ("</Output>\n");
- return new String (buf);
- }
-
- /**************************************************************************
- * Return a piece of XML represented a query object (an object used
- * to find a service).
- *
- * The returned XML looks like this:
- *
- * <inputObjects>
- * <Input>
- * <!-- one or more Simple or Complex Primary articles -->
- * </Input>
- * </inputObjects>
- * <outputObjects>
- * <Output>
- * <!-- one or more Simple or Complex Primary articles -->
- * </Output>
- * </outputObjects>
- * <serviceType>ServiceTypeTerm</serviceType>
- * <serviceName>ServiceName</serviceName>
- * <Category>moby</Category>
- * <authURI>http://desired.service.provider</authURI>;
- * <expandObjects>1|0</expandObjects>
- * <expandServices>1|0</expandServices>
- * <authoritative>1|0</authoritative>
- * <keywords>
- * <keyword>something</keyword>
- * ....
- * ....
- * </keywords>
- *************************************************************************/
- protected String buildQueryObject (MobyService service,
- String[] keywords,
- boolean expandObjects,
- boolean expandServices,
- boolean authoritative) {
- if (service == null) {
- service = new MobyService ("dummy");
- service.setCategory ("");
- }
- StringBuffer buf = new StringBuffer();
-
- buf.append ("<inputObjects>\n<Input>\n");
- MobyData[] pi = service.getPrimaryInputs();
- if (pi.length > 0) {
- for (int i = 0; i < pi.length; i++)
- buf.append (pi[i].toXML());
- }
- buf.append ("</Input>\n</inputObjects>\n");
-
- buf.append ("<outputObjects>\n<Output>\n");
- MobyData[] po = service.getPrimaryOutputs();
- if (po.length > 0) {
- for (int i = 0; i < po.length; i++)
- buf.append (po[i].toXML());
- }
- buf.append ("</Output>\n</outputObjects>\n");
-
- buf.append ("<serviceType>" + service.getType() + "</serviceType>\n");
-
- String name = service.getName();
- if (!name.equals ("") && !name.equals ("dummy") && !name.equals (MobyService.DUMMY_NAME))
- buf.append ("<serviceName>" + service.getName() + "</serviceName>\n");
-
- String sigURL = service.getSignatureURL();
- if (!sigURL.equals (""))
- buf.append ("<signatureURL>" + sigURL + "</signatureURL>\n");
-
- buf.append ("<Category>" + service.getCategory() + "</Category>\n");
- buf.append ("<authURI>" + service.getAuthority() + "</authURI>\n");
-
- buf.append ("<expandObjects>");
- buf.append (expandObjects ? "1" : "0");
- buf.append ("</expandObjects>\n");
-
- buf.append ("<expandServices>");
- buf.append (expandServices ? "1" : "0");
- buf.append ("</expandServices>\n");
-
- buf.append ("<authoritative>");
- buf.append (authoritative ? "1" : "0");
- buf.append ("</authoritative>\n");
-
- buf.append ("<keywords>\n");
- if (keywords != null && keywords.length > 0) {
- for (int i = 0; i < keywords.length; i++) {
- buf.append ("<keyword>");
- buf.append (keywords[i]);
- buf.append ("</keyword>\n");
- }
- }
- buf.append ("</keywords>\n");
-
- return new String (buf);
- }
-
- /**************************************************************************
- * Extract one or more MobyService objects from the given XML piece.
- * The XML should look like this:
- * <pre>
- * <Services>
- * <Service authURI="authority.URI.here" lsid="..." serviceName="MyService">
- * <serviceType>Service_Ontology_Term</serviceType>
- * <Category>moby</Category> <!-- or 'cgi' or 'soap' -->
- * <contactEmail>your at email.addy.here</contactEmail>
- * <signatureURL>http://service.RDF.here</signatureURL>
- * <URL>http://service.endpoint.here/scriptname</URL>
- * <authoritative>1</authoritative>
- * <Input>
- * <!-- one or more Simple and/or Complex Primary articles -->
- * </Input>
- * <Output>
- * <!-- one or more Simple and/or Complex Primary articles -->
- * </Output>
- * <secondaryArticles>
- * <!-- one or more Secondary articles -->
- * </secondaryArticles>
- * <Description><![CDATA[free text description here]]></Description>
- * </Service>
- * ... <!-- one or more Service blocks may be returned -->
- * ...
- * ...
- * </Services>
- * </pre>
- * @throws MobyException if the XML document is invalid
- *************************************************************************/
- public MobyService[] extractServices (String xml)
- throws MobyException {
-
- Document document = loadDocument (new ByteArrayInputStream (xml.getBytes()));
- NodeList list = document.getElementsByTagName ("Service");
- MobyService[] results = new MobyService [list.getLength()];
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- MobyService service = new MobyService (elem.getAttribute ("serviceName"));
- service.setAuthority (elem.getAttribute ("authURI"));
- service.setLSID (elem.getAttribute ("lsid"));
- NodeList children = elem.getChildNodes();
- for (int j = 0; j < children.getLength(); j++) {
- String nodeName = children.item (j).getNodeName();
- if (nodeName.equals ("Description")) {
- service.setDescription (getFirstValue (children.item (j)));
- } else if (nodeName.equals ("Category")) {
- service.setCategory (getFirstValue (children.item (j)));
- } else if (nodeName.equals ("URL")) {
- service.setURL (getFirstValue (children.item (j)));
- } else if (nodeName.equals ("signatureURL")) {
- service.setSignatureURL (getFirstValue (children.item (j)));
- } else if (nodeName.equals ("contactEmail")) {
- service.setEmailContact (getFirstValue (children.item (j)));
- } else if (nodeName.equals ("serviceType")) {
- service.setType (getFirstValue (children.item (j)));
- MobyServiceType mst = new MobyServiceType(service.getType());
- NamedNodeMap map = (children.item (j).getAttributes());
- if (map != null) {
- Node node = map.getNamedItemNS(children.item(j).getNamespaceURI(),"lsid");
- if (node != null)
- mst.setLSID(node.getNodeValue());
- }
- service.setServiceType(mst);
- } else if (nodeName.equals ("authoritative")) {
- String authoritative = getFirstValue (children.item (j));
- service.setAuthoritative (authoritative.equals ("1") ? true : false);
- } else if (nodeName.equals ("Input")) {
- // <Input>
- // <!-- one or more Simple and/or Complex Primary articles -->
- // <Simple articleName="NameOfArticle">
- // ...
- // </Simple>
- // <Collection articleName="NameOfArticle">
- // <Simple>......</Simple>
- // <Simple>......</Simple>
- // </Collection>
- // </Input>
- NodeList inputs = children.item (j).getChildNodes();
- for (int k = 0; k < inputs.getLength(); k++) {
- if (inputs.item (k).getNodeName().equals ("Simple")) {
- MobyPrimaryDataSimple data = new MobyPrimaryDataSimple ((Element)inputs.item (k));
- service.addInput (data);
- } else if (inputs.item (k).getNodeName().equals ("Collection")) {
- MobyPrimaryDataSet data = new MobyPrimaryDataSet ((Element)inputs.item (k));
- service.addInput (data);
- }
- }
- } else if (nodeName.equals ("Output")) {
- // <Output>
- // <!-- one or more Simple and/or Complex Primary articles -->
- // </Output>
- NodeList inputs = children.item (j).getChildNodes();
- for (int k = 0; k < inputs.getLength(); k++) {
- if (inputs.item (k).getNodeName().equals ("Simple")) {
- MobyPrimaryDataSimple data = new MobyPrimaryDataSimple ((Element)inputs.item (k));
- service.addOutput (data);
- } else if (inputs.item (k).getNodeName().equals ("Collection")) {
- MobyPrimaryDataSet data = new MobyPrimaryDataSet ((Element)inputs.item (k));
- service.addOutput (data);
- }
- }
-
- } else if (nodeName.equals ("secondaryArticles")) {
- // <Parameter articleName="NameOfArticle">
- // ...
- // </Parameter>
- NodeList parameters = children.item (j).getChildNodes();
- for (int k = 0; k < parameters.getLength(); k++) {
- if (parameters.item (k).getNodeName().equals ("Parameter")) {
- MobySecondaryData data = new MobySecondaryData ((Element)parameters.item (k));
- service.addInput (data);
- }
- }
- }
- }
- results [i] = service;
- }
- return results;
- }
-
- // protect against null values
- protected String getFirstValue (Node child) {
- Node node = child.getFirstChild();
- if (node == null) return "";
- String value = node.getNodeValue();
- if (value == null) return "";
- return value;
- }
-
- protected String getFirstValue (NodeList children) {
- if (children.item(0) != null && children.item(0).hasChildNodes()) {
- children.item(0).normalize();
- return getFirstValue (children.item(0));
- }
- return "";
- }
-
- /**************************************************************************
- *
- * Implementing SimpleCache interface.
- *
- * Why to have an interface for such trivial thing? Well, because
- * I needed to overwrite the caching mechanism in the subclasses
- * so I needed to have all caching functions as separate methods -
- * that's why I have collect them in an interface.
- *
- *************************************************************************/
- private Hashtable<String,Object> cache; // this is the cache itself
- private boolean useCache; // this signal that we are actually caching things
-
- // not used here
- public String createId (String rootName,
- String semanticType, String syntaxType,
- long lastModified,
- Properties props) {
- return ""; // not used here
- }
-
- // check existence of a cached object
- public boolean existsInCache (String id) {
- synchronized (cache) {
- if (useCache) return cache.containsKey (id);
- else return false;
- }
- }
-
- // retrieve from cache
- public Object getContents (String id) {
- synchronized (cache) {
- if (useCache) return cache.get (id);
- else return null;
- }
- }
-
- // cache an object
- public void setContents (String id, java.lang.Object data) {
- synchronized (cache) {
- if (useCache) cache.put (id, data);
- }
- }
-
- // in this implementation, it clears the whole cache, regardless
- // what 'id' is passed
- public void removeFromCache (String id) {
- cache.clear();
- }
-
- /**************************************************************************
- *
- * And the other methods related to caching (but not part of the
- * SimpleCache interface).
- *
- **************************************************************************/
-
- /**************************************************************************
- * By default, caching is enabled to reduce network traffic.
- * Setting this to false will clear the cache, and not cache any
- * further calls unless it is set to true again. <p>
- *
- * @param shouldCache whether retrieveXXX call results should be
- * cached in case they are called again (i.e. don't request
- * MobyCentral every time)
- **************************************************************************/
- public void setCacheMode (boolean shouldCache) {
- useCache = shouldCache;
- if (! useCache)
- removeFromCache (null);
- }
-
- /**************************************************************************
- * Find if caching is currently enabled.
- *
- * @return true if caching is enabled
- **************************************************************************/
- public boolean getCacheMode(){
- return useCache;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- * <serviceNames>
- * <serviceName name="serviceName" authURI='authority.info.here'/>
- * ...
- * ...
- * </serviceNames>
- * </pre>
- *
- * @deprecated Replaced by {@link
- * #getServiceNamesByAuthority}. The reason is that this method
- * returns a random result if there are more services with the
- * same name but belonging to different authorities. <p>
- *
- *************************************************************************/
- public Map<String,String> getServiceNames()
- throws MobyException {
-
- String result = (String)doCall ("retrieveServiceNames",
- new Object[] {});
- // parse returned XML
- Map<String,String> results = new TreeMap<String,String> (getStringComparator());
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getElementsByTagName ("serviceName");
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- results.put (elem.getAttribute ("name"),
- elem.getAttribute ("authURI"));
- }
-
- return results;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- * <serviceNames>
- * <serviceName name="serviceName" lsid="..." authURI='authority.info.here'/>
- * ...
- * ...
- * </serviceNames>
- * </pre>
- *
- * @return a Map which has authorities as keys, and String arrays
- * with service names as a values.
- *************************************************************************/
- public Map getServiceNamesByAuthority()
- throws MobyException {
- String result = getServiceNamesByAuthorityAsXML();
- return createServicesByAuthorityFromXML (result, true);
- }
-
- /**************************************************************************
- * Similar to {@link #getServiceNamesByAuthority} but the
- * resulting Map contains slightly more. <p>
- *
- * @return a Map which has authorities as keys, and arrays of
- * MobyServices as a values. Each MobyService is filled with its
- * name, authority and LSID.
- *************************************************************************/
- public Map getServicesByAuthority()
- throws MobyException {
- String result = getServiceNamesByAuthorityAsXML();
- return createServicesByAuthorityFromXML (result, false);
- }
-
- //
- protected String getServiceNamesByAuthorityAsXML()
- throws MobyException {
- return (String)doCall ("retrieveServiceNames",
- new Object[] {});
- }
-
- // if onlyNames == true
- // Map: authority name -> String[]
- // (filled with service namea)
- // else
- // Map: authority name -> MobyService[]
- // (filled with service name, authority and lsid)
- protected Map createServicesByAuthorityFromXML (String result,
- boolean onlyNames)
- throws MobyException {
-
- // parse returned XML
- Map results = new TreeMap (getStringComparator());
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getElementsByTagName ("serviceName");
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- String name = elem.getAttribute ("name");
- String auth = elem.getAttribute ("authURI");
- Vector<Object> v =
- (results.containsKey (auth) ? (Vector)results.get (auth) : new Vector<Object>());
- if (onlyNames) {
- v.addElement (name);
- } else {
- MobyService ms = new MobyService (name);
- ms.setAuthority (auth);
- ms.setLSID (elem.getAttribute ("lsid"));
- v.addElement (ms);
- }
- results.put (auth, v);
- }
-
- // change values of type Vector to MobyService[] or String[]
- for (Iterator it = results.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry)it.next();
- Vector v = (Vector)entry.getValue();
- if (onlyNames) {
- String[] sNames = new String [v.size()];
- v.copyInto (sNames);
- entry.setValue (sNames);
- } else {
- MobyService[] mss = new MobyService [v.size()];
- v.copyInto (mss);
- entry.setValue (mss);
- }
- }
-
- return results;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- * <serviceProviders>
- * <serviceProvider name="authority.URI.here"/>
- * ...
- * ...
- * </serviceProviders>
- * </pre>
- *************************************************************************/
- public String[] getProviders()
- throws MobyException {
-
- String cacheId = "retrieveServiceProviders";
- String[] cachedResults = (String[])getContents (cacheId);
- if (cachedResults != null)
- return cachedResults;
-
- String result = (String)doCall ("retrieveServiceProviders",
- new Object[] {});
-
- // parse returned XML
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getElementsByTagName ("serviceProvider");
- String[] results = new String [list.getLength()];
- for (int i = 0; i < list.getLength(); i++)
- results[i] = ((Element)list.item (i)).getAttribute ("name");
-
- // Add this data to the cache in case we get called again
- setContents (cacheId, results);
-
- return results;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- * <serviceTypes>
- * <serviceType name="serviceName" lsid="...">
- * <Description><![CDATA[free text description here]]></Description>
- * <contactEmail>...</contactEmail>
- * <authURI>...</authURI>
- * </serviceType>
- * ...
- * ...
- * </serviceTypes>
- * </pre>
- *************************************************************************/
- public Map getServiceTypes()
- throws MobyException {
- String result = getServiceTypesAsXML();
- Map results = new TreeMap (getStringComparator());
- MobyServiceType[] types = createServiceTypesFromXML (result);
- for (int i = 0; i < types.length; i++) {
- results.put (types[i].getName(),
- types[i].getDescription());
- }
- return results;
- }
-
- //
- protected String getServiceTypesAsXML()
- throws MobyException {
- return (String)doCall ("retrieveServiceTypes",
- new Object[] {});
- }
-
- // but be aware that the created MobyServiceTypes are not complete
- // - they do not have the relationship information; that's why
- // this method is not public; the full service types are available
- // from CentralDigest implementations
- protected MobyServiceType[] createServiceTypesFromXML (String result)
- throws MobyException {
-
- // parse returned XML
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getElementsByTagName ("serviceType");
- if (list == null || list.getLength() == 0)
- return new MobyServiceType[] {};
- MobyServiceType[] results = new MobyServiceType [list.getLength()];
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- MobyServiceType st = new MobyServiceType (elem.getAttribute ("name"));
- st.setLSID (elem.getAttribute ("lsid"));
- st.setDescription (getFirstValue (elem.getElementsByTagName ("Description")));
- st.setEmailContact (getFirstValue (elem.getElementsByTagName ("contactEmail")));
- st.setAuthority (getFirstValue (elem.getElementsByTagName ("authURI")));
- results[i] = st;
- }
- java.util.Arrays.sort (results);
- return results;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- * <Namespaces>
- * <Namespace name="namespace" lsid="...">
- * <Description><![CDATA[free text description here]]></Description>
- * <contactEmail>...</contactEmail>
- * <authURI>...</authURI>
- * </Namespace>
- * ...
- * ...
- * </Namespaces>
- * </pre>
- *************************************************************************/
- public MobyNamespace[] getFullNamespaces()
- throws MobyException {
-
- String result = getNamespacesAsXML();
- return createNamespacesFromXML (result);
- }
-
- //
- protected String getNamespacesAsXML()
- throws MobyException {
- return (String)doCall ("retrieveNamespaces",
- new Object[] {});
- }
-
- //
- protected MobyNamespace[] createNamespacesFromXML (String result)
- throws MobyException {
-
- // parse returned XML
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getDocumentElement().getElementsByTagName ("Namespace");
- if (list == null || list.getLength() == 0) {
- return new MobyNamespace[] {};
- }
- MobyNamespace[] results = new MobyNamespace [list.getLength()];
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- MobyNamespace nm = new MobyNamespace (elem.getAttribute ("name"));
- nm.setLSID (elem.getAttribute ("lsid"));
- nm.setDescription (getFirstValue (elem.getElementsByTagName ("Description")));
- nm.setEmailContact (getFirstValue (elem.getElementsByTagName ("contactEmail")));
- nm.setAuthority (getFirstValue (elem.getElementsByTagName ("authURI")));
- results[i] = nm;
- }
-
- java.util.Arrays.sort (results);
- return results;
- }
-
- /**************************************************************************
- *
- * @deprecated Replaced by {@link #getFullNamespaces} that gives
- * more information for the same price. <p>
- *************************************************************************/
- public Map getNamespaces()
- throws MobyException {
-
- Map results = new TreeMap (getStringComparator());
- MobyNamespace[] namespaces = getFullNamespaces();
- for (int i = 0; i < namespaces.length; i++) {
- results.put (namespaces[i].getName(),
- namespaces[i].getDescription());
- }
- return results;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- * <objectNames>
- * <Object name="objectName" lsid="...">
- * <Description><![CDATA[free text description here]]></Description>
- * </Object>
- * ...
- * ...
- * </objectNames>
- * </pre>
- *************************************************************************/
- public Map getDataTypeNames()
- throws MobyException {
- String result = getDataTypeNamesAsXML();
- return createDataTypeNamesFromXML (result, true);
- }
-
- //
- protected String getDataTypeNamesAsXML()
- throws MobyException {
- return (String)doCall ("retrieveObjectNames",
- new Object[] {});
- }
-
- // if onlyNames == true
- // Map: data type name -> description (String)
- // else
- // Map: data type name -> MobyDataType[]
- // (filled with name, description, and lsid)
- protected Map createDataTypeNamesFromXML (String result,
- boolean onlyNames)
- throws MobyException {
-
- // parse returned XML
- Map results = new TreeMap (getStringComparator());
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getElementsByTagName ("Object");
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- String name = elem.getAttribute ("name");
- if (name == null)
- continue; // ignore no-named data types
- String desc = "";
- NodeList children = elem.getChildNodes();
- for (int j = 0; j < children.getLength(); j++) {
- if (children.item (j).getNodeName().equals ("Description")) {
- desc = getFirstValue (children.item (j));
- break;
- }
- }
- if (onlyNames) {
- results.put (name, desc);
- } else {
- MobyDataType dt = new MobyDataType (name);
- dt.setDescription (desc);
- dt.setLSID (elem.getAttribute ("lsid"));
- results.put (name, dt);
- }
- }
- return results;
- }
-
-
- /**************************************************************************
- * Parses and imports the following XML. An example:
- *
- * <pre>
- * <retrieveObjectDefinition>
- * <objectType lsid="...">go_term</objectType>
- * <Description><![CDATA[A very lightweight object holding a GO term name and its definition]]></Description>
- * <authURI>http://www.illuminae.com</authURI>
- * <contactEmail>markw at illuminae.com</contactEmail>
- * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:isa'>
- * <objectType articleName=''>urn:lsid:biomoby.org:objectclass:object</objectType>
- * </Relationship>
- * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:hasa'>
- * <objectType articleName='Term'>urn:lsid:biomoby.org:objectclass:string</objectType>
- * <objectType articleName='Definition'>urn:lsid:biomoby.org:objectclass:string</objectType>
- * </Relationship>
- * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:has'>
- * <objectType articleName='Problems'>urn:lsid:biomoby.org:objectclass:string</objectType>
- * <objectType articleName='Issues'>urn:lsid:biomoby.org:objectclass:string</objectType>
- * </Relationship>
- * </retrieveObjectDefinition>
- * </pre>
- *************************************************************************/
- public MobyDataType getDataType (String dataTypeName)
- throws MobyException, NoSuccessException {
-
- String result = getDataTypeAsXML (dataTypeName);
- return createDataTypeFromXML (result, dataTypeName);
- }
-
- public MobyDataType[] getDataTypes()
- throws MobyException, NoSuccessException {
- Map<String,String> datatypeMap = getDataTypeNames();
- MobyDataType[] datatypes = new MobyDataType[datatypeMap.size()];
- int i = 0;
- for(String dataTypeName: datatypeMap.keySet()){
- datatypes[i++] = getDataType(dataTypeName);
- }
- return datatypes;
- }
-
- protected String getDataTypeAsXML (String dataTypeName)
- throws MobyException, NoSuccessException {
-
- return (String)doCall ("retrieveObjectDefinition",
- new Object[] {
- "<retrieveObjectDefinition>" +
- "<objectType>" + dataTypeName + "</objectType>" +
- "</retrieveObjectDefinition>"
- });
- }
-
- protected MobyDataType createDataTypeFromXML (String xmlSource, String dataTypeName)
- throws MobyException, NoSuccessException {
-
- // parse returned XML
- Document document = loadDocument (new ByteArrayInputStream (xmlSource.getBytes()));
- NodeList list = document.getElementsByTagName ("retrieveObjectDefinition");
- if (list == null || list.getLength() == 0)
- throw new NoSuccessException ("Data Type name was not found.",
- dataTypeName);
- MobyDataType data = null;
- Element elem = (Element)list.item (0);
- NodeList children = elem.getChildNodes();
-
- // first find the "real" (LSID-ized) data type name
- for (int j = 0; j < children.getLength(); j++) {
- String nodeName = children.item (j).getNodeName();
- if (nodeName.equals ("objectType")) {
- data = new MobyDataType (getFirstValue (children.item (j)));
- data.setLSID ( ((Element)children.item (j) ).getAttribute ("lsid"));
- break;
- }
- }
-
- // if not found (unprobable) use the name given by the caller
- if (data == null)
- data = new MobyDataType (dataTypeName);
-
- // now fill the data type object with the rest of attributes
- for (int j = 0; j < children.getLength(); j++) {
- String nodeName = children.item (j).getNodeName();
- if (nodeName.equals ("Description")) {
- data.setDescription (getFirstValue (children.item (j)));
- } else if (nodeName.equals ("authURI")) {
- data.setAuthority (getFirstValue (children.item (j)));
- } else if (nodeName.equals ("contactEmail")) {
- data.setEmailContact (getFirstValue (children.item (j)));
- } else if (nodeName.equals ("Relationship")) {
- String relationshipType = ((Element)children.item (j)).getAttribute ("relationshipType");
- if (relationshipType.endsWith ("isa")) {
-
- NodeList parents = children.item (j).getChildNodes();
- for (int k = 0; k < parents.getLength(); k++) {
- if (parents.item (k).getNodeName().equals ("objectType")) {
- data.addParentName (getFirstValue (parents.item (k)));
- }
- }
- } else if (relationshipType.endsWith ("hasa")) {
-
- NodeList belows = children.item (j).getChildNodes();
- for (int k = 0; k < belows.getLength(); k++) {
- if (belows.item (k).getNodeName().equals ("objectType")) {
- data.addChild ( ((Element)belows.item (k)).getAttribute ("articleName"),
- getFirstValue (belows.item (k)),
- Central.iHASA );
- }
- }
- } else if (relationshipType.endsWith ("has")) {
-
- NodeList belows = children.item (j).getChildNodes();
- for (int k = 0; k < belows.getLength(); k++) {
- if (belows.item (k).getNodeName().equals ("objectType")) {
- data.addChild ( ((Element)belows.item (k)).getAttribute ("articleName"),
- belows.item (k).getFirstChild().getNodeValue(),
- Central.iHAS );
- }
- }
- }
- }
- }
- return data;
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public String getServiceWSDL (String serviceName)
- throws MobyException, NoSuccessException {
-
- Map names = getServiceNames();
-
- for (Iterator it = names.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry)it.next();
- if ( ((String)entry.getKey()).equals (serviceName) )
- return getServiceWSDL (serviceName, (String)entry.getValue());
- }
-
- throw new NoSuccessException ("Service not found.", serviceName);
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public String getServiceWSDL (String serviceName, String authority)
- throws MobyException, NoSuccessException {
-
- String cacheId = "getServiceWSDL" + serviceName + ":" + authority;
- String cachedResults = (String)getContents (cacheId);
- if (cachedResults != null)
- return cachedResults;
-
- String result =
- (String)doCall ("retrieveService",
- new Object[] {
- "<retrieveService>" +
- "<Service authURI=\"" + authority + "\" serviceName=\"" + serviceName + "\"/>" +
- "</retrieveService>"
- });
-
- // parse returned XML
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- Element service = document.getDocumentElement();
- Node wsdl = service.getFirstChild();
- if (wsdl == null)
- throw new NoSuccessException ("Service not found OR WSDL is not available.",
- serviceName + " (" + authority + ")");
-
- String results = wsdl.getNodeValue();
- setContents (cacheId, results);
- return results;
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public String getRegisterDataTypeXML (MobyDataType dataType) {
-
- // build the ISA tag (expressing hierarchy of data types)
- String[] names = dataType.getParentNames();
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < names.length; i++) {
- buf.append ("<objectType>");
- buf.append (names[i]);
- buf.append ("</objectType>");
- buf.append ("\n");
- }
-
- // build the HASA/HAS tags (expressing containments of data types)
- MobyRelationship[] children = dataType.getChildren();
- StringBuffer buf2 = new StringBuffer(); // for HASA
- StringBuffer buf3 = new StringBuffer(); // for HAS
- for (int i = 0; i < children.length; i++) {
- if (children[i].getRelationshipType() == Central.iHASA) {
- buf2.append ("<objectType articleName=\"");
- buf2.append (children[i].getName());
- buf2.append ("\">");
- buf2.append (children[i].getDataTypeName());
- buf2.append ("</objectType>");
- } else if (children[i].getRelationshipType() == Central.iHAS) {
- buf3.append ("<objectType articleName=\"");
- buf3.append (children[i].getName());
- buf3.append ("\">");
- buf3.append (children[i].getDataTypeName());
- buf3.append ("</objectType>");
- }
- }
-
- return
- "<registerObjectClass>" +
- "<objectType>" + dataType.getName() + "</objectType>" +
- "<Description><![CDATA[" + dataType.getDescription() + "]]>" +
- "</Description>" +
- "<Relationship relationshipType=\"ISA\">" + new String (buf) +
- "</Relationship>" +
- "<Relationship relationshipType=\"HASA\">" + new String (buf2) +
- "</Relationship>" +
- "<Relationship relationshipType=\"HAS\">" + new String (buf3) +
- "</Relationship>" +
- "<authURI>" + dataType.getAuthority() + "</authURI>" +
- "<contactEmail>" + dataType.getEmailContact() + "</contactEmail>" +
- "</registerObjectClass>";
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public void registerDataType (MobyDataType dataType)
- throws MobyException, NoSuccessException, PendingCurationException {
-
- String result =
- (String)doCall ("registerObjectClass",
- new Object[] { getRegisterDataTypeXML (dataType) });
- dataType.setId (checkRegistration (result, dataType)[0]);
- }
-
- /*************************************************************************
- * B
- *************************************************************************/
- public void unregisterDataType (MobyDataType dataType)
- throws MobyException, NoSuccessException, PendingCurationException {
- String result =
- (String)doCall ("deregisterObjectClass",
- new Object[] {
- "<deregisterObjectClass>" +
- "<objectType>" + dataType.getName() + "</objectType>" +
- "</deregisterObjectClass>"
- });
- checkRegistration (result, dataType);
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public String getRegisterServiceTypeXML (MobyServiceType serviceType) {
-
- // build the ISA tag (expressing hierarchy of service types)
- String[] names = serviceType.getParentNames();
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < names.length; i++) {
- buf.append ("<serviceType>");
- buf.append (names[i]);
- buf.append ("</serviceType>");
- buf.append ("\n");
- }
-
- return
- "<registerServiceType>" +
- "<serviceType>" + serviceType.getName() + "</serviceType>" +
- "<contactEmail>" + serviceType.getEmailContact() + "</contactEmail>" +
- "<authURI>" + serviceType.getAuthority() + "</authURI>" +
- "<Description><![CDATA[" + serviceType.getDescription() + "]]>" +
- "</Description>" +
- "<Relationship relationshipType=\"ISA\">" + new String (buf) +
- "</Relationship>" +
- "</registerServiceType>";
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public void registerServiceType (MobyServiceType serviceType)
- throws MobyException, NoSuccessException, PendingCurationException {
-
- String result =
- (String)doCall ("registerServiceType",
- new Object[] { getRegisterServiceTypeXML (serviceType) });
- serviceType.setId (checkRegistration (result, serviceType)[0]);
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public void unregisterServiceType (MobyServiceType serviceType)
- throws MobyException, NoSuccessException, PendingCurationException {
- String result =
- (String)doCall ("deregisterServiceType",
- new Object[] {
- "<deregisterServiceType>" +
- "<serviceType>" + serviceType.getName() + "</serviceType>" +
- "</deregisterServiceType>"
- });
- checkRegistration (result, serviceType);
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public String getRegisterNamespaceXML (MobyNamespace namespace) {
- return
- "<registerNamespace>" +
- "<namespaceType>" + namespace.getName() + "</namespaceType>" +
- "<contactEmail>" + namespace.getEmailContact() + "</contactEmail>" +
- "<authURI>" + namespace.getAuthority() + "</authURI>" +
- "<Description><![CDATA[" + namespace.getDescription() + "]]>" +
- "</Description>" +
- "</registerNamespace>";
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public void registerNamespace (MobyNamespace namespace)
- throws MobyException, NoSuccessException, PendingCurationException {
- String result =
- (String)doCall ("registerNamespace",
- new Object[] { getRegisterNamespaceXML (namespace) });
- namespace.setId (checkRegistration (result, namespace)[0]);
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public void unregisterNamespace (MobyNamespace namespace)
- throws MobyException, NoSuccessException, PendingCurationException {
- String result =
- (String)doCall ("deregisterNamespace",
- new Object[] {
- "<deregisterNamespace>" +
- "<namespaceType>" + namespace.getName() + "</namespaceType>" +
- "</deregisterNamespace>"
- });
- checkRegistration (result, namespace);
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public String getRegisterServiceXML (MobyService service) {
- return
- "<registerService>" +
- "<Category>" + service.getCategory() + "</Category>" +
- "<serviceName>" + service.getName() + "</serviceName>" +
- "<serviceType>" + service.getType() + "</serviceType>" +
- "<serviceLSID>" + (service.getLSID() == null ? "" : service.getLSID().trim() )+ "</serviceLSID>" +
- "<authURI>" + service.getAuthority() + "</authURI>" +
- "<signatureURL>" + escapeXML (service.getSignatureURL()) + "</signatureURL>" +
- "<URL>" + escapeXML (service.getURL()) + "</URL>" +
- "<contactEmail>" + service.getEmailContact() + "</contactEmail>" +
- "<authoritativeService>" + (service.isAuthoritative() ? "1" : "0") + "</authoritativeService>" +
- "<Description><![CDATA[" + service.getDescription() + "]]>" +
- "</Description>" +
- buildPrimaryInputTag (service) +
- buildSecondaryInputTag (service) +
- buildOutputTag (service) +
- "</registerService>";
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public void registerService (MobyService service)
- throws MobyException, NoSuccessException, PendingCurationException {
-
- String result =
- (String)doCall ("registerService",
- new Object[] { getRegisterServiceXML (service) });
- String[] registered = checkRegistration (result, service);
- service.setId (registered [0]);
- service.setRDF (registered [1]);
- String pathToRDF = service.getPathToRDF();
- if ( ! pathToRDF.equals ("") ) {
- File fileRDF = new File (pathToRDF);
- try {
- PrintStream fileout = new PrintStream (new FileOutputStream (fileRDF));
- fileout.println (registered [1]);
- fileout.close();
- } catch (IOException e) {
- StringBuffer buf = new StringBuffer (100);
- buf.append ("Failed to save RDF in '");
- buf.append (fileRDF.getAbsolutePath() + "'. ");
- buf.append (e.toString());
- try {
- File tmpFile = File.createTempFile (service.getName() + "-", ".rdf");
- PrintStream fileout = new PrintStream (new FileOutputStream (tmpFile));
- fileout.println (registered [1]);
- fileout.close();
- buf.append ("\nReturned RDF file was therefore stored in: ");
- buf.append (tmpFile.getAbsolutePath());
- } catch (IOException e2) {
- buf.append ("\nEven saving in a temporary file failed: ");
- buf.append (e2.toString());
- }
- throw new MobyException (buf.toString());
- }
- }
- }
-
- /*************************************************************************
- *
- *************************************************************************/
- public void unregisterService (MobyService service)
- throws MobyException, NoSuccessException, PendingCurationException {
- String result =
- (String)doCall ("deregisterService",
- new Object[] {
- "<deregisterService>" +
- "<authURI>" + service.getAuthority() + "</authURI>" +
- "<serviceName>" + service.getName() + "</serviceName>" +
- "</deregisterService>"
- });
- checkRegistration (result, service);
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public MobyService[] findService (String serviceType)
- throws MobyException {
- if (serviceType == null)
- return new MobyService[] {};
- MobyService pattern = new MobyService ("dummy");
- pattern.setCategory ("");
- pattern.setType (serviceType);
- return findService (pattern, null);
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public MobyService[] findService (String[] keywords)
- throws MobyException {
- if (keywords == null)
- return new MobyService[] {};
- return findService (null, keywords);
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public MobyService[] findService (MobyService pattern)
- throws MobyException {
- if (pattern == null)
- return new MobyService[] {};
- return findService (pattern, null);
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public MobyService[] findService (MobyService pattern, String[] keywords)
- throws MobyException {
- return findService (pattern, keywords, true, true);
- }
-
- /**************************************************************************
- * All 'findService' methods end up here.
- *************************************************************************/
- public MobyService[] findService (MobyService pattern, String[] keywords,
- boolean includeChildrenServiceTypes,
- boolean includeParentDataTypes)
- throws MobyException {
- if (pattern == null) {
- pattern = new MobyService ("dummy");
- pattern.setCategory ("");
- }
-
- String result =
- getServicesAsXML (pattern, keywords, includeChildrenServiceTypes, includeParentDataTypes);
- MobyService[] services = extractServices (result);
- return services;
- }
-
- // ...actually all 'findService' methods end up here
- protected String getServicesAsXML (MobyService pattern, String[] keywords,
- boolean includeChildrenServiceTypes,
- boolean includeParentDataTypes)
- throws MobyException {
- String[] query = new String[] {
- "<findService>" +
- buildQueryObject (pattern, keywords,
- includeParentDataTypes,
- includeChildrenServiceTypes,
- false) +
- "</findService>"
- };
- return (String)doCall ("findService", query);
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public String call (String methodName, String inputXML)
- throws MobyException {
- Object result;
- if (inputXML == null || inputXML.equals (""))
- result = doCall (methodName, new Object[] { });
- else
- result = doCall (methodName, new Object[] { inputXML });
- return (String)result;
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- protected static String resultToString (Object result)
- throws MobyException {
- if (result == null)
- throw new MobyException ("Returned result is null.");
- if (result instanceof String)
- return (String)result;
- if (result instanceof String[]) {
- String[] tmp = (String[])result;
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < tmp.length; i++)
- buf.append (tmp[i]);
- return new String (buf);
- }
- if (result instanceof byte[])
- return new String ((byte[])result);
-
- throw new MobyException ("Unknown type of result: " + result.getClass().getName());
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public boolean setDebug (boolean enabled) {
- boolean oldMode = debug;
- debug = enabled;
- return oldMode;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- * <Relationships>
- * <Relationship relationshipType='urn:lsid:biomoby.org:servicerelation:isa'>
- * <serviceType>urn:lsid:biomoby.org:servicetype:analysis</serviceType>
- * <serviceType>urn:lsid:biomoby.org:servicetype:service</serviceType>
- * </Relationship>
- * </Relationships>
- * </pre>
- *************************************************************************/
- public String[] getServiceTypeRelationships (String serviceTypeName,
- boolean expand)
- throws MobyException {
- String result = getServiceTypeRelationshipsAsXML (serviceTypeName, expand);
- return createServiceTypeRelationshipsFromXML (result);
- }
-
- //
- protected String getServiceTypeRelationshipsAsXML (String serviceTypeName,
- boolean expand)
- throws MobyException {
- return
- (String)doCall ("Relationships",
- new Object[] {
- "<Relationship>" +
- "<serviceType>" + serviceTypeName + "</serviceType>" +
- "<relationshipType>" + Central.ISA + "</relationshipType>" +
- "<expandRelationship>" + (expand ? "1" : "0") + "</expandRelationship>" +
- "</Relationship>"
- });
- }
-
- //
- protected String[] createServiceTypeRelationshipsFromXML (String result)
- throws MobyException {
-
- // parse returned XML
- Vector<String> v = new Vector<String>();
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getElementsByTagName ("Relationship");
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- NodeList children = elem.getChildNodes();
- for (int j = 0; j < children.getLength(); j++) {
- if (children.item (j).getNodeName().equals ("serviceType")) {
- v.addElement (getFirstValue (children.item (j)));
- }
- }
- }
- String[] results = new String [v.size()];
- v.copyInto (results);
- return results;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- *<Relationships>
- * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:isa'>
- * <objectType>urn:lsid:biomoby.org:objectclass:virtualsequence</objectType>
- * <objectType>urn:lsid:biomoby.org:objectclass:object</objectType>
- * </Relationship>
- * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:hasa'>
- * <objectType>urn:lsid:biomoby.org:objectclass:string</objectType>
- * <objectType>urn:lsid:biomoby.org:objectclass:integer</objectType>
- * </Relationship>
- *</Relationships>
- * </pre>
- *
- * Added at Sun Feb 19 19:32:31 PHT 2006: it recognizes also an
- * attributes 'lsid' and 'articleName' in <objectType> element.
- *************************************************************************/
- public Map getDataTypeRelationships (String dataTypeName)
- throws MobyException {
-
- String cacheId = "getDataTypeRelationships_" + dataTypeName;
- Map cachedResults = (Map)getContents (cacheId);
- if (cachedResults != null)
- return cachedResults;
-
- String result =
- (String)doCall ("Relationships",
- new Object[] {
- "<Relationships>" +
- "<objectType>" + dataTypeName + "</objectType>" +
- "<relationshipType>" + Central.ISA + "</relationshipType>" +
- "<relationshipType>" + Central.HASA + "</relationshipType>" +
- "<relationshipType>" + Central.HAS + "</relationshipType>" +
- "<expandRelationship>1</expandRelationship>" +
- "</Relationships>"
- });
-
- // parse returned XML
- Map results = new HashMap();
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getElementsByTagName ("Relationship");
-
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- String relType = elem.getAttribute ("relationshipType");
- NodeList children = elem.getChildNodes();
- Vector<String> v = new Vector<String>();
- for (int j = 0; j < children.getLength(); j++) {
- if (children.item (j).getNodeName().equals ("objectType")) {
- v.addElement (getFirstValue (children.item (j)));
- }
- }
- String[] names = new String [v.size()];
- v.copyInto (names);
- results.put (relType, names);
- }
-
- setContents (cacheId, results);
- return results;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- *<Relationships>
- * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:isa'>
- * <objectType>urn:lsid:biomoby.org:objectclass:virtualsequence</objectType>
- * <objectType>urn:lsid:biomoby.org:objectclass:object</objectType>
- * </Relationship>
- *</Relationships>
- * </pre>
- *************************************************************************/
- public String[] getDataTypeRelationships (String dataTypeName,
- String relationshipType)
- throws MobyException {
-
- String cacheId = "getDataTypeRelationships_" + dataTypeName + ":" + relationshipType;
- String[] cachedResults = (String[])getContents (cacheId);
- if (cachedResults != null)
- return cachedResults;
-
- String result =
- (String)doCall ("Relationships",
- new Object[] {
- "<Relationships>" +
- "<objectType>" + dataTypeName + "</objectType>" +
- "<relationshipType>" + relationshipType + "</relationshipType>" +
- "<expandRelationship>1</expandRelationship>" +
- "</Relationships>"
- });
-
- // parse returned XML
- Vector<String> v = new Vector<String>();
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getElementsByTagName ("Relationship");
-
- // it should always be just one element in this list
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- NodeList children = elem.getChildNodes();
- for (int j = 0; j < children.getLength(); j++) {
- if (children.item (j).getNodeName().equals ("objectType")) {
- v.addElement (getFirstValue (children.item (j)));
- }
- }
- }
- String[] results = new String [v.size()];
- v.copyInto (results);
-
- setContents (cacheId, results);
- return results;
- }
-
-// /**************************************************************************
-// *
-// *************************************************************************/
-// public MobyRelationship[] getRelationships (String dataTypeName)
-// throws MobyException {
-// return null;
-// }
-
-
- /**************************************************************************
- *
- *************************************************************************/
- public String getRegistryEndpoint() {
- return endpoint.toString();
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public String getRegistryNamespace() {
- return uri;
- }
-
- /**************************************************************************
- * Parses and imports the following XML.
- * <pre>
- * <resourceURLs>
- * <Resource name="Service" url="..." />
- * <Resource name="Object" url="..." />
- * <Resource name="Namespace" url="..." />
- * <Resource name="ServiceInstance" url="..." />
- * <Resource name="Full" url="..." />
- * </resourceURLs>
- * </pre>
- *************************************************************************/
- public MobyResourceRef[] getResourceRefs()
- throws MobyException {
-
- String cacheId = "retrieveResourceURLs";
- MobyResourceRef[] cachedResults = (MobyResourceRef[])getContents (cacheId);
- if (cachedResults != null)
- return cachedResults;
-
- String result = (String)doCall ("retrieveResourceURLs",
- new Object[] {});
-
- // parse returned XML
- Vector<MobyResourceRef> v = new Vector<MobyResourceRef>();
- Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
- NodeList list = document.getElementsByTagName ("Resource");
- for (int i = 0; i < list.getLength(); i++) {
- Element elem = (Element)list.item (i);
- try {
- v.addElement
- (new MobyResourceRef (elem.getAttribute ("name"),
- new URL ((String)elem.getAttribute ("url")),
- elem.getAttribute ("type")));
- } catch (MalformedURLException e2) {
- if (debug)
- System.err.println ("Bad URL: " + elem.getAttribute ("url"));
- }
- }
-
- MobyResourceRef[] results = new MobyResourceRef [v.size()];
- v.copyInto (results);
-
- // Add this data to the cache in case we get called again
- setContents (cacheId, results);
-
- return results;
- }
-
- /**************************************************************************
- *
- *************************************************************************/
- public InputStream getResource (String resourceName)
- throws MobyException {
-
- MobyResourceRef[] resourceRefs = getResourceRefs();
- for (int i = 0; i < resourceRefs.length; i++) {
- if (resourceName.equalsIgnoreCase (resourceRefs[i].getResourceName())) {
- return Utils.getInputStream (resourceRefs[i].getResourceLocation());
- }
- }
- throw new MobyException ("No resource found for '" + resourceName + "'.");
- }
-
- /**************************************************************************
- * Return a case-insensitive comparator of Strings. It is used to
- * create various TreeMaps where keys are strings.
- *************************************************************************/
- protected static Comparator getStringComparator() {
- return new Comparator() {
- public int compare (Object o1, Object o2) {
- return ((String)o1).compareToIgnoreCase ((String)o2);
- }
- };
- }
-
- // cache URL/URI so we only check once
- private static String CHECKED_URL = null;
- private static String CHECKED_URI = null;
-
- /**
- * Using this method to get a Central object will ensure that other parts of the org.biomoby.shared
- * class hierarchy that implicitly check the registry will use the same cache. Otherwise, methods
- * such as MobyNamespace.getNamespace() must be passed a Central object parameter as well.
- *
- * @return a CentralImpl using the default Central URI, and currently a class implementing a caching mechanism
- */
- public static CentralImpl getDefaultCentral() throws MobyException{
- return getDefaultCentral(null);
- }
-
- public static CentralImpl getDefaultCentral(Registry reg) throws MobyException{
- if(reg == null && defaultCentrals.containsKey("")){
- return defaultCentrals.get("");
- }
- else if(reg != null && defaultCentrals.containsKey(reg.getEndpoint())){
- return defaultCentrals.get(reg.getEndpoint());
- }
-
- String className = DEFAULT_CENTRAL_IMPL_CLASSNAME;
- ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
- URL resURL = classLoader.getResource("META-INF/"+CENTRAL_IMPL_RESOURCE_NAME);
- if(resURL != null){
- System.err.println("Loading "+resURL);
- try{
- LineNumberReader reader = new LineNumberReader(new InputStreamReader(resURL.openStream()));
- for(String line = reader.readLine(); line != null; line = reader.readLine()){
- if(!line.trim().startsWith("#")){
- className = line.trim();
- break;
- }
- }
- } catch(Exception e){
- logger.log(Level.WARNING,
- "Error reading " + resURL,
- e);
- }
- }
- try{
- System.err.println("Central class is "+className);
- Class clazz = Class.forName(className);
- if(reg == null){ // should use default nullary c-tor
- defaultCentrals.put("", (CentralImpl) clazz.newInstance());
- }
- else{ // should have (String endpoint, String namespace) c-tor
- for(Constructor ctor: clazz.getDeclaredConstructors()){
- Class[] params = ctor.getParameterTypes();
- if(params.length == 2 && params[0].getName().equals("java.lang.String") &&
- params[1].getName().equals("java.lang.String") ){
- defaultCentrals.put(reg.getEndpoint(),
- (CentralImpl) ctor.newInstance(reg.getEndpoint(), reg.getNamespace()));
- break;
- }
- }
- if(!defaultCentrals.containsKey(reg.getEndpoint())){
- logger.log(Level.WARNING,
- "Could not find required (String endpoint, String namespace)" +
- "constructor for class " + className);
- }
- }
- } catch(Exception e){
- logger.log(Level.WARNING,
- "Could not load class " + className,
- e);
- if(reg == null){
- defaultCentrals.put("", new CentralImpl()); //fallback to this class, no caching, etc.
- }
- else{
- defaultCentrals.put(reg.getEndpoint(),
- new CentralImpl(reg.getEndpoint(), reg.getNamespace()));
- }
- }
-
- return defaultCentrals.get(reg == null ? "" : reg.getEndpoint());
- }
-
- /**
- *
- * @return a String representing the Default mobycentral endpoint. If the
- * system property 'moby.check.default' exists and is set to true,
- * then the URL http://biomoby.org/mobycentral is queried and the
- * default central endpoint is returned, otherwise DEFAULT_ENDPOINT
- * is returned.
- */
- public static String getDefaultURL() {
- boolean check = false;
- try {
- check = Boolean.getBoolean("moby.check.default");
- } catch (Exception e) {
-
- }
-
- if (check) {
- // return the last checked url if we have done this before
- if (CHECKED_URL != null && CHECKED_URL.trim() != "") {
- return CHECKED_URL;
- }
-
- // create a HttpClient object
- HttpClient client = new HttpClient();
- // set up the Head method
- HeadMethod method = new HeadMethod("http://biomoby.org/mobycentral");
- // do not follow redirects or we will get a 411 error
- method.setFollowRedirects(false);
- // retry 3 times
- method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler(3, false));
- // set the user agent ... should probably make this something more reasonable
- method.getParams().setParameter(HttpMethodParams.USER_AGENT,"jMoby/1.0");
- try {
- // Execute the method.
- int statusCode = client.executeMethod(method);
-
- if (statusCode != HttpStatus.SC_MOVED_PERMANENTLY) {
- System.err.println("Method failed: "
- + method.getStatusLine());
- } else {
- try {
- String location = method.getResponseHeader("location").getValue();
- CHECKED_URL = location;
- try {
- CHECKED_URI = "http://" + (new URL(CHECKED_URL).getAuthority()) + "/MOBY/Central";
- } catch (MalformedURLException murle ) {
- CHECKED_URI = DEFAULT_NAMESPACE;
- }
- return CHECKED_URL;
- } catch (NullPointerException npe) {
- return DEFAULT_ENDPOINT;
- }
- }
- } catch (HttpException e) {
- System.err.println("Fatal protocol violation: "
- + e.getMessage());
- e.printStackTrace();
- } catch (IOException e) {
- System.err.println("Fatal transport error: " + e.getMessage());
- e.printStackTrace();
- } finally {
- // Release the connection.
- method.releaseConnection();
- }
-
- } else {
- return DEFAULT_ENDPOINT;
- }
- return DEFAULT_ENDPOINT;
- }
-
- /**
- *
- * @return a String representing the default mobycentral uri. If the
- * system property 'moby.check.default' exists and is set to true,
- * then the URL http://biomoby.org/mobycentral is queried and the
- * default central namespace is returned, otherwise DEFAULT_NAMESPACE
- * is returned.
- */
- public static String getDefaultURI() {
- boolean check = false;
- try {
- check = Boolean.getBoolean("moby.check.default");
- } catch (Exception e) {
-
- }
- if (check) {
- if (CHECKED_URI != null && CHECKED_URI.trim() != "") {
- return CHECKED_URI;
- }
- // need to check ...
- getDefaultURL();
- return CHECKED_URI;
- } else {
- return DEFAULT_NAMESPACE;
- }
- }
- /**************************************************************************
- * Convert non-suitable characters in a XML string into their
- * entity references. <p>
- *
- * <em>Adapted from jDom.</em>
- *
- * @param str input to be converted
- * @return If there were any non-suitable characters, return a new
- * string with those characters escaped, otherwise return the
- * unmodified input string
- *
- *************************************************************************/
- public String escapeXML (String str) {
- StringBuffer buffer = null;
- char ch;
- String entity;
- for (int i = 0; i < str.length(); i++) {
- ch = str.charAt (i);
- switch (ch) {
- case '<' :
- entity = "<";
- break;
- case '>' :
- entity = ">";
- break;
- case '&' :
- entity = "&";
- break;
- default :
- entity = null;
- break;
- }
- if (buffer == null) {
- if (entity != null) {
- // An entity occurred, so we'll have to use StringBuffer
- // (allocate room for it plus a few more entities).
- buffer = new StringBuffer (str.length() + 20);
- // Copy previous skipped characters and fall through
- // to pickup current character
- buffer.append (str.substring (0, i));
- buffer.append (entity);
- }
- } else {
- if (entity == null) {
- buffer.append (ch);
- } else {
- buffer.append (entity);
- }
- }
- }
-
- // If there were any entities, return the escaped characters
- // that we put in the StringBuffer. Otherwise, just return
- // the unmodified input string.
- return (buffer == null) ? str : buffer.toString();
- }
-
- /*************************************************************************
- * Format an exception.
- *************************************************************************/
- public static String formatFault (AxisFault e, String endpoint, QName method) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- formatFault (e, new PrintStream (baos), endpoint, method);
- return baos.toString();
- }
-
- /*************************************************************************
- * Format an exception.
- *************************************************************************/
- public static void formatFault (AxisFault e, PrintStream out,
- String endpoint, QName method) {
-
- out.println ("===ERROR===");
- out.println ("Fault details:");
- // for some obvious errors I do not print all details (with a lenghty trace stack)
- String faultString = e.getFaultString();
- if ( (! faultString.startsWith ("java.net.ConnectException")) &&
- (faultString.indexOf ("Could not find class for the service named:") == -1)
- ) {
- org.w3c.dom.Element[] details = e.getFaultDetails();
- for (int i = 0; i < details.length; i++) {
- String s = details[i].toString().replaceAll ("<", "<");
- s = s.replaceAll (">", ">");
- out.println (s);
- }
- }
- out.println ("Fault string: " + faultString);
- out.println ("Fault code: " + e.getFaultCode());
- out.println ("Fault actor: " + e.getFaultActor());
- if (endpoint != null || method != null)
- out.println ("When calling:");
- if (endpoint != null)
- out.println ("\t" + endpoint);
- if (method != null)
- out.println ("\t" + method);
- out.println ("===========");
- }
-
-
-}
+// CentralImpl.java
+// A default client to the Moby Central service.
+//
+// senger at ebi.ac.uk
+// February 2003
+//
+
+package org.biomoby.client;
+
+import org.biomoby.registry.meta.Registry;
+import org.biomoby.shared.Central;
+import org.biomoby.shared.MobyData;
+import org.biomoby.shared.MobyDataType;
+import org.biomoby.shared.MobyException;
+import org.biomoby.shared.MobyNamespace;
+import org.biomoby.shared.MobyPrimaryDataSet;
+import org.biomoby.shared.MobyPrimaryDataSimple;
+import org.biomoby.shared.MobyRelationship;
+import org.biomoby.shared.MobySecondaryData;
+import org.biomoby.shared.MobyService;
+import org.biomoby.shared.MobyServiceType;
+import org.biomoby.shared.NoSuccessException;
+import org.biomoby.shared.PendingCurationException;
+import org.biomoby.shared.MobyResourceRef;
+import org.biomoby.shared.Utils;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.namespace.QName;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import org.apache.axis.AxisFault;
+import org.apache.axis.client.Call;
+import org.apache.axis.client.Service;
+import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.methods.HeadMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.io.PrintStream;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.TreeMap;
+import java.util.Comparator;
+import java.util.zip.GZIPInputStream;
+import java.util.logging.*;
+
+/**
+ * A default implementation of the
+ * interface {@link org.biomoby.shared.Central Central}
+ * allowing access to a Moby registry.
+ *<p>
+ * This class is supposed to be used by all other clients that wish
+ * to communicate with the Moby Registry, but do not want to know
+ * about all XML details that are necessary for talking with the Moby Central
+ * directly. This is an example of a client program:
+ *<pre>
+ * import org.biomoby.shared.Central;
+ * import org.biomoby.shared.MobyException;
+ * import org.biomoby.client.CentralImpl;
+ * import java.util.Map;
+ * import java.util.Iterator;
+ *
+ * public class Test {
+ *
+ * public static void main (String[] args)
+ * throws MobyException {
+ *
+ * Central worker = new CentralImpl();
+ * Map authorities = worker.getServiceNamesByAuthority();
+ *
+ * for (Iterator it = authorities.entrySet().iterator(); it.hasNext(); ) {
+ * Map.Entry entry = (Map.Entry)it.next();
+ * System.out.println (entry.getKey());
+ * String[] names = (String[])entry.getValue();
+ * for (int i = 0; i < names.length; i++)
+ * System.out.println ("\t" + names[i]);
+ * }
+ * }
+ * }
+ *</pre>
+ *
+ * @author <A HREF="mailto:senger at ebi.ac.uk">Martin Senger</A>
+ * @version $Id$
+ */
+
+public class CentralImpl
+ implements Central, SimpleCache {
+
+ private URL endpoint;
+ private String uri;
+ protected boolean debug = false;
+
+ /** Common central used to if getDefaultCentral() is called */
+ protected static Map<String,CentralImpl> defaultCentrals = new HashMap<String,CentralImpl>();
+
+ /** Default location (endpoint) of a Moby registry. */
+ public static final String DEFAULT_ENDPOINT = "http://moby.ucalgary.ca/moby/MOBY-Central.pl";
+
+ /** Default namespace used by the contacted Moby registry. */
+ public static final String DEFAULT_NAMESPACE = "http://moby.ucalgary.ca/MOBY/Central";
+
+ /**
+ * The META-INF resource file that will be checked to determine what
+ * default class should be instantiated in order to create a Central Implementation
+ * when getDefaultCentral() is called.
+ */
+ public static final String CENTRAL_IMPL_RESOURCE_NAME = "org.biomoby.shared.CentralDefaultImpl";
+ /** The class to use for getDefaultCentral if all else fails */
+ public static final String DEFAULT_CENTRAL_IMPL_CLASSNAME = "org.biomoby.client.CentralDigestCachedImpl";
+ private static Logger logger = Logger.getLogger("org.biomoby.client.CentralImpl");
+
+ /**
+ * Thread local that gives each thread its own
+ * DocumentBuilderFactory (since it is not thread-safe). Code taken
+ * from Apache's JaxpUtils.
+ */
+ public static ThreadLocal DOCUMENT_BUILDER_FACTORIES = new ThreadLocal() {
+ protected synchronized Object initialValue() {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware (true);
+ return dbf;
+ }
+ };
+
+
+ /*************************************************************************
+ * Default constructor. It connects to a default Moby registry
+ * (as defined in {@link #DEFAULT_ENDPOINT}) using a default namespace
+ * (as defined int {@link #DEFAULT_NAMESPACE}).
+ *************************************************************************/
+ public CentralImpl()
+ throws MobyException {
+ this (DEFAULT_ENDPOINT, DEFAULT_NAMESPACE);
+ }
+
+ /*************************************************************************
+ * Constructor allowing to specify which Moby Registry to use.
+ *
+ * @throws MobyException if 'endpoint' is not a valid URL, or if no
+ * DOM parser is available
+ *************************************************************************/
+ public CentralImpl (String endpoint)
+ throws MobyException {
+ this (endpoint, DEFAULT_NAMESPACE);
+ }
+
+ /*************************************************************************
+ * Constructor allowing to specify which Moby Registry and what
+ * namespace to use. If any of the parameters is null, its default
+ * value is used instead.
+ *<p>
+ * @throws MobyException if 'endpoint' is not a valid URL, or if no
+ * DOM parser was found
+ *************************************************************************/
+ public CentralImpl (String endpoint, String namespace)
+ throws MobyException {
+
+ if (endpoint == null || "".equals (endpoint.trim()))
+ endpoint = DEFAULT_ENDPOINT;
+ if (namespace == null || "".equals (namespace.trim()))
+ namespace = DEFAULT_NAMESPACE;
+
+ try {
+ this.endpoint = new URL (endpoint);
+ } catch (MalformedURLException e) {
+ throw new MobyException ("Bad URL: " + endpoint);
+ }
+ this.uri = namespace;
+
+ cache = new Hashtable<String,Object>();
+ useCache = true;
+ }
+
+ /*************************************************************************
+ * Loads a DOM Document from an InputStream. Uses thread-safe
+ * mechanism.
+ *************************************************************************/
+ public static Document loadDocument (InputStream input)
+ throws MobyException {
+ try {
+ DocumentBuilderFactory dbf
+ = (DocumentBuilderFactory)DOCUMENT_BUILDER_FACTORIES.get();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ return (db.parse (input));
+ } catch (Exception e) {
+ throw new MobyException ("Problem with reading XML input: " + e.toString(), e);
+ }
+ }
+
+ /*************************************************************************
+ * Call 'method' with 'parameters' and return its result.
+ *************************************************************************/
+ protected Object doCall (String method, Object[] parameters)
+ throws MobyException {
+
+ Call call = null;
+ try {
+ Service service = new Service();
+ call = (Call) service.createCall();
+ call.setTargetEndpointAddress (endpoint);
+ call.setTimeout (new Integer (0));
+
+ call.setSOAPActionURI (uri + "#" + method);
+
+ if (debug) {
+ System.err.println ("METHOD CALL: " + method);
+ System.err.println ("------------");
+ if (parameters.length > 0)
+ System.err.println (parameters[0] + "\n");
+ System.err.println ("------------\n");
+
+ Object result = call.invoke (uri, method, parameters);
+
+ System.err.println ("METHOD RETURN:");
+ System.err.println ("------------");
+ if (result != null)
+ System.err.println (result + "\n");
+ System.err.println ("------------\n");
+
+ return resultToString (result);
+
+ } else {
+ return resultToString (call.invoke (uri, method, parameters));
+ }
+
+ } catch (AxisFault e) {
+ throw new MobyException
+ (formatFault (e,
+ endpoint.toString(),
+ (call == null ? null : call.getOperationName())),
+ e);
+// (endpoint.toString()+(call == null ? "" : call.getOperationName()), e);
+
+ } catch (Exception e) {
+ throw new MobyException (e.toString(), e);
+// e.printStackTrace();
+ }
+ }
+
+
+ /**************************************************************************
+ * Parse the given XML sniplet to find tag 'success'. If it has value '1'
+ * look further for tag 'id' and return it back (or return an empty string
+ * if ID is not there). Otherwise raise an exception with the 'culprit'
+ * and with the message from the tag 'message'. <p>
+ *
+ * The return value is a two-element long array. The first element
+ * is the ID (given by BioMobe registry), and the second element
+ * is RDF corresponding with the registered object (BioMoby
+ * returns this only for service instances, so for other objects
+ * this will be null). <p>
+ *
+ * This is how the XML is supposed to look:
+ * <MOBYRegistration>
+ * <success> <!-- 1 | 0 | -1 --> </success>
+ * <id> <!-- some id number for your registration --> </id>
+ * <message> <![CDATA[message here]]> </message>
+ * <RDF> <!-- RDF of your service instance here (if applicable) --> </RDF>
+ * </MOBYRegistration>
+ *
+ * Success takes the value "1" to indicate success, "0" to
+ * indicate failure, and "-1" to indicate "Pending Curation".
+ *************************************************************************/
+ protected String[] checkRegistration (String xml, Object culprit)
+ throws MobyException, NoSuccessException, PendingCurationException {
+
+ String id = "", success = "0", message = "", rdf = "";
+
+ // parse returned XML
+ Document document = loadDocument (new ByteArrayInputStream (xml.getBytes()));
+ Element root = document.getDocumentElement();
+
+ NodeList children = root.getChildNodes();
+ for (int i = 0; i < children.getLength(); i++) {
+ if (children.item (i).getNodeType() != Node.ELEMENT_NODE)
+ continue;
+ Element elem = (Element)children.item (i);
+ if (elem.getNodeName().equals ("id")) {
+ if (elem.getFirstChild() != null)
+ id = elem.getFirstChild().getNodeValue();
+ } else if (elem.getNodeName().equals("success")) {
+ if (elem.getFirstChild() != null)
+ success = elem.getFirstChild().getNodeValue();
+ } else if (elem.getNodeName().equals ("message")) {
+ if (elem.getFirstChild() != null)
+ message = elem.getFirstChild().getNodeValue();
+ } else if (elem.getNodeName().equals ("RDF")) {
+ if (elem.getFirstChild() != null)
+ rdf = elem.getFirstChild().getNodeValue();
+ }
+ }
+
+ if (success.equals ("0"))
+ throw new NoSuccessException (message, culprit);
+ else if (success.equals ("-1"))
+ throw new PendingCurationException();
+ return new String[] { id, rdf };
+ }
+
+ /**************************************************************************
+ * Return a piece of XML created from the definitions representing input
+ * data types and their usage in the given service. Only data considered
+ * primary are included. Note that the main job of converting to XML is
+ * done by instances of MobyPrimaryData.
+ *
+ * The returned XML looks like this:
+ * <Input>
+ * <!-- zero or more Primary (Simple and/or Complex) articles -->
+ * </Input>
+ *************************************************************************/
+ protected String buildPrimaryInputTag (MobyService service) {
+ StringBuffer buf = new StringBuffer();
+ MobyData[] primaryInputs = service.getPrimaryInputs();
+ buf.append ("<Input>\n");
+ for (int i = 0; i < primaryInputs.length; i++)
+ buf.append (primaryInputs[i].toXML());
+ buf.append ("</Input>\n");
+ return new String (buf);
+ }
+
+ /**************************************************************************
+ * Return a piece of XML created from the definitions representing input
+ * data types and their usage in the given service. Only data considered
+ * secondary are included. Note that the main job of converting to XML is
+ * done by instances of MobySecondaryData.
+ *
+ * The returned XML looks like this:
+ * <secondaryArticles>
+ * <!-- zero or more INPUT Secondary articles -->
+ * </secondaryArticles>
+ *************************************************************************/
+ protected String buildSecondaryInputTag (MobyService service) {
+ StringBuffer buf = new StringBuffer();
+ MobyData[] secInputs = service.getSecondaryInputs();
+ buf.append ("<secondaryArticles>\n");
+ for (int i = 0; i < secInputs.length; i++) {
+ buf.append (secInputs[i].toXML());
+ }
+ buf.append ("</secondaryArticles>\n");
+ return new String (buf);
+ }
+
+ /**************************************************************************
+ * Return a piece of XML created from the definitions representing output
+ * data types and their usage in the given service. Only data considered
+ * primary are included. Note that the main job of converting to XML is
+ * done by instances of MobyPrimaryData.
+ *
+ * The returned XML looks like this:
+ * <Output>
+ * <!-- zero or more Primary (Simple and/or Complex) articles -->
+ * </Output>
+ *
+ *************************************************************************/
+ protected String buildOutputTag (MobyService service) {
+ StringBuffer buf = new StringBuffer();
+ MobyData[] primaryOutputs = service.getPrimaryOutputs();
+ buf.append ("<Output>\n");
+ for (int i = 0; i < primaryOutputs.length; i++)
+ buf.append (primaryOutputs[i].toXML());
+ buf.append ("</Output>\n");
+ return new String (buf);
+ }
+
+ /**************************************************************************
+ * Return a piece of XML represented a query object (an object used
+ * to find a service).
+ *
+ * The returned XML looks like this:
+ *
+ * <inputObjects>
+ * <Input>
+ * <!-- one or more Simple or Complex Primary articles -->
+ * </Input>
+ * </inputObjects>
+ * <outputObjects>
+ * <Output>
+ * <!-- one or more Simple or Complex Primary articles -->
+ * </Output>
+ * </outputObjects>
+ * <serviceType>ServiceTypeTerm</serviceType>
+ * <serviceName>ServiceName</serviceName>
+ * <Category>moby</Category>
+ * <authURI>http://desired.service.provider</authURI>;
+ * <expandObjects>1|0</expandObjects>
+ * <expandServices>1|0</expandServices>
+ * <authoritative>1|0</authoritative>
+ * <keywords>
+ * <keyword>something</keyword>
+ * ....
+ * ....
+ * </keywords>
+ *************************************************************************/
+ protected String buildQueryObject (MobyService service,
+ String[] keywords,
+ boolean expandObjects,
+ boolean expandServices,
+ boolean authoritative) {
+ if (service == null) {
+ service = new MobyService ("dummy");
+ service.setCategory ("");
+ }
+ StringBuffer buf = new StringBuffer();
+
+ buf.append ("<inputObjects>\n<Input>\n");
+ MobyData[] pi = service.getPrimaryInputs();
+ if (pi.length > 0) {
+ for (int i = 0; i < pi.length; i++)
+ buf.append (pi[i].toXML());
+ }
+ buf.append ("</Input>\n</inputObjects>\n");
+
+ buf.append ("<outputObjects>\n<Output>\n");
+ MobyData[] po = service.getPrimaryOutputs();
+ if (po.length > 0) {
+ for (int i = 0; i < po.length; i++)
+ buf.append (po[i].toXML());
+ }
+ buf.append ("</Output>\n</outputObjects>\n");
+
+ buf.append ("<serviceType>" + service.getType() + "</serviceType>\n");
+
+ String name = service.getName();
+ if (!name.equals ("") && !name.equals ("dummy") && !name.equals (MobyService.DUMMY_NAME))
+ buf.append ("<serviceName>" + service.getName() + "</serviceName>\n");
+
+ String sigURL = service.getSignatureURL();
+ if (!sigURL.equals (""))
+ buf.append ("<signatureURL>" + sigURL + "</signatureURL>\n");
+
+ buf.append ("<Category>" + service.getCategory() + "</Category>\n");
+ buf.append ("<authURI>" + service.getAuthority() + "</authURI>\n");
+
+ buf.append ("<expandObjects>");
+ buf.append (expandObjects ? "1" : "0");
+ buf.append ("</expandObjects>\n");
+
+ buf.append ("<expandServices>");
+ buf.append (expandServices ? "1" : "0");
+ buf.append ("</expandServices>\n");
+
+ buf.append ("<authoritative>");
+ buf.append (authoritative ? "1" : "0");
+ buf.append ("</authoritative>\n");
+
+ buf.append ("<keywords>\n");
+ if (keywords != null && keywords.length > 0) {
+ for (int i = 0; i < keywords.length; i++) {
+ buf.append ("<keyword>");
+ buf.append (keywords[i]);
+ buf.append ("</keyword>\n");
+ }
+ }
+ buf.append ("</keywords>\n");
+
+ return new String (buf);
+ }
+
+ /**************************************************************************
+ * Extract one or more MobyService objects from the given XML piece.
+ * The XML should look like this:
+ * <pre>
+ * <Services>
+ * <Service authURI="authority.URI.here" lsid="..." serviceName="MyService">
+ * <serviceType>Service_Ontology_Term</serviceType>
+ * <Category>moby</Category> <!-- or 'cgi' or 'soap' -->
+ * <contactEmail>your at email.addy.here</contactEmail>
+ * <signatureURL>http://service.RDF.here</signatureURL>
+ * <URL>http://service.endpoint.here/scriptname</URL>
+ * <authoritative>1</authoritative>
+ * <Input>
+ * <!-- one or more Simple and/or Complex Primary articles -->
+ * </Input>
+ * <Output>
+ * <!-- one or more Simple and/or Complex Primary articles -->
+ * </Output>
+ * <secondaryArticles>
+ * <!-- one or more Secondary articles -->
+ * </secondaryArticles>
+ * <Description><![CDATA[free text description here]]></Description>
+ * </Service>
+ * ... <!-- one or more Service blocks may be returned -->
+ * ...
+ * ...
+ * </Services>
+ * </pre>
+ * @throws MobyException if the XML document is invalid
+ *************************************************************************/
+ public MobyService[] extractServices (String xml)
+ throws MobyException {
+
+ Document document = loadDocument (new ByteArrayInputStream (xml.getBytes()));
+ NodeList list = document.getElementsByTagName ("Service");
+ MobyService[] results = new MobyService [list.getLength()];
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ MobyService service = new MobyService (elem.getAttribute ("serviceName"));
+ service.setAuthority (elem.getAttribute ("authURI"));
+ service.setLSID (elem.getAttribute ("lsid"));
+ NodeList children = elem.getChildNodes();
+ for (int j = 0; j < children.getLength(); j++) {
+ String nodeName = children.item (j).getNodeName();
+ if (nodeName.equals ("Description")) {
+ service.setDescription (getFirstValue (children.item (j)));
+ } else if (nodeName.equals ("Category")) {
+ service.setCategory (getFirstValue (children.item (j)));
+ } else if (nodeName.equals ("URL")) {
+ service.setURL (getFirstValue (children.item (j)));
+ } else if (nodeName.equals ("signatureURL")) {
+ service.setSignatureURL (getFirstValue (children.item (j)));
+ } else if (nodeName.equals ("contactEmail")) {
+ service.setEmailContact (getFirstValue (children.item (j)));
+ } else if (nodeName.equals ("serviceType")) {
+ service.setType (getFirstValue (children.item (j)));
+ MobyServiceType mst = new MobyServiceType(service.getType());
+ NamedNodeMap map = (children.item (j).getAttributes());
+ if (map != null) {
+ Node node = map.getNamedItemNS(children.item(j).getNamespaceURI(),"lsid");
+ if (node != null)
+ mst.setLSID(node.getNodeValue());
+ }
+ service.setServiceType(mst);
+ } else if (nodeName.equals ("authoritative")) {
+ String authoritative = getFirstValue (children.item (j));
+ service.setAuthoritative (authoritative.equals ("1") ? true : false);
+ } else if (nodeName.equals ("Input")) {
+ // <Input>
+ // <!-- one or more Simple and/or Complex Primary articles -->
+ // <Simple articleName="NameOfArticle">
+ // ...
+ // </Simple>
+ // <Collection articleName="NameOfArticle">
+ // <Simple>......</Simple>
+ // <Simple>......</Simple>
+ // </Collection>
+ // </Input>
+ NodeList inputs = children.item (j).getChildNodes();
+ for (int k = 0; k < inputs.getLength(); k++) {
+ if (inputs.item (k).getNodeName().equals ("Simple")) {
+ MobyPrimaryDataSimple data = new MobyPrimaryDataSimple ((Element)inputs.item (k));
+ service.addInput (data);
+ } else if (inputs.item (k).getNodeName().equals ("Collection")) {
+ MobyPrimaryDataSet data = new MobyPrimaryDataSet ((Element)inputs.item (k));
+ service.addInput (data);
+ }
+ }
+ } else if (nodeName.equals ("Output")) {
+ // <Output>
+ // <!-- one or more Simple and/or Complex Primary articles -->
+ // </Output>
+ NodeList inputs = children.item (j).getChildNodes();
+ for (int k = 0; k < inputs.getLength(); k++) {
+ if (inputs.item (k).getNodeName().equals ("Simple")) {
+ MobyPrimaryDataSimple data = new MobyPrimaryDataSimple ((Element)inputs.item (k));
+ service.addOutput (data);
+ } else if (inputs.item (k).getNodeName().equals ("Collection")) {
+ MobyPrimaryDataSet data = new MobyPrimaryDataSet ((Element)inputs.item (k));
+ service.addOutput (data);
+ }
+ }
+
+ } else if (nodeName.equals ("secondaryArticles")) {
+ // <Parameter articleName="NameOfArticle">
+ // ...
+ // </Parameter>
+ NodeList parameters = children.item (j).getChildNodes();
+ for (int k = 0; k < parameters.getLength(); k++) {
+ if (parameters.item (k).getNodeName().equals ("Parameter")) {
+ MobySecondaryData data = new MobySecondaryData ((Element)parameters.item (k));
+ service.addInput (data);
+ }
+ }
+ }
+ }
+ results [i] = service;
+ }
+ return results;
+ }
+
+ // protect against null values
+ protected String getFirstValue (Node child) {
+ Node node = child.getFirstChild();
+ if (node == null) return "";
+ String value = node.getNodeValue();
+ if (value == null) return "";
+ return value;
+ }
+
+ protected String getFirstValue (NodeList children) {
+ if (children.item(0) != null && children.item(0).hasChildNodes()) {
+ children.item(0).normalize();
+ return getFirstValue (children.item(0));
+ }
+ return "";
+ }
+
+ /**************************************************************************
+ *
+ * Implementing SimpleCache interface.
+ *
+ * Why to have an interface for such trivial thing? Well, because
+ * I needed to overwrite the caching mechanism in the subclasses
+ * so I needed to have all caching functions as separate methods -
+ * that's why I have collect them in an interface.
+ *
+ *************************************************************************/
+ private Hashtable<String,Object> cache; // this is the cache itself
+ private boolean useCache; // this signal that we are actually caching things
+
+ // not used here
+ public String createId (String rootName,
+ String semanticType, String syntaxType,
+ long lastModified,
+ Properties props) {
+ return ""; // not used here
+ }
+
+ // check existence of a cached object
+ public boolean existsInCache (String id) {
+ synchronized (cache) {
+ if (useCache) return cache.containsKey (id);
+ else return false;
+ }
+ }
+
+ // retrieve from cache
+ public Object getContents (String id) {
+ synchronized (cache) {
+ if (useCache) return cache.get (id);
+ else return null;
+ }
+ }
+
+ // cache an object
+ public void setContents (String id, java.lang.Object data) {
+ synchronized (cache) {
+ if (useCache) cache.put (id, data);
+ }
+ }
+
+ // in this implementation, it clears the whole cache, regardless
+ // what 'id' is passed
+ public void removeFromCache (String id) {
+ cache.clear();
+ }
+
+ /**************************************************************************
+ *
+ * And the other methods related to caching (but not part of the
+ * SimpleCache interface).
+ *
+ **************************************************************************/
+
+ /**************************************************************************
+ * By default, caching is enabled to reduce network traffic.
+ * Setting this to false will clear the cache, and not cache any
+ * further calls unless it is set to true again. <p>
+ *
+ * @param shouldCache whether retrieveXXX call results should be
+ * cached in case they are called again (i.e. don't request
+ * MobyCentral every time)
+ **************************************************************************/
+ public void setCacheMode (boolean shouldCache) {
+ useCache = shouldCache;
+ if (! useCache)
+ removeFromCache (null);
+ }
+
+ /**************************************************************************
+ * Find if caching is currently enabled.
+ *
+ * @return true if caching is enabled
+ **************************************************************************/
+ public boolean getCacheMode(){
+ return useCache;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ * <serviceNames>
+ * <serviceName name="serviceName" authURI='authority.info.here'/>
+ * ...
+ * ...
+ * </serviceNames>
+ * </pre>
+ *
+ * @deprecated Replaced by {@link
+ * #getServiceNamesByAuthority}. The reason is that this method
+ * returns a random result if there are more services with the
+ * same name but belonging to different authorities. <p>
+ *
+ *************************************************************************/
+ public Map<String,String> getServiceNames()
+ throws MobyException {
+
+ String result = (String)doCall ("retrieveServiceNames",
+ new Object[] {});
+ // parse returned XML
+ Map<String,String> results = new TreeMap<String,String> (getStringComparator());
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getElementsByTagName ("serviceName");
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ results.put (elem.getAttribute ("name"),
+ elem.getAttribute ("authURI"));
+ }
+
+ return results;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ * <serviceNames>
+ * <serviceName name="serviceName" lsid="..." authURI='authority.info.here'/>
+ * ...
+ * ...
+ * </serviceNames>
+ * </pre>
+ *
+ * @return a Map which has authorities as keys, and String arrays
+ * with service names as a values.
+ *************************************************************************/
+ public Map getServiceNamesByAuthority()
+ throws MobyException {
+ String result = getServiceNamesByAuthorityAsXML();
+ return createServicesByAuthorityFromXML (result, true);
+ }
+
+ /**************************************************************************
+ * Similar to {@link #getServiceNamesByAuthority} but the
+ * resulting Map contains slightly more. <p>
+ *
+ * @return a Map which has authorities as keys, and arrays of
+ * MobyServices as a values. Each MobyService is filled with its
+ * name, authority and LSID.
+ *************************************************************************/
+ public Map getServicesByAuthority()
+ throws MobyException {
+ String result = getServiceNamesByAuthorityAsXML();
+ return createServicesByAuthorityFromXML (result, false);
+ }
+
+ //
+ protected String getServiceNamesByAuthorityAsXML()
+ throws MobyException {
+ return (String)doCall ("retrieveServiceNames",
+ new Object[] {});
+ }
+
+ // if onlyNames == true
+ // Map: authority name -> String[]
+ // (filled with service namea)
+ // else
+ // Map: authority name -> MobyService[]
+ // (filled with service name, authority and lsid)
+ protected Map createServicesByAuthorityFromXML (String result,
+ boolean onlyNames)
+ throws MobyException {
+
+ // parse returned XML
+ Map results = new TreeMap (getStringComparator());
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getElementsByTagName ("serviceName");
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ String name = elem.getAttribute ("name");
+ String auth = elem.getAttribute ("authURI");
+ Vector<Object> v =
+ (results.containsKey (auth) ? (Vector)results.get (auth) : new Vector<Object>());
+ if (onlyNames) {
+ v.addElement (name);
+ } else {
+ MobyService ms = new MobyService (name);
+ ms.setAuthority (auth);
+ ms.setLSID (elem.getAttribute ("lsid"));
+ v.addElement (ms);
+ }
+ results.put (auth, v);
+ }
+
+ // change values of type Vector to MobyService[] or String[]
+ for (Iterator it = results.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry entry = (Map.Entry)it.next();
+ Vector v = (Vector)entry.getValue();
+ if (onlyNames) {
+ String[] sNames = new String [v.size()];
+ v.copyInto (sNames);
+ entry.setValue (sNames);
+ } else {
+ MobyService[] mss = new MobyService [v.size()];
+ v.copyInto (mss);
+ entry.setValue (mss);
+ }
+ }
+
+ return results;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ * <serviceProviders>
+ * <serviceProvider name="authority.URI.here"/>
+ * ...
+ * ...
+ * </serviceProviders>
+ * </pre>
+ *************************************************************************/
+ public String[] getProviders()
+ throws MobyException {
+
+ String cacheId = "retrieveServiceProviders";
+ String[] cachedResults = (String[])getContents (cacheId);
+ if (cachedResults != null)
+ return cachedResults;
+
+ String result = (String)doCall ("retrieveServiceProviders",
+ new Object[] {});
+
+ // parse returned XML
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getElementsByTagName ("serviceProvider");
+ String[] results = new String [list.getLength()];
+ for (int i = 0; i < list.getLength(); i++)
+ results[i] = ((Element)list.item (i)).getAttribute ("name");
+
+ // Add this data to the cache in case we get called again
+ setContents (cacheId, results);
+
+ return results;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ * <serviceTypes>
+ * <serviceType name="serviceName" lsid="...">
+ * <Description><![CDATA[free text description here]]></Description>
+ * <contactEmail>...</contactEmail>
+ * <authURI>...</authURI>
+ * </serviceType>
+ * ...
+ * ...
+ * </serviceTypes>
+ * </pre>
+ *************************************************************************/
+ public Map getServiceTypes()
+ throws MobyException {
+ String result = getServiceTypesAsXML();
+ Map results = new TreeMap (getStringComparator());
+ MobyServiceType[] types = createServiceTypesFromXML (result);
+ for (int i = 0; i < types.length; i++) {
+ results.put (types[i].getName(),
+ types[i].getDescription());
+ }
+ return results;
+ }
+
+ //
+ protected String getServiceTypesAsXML()
+ throws MobyException {
+ return (String)doCall ("retrieveServiceTypes",
+ new Object[] {});
+ }
+
+ // but be aware that the created MobyServiceTypes are not complete
+ // - they do not have the relationship information; that's why
+ // this method is not public; the full service types are available
+ // from CentralDigest implementations
+ protected MobyServiceType[] createServiceTypesFromXML (String result)
+ throws MobyException {
+
+ // parse returned XML
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getElementsByTagName ("serviceType");
+ if (list == null || list.getLength() == 0)
+ return new MobyServiceType[] {};
+ MobyServiceType[] results = new MobyServiceType [list.getLength()];
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ MobyServiceType st = new MobyServiceType (elem.getAttribute ("name"));
+ st.setLSID (elem.getAttribute ("lsid"));
+ st.setDescription (getFirstValue (elem.getElementsByTagName ("Description")));
+ st.setEmailContact (getFirstValue (elem.getElementsByTagName ("contactEmail")));
+ st.setAuthority (getFirstValue (elem.getElementsByTagName ("authURI")));
+ results[i] = st;
+ }
+ java.util.Arrays.sort (results);
+ return results;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ * <Namespaces>
+ * <Namespace name="namespace" lsid="...">
+ * <Description><![CDATA[free text description here]]></Description>
+ * <contactEmail>...</contactEmail>
+ * <authURI>...</authURI>
+ * </Namespace>
+ * ...
+ * ...
+ * </Namespaces>
+ * </pre>
+ *************************************************************************/
+ public MobyNamespace[] getFullNamespaces()
+ throws MobyException {
+
+ String result = getNamespacesAsXML();
+ return createNamespacesFromXML (result);
+ }
+
+ //
+ protected String getNamespacesAsXML()
+ throws MobyException {
+ return (String)doCall ("retrieveNamespaces",
+ new Object[] {});
+ }
+
+ //
+ protected MobyNamespace[] createNamespacesFromXML (String result)
+ throws MobyException {
+
+ // parse returned XML
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getDocumentElement().getElementsByTagName ("Namespace");
+ if (list == null || list.getLength() == 0) {
+ return new MobyNamespace[] {};
+ }
+ MobyNamespace[] results = new MobyNamespace [list.getLength()];
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ MobyNamespace nm = new MobyNamespace (elem.getAttribute ("name"));
+ nm.setLSID (elem.getAttribute ("lsid"));
+ nm.setDescription (getFirstValue (elem.getElementsByTagName ("Description")));
+ nm.setEmailContact (getFirstValue (elem.getElementsByTagName ("contactEmail")));
+ nm.setAuthority (getFirstValue (elem.getElementsByTagName ("authURI")));
+ results[i] = nm;
+ }
+
+ java.util.Arrays.sort (results);
+ return results;
+ }
+
+ /**************************************************************************
+ *
+ * @deprecated Replaced by {@link #getFullNamespaces} that gives
+ * more information for the same price. <p>
+ *************************************************************************/
+ public Map getNamespaces()
+ throws MobyException {
+
+ Map results = new TreeMap (getStringComparator());
+ MobyNamespace[] namespaces = getFullNamespaces();
+ for (int i = 0; i < namespaces.length; i++) {
+ results.put (namespaces[i].getName(),
+ namespaces[i].getDescription());
+ }
+ return results;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ * <objectNames>
+ * <Object name="objectName" lsid="...">
+ * <Description><![CDATA[free text description here]]></Description>
+ * </Object>
+ * ...
+ * ...
+ * </objectNames>
+ * </pre>
+ *************************************************************************/
+ public Map getDataTypeNames()
+ throws MobyException {
+ String result = getDataTypeNamesAsXML();
+ return createDataTypeNamesFromXML (result, true);
+ }
+
+ //
+ protected String getDataTypeNamesAsXML()
+ throws MobyException {
+ return (String)doCall ("retrieveObjectNames",
+ new Object[] {});
+ }
+
+ // if onlyNames == true
+ // Map: data type name -> description (String)
+ // else
+ // Map: data type name -> MobyDataType[]
+ // (filled with name, description, and lsid)
+ protected Map createDataTypeNamesFromXML (String result,
+ boolean onlyNames)
+ throws MobyException {
+
+ // parse returned XML
+ Map results = new TreeMap (getStringComparator());
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getElementsByTagName ("Object");
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ String name = elem.getAttribute ("name");
+ if (name == null)
+ continue; // ignore no-named data types
+ String desc = "";
+ NodeList children = elem.getChildNodes();
+ for (int j = 0; j < children.getLength(); j++) {
+ if (children.item (j).getNodeName().equals ("Description")) {
+ desc = getFirstValue (children.item (j));
+ break;
+ }
+ }
+ if (onlyNames) {
+ results.put (name, desc);
+ } else {
+ MobyDataType dt = new MobyDataType (name);
+ dt.setDescription (desc);
+ dt.setLSID (elem.getAttribute ("lsid"));
+ results.put (name, dt);
+ }
+ }
+ return results;
+ }
+
+
+ /**************************************************************************
+ * Parses and imports the following XML. An example:
+ *
+ * <pre>
+ * <retrieveObjectDefinition>
+ * <objectType lsid="...">go_term</objectType>
+ * <Description><![CDATA[A very lightweight object holding a GO term name and its definition]]></Description>
+ * <authURI>http://www.illuminae.com</authURI>
+ * <contactEmail>markw at illuminae.com</contactEmail>
+ * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:isa'>
+ * <objectType articleName=''>urn:lsid:biomoby.org:objectclass:object</objectType>
+ * </Relationship>
+ * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:hasa'>
+ * <objectType articleName='Term'>urn:lsid:biomoby.org:objectclass:string</objectType>
+ * <objectType articleName='Definition'>urn:lsid:biomoby.org:objectclass:string</objectType>
+ * </Relationship>
+ * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:has'>
+ * <objectType articleName='Problems'>urn:lsid:biomoby.org:objectclass:string</objectType>
+ * <objectType articleName='Issues'>urn:lsid:biomoby.org:objectclass:string</objectType>
+ * </Relationship>
+ * </retrieveObjectDefinition>
+ * </pre>
+ *************************************************************************/
+ public MobyDataType getDataType (String dataTypeName)
+ throws MobyException, NoSuccessException {
+
+ String result = getDataTypeAsXML (dataTypeName);
+ return createDataTypeFromXML (result, dataTypeName);
+ }
+
+ public MobyDataType[] getDataTypes()
+ throws MobyException, NoSuccessException {
+ Map<String,String> datatypeMap = getDataTypeNames();
+ MobyDataType[] datatypes = new MobyDataType[datatypeMap.size()];
+ int i = 0;
+ for(String dataTypeName: datatypeMap.keySet()){
+ datatypes[i++] = getDataType(dataTypeName);
+ }
+ return datatypes;
+ }
+
+ protected String getDataTypeAsXML (String dataTypeName)
+ throws MobyException, NoSuccessException {
+
+ return (String)doCall ("retrieveObjectDefinition",
+ new Object[] {
+ "<retrieveObjectDefinition>" +
+ "<objectType>" + dataTypeName + "</objectType>" +
+ "</retrieveObjectDefinition>"
+ });
+ }
+
+ protected MobyDataType createDataTypeFromXML (String xmlSource, String dataTypeName)
+ throws MobyException, NoSuccessException {
+
+ // parse returned XML
+ Document document = loadDocument (new ByteArrayInputStream (xmlSource.getBytes()));
+ NodeList list = document.getElementsByTagName ("retrieveObjectDefinition");
+ if (list == null || list.getLength() == 0)
+ throw new NoSuccessException ("Data Type name was not found.",
+ dataTypeName);
+ MobyDataType data = null;
+ Element elem = (Element)list.item (0);
+ NodeList children = elem.getChildNodes();
+
+ // first find the "real" (LSID-ized) data type name
+ for (int j = 0; j < children.getLength(); j++) {
+ String nodeName = children.item (j).getNodeName();
+ if (nodeName.equals ("objectType")) {
+ data = new MobyDataType (getFirstValue (children.item (j)));
+ data.setLSID ( ((Element)children.item (j) ).getAttribute ("lsid"));
+ break;
+ }
+ }
+
+ // if not found (unprobable) use the name given by the caller
+ if (data == null)
+ data = new MobyDataType (dataTypeName);
+
+ // now fill the data type object with the rest of attributes
+ for (int j = 0; j < children.getLength(); j++) {
+ String nodeName = children.item (j).getNodeName();
+ if (nodeName.equals ("Description")) {
+ data.setDescription (getFirstValue (children.item (j)));
+ } else if (nodeName.equals ("authURI")) {
+ data.setAuthority (getFirstValue (children.item (j)));
+ } else if (nodeName.equals ("contactEmail")) {
+ data.setEmailContact (getFirstValue (children.item (j)));
+ } else if (nodeName.equals ("Relationship")) {
+ String relationshipType = ((Element)children.item (j)).getAttribute ("relationshipType");
+ if (relationshipType.endsWith ("isa")) {
+
+ NodeList parents = children.item (j).getChildNodes();
+ for (int k = 0; k < parents.getLength(); k++) {
+ if (parents.item (k).getNodeName().equals ("objectType")) {
+ data.addParentName (getFirstValue (parents.item (k)));
+ }
+ }
+ } else if (relationshipType.endsWith ("hasa")) {
+
+ NodeList belows = children.item (j).getChildNodes();
+ for (int k = 0; k < belows.getLength(); k++) {
+ if (belows.item (k).getNodeName().equals ("objectType")) {
+ data.addChild ( ((Element)belows.item (k)).getAttribute ("articleName"),
+ getFirstValue (belows.item (k)),
+ Central.iHASA );
+ }
+ }
+ } else if (relationshipType.endsWith ("has")) {
+
+ NodeList belows = children.item (j).getChildNodes();
+ for (int k = 0; k < belows.getLength(); k++) {
+ if (belows.item (k).getNodeName().equals ("objectType")) {
+ data.addChild ( ((Element)belows.item (k)).getAttribute ("articleName"),
+ belows.item (k).getFirstChild().getNodeValue(),
+ Central.iHAS );
+ }
+ }
+ }
+ }
+ }
+ return data;
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public String getServiceWSDL (String serviceName)
+ throws MobyException, NoSuccessException {
+
+ Map names = getServiceNames();
+
+ for (Iterator it = names.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry entry = (Map.Entry)it.next();
+ if ( ((String)entry.getKey()).equals (serviceName) )
+ return getServiceWSDL (serviceName, (String)entry.getValue());
+ }
+
+ throw new NoSuccessException ("Service not found.", serviceName);
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public String getServiceWSDL (String serviceName, String authority)
+ throws MobyException, NoSuccessException {
+
+ String cacheId = "getServiceWSDL" + serviceName + ":" + authority;
+ String cachedResults = (String)getContents (cacheId);
+ if (cachedResults != null)
+ return cachedResults;
+
+ String result =
+ (String)doCall ("retrieveService",
+ new Object[] {
+ "<retrieveService>" +
+ "<Service authURI=\"" + authority + "\" serviceName=\"" + serviceName + "\"/>" +
+ "</retrieveService>"
+ });
+
+ // parse returned XML
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ Element service = document.getDocumentElement();
+ Node wsdl = service.getFirstChild();
+ if (wsdl == null)
+ throw new NoSuccessException ("Service not found OR WSDL is not available.",
+ serviceName + " (" + authority + ")");
+
+ String results = wsdl.getNodeValue();
+ setContents (cacheId, results);
+ return results;
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public String getRegisterDataTypeXML (MobyDataType dataType) {
+
+ // build the ISA tag (expressing hierarchy of data types)
+ String[] names = dataType.getParentNames();
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < names.length; i++) {
+ buf.append ("<objectType>");
+ buf.append (names[i]);
+ buf.append ("</objectType>");
+ buf.append ("\n");
+ }
+
+ // build the HASA/HAS tags (expressing containments of data types)
+ MobyRelationship[] children = dataType.getChildren();
+ StringBuffer buf2 = new StringBuffer(); // for HASA
+ StringBuffer buf3 = new StringBuffer(); // for HAS
+ for (int i = 0; i < children.length; i++) {
+ if (children[i].getRelationshipType() == Central.iHASA) {
+ buf2.append ("<objectType articleName=\"");
+ buf2.append (children[i].getName());
+ buf2.append ("\">");
+ buf2.append (children[i].getDataTypeName());
+ buf2.append ("</objectType>");
+ } else if (children[i].getRelationshipType() == Central.iHAS) {
+ buf3.append ("<objectType articleName=\"");
+ buf3.append (children[i].getName());
+ buf3.append ("\">");
+ buf3.append (children[i].getDataTypeName());
+ buf3.append ("</objectType>");
+ }
+ }
+
+ return
+ "<registerObjectClass>" +
+ "<objectType>" + dataType.getName() + "</objectType>" +
+ "<Description><![CDATA[" + dataType.getDescription() + "]]>" +
+ "</Description>" +
+ "<Relationship relationshipType=\"ISA\">" + new String (buf) +
+ "</Relationship>" +
+ "<Relationship relationshipType=\"HASA\">" + new String (buf2) +
+ "</Relationship>" +
+ "<Relationship relationshipType=\"HAS\">" + new String (buf3) +
+ "</Relationship>" +
+ "<authURI>" + dataType.getAuthority() + "</authURI>" +
+ "<contactEmail>" + dataType.getEmailContact() + "</contactEmail>" +
+ "</registerObjectClass>";
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public void registerDataType (MobyDataType dataType)
+ throws MobyException, NoSuccessException, PendingCurationException {
+
+ String result =
+ (String)doCall ("registerObjectClass",
+ new Object[] { getRegisterDataTypeXML (dataType) });
+ dataType.setId (checkRegistration (result, dataType)[0]);
+ }
+
+ /*************************************************************************
+ * B
+ *************************************************************************/
+ public void unregisterDataType (MobyDataType dataType)
+ throws MobyException, NoSuccessException, PendingCurationException {
+ String result =
+ (String)doCall ("deregisterObjectClass",
+ new Object[] {
+ "<deregisterObjectClass>" +
+ "<objectType>" + dataType.getName() + "</objectType>" +
+ "</deregisterObjectClass>"
+ });
+ checkRegistration (result, dataType);
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public String getRegisterServiceTypeXML (MobyServiceType serviceType) {
+
+ // build the ISA tag (expressing hierarchy of service types)
+ String[] names = serviceType.getParentNames();
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < names.length; i++) {
+ buf.append ("<serviceType>");
+ buf.append (names[i]);
+ buf.append ("</serviceType>");
+ buf.append ("\n");
+ }
+
+ return
+ "<registerServiceType>" +
+ "<serviceType>" + serviceType.getName() + "</serviceType>" +
+ "<contactEmail>" + serviceType.getEmailContact() + "</contactEmail>" +
+ "<authURI>" + serviceType.getAuthority() + "</authURI>" +
+ "<Description><![CDATA[" + serviceType.getDescription() + "]]>" +
+ "</Description>" +
+ "<Relationship relationshipType=\"ISA\">" + new String (buf) +
+ "</Relationship>" +
+ "</registerServiceType>";
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public void registerServiceType (MobyServiceType serviceType)
+ throws MobyException, NoSuccessException, PendingCurationException {
+
+ String result =
+ (String)doCall ("registerServiceType",
+ new Object[] { getRegisterServiceTypeXML (serviceType) });
+ serviceType.setId (checkRegistration (result, serviceType)[0]);
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public void unregisterServiceType (MobyServiceType serviceType)
+ throws MobyException, NoSuccessException, PendingCurationException {
+ String result =
+ (String)doCall ("deregisterServiceType",
+ new Object[] {
+ "<deregisterServiceType>" +
+ "<serviceType>" + serviceType.getName() + "</serviceType>" +
+ "</deregisterServiceType>"
+ });
+ checkRegistration (result, serviceType);
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public String getRegisterNamespaceXML (MobyNamespace namespace) {
+ return
+ "<registerNamespace>" +
+ "<namespaceType>" + namespace.getName() + "</namespaceType>" +
+ "<contactEmail>" + namespace.getEmailContact() + "</contactEmail>" +
+ "<authURI>" + namespace.getAuthority() + "</authURI>" +
+ "<Description><![CDATA[" + namespace.getDescription() + "]]>" +
+ "</Description>" +
+ "</registerNamespace>";
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public void registerNamespace (MobyNamespace namespace)
+ throws MobyException, NoSuccessException, PendingCurationException {
+ String result =
+ (String)doCall ("registerNamespace",
+ new Object[] { getRegisterNamespaceXML (namespace) });
+ namespace.setId (checkRegistration (result, namespace)[0]);
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public void unregisterNamespace (MobyNamespace namespace)
+ throws MobyException, NoSuccessException, PendingCurationException {
+ String result =
+ (String)doCall ("deregisterNamespace",
+ new Object[] {
+ "<deregisterNamespace>" +
+ "<namespaceType>" + namespace.getName() + "</namespaceType>" +
+ "</deregisterNamespace>"
+ });
+ checkRegistration (result, namespace);
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public String getRegisterServiceXML (MobyService service) {
+ return
+ "<registerService>" +
+ "<Category>" + service.getCategory() + "</Category>" +
+ "<serviceName>" + service.getName() + "</serviceName>" +
+ "<serviceType>" + service.getType() + "</serviceType>" +
+ "<serviceLSID>" + (service.getLSID() == null ? "" : service.getLSID().trim() )+ "</serviceLSID>" +
+ "<authURI>" + service.getAuthority() + "</authURI>" +
+ "<signatureURL>" + escapeXML (service.getSignatureURL()) + "</signatureURL>" +
+ "<URL>" + escapeXML (service.getURL()) + "</URL>" +
+ "<contactEmail>" + service.getEmailContact() + "</contactEmail>" +
+ "<authoritativeService>" + (service.isAuthoritative() ? "1" : "0") + "</authoritativeService>" +
+ "<Description><![CDATA[" + service.getDescription() + "]]>" +
+ "</Description>" +
+ buildPrimaryInputTag (service) +
+ buildSecondaryInputTag (service) +
+ buildOutputTag (service) +
+ "</registerService>";
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public void registerService (MobyService service)
+ throws MobyException, NoSuccessException, PendingCurationException {
+
+ String result =
+ (String)doCall ("registerService",
+ new Object[] { getRegisterServiceXML (service) });
+ String[] registered = checkRegistration (result, service);
+ service.setId (registered [0]);
+ service.setRDF (registered [1]);
+ String pathToRDF = service.getPathToRDF();
+ if ( ! pathToRDF.equals ("") ) {
+ File fileRDF = new File (pathToRDF);
+ try {
+ PrintStream fileout = new PrintStream (new FileOutputStream (fileRDF));
+ fileout.println (registered [1]);
+ fileout.close();
+ } catch (IOException e) {
+ StringBuffer buf = new StringBuffer (100);
+ buf.append ("Failed to save RDF in '");
+ buf.append (fileRDF.getAbsolutePath() + "'. ");
+ buf.append (e.toString());
+ try {
+ File tmpFile = File.createTempFile (service.getName() + "-", ".rdf");
+ PrintStream fileout = new PrintStream (new FileOutputStream (tmpFile));
+ fileout.println (registered [1]);
+ fileout.close();
+ buf.append ("\nReturned RDF file was therefore stored in: ");
+ buf.append (tmpFile.getAbsolutePath());
+ } catch (IOException e2) {
+ buf.append ("\nEven saving in a temporary file failed: ");
+ buf.append (e2.toString());
+ }
+ throw new MobyException (buf.toString());
+ }
+ }
+ }
+
+ /*************************************************************************
+ *
+ *************************************************************************/
+ public void unregisterService (MobyService service)
+ throws MobyException, NoSuccessException, PendingCurationException {
+ String result =
+ (String)doCall ("deregisterService",
+ new Object[] {
+ "<deregisterService>" +
+ "<authURI>" + service.getAuthority() + "</authURI>" +
+ "<serviceName>" + service.getName() + "</serviceName>" +
+ "</deregisterService>"
+ });
+ checkRegistration (result, service);
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public MobyService[] findService (String serviceType)
+ throws MobyException {
+ if (serviceType == null)
+ return new MobyService[] {};
+ MobyService pattern = new MobyService ("dummy");
+ pattern.setCategory ("");
+ pattern.setType (serviceType);
+ return findService (pattern, null);
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public MobyService[] findService (String[] keywords)
+ throws MobyException {
+ if (keywords == null)
+ return new MobyService[] {};
+ return findService (null, keywords);
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public MobyService[] findService (MobyService pattern)
+ throws MobyException {
+ if (pattern == null)
+ return new MobyService[] {};
+ return findService (pattern, null);
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public MobyService[] findService (MobyService pattern, String[] keywords)
+ throws MobyException {
+ return findService (pattern, keywords, true, true);
+ }
+
+ /**************************************************************************
+ * All 'findService' methods end up here.
+ *************************************************************************/
+ public MobyService[] findService (MobyService pattern, String[] keywords,
+ boolean includeChildrenServiceTypes,
+ boolean includeParentDataTypes)
+ throws MobyException {
+ if (pattern == null) {
+ pattern = new MobyService ("dummy");
+ pattern.setCategory ("");
+ }
+
+ String result =
+ getServicesAsXML (pattern, keywords, includeChildrenServiceTypes, includeParentDataTypes);
+ MobyService[] services = extractServices (result);
+ return services;
+ }
+
+ // ...actually all 'findService' methods end up here
+ protected String getServicesAsXML (MobyService pattern, String[] keywords,
+ boolean includeChildrenServiceTypes,
+ boolean includeParentDataTypes)
+ throws MobyException {
+ String[] query = new String[] {
+ "<findService>" +
+ buildQueryObject (pattern, keywords,
+ includeParentDataTypes,
+ includeChildrenServiceTypes,
+ false) +
+ "</findService>"
+ };
+ return (String)doCall ("findService", query);
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public String call (String methodName, String inputXML)
+ throws MobyException {
+ Object result;
+ if (inputXML == null || inputXML.equals (""))
+ result = doCall (methodName, new Object[] { });
+ else
+ result = doCall (methodName, new Object[] { inputXML });
+ return (String)result;
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ protected static String resultToString (Object result)
+ throws MobyException {
+ if (result == null)
+ throw new MobyException ("Returned result is null.");
+ if (result instanceof String)
+ return (String)result;
+ if (result instanceof String[]) {
+ String[] tmp = (String[])result;
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < tmp.length; i++)
+ buf.append (tmp[i]);
+ return new String (buf);
+ }
+ if (result instanceof byte[])
+ return new String ((byte[])result);
+
+ throw new MobyException ("Unknown type of result: " + result.getClass().getName());
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public boolean setDebug (boolean enabled) {
+ boolean oldMode = debug;
+ debug = enabled;
+ return oldMode;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ * <Relationships>
+ * <Relationship relationshipType='urn:lsid:biomoby.org:servicerelation:isa'>
+ * <serviceType>urn:lsid:biomoby.org:servicetype:analysis</serviceType>
+ * <serviceType>urn:lsid:biomoby.org:servicetype:service</serviceType>
+ * </Relationship>
+ * </Relationships>
+ * </pre>
+ *************************************************************************/
+ public String[] getServiceTypeRelationships (String serviceTypeName,
+ boolean expand)
+ throws MobyException {
+ String result = getServiceTypeRelationshipsAsXML (serviceTypeName, expand);
+ return createServiceTypeRelationshipsFromXML (result);
+ }
+
+ //
+ protected String getServiceTypeRelationshipsAsXML (String serviceTypeName,
+ boolean expand)
+ throws MobyException {
+ return
+ (String)doCall ("Relationships",
+ new Object[] {
+ "<Relationship>" +
+ "<serviceType>" + serviceTypeName + "</serviceType>" +
+ "<relationshipType>" + Central.ISA + "</relationshipType>" +
+ "<expandRelationship>" + (expand ? "1" : "0") + "</expandRelationship>" +
+ "</Relationship>"
+ });
+ }
+
+ //
+ protected String[] createServiceTypeRelationshipsFromXML (String result)
+ throws MobyException {
+
+ // parse returned XML
+ Vector<String> v = new Vector<String>();
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getElementsByTagName ("Relationship");
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ NodeList children = elem.getChildNodes();
+ for (int j = 0; j < children.getLength(); j++) {
+ if (children.item (j).getNodeName().equals ("serviceType")) {
+ v.addElement (getFirstValue (children.item (j)));
+ }
+ }
+ }
+ String[] results = new String [v.size()];
+ v.copyInto (results);
+ return results;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ *<Relationships>
+ * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:isa'>
+ * <objectType>urn:lsid:biomoby.org:objectclass:virtualsequence</objectType>
+ * <objectType>urn:lsid:biomoby.org:objectclass:object</objectType>
+ * </Relationship>
+ * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:hasa'>
+ * <objectType>urn:lsid:biomoby.org:objectclass:string</objectType>
+ * <objectType>urn:lsid:biomoby.org:objectclass:integer</objectType>
+ * </Relationship>
+ *</Relationships>
+ * </pre>
+ *
+ * Added at Sun Feb 19 19:32:31 PHT 2006: it recognizes also an
+ * attributes 'lsid' and 'articleName' in <objectType> element.
+ *************************************************************************/
+ public Map getDataTypeRelationships (String dataTypeName)
+ throws MobyException {
+
+ String cacheId = "getDataTypeRelationships_" + dataTypeName;
+ Map cachedResults = (Map)getContents (cacheId);
+ if (cachedResults != null)
+ return cachedResults;
+
+ String result =
+ (String)doCall ("Relationships",
+ new Object[] {
+ "<Relationships>" +
+ "<objectType>" + dataTypeName + "</objectType>" +
+ "<relationshipType>" + Central.ISA + "</relationshipType>" +
+ "<relationshipType>" + Central.HASA + "</relationshipType>" +
+ "<relationshipType>" + Central.HAS + "</relationshipType>" +
+ "<expandRelationship>1</expandRelationship>" +
+ "</Relationships>"
+ });
+
+ // parse returned XML
+ Map results = new HashMap();
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getElementsByTagName ("Relationship");
+
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ String relType = elem.getAttribute ("relationshipType");
+ NodeList children = elem.getChildNodes();
+ Vector<String> v = new Vector<String>();
+ for (int j = 0; j < children.getLength(); j++) {
+ if (children.item (j).getNodeName().equals ("objectType")) {
+ v.addElement (getFirstValue (children.item (j)));
+ }
+ }
+ String[] names = new String [v.size()];
+ v.copyInto (names);
+ results.put (relType, names);
+ }
+
+ setContents (cacheId, results);
+ return results;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ *<Relationships>
+ * <Relationship relationshipType='urn:lsid:biomoby.org:objectrelation:isa'>
+ * <objectType>urn:lsid:biomoby.org:objectclass:virtualsequence</objectType>
+ * <objectType>urn:lsid:biomoby.org:objectclass:object</objectType>
+ * </Relationship>
+ *</Relationships>
+ * </pre>
+ *************************************************************************/
+ public String[] getDataTypeRelationships (String dataTypeName,
+ String relationshipType)
+ throws MobyException {
+
+ String cacheId = "getDataTypeRelationships_" + dataTypeName + ":" + relationshipType;
+ String[] cachedResults = (String[])getContents (cacheId);
+ if (cachedResults != null)
+ return cachedResults;
+
+ String result =
+ (String)doCall ("Relationships",
+ new Object[] {
+ "<Relationships>" +
+ "<objectType>" + dataTypeName + "</objectType>" +
+ "<relationshipType>" + relationshipType + "</relationshipType>" +
+ "<expandRelationship>1</expandRelationship>" +
+ "</Relationships>"
+ });
+
+ // parse returned XML
+ Vector<String> v = new Vector<String>();
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getElementsByTagName ("Relationship");
+
+ // it should always be just one element in this list
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ NodeList children = elem.getChildNodes();
+ for (int j = 0; j < children.getLength(); j++) {
+ if (children.item (j).getNodeName().equals ("objectType")) {
+ v.addElement (getFirstValue (children.item (j)));
+ }
+ }
+ }
+ String[] results = new String [v.size()];
+ v.copyInto (results);
+
+ setContents (cacheId, results);
+ return results;
+ }
+
+// /**************************************************************************
+// *
+// *************************************************************************/
+// public MobyRelationship[] getRelationships (String dataTypeName)
+// throws MobyException {
+// return null;
+// }
+
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public String getRegistryEndpoint() {
+ return endpoint.toString();
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public String getRegistryNamespace() {
+ return uri;
+ }
+
+ /**************************************************************************
+ * Parses and imports the following XML.
+ * <pre>
+ * <resourceURLs>
+ * <Resource name="Service" url="..." />
+ * <Resource name="Object" url="..." />
+ * <Resource name="Namespace" url="..." />
+ * <Resource name="ServiceInstance" url="..." />
+ * <Resource name="Full" url="..." />
+ * </resourceURLs>
+ * </pre>
+ *************************************************************************/
+ public MobyResourceRef[] getResourceRefs()
+ throws MobyException {
+
+ String cacheId = "retrieveResourceURLs";
+ MobyResourceRef[] cachedResults = (MobyResourceRef[])getContents (cacheId);
+ if (cachedResults != null)
+ return cachedResults;
+
+ String result = (String)doCall ("retrieveResourceURLs",
+ new Object[] {});
+
+ // parse returned XML
+ Vector<MobyResourceRef> v = new Vector<MobyResourceRef>();
+ Document document = loadDocument (new ByteArrayInputStream (result.getBytes()));
+ NodeList list = document.getElementsByTagName ("Resource");
+ for (int i = 0; i < list.getLength(); i++) {
+ Element elem = (Element)list.item (i);
+ try {
+ v.addElement
+ (new MobyResourceRef (elem.getAttribute ("name"),
+ new URL ((String)elem.getAttribute ("url")),
+ elem.getAttribute ("type")));
+ } catch (MalformedURLException e2) {
+ if (debug)
+ System.err.println ("Bad URL: " + elem.getAttribute ("url"));
+ }
+ }
+
+ MobyResourceRef[] results = new MobyResourceRef [v.size()];
+ v.copyInto (results);
+
+ // Add this data to the cache in case we get called again
+ setContents (cacheId, results);
+
+ return results;
+ }
+
+ /**************************************************************************
+ *
+ *************************************************************************/
+ public InputStream getResource (String resourceName)
+ throws MobyException {
+
+ MobyResourceRef[] resourceRefs = getResourceRefs();
+ for (int i = 0; i < resourceRefs.length; i++) {
+ if (resourceName.equalsIgnoreCase (resourceRefs[i].getResourceName())) {
+ return Utils.getInputStream (resourceRefs[i].getResourceLocation());
+ }
+ }
+ throw new MobyException ("No resource found for '" + resourceName + "'.");
+ }
+
+ /**************************************************************************
+ * Return a case-insensitive comparator of Strings. It is used to
+ * create various TreeMaps where keys are strings.
+ *************************************************************************/
+ protected static Comparator getStringComparator() {
+ return new Comparator() {
+ public int compare (Object o1, Object o2) {
+ return ((String)o1).compareToIgnoreCase ((String)o2);
+ }
+ };
+ }
+
+ // cache URL/URI so we only check once
+ private static String CHECKED_URL = null;
+ private static String CHECKED_URI = null;
+
+ /**
+ * Using this method to get a Central object will ensure that other parts of the org.biomoby.shared
+ * class hierarchy that implicitly check the registry will use the same cache. Otherwise, methods
+ * such as MobyNamespace.getNamespace() must be passed a Central object parameter as well.
+ *
+ * @return a CentralImpl using the default Central URI, and currently a class implementing a caching mechanism
+ */
+ public static CentralImpl getDefaultCentral() throws MobyException{
+ return getDefaultCentral(null);
+ }
+
+ public static CentralImpl getDefaultCentral(Registry reg) throws MobyException{
+ if(reg == null && defaultCentrals.containsKey("")){
+ return defaultCentrals.get("");
+ }
+ else if(reg != null && defaultCentrals.containsKey(reg.getEndpoint())){
+ return defaultCentrals.get(reg.getEndpoint());
+ }
+
+ String className = DEFAULT_CENTRAL_IMPL_CLASSNAME;
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ URL resURL = classLoader.getResource("META-INF/"+CENTRAL_IMPL_RESOURCE_NAME);
+ if(resURL != null){
+ System.err.println("Loading "+resURL);
+ try{
+ LineNumberReader reader = new LineNumberReader(new InputStreamReader(resURL.openStream()));
+ for(String line = reader.readLine(); line != null; line = reader.readLine()){
+ if(!line.trim().startsWith("#")){
+ className = line.trim();
+ break;
+ }
+ }
+ } catch(Exception e){
+ logger.log(Level.WARNING,
+ "Error reading " + resURL,
+ e);
+ }
+ }
+ try{
+ System.err.println("Central class is "+className);
+ Class clazz = Class.forName(className);
+ if(reg == null){ // should use default nullary c-tor
+ defaultCentrals.put("", (CentralImpl) clazz.newInstance());
+ }
+ else{ // should have (String endpoint, String namespace) c-tor
+ for(Constructor ctor: clazz.getDeclaredConstructors()){
+ Class[] params = ctor.getParameterTypes();
+ if(params.length == 2 && params[0].getName().equals("java.lang.String") &&
+ params[1].getName().equals("java.lang.String") ){
+ defaultCentrals.put(reg.getEndpoint(),
+ (CentralImpl) ctor.newInstance(reg.getEndpoint(), reg.getNamespace()));
+ break;
+ }
+ }
+ if(!defaultCentrals.containsKey(reg.getEndpoint())){
+ logger.log(Level.WARNING,
+ "Could not find required (String endpoint, String namespace)" +
+ "constructor for class " + className);
+ }
+ }
+ } catch(Exception e){
+ logger.log(Level.WARNING,
+ "Could not load class " + className,
+ e);
+ if(reg == null){
+ defaultCentrals.put("", new CentralImpl()); //fallback to this class, no caching, etc.
+ }
+ else{
+ defaultCentrals.put(reg.getEndpoint(),
+ new CentralImpl(reg.getEndpoint(), reg.getNamespace()));
+ }
+ }
+
+ return defaultCentrals.get(reg == null ? "" : reg.getEndpoint());
+ }
+
+ /**
+ *
+ * @return a String representing the Default mobycentral endpoint. If the
+ * system property 'moby.check.default' exists and is set to true,
+ * then the URL http://biomoby.org/mobycentral is queried and the
+ * default central endpoint is returned, otherwise DEFAULT_ENDPOINT
+ * is returned.
+ */
+ public static String getDefaultURL() {
+ boolean check = false;
+ try {
+ check = Boolean.getBoolean("moby.check.default");
+ } catch (Exception e) {
+
+ }
+
+ if (check) {
+ // return the last checked url if we have done this before
+ if (CHECKED_URL != null && CHECKED_URL.trim() != "") {
+ return CHECKED_URL;
+ }
+
+ // create a HttpClient object
+ HttpClient client = new HttpClient();
+ // set up the Head method
+ HeadMethod method = new HeadMethod("http://biomoby.org/mobycentral");
+ // do not follow redirects or we will get a 411 error
+ method.setFollowRedirects(false);
+ // retry 3 times
+ method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler(3, false));
+ // set the user agent ... should probably make this something more reasonable
+ method.getParams().setParameter(HttpMethodParams.USER_AGENT,"jMoby/1.0");
+ try {
+ // Execute the method.
+ int statusCode = client.executeMethod(method);
+
+ if (statusCode != HttpStatus.SC_MOVED_PERMANENTLY) {
+ System.err.println("Method failed: "
+ + method.getStatusLine());
+ } else {
+ try {
+ String location = method.getResponseHeader("location").getValue();
+ CHECKED_URL = location;
+ try {
+ CHECKED_URI = "http://" + (new URL(CHECKED_URL).getAuthority()) + "/MOBY/Central";
+ } catch (MalformedURLException murle ) {
+ CHECKED_URI = DEFAULT_NAMESPACE;
+ }
+ return CHECKED_URL;
+ } catch (NullPointerException npe) {
+ return DEFAULT_ENDPOINT;
+ }
+ }
+ } catch (HttpException e) {
+ System.err.println("Fatal protocol violation: "
+ + e.getMessage());
+ e.printStackTrace();
+ } catch (IOException e) {
+ System.err.println("Fatal transport error: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ // Release the connection.
+ method.releaseConnection();
+ }
+
+ } else {
+ return DEFAULT_ENDPOINT;
+ }
+ return DEFAULT_ENDPOINT;
+ }
+
+ /**
+ *
+ * @return a String representing the default mobycentral uri. If the
+ * system property 'moby.check.default' exists and is set to true,
+ * then the URL http://biomoby.org/mobycentral is queried and the
+ * default central namespace is returned, otherwise DEFAULT_NAMESPACE
+ * is returned.
+ */
+ public static String getDefaultURI() {
+ boolean check = false;
+ try {
+ check = Boolean.getBoolean("moby.check.default");
+ } catch (Exception e) {
+
+ }
+ if (check) {
+ if (CHECKED_URI != null && CHECKED_URI.trim() != "") {
+ return CHECKED_URI;
+ }
+ // need to check ...
+ getDefaultURL();
+ return CHECKED_URI;
+ } else {
+ return DEFAULT_NAMESPACE;
+ }
+ }
+ /**************************************************************************
+ * Convert non-suitable characters in a XML string into their
+ * entity references. <p>
+ *
+ * <em>Adapted from jDom.</em>
+ *
+ * @param str input to be converted
+ * @return If there were any non-suitable characters, return a new
+ * string with those characters escaped, otherwise return the
+ * unmodified input string
+ *
+ *************************************************************************/
+ public String escapeXML (String str) {
+ StringBuffer buffer = null;
+ char ch;
+ String entity;
+ for (int i = 0; i < str.length(); i++) {
+ ch = str.charAt (i);
+ switch (ch) {
+ case '<' :
+ entity = "<";
+ break;
+ case '>' :
+ entity = ">";
+ break;
+ case '&' :
+ entity = "&";
+ break;
+ default :
+ entity = null;
+ break;
+ }
+ if (buffer == null) {
+ if (entity != null) {
+ // An entity occurred, so we'll have to use StringBuffer
+ // (allocate room for it plus a few more entities).
+ buffer = new StringBuffer (str.length() + 20);
+ // Copy previous skipped characters and fall through
+ // to pickup current character
+ buffer.append (str.substring (0, i));
+ buffer.append (entity);
+ }
+ } else {
+ if (entity == null) {
+ buffer.append (ch);
+ } else {
+ buffer.append (entity);
+ }
+ }
+ }
+
+ // If there were any entities, return the escaped characters
+ // that we put in the StringBuffer. Otherwise, just return
+ // the unmodified input string.
+ return (buffer == null) ? str : buffer.toString();
+ }
+
+ /*************************************************************************
+ * Format an exception.
+ *************************************************************************/
+ public static String formatFault (AxisFault e, String endpoint, QName method) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ formatFault (e, new PrintStream (baos), endpoint, method);
+ return baos.toString();
+ }
+
+ /*************************************************************************
+ * Format an exception.
+ *************************************************************************/
+ public static void formatFault (AxisFault e, PrintStream out,
+ String endpoint, QName method) {
+
+ out.println ("===ERROR===");
+ out.println ("Fault details:");
+ // for some obvious errors I do not print all details (with a lenghty trace stack)
+ String faultString = e.getFaultString();
+ if ( (! faultString.startsWith ("java.net.ConnectException")) &&
+ (faultString.indexOf ("Could not find class for the service named:") == -1)
+ ) {
+ org.w3c.dom.Element[] details = e.getFaultDetails();
+ for (int i = 0; i < details.length; i++) {
+ String s = details[i].toString().replaceAll ("<", "<");
+ s = s.replaceAll (">", ">");
+ out.println (s);
+ }
+ }
+ out.println ("Fault string: " + faultString);
+ out.println ("Fault code: " + e.getFaultCode());
+ out.println ("Fault actor: " + e.getFaultActor());
+ if (endpoint != null || method != null)
+ out.println ("When calling:");
+ if (endpoint != null)
+ out.println ("\t" + endpoint);
+ if (method != null)
+ out.println ("\t" + method);
+ out.println ("===========");
+ }
+
+
+}
More information about the MOBY-guts
mailing list