[MOBY-guts] biomoby commit

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


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

Modified Files:
	LegacyService.java WSDLService.java 
Log Message:
Updates related to SAWSDL wrapping Web Service implementation
moby-live/Java/src/main/ca/ucalgary/services LegacyService.java,1.3,1.4 WSDLService.java,1.1,1.2
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/LegacyService.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/LegacyService.java	2008/06/30 17:42:29	1.3
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/LegacyService.java	2008/10/30 02:33:24	1.4
@@ -41,6 +41,19 @@
 	return null;
     }
     
+    protected MobyDataInstance getMobyData(org.w3c.dom.Node legacyDOMNode, 
+					   MobyPrimaryData mobyDataTemplate)
+	throws Exception{	
+	try{
+	    return mobyClient.getMobyObject(legacyDOMNode, mobyDataTemplate);
+	} catch(MobyServiceException mse){
+	    //getMobyObject() throws untransformed-data warnings
+	    addException(mse);
+	}
+
+	return null;
+    }
+
     protected byte[] getLegacyData(MobyDataInstance mobyData, String legacyFormatName)
 	throws Exception{
 	// binary data should be passed through as-is 
@@ -54,8 +67,8 @@
     /**
      * Mechanism to incorporate new tranformation rules
      */
-    protected void addLoweringMappingsFromURL(URL u) throws Exception{
-	textClient.addMappingsFromURL(u);
+    protected String addLoweringMappingsFromURL(URL u) throws Exception{
+	return textClient.addMappingsFromURL(u);
     }
 
     protected void addLiftingMappingsFromURL(URL u) throws Exception{

===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/WSDLService.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/WSDLService.java	2008/06/30 21:19:33	1.1
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/WSDLService.java	2008/10/30 02:33:24	1.2
@@ -11,8 +11,12 @@
 import org.biomoby.shared.*;
 import org.biomoby.shared.data.*; 
 
+import org.w3c.dom.*;
+
 import javax.xml.namespace.QName;
+import javax.xml.parsers.*;
 import javax.xml.transform.*;
+import javax.xml.transform.dom.*;
 import javax.xml.transform.stream.*;
 import javax.xml.ws.*;
 
@@ -38,16 +42,32 @@
     protected URL remoteWSDLUrl;
     protected WSDLConfig wsdlConfig;
     protected Dispatch<Source> dispatch;
-    private LSIDResolver lsidResolver; //used to fetch transformation rules, etc. given in the SAWSDL attributes
+    private TransformerFactory transformerFactory;
+    private LSIDResolver lsidResolver; // used to fetch transformation rules, etc. given in the SAWSDL attributes
     private Transformer nullTransformer;
+    private Map<String,Transformer> secondaryTransformers; // secondary param to xml schema engines
+    // SAWSDL deals with transformation URIs, but the transformation engine needs a data format name
+    private Map<String,String> uri2XmlFormat; 
+    private static DocumentBuilder docBuilder;
 
     private static Logger logger = Logger.getLogger("ca.ucalgary.services.WSDLService");
 
     public void init(){
 	super.init();
 
+	// Explicitly set these so Java Web services will work in Java 1.5
+	if(System.getProperty("javax.xml.stream.XMLInputFactory") == null){
+	    System.setProperty("javax.xml.stream.XMLInputFactory",
+			       "com.ctc.wstx.stax.WstxInputFactory");
+	}
+
+	if(System.getProperty("javax.xml.stream.XMLOutputFactory") == null){
+	    System.setProperty("javax.xml.stream.XMLOutputFactory",
+			       "com.ctc.wstx.stax.WstxOutputFactory");
+	}
+
 	lsidResolver = new LSIDResolver();
-	TransformerFactory transformerFactory = TransformerFactory.newInstance();
+	transformerFactory = TransformerFactory.newInstance();
 	try{
 	    nullTransformer = transformerFactory.newTransformer();  // for verbatim copying of SOAP response XML
 	} catch (TransformerConfigurationException tce){
@@ -55,15 +75,29 @@
 		       "Could not create an XSLT transformer: " + tce,
 		       tce);
 	}
+	// Keep track of the sawsdl schema mapping uris and link them to the data format names
+	// our engine needs (the mode attribute value in the XSLT template)
+	uri2XmlFormat = new HashMap<String,String>();
+	secondaryTransformers = new HashMap<String,Transformer>();
+
+	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        try{
+            docBuilder = dbf.newDocumentBuilder();
+        } catch(Exception e){
+            e.printStackTrace();
+        }
     }
 
     public void processRequest(MobyDataJob request, MobyDataJob result) throws Exception{
 	MobyService service = getService();
 
 	// converts a map of strings into a source for the SOAP library
-	SourceMap source = new SourceMap(wsdlConfig.getOperationInputQName()); 
+	//SourceMap source = new SourceMap(wsdlConfig.getOperationInputQName()); 
+	SourceMap source = new SourceMap(new QName(wsdlConfig.getOperationInputQName().getNamespaceURI(), 
+						   wsdlConfig.getOperationName())); 
 
-	Map<String,String> xmlFormats = wsdlConfig.getPrimaryInputFormats();
+	Map<String,String> ruleURIs = wsdlConfig.getPrimaryInputFormats();
 	for(MobyPrimaryData mobyInputTemplate: service.getPrimaryInputs()){
 	    String paramName = mobyInputTemplate.getName();
 	    MobyDataInstance mobyData = request.get(paramName);
@@ -77,18 +111,46 @@
 	    // Transform the moby data as required and put it into the SOAP message
 	    // NOTE: We assume, since it's WSDL, that the "legacy" format is XML Schema, which means the
 	    // coercion of the legacy byte data to a String is kosher.
+	    String xmlFormat = uri2XmlFormat.get(ruleURIs.get(paramName));
+
+	    byte[] paramBytes = getLegacyData(mobyData, xmlFormat);
+	    if(paramBytes == null){
+		mobyData.setXmlMode(MobyDataInstance.SERVICE_XML_MODE);
+		throw new MobyException("The Moby parameter '" + paramName + 
+					"' could not be transformed into '" + 
+					xmlFormat + 
+					"' format by an XSLT rule.  Source data was:\n"+
+					mobyData.toXML());
+	    }
 	    source.put(paramName,
-		       new String(getLegacyData(mobyData, xmlFormats.get(paramName))));
+		       new String(paramBytes));
+	}
+
+	// Now deal with the secondaries
+	for(MobyDataSecondaryInstance mobySec: request.getSecondaryData()){
+	    Transformer transformer = secondaryTransformers.get(mobySec.getName());
+	    //System.err.println("Transformer class being used is " + transformer.getClass().getName());
+	    mobySec.setXmlMode(MobyDataInstance.SERVICE_XML_MODE);
+	    StreamSource secSrc = new StreamSource(new ByteArrayInputStream(mobySec.toXML().getBytes()));
+	    StringWriter xsltResult = new StringWriter();
+	    transformer.transform(secSrc, new StreamResult(xsltResult));
+	    source.put(mobySec.getName(), xsltResult.toString());
 	}
 
 	Source resultSource = dispatch.invoke(source);
-	Map<String,Map<String,byte[]>> responseData = getResponseData(resultSource);
+	Map<String,Node> responseData = getResponseData(resultSource);
+
+	//for(String key: responseData.keySet()){
+	//    System.err.println("Have response key " + key);
+	//    System.err.println("Value is "+responseData.get(key));
+	//}
 
 	// Parse the results, matching up the correct parameter in the WSDL with the correct Moby type.
 	// Note that output WSDL and Moby names are the same, allowing auto-matchup.
 	// Also note that for the moment you can't write a MOB rule that aggregates multiple outputs.
 	for(MobyPrimaryData mobyOutputTemplate: service.getPrimaryOutputs()){
 	    if(!responseData.containsKey(mobyOutputTemplate.getName())){
+		System.err.println("Couldn't find required service output called " + mobyOutputTemplate.getName());
 		continue;  // Not an output Moby will use
 	    }
 	    MobyDataInstance mdi = getMobyData(responseData.get(mobyOutputTemplate.getName()), mobyOutputTemplate);
@@ -100,7 +162,6 @@
 	    }
 	    result.put(mobyOutputTemplate.getName(), mdi);
 	}
-
     }
 
     public MobyService createServiceFromConfig(javax.servlet.http.HttpServletRequest request)
