[MOBY-guts] biomoby commit

Paul Gordon gordonp at dev.open-bio.org
Thu Oct 30 02:33:25 UTC 2008


gordonp
Wed Oct 29 22:33:24 EDT 2008
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util
In directory dev.open-bio.org:/tmp/cvs-serv10500/src/main/ca/ucalgary/services/util

Modified Files:
	MobySpecWrapper.java SourceMap.java WSDLConfig.java 
Log Message:
Updates related to SAWSDL wrapping Web Service implementation
moby-live/Java/src/main/ca/ucalgary/services/util MobySpecWrapper.java,1.1,1.2 SourceMap.java,1.1,1.2 WSDLConfig.java,1.4,1.5
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/MobySpecWrapper.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/MobySpecWrapper.java	2008/03/13 23:05:47	1.1
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/MobySpecWrapper.java	2008/10/30 02:33:24	1.2
@@ -19,6 +19,7 @@
     private Map<String,Map<String,String>> serviceInputs;
     private Map<String,Map<String,String>> serviceInputFormats;
     private Map<String,Map<String,String>> serviceSecondaries;
+    private Map<String,Map<String,String>> serviceSecondaryFormats;
     private Map<String,Map<String,String>> serviceOutputs;
     private Map<String,Map<String,String>> serviceOutputFormats;
     private Map<String,Map<String,String>> fixedParams;
@@ -36,6 +37,7 @@
 	serviceOutputs = new HashMap<String,Map<String,String>>();
 	fixedParams = new HashMap<String,Map<String,String>>();
 	serviceInputFormats = new HashMap<String,Map<String,String>>();
+	serviceSecondaryFormats = new HashMap<String,Map<String,String>>();
 	serviceOutputFormats = new HashMap<String,Map<String,String>>();
     }
 
@@ -102,10 +104,23 @@
 	return serviceInputs.get(currentService);
     }
 
+    public void setSecondaryInputFormats(Map<String,String> specs){
+	serviceSecondaryFormats.put(currentService, specs);
+    }
+
+    public Map<String,String> getSecondaryInputFormats(){
+	return serviceSecondaryFormats.get(currentService);
+    }
+
     public void setPrimaryInputFormats(Map<String,String> specs){
 	serviceInputFormats.put(currentService, specs);
     }
 
+    /**
+     * Note that the string values for the formats are specialized for the 
+     * various LegacyService child classes, as they will all have their own naming scheme for legacy
+     * formats.
+     */
     public Map<String,String> getPrimaryInputFormats(){
 	return serviceInputFormats.get(currentService);
     }

===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/SourceMap.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/SourceMap.java	2008/06/30 17:42:29	1.1
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/SourceMap.java	2008/10/30 02:33:24	1.2
@@ -4,23 +4,21 @@
 
 import java.io.*;
 import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 
 /**
  * Converts a Map of Strings into a Source for the Java SOAP libraries.
  * The Map should be of the form (SOAP input param name -> XML Schema Instance data).
  */
