[MOBY-guts] biomoby commit

Paul Gordon gordonp at dev.open-bio.org
Tue Jun 9 19:25:12 UTC 2009


gordonp
Tue Jun  9 15:25:12 EDT 2009
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services
In directory dev.open-bio.org:/tmp/cvs-serv20945/src/main/ca/ucalgary/seahawk/services

Modified Files:
	MobyClient.java 
Log Message:
Many changed related to adding id support for rules
moby-live/Java/src/main/ca/ucalgary/seahawk/services MobyClient.java,1.21,1.22
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java	2008/10/30 02:33:24	1.21
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java	2009/06/09 19:25:12	1.22
@@ -6,6 +6,7 @@
 import org.biomoby.registry.meta.*;
 import org.biomoby.shared.*;
 import org.biomoby.shared.data.*;
+import org.biomoby.shared.parser.MobyTags;
 
 import javax.xml.xpath.*; // compiled xpath statement
 import javax.xml.namespace.NamespaceContext;
@@ -94,6 +95,7 @@
     public MobyClient(Registry reg) throws MobyException{
 	registry = reg;
         c = CentralImpl.getDefaultCentral(registry);
+	c.setCacheMode(true);
 
 	xpathMap = new HashMap<XPathExpression,MobyComplexBuilder>();
 	urlRegexMap = new HashMap<Pattern,MobyComplexBuilder>();
@@ -101,7 +103,9 @@
 	builderNameMap = new HashMap<String,MobyComplexBuilder>(); 
 	patternNameMap = new HashMap<String,Pattern>(); 
 	nsContext = new NamespaceContextImpl();
-	commonXPath = XPathFactory.newInstance().newXPath();
+	//PG point to xalan until Google App Engine bug is fixed
+	//commonXPath = XPathFactory.newInstance().newXPath();
+	commonXPath = (new org.apache.xpath.jaxp.XPathFactoryImpl()).newXPath();
 	commonXPath.setNamespaceContext(nsContext);
 
  	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
@@ -121,7 +125,7 @@
         if(rulesResource == null){
 	  dataMappingXMLURL = cl.getResource(DATA_MAPPING_XML_RESOURCE);
         }
-	else{
+	else if(rulesResource.length() != 0){
 	    // See if it's a URL
 	    try{
 		dataMappingXMLURL = new URL(rulesResource);
@@ -131,8 +135,10 @@
 	    }
 	}
 	if(dataMappingXMLURL == null){
-	    System.err.println("Could not find MOBY data mapping resource '"+
-			       rulesResource+"'");
+	    if(rulesResource.length() != 0){ // if not left intentionally blank
+		System.err.println("Could not find MOBY data mapping resource '"+
+				   rulesResource+"'");
+	    }
 	}
 	else{
 	    try{
@@ -145,6 +151,42 @@
 	}
     }
 
+    /**
+     * Convenience method to backtrack from a mapping rule to the Moby datatype it produces.
+     *
+     * @param ruleSource where the rule should be loaded from
+     * @param ruleURI a unique ID for the rule, in the source XML using Dublin Core
+     *
+     * @return a template object with the datatype and namespaces produced by the rule
+     */
+    public static MobyPrimaryDataSimple getObjectProduced(URL ruleSource, String ruleURI, Registry reg) throws Exception{
+	MobyPrimaryDataSimple template = null;
+	// Load the rule from the URL to make sure it's really accessible
+	MobyClient client = null;
+	try{
+	    System.setProperty(MobyClient.RESOURCE_SYSTEM_PROPERTY, ""); //load no rules by default
+	    client = new MobyClient(reg);
+	    client.addMappingsFromURL(ruleSource);
+	} catch(Exception e){
+	    throw new Exception("Internal error: Could not create MobyClient and load the rule (from " + 
+				ruleSource+"): "+e.getMessage(), 
+				e);
+	}
+	MobyComplexBuilder mobyBuilder = client.getBuilder(ruleURI);
+	if(mobyBuilder == null){
+	    throw new Exception("Internal error: loaded the transformation rule (URI " + ruleURI + 
+				") from " + ruleSource + " but could not retrieve it from MobyClient " +
+				"using the URI.  Make sure the transformation rule contains a Dublin Core " +
+				"identifier element specifying this URI.");
+	}
+	else{
+	    template = new MobyPrimaryDataSimple("templateRuleReturnedObject");
+	    template.setDataType(mobyBuilder.getDataType());
+	    template.setNamespaces(mobyBuilder.getNamespaces());
+	}
+	return template;	
+    }
+
     public Registry getRegistry(){
 	return registry;
     }
@@ -200,7 +242,12 @@
     protected void addMappingsFromDOM(Document d) throws Exception{
 	Element root = d.getDocumentElement();
 
+	// The document may be either <mappings><object><object>...</mapping>,
 	NodeList ruleSets = root.getChildNodes();
+	if(root.getLocalName().equals(RULE_SET_TAG)){ // or just <object>, make it its own set
+	    ruleSets = new MobyPrefixResolver.MobyNodeList();
+	    (( MobyPrefixResolver.MobyNodeList) ruleSets).add(root);
+	}    
 	for(int i = 0; i < ruleSets.getLength(); i++){
 	    Node node = ruleSets.item(i);
 	    if(node == null || !(node instanceof Element)){
@@ -220,6 +267,7 @@
 	    }
 
 	    String ruleName = ruleSet.getAttribute(RULE_NAME_ATTR);
+	    String urn = getURN(ruleSet);
 
 	    Vector<String> regexStrings = new Vector<String>();
 	    Vector<String> urlRegexStrings = new Vector<String>();
@@ -268,12 +316,15 @@
 			continue;
 		    }
 		    dataTypeString = getDataType(ruleMember);
+		    if(isPrimitiveDataType(dataTypeString)){
+			addMemberMapping(ruleMember, memberMap, dataTypeString);
+		    }
 		}
 		else if(isMemberRule(ruleMember)){
 		    addMemberMapping(ruleMember, memberMap, dataTypeString);
 		}
-		// TODO add other production rules
-		else{
+		// skip any Dublin Core metadata in validation
+		else if(!MobyPrefixResolver.DUBLIN_CORE_NAMESPACE.equals(ruleMember.getNamespaceURI())){
 		    System.err.println("Skipping unexpected "+RULE_SET_TAG+
 				       " child node " + ruleMember.getLocalName());
 		    continue;
@@ -296,13 +347,13 @@
 		}
 
 		for(int j = 0; j < xpathStrings.size(); j++){
-		    addXPathMapping((String) xpathStrings.elementAt(j), namespaceMap, articleNameString);
+		    addXPathMapping((String) xpathStrings.elementAt(j), namespaceMap, articleNameString, urn);
 		}
 		for(int j = 0; j < regexStrings.size(); j++){
-		    addRegexMapping((String) regexStrings.elementAt(j), namespaceMap, articleNameString, ruleName);
+		    addRegexMapping((String) regexStrings.elementAt(j), namespaceMap, articleNameString, ruleName, urn);
 		}
 		for(int j = 0; j < urlRegexStrings.size(); j++){
-		    addURLRegexMapping((String) urlRegexStrings.elementAt(j), namespaceMap, articleNameString);
+		    addURLRegexMapping((String) urlRegexStrings.elementAt(j), namespaceMap, articleNameString, urn);
 		}
 	    }
 	    // Build complex object
@@ -313,13 +364,13 @@
 		}
 
 		for(int j = 0; j < xpathStrings.size(); j++){
-		    addXPathMapping((String) xpathStrings.elementAt(j), namespaceMap, dataTypeString, memberMap, articleNameString);
+		    addXPathMapping((String) xpathStrings.elementAt(j), namespaceMap, dataTypeString, memberMap, articleNameString, urn);
 		}
 		for(int j = 0; j < regexStrings.size(); j++){
-		    addRegexMapping((String) regexStrings.elementAt(j), namespaceMap, dataTypeString, memberMap, articleNameString, ruleName);
+		    addRegexMapping((String) regexStrings.elementAt(j), namespaceMap, dataTypeString, memberMap, articleNameString, ruleName, urn);
 		}
 		for(int j = 0; j < urlRegexStrings.size(); j++){
-		    addURLRegexMapping((String) urlRegexStrings.elementAt(j), namespaceMap, dataTypeString, memberMap, articleNameString);
+		    addURLRegexMapping((String) urlRegexStrings.elementAt(j), namespaceMap, dataTypeString, memberMap, articleNameString, urn);
 		}
 	    }
 