@@ -142,8 +203,15 @@
 		       "the service " + wsdlConfig.getServiceQName() + ", either the WSDL or the WSDLConfig's " +
 		       "portQName parsed (" + wsdlConfig.getPortQName() + ") is wrong",
 		       e);
+	    throw e;
 	}
-	
+
+        // Call to parent, which handles spec-wrapper-to-MobyServlet-config conversion
+	// Need to call the parent so that addLoweringMappingsFromURL(), etc. calls below
+	// work on the instantiated WrapperService data transformation engines (TextClient and MobyClient)
+	// FYI: wsdlConfig contains all of the info about how many parameters there are, their types, etc.
+	MobyService ms = createServiceFromConfig(request, wsdlConfig);
+
 	// Resolve the LSIDs used to describe the I/O formats into their actual data 
 	// (Moby DEM and MOB conversion rules)
 	for(String schemaMappingLSID: wsdlConfig.getPrimaryInputFormats().values()){
@@ -155,18 +223,21 @@
 			   e.getClass().getName() + " while resolving lowering schema mapping LSID " +
 			   schemaMappingLSID +" from the SAWSDL document",
 			   e);
+		throw e;
 	    }
 	    try{
-		addLoweringMappingsFromURL(u);
+		String dataFormatReturned = addLoweringMappingsFromURL(u);
+		uri2XmlFormat.put(schemaMappingLSID, dataFormatReturned);
 	    } catch(Exception e){
 		logger.log(Level.SEVERE,
 			   e.getClass().getName() + " while parsing lowering schema mapping (LSID " +
 			   schemaMappingLSID +")",
 			   e);
+		throw e;
 	    }
 	}
 	