-public class SourceMap extends javax.xml.transform.stream.StreamSource implements ConcurrentMap<String,String>{
+public class SourceMap extends javax.xml.transform.stream.StreamSource implements Map<String,String>{
 
-    private ConcurrentHashMap<String,String> members;
+    private TreeMap<String,String> members;
     private QName messageName;
 
     /**
      * @param msgName the name of the operation message (WSDL 1.1) or operation element (WSDL 2.0) that is being encapsulated
      */
     public SourceMap(QName msgName){
-	members = new ConcurrentHashMap<String,String>();
+	members = new TreeMap<String,String>();
 	messageName = msgName;
     }
 
@@ -38,7 +36,7 @@
 	xmlContents.append("<?xml version='1.0'?>\n");
 	xmlContents.append("<m:"+messageName.getLocalPart()+" xmlns:m=\""+messageName.getNamespaceURI()+"\">");
 
-	// Serialize map members NOTE: not correct yet!
+	// Serialize map members 
 	for(String value: values()){
 	    xmlContents.append(value);
 	}
@@ -140,41 +138,5 @@
     public int size(){
 	return members.size();
     }
-
-    /*
-     * If the field with a given name is not yet associated with any value, associate it with the given value.
-     * Note that this operation is atomic for data integrity purposes in multi-threaded apps.
-     */
-    public String putIfAbsent(String key, String value){
-	return members.putIfAbsent(key, value);
-    }
-
-    /*
-     * Removes the field with the given name only if it currently has the given value.
-     * Note that this operation is atomic for data integrity purposes in multi-threaded apps.
-     *
-     * @return true if the replacement operation caused a change in the object value
-     */
-    public boolean remove(Object key, Object value){
-	return members.remove(key, value);
-    }
-
-    /*
-     * Replaces the field with the given name only if the field already exists in the composite.
-     * Note that this operation is atomic for data integrity purposes in multi-threaded apps.
-     */
-    public String replace(String fieldName, String value){
-	return members.replace(fieldName, value);
-    }
-
-    /*
-     * Replaces the field with the given name only if it currently has a given value
-     * Note that this operation is atomic for data integrity purposes in multi-threaded apps.
-     *
-     * @return true if the replacement operation caused a change in the object value
-     */
-    public boolean replace(String fieldName, String oldValue, String newValue){
-	return members.replace(fieldName, oldValue, newValue);
-    }
   
 }

===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/WSDLConfig.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/WSDLConfig.java	2008/07/03 16:29:25	1.4
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/WSDLConfig.java	2008/10/30 02:33:24	1.5
@@ -138,6 +138,7 @@
 	NodeList partElements = messageElement.getElementsByTagNameNS(MobyPrefixResolver.WSDL_NAMESPACE, "part");
 	Map<String,String> inputs = new HashMap<String,String>();
 	Map<String,String> inputMappings = new HashMap<String,String>();
+	Map<String,String> secondaryMappings = new HashMap<String,String>();
 	Map<String,String> inputTypes = new HashMap<String,String>();
 	Map<String,String> secondaryInputs = new HashMap<String,String>();
 	Map<String,String> outputs = new HashMap<String,String>();
@@ -177,6 +178,7 @@
 					    "' is not a properly formed Moby primary or secondary param LSID as required");
 		    }
 		    secondaryInputs.put(partName, mobyParam);
+		    secondaryMappings.put(partName, schemaMapping);
 		}
 		else{
 		    inputs.put(partName, mobyParam);
@@ -200,6 +202,7 @@
 	    setPrimaryInputFormats(inputMappings);
 	    setInputXSDTypes(inputTypes);
 	    setSecondaryInputs(secondaryInputs);
+	    setSecondaryInputFormats(secondaryMappings);
 	}
 	else{ // it's output
 	    setPrimaryOutputs(outputs);
@@ -216,25 +219,31 @@
 	   (!dataTypeLSIDFields[3].equals("objectclass") && !dataTypeLSIDFields[3].equals("namespacetype"))){
 	    return null;
 	}