@@ -328,6 +379,28 @@
 	// TODO: add warning if no rules at all were added (the file may not be a MOB rules file!)
     }
 
+    // See if the Dublin Core identifier or source child is available for the element, 
+    // giving us a unique, referencable name for the rule
+    private String getURN(Element e){
+	NodeList children = e.getChildNodes();
+	for(int i = 0; i < children.getLength(); i++){
+	    if(children.item(i) instanceof Element){
+		Element child = (Element) children.item(i);
+		if(!MobyPrefixResolver.DUBLIN_CORE_NAMESPACE.equals(child.getNamespaceURI())){
+		    continue; // not metadata
+		}
+		if(child.getLocalName().equals("identifier") || 
+		   child.getLocalName().equals("source")){
+		    String id = child.getTextContent();
+		    if(id != null && id.trim().length() > 0){
+			return id.trim();
+		    }
+		}
+	    }
+	}
+	return null;
+    }
+
     public boolean isPrefixRule(Element e){
 	return e != null && PREFIX_TAG.equals(e.getLocalName());
     }
@@ -396,7 +469,7 @@
     }
 
     protected String addURLRegexString(Element urlRegexTag, Vector<String> urlRegexStrings) throws Exception{
-	if(!isRegex(urlRegexTag)){
+	if(!isURLRegex(urlRegexTag)){
 	    throw new Exception("Element provided to addURLRegexString (" +
 				(urlRegexTag == null ? null : urlRegexTag.getLocalName()) + 
 				") was not a url_regex rule element");
@@ -431,15 +504,22 @@
 	return str;
     }
 
+    public boolean isPrimitiveDataType(String dataType){
+	return dataType.equals(MobyTags.MOBYSTRING) || dataType.equals(MobyTags.MOBYINTEGER) ||
+	    dataType.equals(MobyTags.MOBYFLOAT) || dataType.equals(MobyTags.MOBYDATETIME) ||
+	    dataType.equals(MobyTags.MOBYBOOLEAN);
+    }
+
     protected void addMemberMapping(Element memTag, Map<String,String[]> membersMap, String dataTypeName) 
 	throws Exception{
-	if(!isMemberRule(memTag)){
+	if(!isMemberRule(memTag) && !isDataTypeRule(memTag)){
 	    throw new Exception("Element provided to addMemberMapping (" +
 				(memTag == null ? null : memTag.getLocalName()) + 
 				") was not a member rule element");
 	}
 	String ruleValue = memTag.getTextContent();
-	String memberNameKey = memTag.getAttribute(DATATYPE_RULE_ATTR);
+	String memberNameKey = isPrimitiveDataType(dataTypeName) ? 
+	    MobyComplexBuilder.PRIMITIVE_VALUE_SENTINEL : memTag.getAttribute(DATATYPE_RULE_ATTR);
 	if(ruleValue == null || ruleValue.length() == 0){
 	    System.err.println("Object member " + memberNameKey + " has a blank value rule");
 	}
@@ -595,18 +675,23 @@
 	return getServices(getMobyObjects(u));
     }
 
+    public MobyDataObject[] getMobyObjects(String textData, MobyDataType targetDataType){
+	return getMobyObjects(textData, targetDataType, null);
+    }
     /**
      * Using the regular expression mappings that have been set up, 
      * maps a string using rules producing moby objects of the given type.
      * @param targetDataType matches any data type if null, otherwise restricts returned items to those that are of (or inherit from) the given type
      */
-    public MobyDataObject[] getMobyObjects(String textData, MobyDataType targetDataType){
+    public MobyDataObject[] getMobyObjects(String textData, MobyDataType targetDataType, MobyNamespace targetNS){
 	Vector<MobyDataObject> objectVector = new Vector<MobyDataObject>();
 
 	for(Pattern pattern: regexMap.keySet()){
 	    MobyComplexBuilder rule = regexMap.get(pattern);
-	    if(targetDataType == null ||
-	       rule.getDataType().inheritsFrom(targetDataType)){
+	    if((targetDataType == null ||
+	       rule.getDataType().inheritsFrom(targetDataType)) &&
+	       (targetNS == null || 
+	       nsArrayContains(rule.getNamespaces(), targetNS))){
 		try{
 		    Matcher matcher = pattern.matcher(textData);
 		    
@@ -630,9 +715,21 @@
 
 	return (MobyDataObject[]) objectVector.toArray(new MobyDataObject[objectVector.size()]);	
     }
+    
+    private boolean nsArrayContains(MobyNamespace[] nss, MobyNamespace tns){
+	if(nss == null || nss.length == 0){
+	    return false;
+	}
+	for(MobyNamespace ns: nss){
+	    if(tns.equals(ns)){
+		return true;
+	    }
+	}
+	return false;
+    }
 
     /**
-     * Create a MOBY data instance from a DOM by applying the rules of the given MobyClient.
+     * Create a MOBY data instance from a DOM by applying the rules of the given MobyClient (xpaths).
      * The creation of a single object or collection is done according to the dataTemplate provided.
      *
      * @throws MobyServiceException NOTE: these are just warning level exceptions about collection-simple casting that you can add to the service response, or ignore if you like
@@ -641,7 +738,60 @@
 	throws Exception, MobyServiceException{
 	Vector<MobyDataObject> results = new Vector<MobyDataObject>();
 
-	for(MobyDataObject resultPart: getMobyObjects(n)){ //TODO: , dataTemplate.getDataType())){
+	for(MobyDataObject resultPart: getMobyObjects(n)){ //, dataTemplate.getDataType())){
+	    results.add(resultPart);
+	}
+
+	if(results.isEmpty()){
+	    throw new Exception("No MOB rules could be applied to the input data");
+	}
+	else if(results.size() > 1){
+	    if(dataTemplate instanceof MobyPrimaryDataSimple){
+		// In this case, eliminate any higher-up objects that
+		// have the exact same contents as the same members who are their
+		// subtypes, as these are superfluous.
+
+		System.err.println("Multiple Moby objects were found in the text data, " +
+				   "but the request was to return a simple. " +
+				   "Only the first value in the collection has been returned.");
+		for(MobyDataObject result: results){
+		    System.err.println("Found object: " + result.getDataType().getName()); 
+		}
+		// TODO: should we instead return the one deepest in the hierarchy (or with the most members)?
+		return results.elementAt(0);
+	    }
+	    else{
+		MobyDataObjectSet resultSet = new MobyDataObjectSet(dataTemplate.getName());
+		resultSet.addAll(results);
+		return resultSet;
+	    }
+	}
+	// One result
+	else{
+	    if(dataTemplate instanceof MobyPrimaryDataSimple){
+		return results.elementAt(0);
+	    }
+	    else{  // Collection of 1
+		MobyDataObjectSet resultSet = new MobyDataObjectSet(dataTemplate.getName());
+		resultSet.add(results.elementAt(0));
+		return resultSet;
+	    }
+	}
+    }
+
+    /**
+     * Create a MOBY data instance from a string by applying the rules of the given MobyClient (regexes).
+     * The creation of a single object or collection is done according to the dataTemplate provided.
+     *
+     * @throws MobyServiceException NOTE: these are just warning level exceptions about collection-simple casting that you can add to the service response, or ignore if you like
+     */
+    public MobyDataInstance getMobyObject(String s, MobyPrimaryData dataTemplate)
+	throws Exception, MobyServiceException{
+	Vector<MobyDataObject> results = new Vector<MobyDataObject>();
+
+	MobyNamespace[] nss = dataTemplate.getNamespaces();
+	MobyNamespace nsRestriction = nss == null || nss.length == 0 ? null : nss[0];
+	for(MobyDataObject resultPart: getMobyObjects(s, dataTemplate.getDataType(), nsRestriction)){
 	    results.add(resultPart);
 	}
 
@@ -794,7 +944,7 @@
     public MobyDataObject[] getMobyObjects(byte[] rawData, MobyDataType targetDataType){
 	// Only do the magic check if the target data type inherits from MOBY's base64 class (i.e. might encode binary data)
 	if(!targetDataType.inheritsFrom(MobyDataType.getDataType(MobyDataBytes.BASE64_DATATYPE, targetDataType.getRegistry()))){
-	    //System.err.println("Data type does not inerit from Base64, continuing with string-based search...");
+	    //System.err.println("Data type does not inherit from Base64, continuing with string-based search...");
 	    return getMobyObjects(new String(rawData), targetDataType);
 	}
 	//System.err.println("Data type " + targetDataType.getName() + " inherits from " + MobyDataBytes.BASE64_DATATYPE +
@@ -874,6 +1024,52 @@
 	return getMobyObjects(textData, (byte[]) null);
     }
 
+    /**
+     * Same as getMobyObjects(String), but returns only those generated Moby objects that 
+     * are derived from URN-addressable rules (which are the keys), mostly for provenance 
+     * and reproducibility purposes.
+     */
+    public Map<String,MobyDataObject[]> getMobyObjectsURNMap(String textData){
+	return getMobyObjectsURNMap(textData, (byte[]) null);
+    }
+
+    public Map<String,MobyDataObject[]> getMobyObjectsURNMap(String textData, byte[] bytes){
+	Map results = new HashMap<String,MobyDataObject[]>();
+	if(regexMap.isEmpty()){
+	    System.out.println("The MOBY Client has not been provided any regex->moby data mappings!");
+	    return results;
+	}
+
+	for(Pattern pattern: regexMap.keySet()){
+	    // Vector of moby objects we construct based on the regex mappings found
+	    Vector<MobyDataObject> objectVector = new Vector<MobyDataObject>(); 
+	    MobyComplexBuilder rule = (MobyComplexBuilder) regexMap.get(pattern);
+	    String urn = rule.getURN();
+	    try{
+		Matcher matcher = pattern.matcher(textData);
+		while(urn != null && matcher.find()){
+		    try{
+			MobyDataObject mobyObj = rule.apply(matcher, bytes);
+			if(mobyObj != null){
+			    objectVector.add(mobyObj);		
+			}
+		    }
+		    catch(MobyException me){
+			System.err.println("Could not build Moby object from match (rule "+urn+"):" + me);
+			me.printStackTrace();
+		    }
+		}
+	    }catch(Throwable t){ // Principally stack overflows
+		System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary");
+	    }
+	    if(urn != null && !objectVector.isEmpty()){
+		results.put(urn, (MobyDataObject[]) objectVector.toArray(new MobyDataObject[objectVector.size()]));
+	    }
+	}
+
+	return results;
+    }
+
     public MobyDataObject[] getMobyObjects(String textData, byte[] bytes){
 	if(regexMap.isEmpty()){
 	    System.out.println("The MOBY Client has not been provided any regex->moby data mappings!");
@@ -981,75 +1177,101 @@
 	    System.out.println("The MOBY Client has not been provided any xpath->moby data mappings!");
 	    return new MobyDataObject[0];
 	}
-
-        Node current_node = n;
-	//for searching (dynamic mapping dependent on doc contents)
-        //PrefixResolver doc_prefix_resolver = new PrefixResolverDefault(current_node); nsContextImpl.setCurrentNode?
-
+	
 	// Vector of moby objects we construct based on the xpath mappings found
 	Vector<MobyDataObject> objectVector = new Vector<MobyDataObject>(); 
-
 	for(XPathExpression xpath: xpathMap.keySet()){ //map still has untraversed xpath entry to test
-	    Object result = null;
-	    try{
-		MobyComplexBuilder rule = (MobyComplexBuilder) xpathMap.get(xpath);
-
-		result = xpath.evaluate(current_node, XPathConstants.NODESET);
+	    objectVector.addAll(applyXPath(n, xpath));
+	}
+	return (MobyDataObject[]) objectVector.toArray(new MobyDataObject[objectVector.size()]);
+    }
+	
+    private Vector<MobyDataObject> applyXPath(Node current_node, XPathExpression xpath){
+	Vector<MobyDataObject> objectVector = new Vector<MobyDataObject>(); 
 
-		// More than one hit?
-		if(result != null){
-		    try{
-			NodeList node_list = (NodeList) result; 
-			//System.out.println("number of nodes in the nodelist: " + node_list.getLength()); 
-			if(node_list == null || node_list.getLength() == 0)
-			    continue;
-			else{
-			    for(int i = 0; i < node_list.getLength(); i++){
-				MobyDataObject mobyObj = rule.applyXPath(node_list.item(i), nsContext);
-				if(mobyObj != null){
-				    objectVector.add(mobyObj);
-				}
+	Object result = null;
+	try{
+	    MobyComplexBuilder rule = (MobyComplexBuilder) xpathMap.get(xpath);
+	    
+	    result = xpath.evaluate(current_node, XPathConstants.NODESET);
+	    
+	    // More than one hit?
+	    if(result != null){
+		try{
+		    NodeList node_list = (NodeList) result; 
+		    //System.out.println("number of nodes in the nodelist: " + node_list.getLength()); 
+		    if(node_list != null && node_list.getLength() != 0){
+			for(int i = 0; i < node_list.getLength(); i++){
+			    MobyDataObject mobyObj = rule.applyXPath(node_list.item(i), nsContext);
+			    if(mobyObj != null){
+				objectVector.add(mobyObj);
 			    }
 			}
-			
-		    }catch(XPathExpressionException xpe2){
-			System.err.println( "Warning: Cannot access resulting node list "+
-					    "due to exception in its retrieval: " + xpe2);
-			return new MobyDataObject[0];
 		    }
+		    
+		}catch(XPathExpressionException xpe2){
+		    System.err.println( "Warning: Cannot access resulting node list "+
+					"due to exception in its retrieval: " + xpe2);
+		    return new Vector<MobyDataObject>();
 		}
-		else{
-		    result = xpath.evaluate(current_node, XPathConstants.STRING);
-		    if(result != null){
-			if(result.toString().equals("")){
-			    continue;  // no useful data
-			}
+	    }
+	    else{
+		//todo: re-eval why we do this! result = xpath.evaluate(current_node, XPathConstants.STRING);
+		if(result != null){
+		    if(!result.toString().equals("")){
 			//System.out.println("Got string result: " + result);
 			MobyDataObject mobyObj = rule.applyXPath(result, nsContext);
 			if(mobyObj != null){
 			    objectVector.add(mobyObj);
 			}
 		    }
-		    else{ //not a node sequence
-			System.out.println( "Warning: the XPath expression ("+ xpath +
-					    ") did not return a node set, cannot select document elements."+
-					    " The returned object was of type "+ result.getClass().getName() );
-			continue;
-		    }
-		}		
-	    }catch(javax.xml.xpath.XPathExpressionException xpe){
-                System.err.println( "Warning: Cannot select nodes due to exception "+
-				    "in XPath expression:" + xpe);
-                return new MobyDataObject[0];
-	    }catch(MobyException me){
-                System.err.println( "Warning: Cannot create objects from select nodes due " +
-				    " to exception in MOBY logic:" + me);
-                return new MobyDataObject[0];
-	    }
-	    
+		}
+		else{ //not a node sequence
+		    System.out.println("Warning: the XPath expression ("+ xpath +
+				       ") did not return a node set, cannot select document elements."+
+				       " The returned object was of type "+ result.getClass().getName() );
+		    return new Vector<MobyDataObject>();
+		}
+	    }		
+	}catch(javax.xml.xpath.XPathExpressionException xpe){
+	    System.err.println("Warning: Cannot select nodes due to exception "+
+			       "in XPath expression ("+xpath+"):" + xpe);
+	    xpe.printStackTrace();
+	    return new Vector<MobyDataObject>();
+	}catch(MobyException me){
+	    System.err.println("Warning: Cannot create objects from select nodes due " +
+			       " to exception in MOBY logic:" + me);
+	    return new Vector<MobyDataObject>();
 	}
+	
+	return objectVector;
+    }
 
-	return (MobyDataObject[]) objectVector.toArray(new MobyDataObject[objectVector.size()]);
+    /**
+     * Same as getMobyObjects(Node), but applies only those rules that have a URN associated with them,
+     * mainly for provenance and reuse purposes.Map<String,MobyDataObject[]>
+     */
+    public Map<String,MobyDataObject[]> getMobyObjectsURNMap(Node n){
+	Map results = new HashMap<String,MobyDataObject[]>();
+
+	// No xpaths to check
+	if(xpathMap.isEmpty()){
+	    System.out.println("The MOBY Client has not been provided any xpath->moby data mappings!");
+	    return results;
+	}
+	
+	// Vector of moby objects we construct based on the xpath mappings found
+	for(XPathExpression xpath: xpathMap.keySet()){ //map still has untraversed xpath entry to test
+	    String urn = xpathMap.get(xpath).getURN();
+	    if(urn == null){
+		continue; // we only want named rules
+	    }
+	    Vector<MobyDataObject> objectVector = applyXPath(n, xpath); 
+	    if(!objectVector.isEmpty()){
+		results.put(urn, (MobyDataObject[]) objectVector.toArray(new MobyDataObject[objectVector.size()]));
+	    }
+	}
+	return results;
     }
 
     public void setRequiredServiceLevel(int level){
@@ -1122,10 +1344,10 @@
     }
 
     public void addRegexMapping(String regexp, String[] mobyObj){ //mobyObj<--mobyNamespaces
-	addRegexMapping(regexp, mobyObj, null);
+	addRegexMapping(regexp, mobyObj, null, null);
     }
 
-    public void addRegexMapping(String regexp, String[] mobyObj, String articleName){ //mobyObj<--mobyNamespaces
+    public void addRegexMapping(String regexp, String[] mobyObj, String articleName, String urn){ //mobyObj<--mobyNamespaces
 	if(mobyObj == null){
 	    System.err.println("Ignoring empty namespace-only regex rule mappings");
 	    return;
@@ -1136,10 +1358,10 @@
 	for(int i = 0; i < mobyObj.length; i++){
 	    nsRules.put(mobyObj[i], "$0");
 	}
-	addRegexMapping(regexp, nsRules, articleName, (String) null);
+	addRegexMapping(regexp, nsRules, articleName, (String) null, urn);
     }
 
-    public void addURLRegexMapping(String url_regexp, String[] mobyObj, String articleName){ //mobyObj<--mobyNamespaces
+    public void addURLRegexMapping(String url_regexp, String[] mobyObj, String articleName, String urn){ //mobyObj<--mobyNamespaces
 	if(mobyObj == null){
 	    System.err.println("Ignoring empty namespace-only url regex rule mappings");
 	    return;
@@ -1150,7 +1372,7 @@
 	for(int i = 0; i < mobyObj.length; i++){
 	    url_nsRules.put(mobyObj[i], "$1");
 	}
-	addURLRegexMapping(url_regexp, url_nsRules, articleName);
+	addURLRegexMapping(url_regexp, url_nsRules, articleName, urn);
     }
 
     /**
@@ -1227,27 +1449,27 @@
 	return url_regex_flexible;
     }
 
-    protected void addRegexMapping(String regexp, Map<String,String> nsRules, String articleName, String ruleName){ //nsRules = Map<String ns, String regex_replacement>
+    protected void addRegexMapping(String regexp, Map<String,String> nsRules, String articleName, String ruleName, String urn){ //nsRules = Map<String ns, String regex_replacement>
 	if(nsRules == null || nsRules.size() == 0){
 	    System.err.println("Ignoring empty namespace-only regex rule mappings");
 	    return;
 	}
 
-	addRegexMapping(regexp, nsRules, (String) null, (Map<String,String[]>) null, articleName, null);
+	addRegexMapping(regexp, nsRules, (String) null, (Map<String,String[]>) null, articleName, null, urn);
     }
 
-    protected void addURLRegexMapping(String url_regexp, Map<String,String> url_nsRules, String articleName){ //nsRules = Map<String ns, String regex_replacement>
+    protected void addURLRegexMapping(String url_regexp, Map<String,String> url_nsRules, String articleName, String urn){ //nsRules = Map<String ns, String regex_replacement>
 	if(url_nsRules == null || url_nsRules.size() == 0){
 	    System.err.println("Ignoring empty namespace-only url regex rule mappings");
 	    return;
 	}
 
-	addURLRegexMapping(url_regexp, url_nsRules, (String) null, (Map<String,String[]>) null, articleName);
+	addURLRegexMapping(url_regexp, url_nsRules, (String) null, (Map<String,String[]>) null, articleName, urn);
     }
 
     public void addRegexMapping(String regexp, Map<String,String> nsRules, 
 				String mobyDataType, Map<String,String[]> membersMap){
-	addRegexMapping(regexp, nsRules, mobyDataType, membersMap, null, null);
+	addRegexMapping(regexp, nsRules, mobyDataType, membersMap, null, null, null);
     }
 
     /**
@@ -1337,7 +1559,7 @@
 
     public void addRegexMapping(String regexp, Map<String,String> nsRules, String mobyDataType, 
 				Map<String,String[]> membersMap, String articleName,
-				String ruleName){ 
+				String ruleName, String urn){ 
 	try{
 	    // Use a StringBuffer so it's mutable by handleHASMembers()
 	    StringBuffer articleNameBuffer = new StringBuffer(articleName == null ? "" : articleName); 
@@ -1348,26 +1570,33 @@
 	    Pattern pattern = Pattern.compile(processRegExp(regexp, membersMap), Pattern.DOTALL | Pattern.COMMENTS);	
 
 	    // Base object
+	    MobyComplexBuilder mcb = null;
 	    if(mobyDataType == null || mobyDataType.length() == 0){
-		regexMap.put(pattern, new MobyComplexBuilder("Object", 
-							     membersMap, 
-							     nsRules,
-							     this,
-							     articleNameBuffer.toString()));
+		mcb = new MobyComplexBuilder("Object", 
+					     membersMap, 
+					     nsRules,
+					     this,
+					     articleNameBuffer.toString());
 	    }
 	    // Complex Object
 	    else{
-		regexMap.put(pattern, new MobyComplexBuilder(mobyDataType, 
-							     membersMap, 
-							     nsRules,
-							     this,
-							     articleNameBuffer.toString()));
+		mcb = new MobyComplexBuilder(mobyDataType, 
+					     membersMap, 
+					     nsRules,
+					     this,
+					     articleNameBuffer.toString());
 	    }
+	    mcb.setURN(urn);
+	    regexMap.put(pattern, mcb);
 
 	    if(ruleName != null && ruleName.length() != 0){
 		patternNameMap.put(ruleName, pattern);
 		builderNameMap.put(ruleName, regexMap.get(pattern));
 	    }
+	    if(urn != null && urn.length() != 0){
+		patternNameMap.put(urn, pattern);
+		builderNameMap.put(urn, regexMap.get(pattern));
+	    }
 
 	}catch(Exception e){
 	    System.err.println("Could not create regular expression statement from '" +
@@ -1377,27 +1606,35 @@
     }
 
     public void addURLRegexMapping(String url_regexp, Map<String,String> url_nsRules, 
-				   String mobyDataType, Map<String,String[]> membersMap, String articleName){ //mobyObj<--mobyNamespaces
+				   String mobyDataType, Map<String,String[]> membersMap, 
+				   String articleName, String urn){ //mobyObj<--mobyNamespaces
 	//System.out.println("url regex addMapping: " + url_regexp);
 	try{
 	    Pattern pattern = Pattern.compile(processURLRegExp(url_regexp));	
 
 	    // Base object
+	    MobyComplexBuilder mcb = null;
 	    if(mobyDataType == null || mobyDataType.length() == 0){
-		urlRegexMap.put(pattern, new MobyComplexBuilder("Object", 
-								membersMap, 
-								url_nsRules,
-								this,
-								articleName));
-		return;
+		mcb = new MobyComplexBuilder("Object", 
+					     membersMap, 
+					     url_nsRules,
+					     this,
+					     articleName);
+	    }
+	    else{
+		// Complex Object
+		mcb = new MobyComplexBuilder(mobyDataType, 
+					     membersMap, 
+					     url_nsRules,
+					     this,
+					     articleName);
 	    }
+	    mcb.setURN(urn);
+	    urlRegexMap.put(pattern, mcb);
 
-	    // Complex Object
-	    urlRegexMap.put(pattern, new MobyComplexBuilder(mobyDataType, 
-							    membersMap, 
-							    url_nsRules,
-							    this,
-							    articleName));
+	    if(urn != null && urn.length() != 0){
+		builderNameMap.put(urn, mcb);
+	    }
 	}catch(Exception e){
 	    System.err.println("Could not create URL regular expression statement from '" +
 			       url_regexp + "': " + e);
@@ -1416,36 +1653,42 @@
 	for(int i = 0; i < mobyObj.length; i++){
 	    nsRules.put(mobyObj[i], ".");
 	}
-	addXPathMapping(xpath, nsRules, null);
+	addXPathMapping(xpath, nsRules, null, null);
     }
 
-    public void addXPathMapping(String xpath_exp, Map<String,String> nsRules, String articleName){ //mobyObj<--mobyNamespaces
-	addXPathMapping(xpath_exp, nsRules, (String) null, (Map<String,String[]>) null, articleName);
+    public void addXPathMapping(String xpath_exp, Map<String,String> nsRules, String articleName, String urn){ //mobyObj<--mobyNamespaces
+	addXPathMapping(xpath_exp, nsRules, (String) null, (Map<String,String[]>) null, articleName, urn);
     }
 
     public void addXPathMapping(String xpath_exp, Map<String,String> nsRules, String mobyDataType, 
-				Map<String,String[]> membersMap, String articleName){ //mobyObj<--mobyNamespaces
+				Map<String,String[]> membersMap, String articleName, String urn){ //mobyObj<--mobyNamespaces
 	//System.out.println("xpath addMapping: " + xpath_exp);
 	try{
 	    XPathExpression xpath = commonXPath.compile(xpath_exp);
 
 	    // Base object
+	    MobyComplexBuilder mcb = null;
 	    if(mobyDataType == null || mobyDataType.length() == 0){
-		xpathMap.put(xpath, new MobyComplexBuilder("Object", 
-							   membersMap, 
-							   nsRules,
-							   this,
-							   articleName));
-		return;
+		mcb = new MobyComplexBuilder("Object", 
+					     membersMap, 
+					     nsRules,
+					     this,
+					     articleName);		
 	    }
+	    else{
+		// Complex Object
+		mcb = new MobyComplexBuilder(mobyDataType, 
+					     membersMap, 
+					     nsRules,
+					     this,
+					     articleName);
+	    }
+	    mcb.setURN(urn);
+	    xpathMap.put(xpath, mcb);
 
-	    // Complex Object
-	    xpathMap.put(xpath, new MobyComplexBuilder(mobyDataType, 
-						       membersMap, 
-						       nsRules,
-						       this,
-						       articleName));
-
+	    if(urn != null && urn.length() != 0){
+		builderNameMap.put(urn, mcb);
+	    }
 	}catch(Exception e){
 	    logger.warn("Could not create XPath select statement from '" +
 			xpath_exp + "': " + e.getMessage());
@@ -1544,7 +1787,7 @@
     }
 
     /**
-     * If a rule was given this name, the MOBY object builder for the rule is returned.
+     * If a rule was given this name, or url/lsid, the MOBY object builder for the rule is returned.
      */
     public MobyComplexBuilder getBuilder(String ruleName){
 	return builderNameMap.get(ruleName);




More information about the MOBY-guts mailing list