-	for(String schemaMappingLSID: wsdlConfig.getPrimaryInputFormats().values()){
+	for(String schemaMappingLSID: wsdlConfig.getPrimaryOutputFormats().values()){
 	    URL u = null;
 	    try{
 		u = lsidResolver.resolveDataURL(schemaMappingLSID);		
@@ -175,6 +246,7 @@
 			   e.getClass().getName() + " while resolving lifting schema mapping LSID " +
 			   schemaMappingLSID +" from the SAWSDL document",
 			   e);
+		throw e;
 	    }
 	    try{
 		addLiftingMappingsFromURL(u);
@@ -183,11 +255,35 @@
 			   e.getClass().getName() + " while parsing lifting schema mapping (LSID " +
 			   schemaMappingLSID +")",
 			   e);
+		throw e;
 	    }
 	}
 
-        // Call to parent, which handles spec-wrapper-to-MobyServlet-config conversion
-	return createServiceFromConfig(request, wsdlConfig);
+	// Deal with secondary parameters
+	for(Map.Entry<String,String> mapping: wsdlConfig.getSecondaryInputFormats().entrySet()){
+	    URL u = null;
+	    try{
+		u = lsidResolver.resolveDataURL(mapping.getValue());		
+	    } catch(Exception e){
+		logger.log(Level.SEVERE,
+			   e.getClass().getName() + " while resolving lifting schema mapping LSID " +
+			   mapping.getValue() +" from the SAWSDL document for secondary parameter " +
+			   mapping.getKey(),
+			   e);
+		throw e;
+	    }
+	    Transformer transformer = null;
+	    try{
+		transformer = transformerFactory.newTransformer(new StreamSource(u.openStream()));
+	    } catch (TransformerConfigurationException tce){
+		logger.log(Level.SEVERE,
+			   "Could not create an XSLT transformer: " + tce,
+			   tce);
+		throw tce;
+	    }
+	    secondaryTransformers.put(mapping.getKey(), transformer);
+ 	}
+	return ms;
     }
 
     public String createInputSpecString(WSDLConfig wsdl){
@@ -201,15 +297,53 @@
     }
 
     public String createSecondarySpecString(WSDLConfig form){
-	return "";  //everything's primary for now
+	Map<String,String> params = wsdlConfig.getSecondaryInputs();
+	return XHTMLForm.join(",", params.values().toArray(new String[params.size()]));
     }
 
-    private Map<String,Map<String,byte[]>> getResponseData(Source source) throws Exception{
-	// Structure is (SOAP output param name -> ( -> XML Schema Instance data))
-	Map data = new HashMap<String,Map<String,byte[]>>();
-	//StringWriter stringWriter = new StringWriter();
-	//nullTransformer.transform(source, new StreamResult(stringWriter));
-	//return stringWriter.toString();
-	return data ;
+    private Map<String,Node> getResponseData(Source source) throws Exception{
+	// Structure is (SOAP output param name -> XML Schema Instance data)
+	Map<String,Node> data = new HashMap<String,Node>();
+	DOMResult domResult = new DOMResult();
+	nullTransformer.transform(source, domResult);
+
+	Node domNode = domResult.getNode();
+	if(domNode == null){
+	    throw new Exception("Could not get the result node from the DOM (bad null transformation?)");
+	}
+	Document owner = (domNode instanceof Document ? (Document) domNode : domNode.getOwnerDocument());
+	if(owner == null){
+	    throw new Exception("Could not get the owner document from the DOM result (owner was null, node was " + 
+				domNode.getClass().getName()+")");
+	}
+	Element responseElement = owner.getDocumentElement();
+
+	NodeList responseParams = responseElement.getChildNodes();
+	for(int i = 0; i < responseParams.getLength(); i++){	    
+	    if(!(responseParams.item(i) instanceof Element)){
+		continue;
+	    }
+	    Element responseParam = (Element) responseParams.item(i);
+	    
+	    // Use a TreeMap (as opposed to HashMap) so that the order is preserved on iteration
+	    TreeMap<String,byte[]> responseValues = new TreeMap<String,byte[]>();
+	    
+	    // If the returned param is an array (xsi:type="SOAP-ENC:Array"), iterate over the values
+	    String soapType = responseParam.getAttributeNS(MobyPrefixResolver.XSI_NAMESPACE2001, "type");
+	    if(soapType != null && soapType.endsWith(":Array")){
+		data.put(responseParam.getNodeName(), 
+			 WSDLConfig.renameSoapArrayElements(responseParam, responseParam.getNodeName(), owner));
+	    }
+	    else{
+		data.put(responseParam.getNodeName(), responseParam);
+	    }
+
+	    //StringWriter stringWriter = new StringWriter();
+	    //nullTransformer.transform(new DOMSource(data.get(responseParam.getNodeName())), new StreamResult(stringWriter));
+	    //System.err.println(responseParam.getNodeName()+": "+ stringWriter.toString());
+	}
+
+	return data;
     }
+
 }




More information about the MOBY-guts mailing list