-	// Special case, if the LSID is a namespace, spec out a base object in the given namespace
-	if(dataTypeLSIDFields[3].equals("namespacetype")){
-	    return paramName+":"+MobyTags.MOBYOBJECT+":"+dataTypeLSIDFields[4];
-	}
-	else{
-	    // Deal with the case where the output XSD data type is an array: 
-	    // implicitly make the return data type Collection(Thing)
-
-	    // See if the name is namespace qualified, and separate the local part if so
-	    String nsURI = "";
-	    if(paramXSDType.contains(":")){
-		String nsPrefix = paramXSDType.substring(0, paramXSDType.indexOf(":"));  //XML NS prefix
-		paramXSDType = paramXSDType.substring(paramXSDType.indexOf(":")+1); //local part
-		nsURI = element.lookupNamespaceURI(nsPrefix);  //prefix->URI
+	// Deal with the case where the output XSD data type is an array: 
+	// implicitly make the return data type Collection(Thing)
+	
+	// See if the name is namespace qualified, and separate the local part if so
+	String nsURI = "";
+	if(paramXSDType.contains(":")){
+	    String nsPrefix = paramXSDType.substring(0, paramXSDType.indexOf(":"));  //XML NS prefix
+	    paramXSDType = paramXSDType.substring(paramXSDType.indexOf(":")+1); //local part
+	    nsURI = element.lookupNamespaceURI(nsPrefix);  //prefix->URI
+	}
+	Element schemaDataTypeElement = isBasicType(paramXSDType) ? null : 
+	    getSchemaElement(element.getOwnerDocument(), nsURI, paramXSDType);	    
+	if(getArrayType(schemaDataTypeElement) != null){
+	    // Special case, if the LSID is a namespace, spec out a base object in the given namespace
+	    if(dataTypeLSIDFields[3].equals("namespacetype")){
+		return paramName+":Collection("+MobyTags.MOBYOBJECT+"):"+dataTypeLSIDFields[4];
 	    }
-	    Element schemaDataTypeElement = getSchemaElement(element.getOwnerDocument(), nsURI, paramXSDType);	    
-	    if(getArrayType(schemaDataTypeElement) != null){
+	    else{
 		return paramName+":Collection("+dataTypeLSIDFields[4]+")";
 	    }
+	}
+	else{
+	    if(dataTypeLSIDFields[3].equals("namespacetype")){
+		return paramName+":"+MobyTags.MOBYOBJECT+":"+dataTypeLSIDFields[4];
+	    }
 	    else{
 		return paramName+":"+dataTypeLSIDFields[4];
 	    }
@@ -242,6 +251,10 @@
 	
     }
 
+    private boolean isBasicType(String xsdType){
+	return "string".equals(xsdType); //TODO: fill out list
+    }
+
     public String wsdlParam2MobySecondaryParam(Element partElement, String paramName, 
 					       String paramXSDType, String dataTypeLSID) throws Exception{
 	String[] dataTypeLSIDFields = dataTypeLSID.split(":");
@@ -252,6 +265,7 @@
 	}   
 	// the format for secondaries is "name:type:defaultValue:[min,max]", where [min,max] can be an enumeration as well
 	String restrictionsSpec = getSecondaryParamRestrictions(partElement);
+	//System.err.println("Full secondary spec is " + paramName+":"+dataTypeLSIDFields[4]+":"+restrictionsSpec);
 	return paramName+":"+dataTypeLSIDFields[4]+":"+restrictionsSpec;
     }
 
@@ -478,6 +492,9 @@
 	//  <xsd:restriction base="soapenc:Array">
 	//   <xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="typens:Thing[]"/>
 	// </xsd:restriction></xsd:complexContent></xsd:complexType>
+	if(schemaDefElement == null){
+	    return null;
+	}
 	NodeList contentElements = schemaDefElement.getElementsByTagNameNS(MobyPrefixResolver.XSD_NAMESPACE, 
 									   "complexContent");
 	if(contentElements.getLength() == 1){
@@ -538,6 +555,31 @@
 			    nsUri + " does not exist");
     }
 
+    public static Element renameSoapArrayElements(Element arrayElement, String newName, Document owner){
+	NodeList arrayElements = arrayElement.getChildNodes();
+	Element renamedArray = owner.createElement("soap-array");
+	for(int j = 0; j < arrayElements.getLength(); j++){
+	    if(!(arrayElements.item(j) instanceof Element)){
+		continue;
+	    }
+	    // For XPath rules to work properly, we need to rename the items 
+	    // in the array to the parent name
+	    Element renamedArrayItem = owner.createElement(newName);
+	    // clone the old element attributes and children into the new one
+	    Element oldElement = (Element) arrayElements.item(j);
+	    NamedNodeMap attrs = oldElement.getAttributes();
+	    for(int k = 0; k < attrs.getLength(); k++){
+		renamedArrayItem.setAttributeNodeNS((Attr) attrs.item(k).cloneNode(true));
+	    }
+	    NodeList children = oldElement.getChildNodes();
+	    for(int k = 0; k < children.getLength(); k++){
+		renamedArrayItem.appendChild(children.item(k).cloneNode(true));
+	    }
+	    renamedArray.appendChild(renamedArrayItem);
+	}
+	return renamedArray;
+    }
+
     protected String convertSourceToMobySecondaryValues(Source source, URL liftingSchema, boolean arrayRule) throws Exception{
 	// The source will contain an XML document, lets convert it to a string of the form val1,val2,val3 using a stylesheet
 	TransformerFactory transformerFactory = TransformerFactory.newInstance();
@@ -560,8 +602,22 @@
 	    if(!(source instanceof StreamSource)){
 		StringWriter verbatim = new StringWriter();
 		transformerFactory.newTransformer().transform(source, new StreamResult(verbatim));
-                //System.err.println("Verbatim source is:\n" + verbatim);
-		source = new StreamSource(new StringReader(verbatim.toString()));
+		// Need to compensate for the fact that some XSLT transformers don't copy over the
+		// namespace declaration properly, so declare it manually for xsi if that's the case
+		// otherwise you get a parsing error later on when trying to do the 
+		// xml schema -> moby xml transformation.  Ditto with soap encoding.
+		String verb = verbatim.toString();
+		if(verb.indexOf(" xmlns:xsi") == -1 && 
+		   verb.indexOf(" xsi:") != -1){
+		    verb = verb.replaceFirst(" xsi:", 
+					     " xmlns:xsi=\""+MobyPrefixResolver.XSI_NAMESPACE2001+"\" xsi:");
+		}
+		if(verb.indexOf(" xmlns:SOAP-ENC") == -1 && 
+		   verb.indexOf(" SOAP-ENC:") != -1){
+		    verb = verb.replaceFirst(" SOAP-ENC:", 
+					     " xmlns:SOAP-ENC=\""+MobyPrefixResolver.SOAP_ENC_NAMESPACE+"\" SOAP-ENC:");
+		}
+		source = new StreamSource(new StringReader(verb));
 	    }
 
 	    Document arrayDoc = null;
@@ -572,10 +628,16 @@
 		arrayDoc = docBuilder.parse(new org.xml.sax.InputSource(((StreamSource) source).getReader()));
 	    }
 	    else{
-		throw new Exception("Neither the InputStream or Reader was available from " +
+		throw new Exception("Neither an InputStream nor a Reader was available from " +
 				    "the StreamSource, cannot process the source");
 	    }
-	    NodeList arrayElements = arrayDoc.getElementsByTagName("item");
+	    Element arrayElement = (Element) arrayDoc.getDocumentElement().getFirstChild();
+	    String dataTypeAttr = arrayElement.getAttributeNS(MobyPrefixResolver.SOAP_ENC_NAMESPACE, "arrayType");
+	    String dataType = dataTypeAttr.replaceFirst("^.*:([^\\[]+).*", "$1");
+	    //System.err.println("Array Data Type for secondary source is " + dataType);
+	    // for RPC-encoded data, rename item tags to real data type name
+	    Element renamedArray = renameSoapArrayElements(arrayElement, dataType, arrayDoc);  
+	    NodeList arrayElements = renamedArray.getElementsByTagName(dataType);
 	    for(int i = 0; i < arrayElements.getLength(); i++){
 		if(i != 0){
 		    stringWriter.write(',');  //join values with a comma
@@ -587,7 +649,7 @@
 	else{
 	    transformer.transform(source, new StreamResult(stringWriter));
 	}
-	//System.err.println("Response payload:\n"+stringWriter.toString());
+	//System.err.println("Response payload for secondary param:\n"+stringWriter.toString());
 
 	return stringWriter.toString();
     }




More information about the MOBY-guts mailing list