[MOBY-guts] biomoby commit

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


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

Modified Files:
	WSDLService.java 
Log Message:
First version that realy works, with all document encoding styles
moby-live/Java/src/main/ca/ucalgary/services WSDLService.java,1.2,1.3
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/WSDLService.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/WSDLService.java	2008/10/30 02:33:24	1.2
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/WSDLService.java	2009/06/09 19:19:39	1.3
@@ -1,5 +1,6 @@
 package ca.ucalgary.services;
 
+import ca.ucalgary.services.util.IOUtils;
 import ca.ucalgary.services.util.SourceMap;
 import ca.ucalgary.services.util.WSDLConfig;
 import ca.ucalgary.services.util.XHTMLForm;
@@ -18,10 +19,16 @@
 import javax.xml.transform.*;
 import javax.xml.transform.dom.*;
 import javax.xml.transform.stream.*;
-import javax.xml.ws.*;
+import javax.xml.xpath.*;
+//import javax.xml.ws.*;
+import org.apache.axis.AxisFault;
+import org.apache.axis.client.Call;
+import org.apache.axis.client.Service;
 
 import java.io.*;
+import java.net.HttpURLConnection;
 import java.net.URL;
+import java.net.URLConnection;
 import java.util.*;
 import java.util.logging.*;
 
@@ -41,16 +48,43 @@
     public static final String WSDL_URL_PARAM = "wsdlURL";
     protected URL remoteWSDLUrl;
     protected WSDLConfig wsdlConfig;
-    protected Dispatch<Source> dispatch;
-    private TransformerFactory transformerFactory;
-    private LSIDResolver lsidResolver; // used to fetch transformation rules, etc. given in the SAWSDL attributes
+    //protected Dispatch<Source> dispatch;
+    //PG protected Service webservice;
+    protected URL endpoint;
+
     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 Map<String,XPathExpression> outXPathString2XPath; // precompile the output XPaths 
+    private Map<String,Boolean> outXPathString2IsRegex; // is the rule to apply on the results of XPath a rehgex or another Xpath?
+
+    private static LSIDResolver lsidResolver; // used to fetch transformation rules, etc. given in the SAWSDL attributes
     private static DocumentBuilder docBuilder;
+    private static XPath xPath;  // essentially an XPathExpression builder
 
-    private static Logger logger = Logger.getLogger("ca.ucalgary.services.WSDLService");
+    // by default, expect the SourceMap to be populated with raw XML, not 
+    // named values that are wrapped automatically
+    private boolean usingRawXml = true; 
+
+    private static Logger logger = Logger.getLogger(WSDLService.class.getName());
+    private static final String DEFAULT_NSPREFIX_4_XPATH = "t";
+
+    /**
+     * C-tor for when you want to configure not from a SAWSDL file, but a configuration object.
+     *
+     * @param wsdlConfig the fully configured service def
+     * @param usingRawXml will the lowering schema mappings generate the XML (true, default), or just the named text values for auto-XML-wrapping by SourceMap (false)
+     */
+    public WSDLService(WSDLConfig wsdlConfig, boolean usingRawXml){
+	this();
+	this.wsdlConfig = wsdlConfig;
+	this.usingRawXml = usingRawXml;
+    }
+
+    public WSDLService(){
+	super();
+    }
 
     public void init(){
 	super.init();
@@ -66,8 +100,27 @@
 			       "com.ctc.wstx.stax.WstxOutputFactory");
 	}
 
-	lsidResolver = new LSIDResolver();
-	transformerFactory = TransformerFactory.newInstance();
+	try{
+	    if(lsidResolver == null){
+		lsidResolver = new LSIDResolver();
+	    }
+	} catch(Exception e){
+	    logger.log(Level.SEVERE,
+		       "Could not create an LSID Resolver: " + e.getMessage(),
+		       e);
+	}
+	try{
+	    if(xPath == null){
+		//PG		xPath = XPathFactory.newInstance().newXPath();
+		// For the moment, need to explicitly xalan use due to Google App Engine problem
+		xPath = (new org.apache.xpath.jaxp.XPathFactoryImpl()).newXPath();
+	    }
+	} catch(Exception e){
+	    logger.log(Level.SEVERE,
+		       "Could not create an XPath: " + e.getMessage(),
+		       e);
+	}
+	TransformerFactory transformerFactory = TransformerFactory.newInstance();
 	try{
 	    nullTransformer = transformerFactory.newTransformer();  // for verbatim copying of SOAP response XML
 	} catch (TransformerConfigurationException tce){
@@ -79,23 +132,39 @@
 	// our engine needs (the mode attribute value in the XSLT template)
 	uri2XmlFormat = new HashMap<String,String>();
 	secondaryTransformers = new HashMap<String,Transformer>();
+	outXPathString2XPath = new HashMap<String,XPathExpression>();
+	outXPathString2IsRegex = new HashMap<String,Boolean>();
+    }
 
-	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
-        dbf.setNamespaceAware(true);
-        try{
-            docBuilder = dbf.newDocumentBuilder();
-        } catch(Exception e){
-            e.printStackTrace();
-        }
+    private static DocumentBuilder getDocBuilder(){
+	if(docBuilder == null){
+	    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+	    dbf.setNamespaceAware(true);
+	    try{
+		docBuilder = dbf.newDocumentBuilder();
+	    } catch(Exception e){
+		e.printStackTrace();
+	    }
+	}
+	return docBuilder;
     }
 
     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(new QName(wsdlConfig.getOperationInputQName().getNamespaceURI(), 
-						   wsdlConfig.getOperationName())); 
+	QName qName = "rpc".equals(wsdlConfig.getOperationStyle()) ? 
+	    new QName(wsdlConfig.getOperationInputQName().getNamespaceURI(), wsdlConfig.getOperationName()) : 
+	    wsdlConfig.getOperationInputQName();
+	SourceMap source = new SourceMap(qName, usingRawXml ? "raw" : wsdlConfig.getOperationEncoding());
+	// we assume the results of the XSLTs used below contain the encoding tags as required.
+	// this is solely for SAWSDL reasonableness...a better way would be to use
+	// SourceMap to do the encoding, and just give it values from encoding-independent rules.  Oh well.
+	//SourceMap source = new SourceMap(qName, sourceMode);
+
+	// This is the mapping of moby parameter names to WS request & response 
+	// xpaths for the transformed parameters
+	Map<String,String> paramMap = wsdlConfig.getMobyParams2DocXPaths();
 
 	Map<String,String> ruleURIs = wsdlConfig.getPrimaryInputFormats();
 	for(MobyPrimaryData mobyInputTemplate: service.getPrimaryInputs()){
@@ -122,7 +191,9 @@
 					"' format by an XSLT rule.  Source data was:\n"+
 					mobyData.toXML());
 	    }
-	    source.put(paramName,
+	    //System.err.println("In Param "+paramName+": "+
+	    //	       new String(paramBytes));
+	    source.put(mobyParam2SourceKey(paramMap, paramName),
 		       new String(paramBytes));
 	}
 
@@ -134,84 +205,228 @@
 	    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());
+	    //System.err.println("Sec Param "+mobySec.getName()+": "+
+	    //		       xsltResult.toString());
+	    source.put(mobyParam2SourceKey(paramMap, mobySec.getName()), xsltResult.toString());
+	}
+	//System.err.println("Full source: " + source.toString());
+
+	for(Map.Entry<String,String> fixedParam: wsdlConfig.getFixedParams().entrySet()){
+	    source.put(fixedParam.getKey(), fixedParam.getValue());
+	}
+
+	//Source resultSource = dispatch.invoke(source);
+//PG 	Call dispatch = (Call) webservice.createCall();
+//PG 	dispatch.setTargetEndpointAddress(getSoapEndpoint(wsdlConfig.getPortQName()));
+//PG	dispatch.setPortName(wsdlConfig.getPortQName());
+ 	String soapAction = wsdlConfig.getSoapAction();
+//PG  	if(soapAction != null && soapAction.length() != 0){
+//PG 	    dispatch.setSOAPActionURI(soapAction);
+//PG 	}
+//PG 	org.apache.axis.message.SOAPEnvelope payload = new org.apache.axis.message.SOAPEnvelope();
+//PG 	synchronized(docBuilder){
+//PG 	    payload.getBody().addDocument(docBuilder.parse(new ByteArrayInputStream(source.toString().getBytes())));
+//PG 	}
+
+//PG	Node resultSource = dispatch.invoke(payload).getBody().getFirstChild();
+
+	//PG Temp hack since Google App Engine doesn't support JAX-WS
+	URL u = getSoapEndpoint(wsdlConfig.getPortQName());
+	HttpURLConnection conn = (HttpURLConnection) u.openConnection();
+	IOUtils.writeToConnection(conn, source.toString().getBytes(), soapAction);
+	Node resultSource = IOUtils.readFromConnection(conn);
+
+	// for RPC responses handle the one-level data specially, so array are autoiterated
+	// we don't use paramMap because you can't rename params in SAWSDL
+	if("rpc".equals(wsdlConfig.getOperationStyle())){
+	    Map<String,Node> responseData = getResponseData(resultSource);
+	    
+	    // 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);
+		if(mdi == null){
+		    throw new Exception("The output parameter '" + mobyOutputTemplate.getName() + 
+					"' of data type '" + mobyOutputTemplate.getDataType().getName() + 
+					"' could not be created from the form submission response (" +
+					"MobyClient returned null transforming the legacy data).");
+		}
+		result.put(mobyOutputTemplate.getName(), mdi);
+	    }
+	}
+	else{
+	    for(MobyPrimaryData mobyOutputTemplate: service.getPrimaryOutputs()){
+		String resultXPath = paramMap.get(mobyOutputTemplate.getName());
+		NodeList resultNodes = null;
+		XPathExpression xPathExp = outXPathString2XPath.get(resultXPath);
+		if(xPathExp == null){
+		    throw new Exception("Could not find precompiled XPathExpression " +
+					" to evaluate the output XPath (" + resultXPath +
+					"): init() did not intialize properly");
+		}
+		try{
+		    resultNodes = (NodeList) xPathExp.evaluate(resultSource, 
+							       XPathConstants.NODESET);
+		} catch(Exception e){
+		    throw new Exception("Could not evaluate the XPath (" + resultXPath + 
+					") in Node list mode to retrieve Moby output '"+ 
+					mobyOutputTemplate.getName() +
+					"' from the service response: " + e.getMessage(), e);
+		}
+		if(resultNodes.getLength() == 0){
+		    logger.log(Level.WARNING, "Did not find any results for the XPath "+
+			       resultXPath + " using node " + resultSource.getNodeName());
+		}
+		for(int i = 0; i < resultNodes.getLength(); i++){
+		    Node resultNode = resultNodes.item(i);
+		    // we don't expect every node to contain the value, so put a catch here
+		    MobyDataInstance mdi = null;
+		    try{
+			// is the rule on the XML or the text inside the XML (XPath or regex rules should apply?)
+
+			if(isRegexRule(resultXPath)){  // send text contents for regex rule eval
+			    mdi = getMobyData(resultNode.getNodeValue(),
+					      mobyOutputTemplate);
+			}
+			else{  // send Node for XPath rule eval
+			    mdi = getMobyData(resultNode,
+					      mobyOutputTemplate);
+			}
+		    } catch(Exception e){
+			logger.log(Level.SEVERE, "Could not run MobyClient converters: " + e.getMessage(), e);
+			continue;
+		    }
+		    if(mdi != null){
+			result.put(mobyOutputTemplate.getName(), mdi);
+		    }
+		}
+		//todo: make exception here optional?  not all services will return something useful all the time...
+		if(result.isEmpty()){
+		    throw new Exception("The output parameter '" + mobyOutputTemplate.getName() + 
+					"' of data type '" + mobyOutputTemplate.getDataType().getName() + 
+					"' could not be created from the form submission response (" +
+					"MobyClient returned null transforming the legacy data).");
+		}
+	    }
 	}
+    }
+   
+    private boolean isRegexRule(String xpath){
+	return outXPathString2IsRegex.get(xpath).booleanValue();
+    }
 
-	Source resultSource = dispatch.invoke(source);
-	Map<String,Node> responseData = getResponseData(resultSource);
+    private String mobyParam2SourceKey(Map<String,String> mobyParamName2wsdlXPathMap,
+				       String mobyParamName){
+	if(mobyParamName2wsdlXPathMap == null){
+	    return mobyParamName; //no mapping available, use as-is (mostly for RPC-style SAWSDL)
+	}
+	String xpath = mobyParamName2wsdlXPathMap.get(mobyParamName);
+	return xpath.replaceAll("/", ":");  //SourceMap uses colon instead of slash to denote tag nesting
+    }
 
-	//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);
-	    if(mdi == null){
-		throw new Exception("The output parameter '" + mobyOutputTemplate.getName() + 
-				    "' of data type '" + mobyOutputTemplate.getDataType().getName() + 
-				    "' could not be created from the form submission response (" +
-				    "TextClient returned null transforming the legacy data).");
+    //  parse the wsdl to getthe URL where the call should be made
+    private URL getSoapEndpoint(QName targetPort) throws Exception{
+	if(targetPort == null || targetPort.getLocalPart() == null){
+	    throw new Exception("Asked for SOAP endpoint with a null port name");
+	}
+	if(endpoint != null){
+	    return endpoint;
+	}
+	if(wsdlConfig != null){
+	    Document wsdlDoc = getDocBuilder().parse(wsdlConfig.getSpecURL().openStream());
+	    NodeList ports = wsdlDoc.getDocumentElement().getElementsByTagNameNS("http://schemas.xmlsoap.org/wsdl/", "port");
+	    for(int i = 0; i < ports.getLength(); i++){
+		Element portElem = (Element) ports.item(i);
+		String portName = portElem.getAttribute("name");
+		if(targetPort.getLocalPart().equals(portName)){
+		    NodeList addrs = portElem.getElementsByTagNameNS("http://schemas.xmlsoap.org/wsdl/soap/", "address");
+		    for(int j = 0; j < addrs.getLength(); j++){
+			Element addrElem = (Element) addrs.item(j);
+			String location = addrElem.getAttribute("location");
+			if(location != null && location.length() != 0){
+			    endpoint = new URL(location);
+			    logger.log(Level.SEVERE,
+				       "####The SOAP endpoint is " + endpoint);
+			    return endpoint;
+			}
+		    }
+		}
 	    }
-	    result.put(mobyOutputTemplate.getName(), mdi);
 	}
+	return null;
     }
 
+
     public MobyService createServiceFromConfig(javax.servlet.http.HttpServletRequest request)
         throws Exception{
 
-        remoteWSDLUrl = getSpecURL(WSDL_URL_PARAM);
-        
-        try{
-            wsdlConfig = new WSDLConfig(remoteWSDLUrl);
-        } catch(Exception e){
-            logger.log(Level.SEVERE,
-		       "Could not determine Moby service configuration from the WSDL (" +
-		       remoteWSDLUrl.toString() + ")",
-		       e);
-	    throw e;
-        }
-
-	// Verify if the service info was actually parsed properly by trying to use it with JAX-WS
-	Service service = null;
-	try{
-	    service = Service.create(remoteWSDLUrl, 
-				     wsdlConfig.getServiceQName());
-	} catch(Exception e){
-	    logger.log(Level.SEVERE,
-		       e.getClass().getName() + " while using JAX-WS to create a handle for" +
-		       "the service, either the WSDL or the WSDLConfig's serviceQName parsed (" +
-		       wsdlConfig.getServiceQName() + ") is wrong",
-		       e);
-	    throw e;
-	}
-
-	try{
-	    dispatch = service.createDispatch(wsdlConfig.getPortQName(),
-					      Source.class,
-					      Service.Mode.PAYLOAD);
-	} catch(Exception e){
-	    logger.log(Level.SEVERE,
-		       e.getClass().getName() + " while using JAX-WS to create a dispatch for a port on " +
-		       "the service " + wsdlConfig.getServiceQName() + ", either the WSDL or the WSDLConfig's " +
-		       "portQName parsed (" + wsdlConfig.getPortQName() + ") is wrong",
-		       e);
-	    throw e;
+	// we were given the WSDLConfig explicitly in the c-tor to override the default resolution
+	if(wsdlConfig == null){
+	    remoteWSDLUrl = getSpecURL(WSDL_URL_PARAM);
+	    try{
+		wsdlConfig = new WSDLConfig(remoteWSDLUrl);
+	    } catch(Exception e){
+		logger.log(Level.SEVERE,
+			   "Could not determine Moby service configuration from the WSDL (" +
+			   remoteWSDLUrl.toString() + ")",
+			   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.
+	// FYI: config contains all of the info about how many parameters there are, their types, etc.
 	MobyService ms = createServiceFromConfig(request, wsdlConfig);
 
+	createServiceFromConfig();
+	return ms;
+    }
+
+    public void createServiceFromConfig() throws Exception{
+
+	// Verify if the service info was actually parsed properly by trying to use it with JAX-WS
+// 	Service service = null;
+//PG 	try{
+// 	    service = Service.create(wsdlConfig.getSpecURL(), 
+// 				     wsdlConfig.getServiceQName());
+//PG	    webservice = new Service(//wsdlConfig.getSpecURL(),
+//PG				     wsdlConfig.getServiceQName());
+//PG 	} catch(Exception e){
+//PG 	    logger.log(Level.SEVERE,
+//PG 		       e.getClass().getName() + " while using JAX-WS to create a handle for " +
+//PG 		       "the service, either the WSDL or the WSDLConfig's serviceQName parsed (" +
+//PG 		       wsdlConfig.getServiceQName() + ") is wrong",
+//PG 		       e);
+//PG 	    throw e;
+//PG 	}
+
+// 	try{
+// 	    dispatch = service.createDispatch(wsdlConfig.getPortQName(),
+// 					      Source.class,
+// 					      Service.Mode.PAYLOAD);
+// 	} catch(Exception e){
+// 	    logger.log(Level.SEVERE,
+// 		       e.getClass().getName() + " while using JAX-WS to create a dispatch for a port on " +
+// 		       "the service " + wsdlConfig.getServiceQName() + ", either the WSDL or the WSDLConfig's " +
+// 		       "portQName parsed (" + wsdlConfig.getPortQName() + ") is wrong",
+// 		       e);
+// 	    throw e;
+// 	}
+
+	// Some servers need the soap action set to know what method to invoke
+// 	String soapAction = wsdlConfig.getSoapAction();
+// 	if(soapAction != null && soapAction.length() != 0){
+// 	    Map<String,Object> context = dispatch.getRequestContext();	
+// 	    context.put(Dispatch.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
+// 	    context.put(Dispatch.SOAPACTION_URI_PROPERTY, soapAction);
+// 	}
+
 	// 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()){
@@ -237,7 +452,23 @@
 	    }
 	}
 	
-	for(String schemaMappingLSID: wsdlConfig.getPrimaryOutputFormats().values()){
+	Map<String,String> paramMap = wsdlConfig.getMobyParams2DocXPaths();
+	Map<String,String> outParamURIs = wsdlConfig.getPrimaryOutputFormats();
+	// note, that because of the context, the xpath will probably fail if an xpath function is called
+	NamespaceContextImpl targetNSContext = null;
+	if(wsdlConfig.getTargetNamespaceURI() == null){
+	    targetNSContext = new NamespaceContextImpl();
+	    logger.log(Level.WARNING, 
+		       "***NO namespace for XPaths");
+	}
+	else{
+	    targetNSContext = new NamespaceContextImpl(wsdlConfig.getTargetNamespaceURI(), DEFAULT_NSPREFIX_4_XPATH);
+	    logger.log(Level.WARNING, 
+		       "***Set target namespace (prefix " + DEFAULT_NSPREFIX_4_XPATH + 
+		       ") for XPaths to "+wsdlConfig.getTargetNamespaceURI());
+	}
+	for(String paramName: outParamURIs.keySet()){
+	    String schemaMappingLSID = outParamURIs.get(paramName);
 	    URL u = null;
 	    try{
 		u = lsidResolver.resolveDataURL(schemaMappingLSID);		
@@ -257,9 +488,39 @@
 			   e);
 		throw e;
 	    }
+	    // Record if the rule is a regex or if it is xpath-based for later usage...
+	    outXPathString2IsRegex.put(paramName, getMobyClient().getPattern(schemaMappingLSID) != null);
+
+	    // Haha! the name of the parameter *is* the xpath.  How clever.
+	    // with the exception of the fact an attribute and the text of an element
+	    // may both be useful, so we kept the /@... or /text() suffixes
+	    // to avoid name collision in the parameter hash. To get the result node
+	    // on which MOB rules will be applied, we need to strip these parts off
+	    // don't worry, they appear in the MOB rules, so we get the correct response.
+	    // Here we're just getting the evaluation context for the MOB rule.
+	    String resultXPathString = paramName.replaceAll("/(?:text\\(\\)|@[^/]+)$","");
+	    // We will cheat slightly by making any paths e.g. /a/b/c into //a/b/c 
+	    // because the XML doc may actually contain the soap envelope, etc.
+	    if(resultXPathString.indexOf("//") != 0){
+		resultXPathString = fixXPath(resultXPathString).substring(1); 
+		resultXPathString = resultXPathString.substring(resultXPathString.indexOf("/")+1);
+	    }
+	    try{
+		xPath.setNamespaceContext(targetNSContext);
+		outXPathString2XPath.put(paramName,
+					 xPath.compile(resultXPathString));
+		//logger.log(Level.WARNING, "%%%%%%Compiled " + resultXPathString);
+	    } catch(Exception e){
+		logger.log(Level.SEVERE,
+			   "While parsing service result XPath (" + resultXPathString +
+			   "): " + e.getMessage(),
+			   e);
+		throw e;
+	    }
 	}
 
 	// Deal with secondary parameters
+	TransformerFactory transformerFactory = TransformerFactory.newInstance();
 	for(Map.Entry<String,String> mapping: wsdlConfig.getSecondaryInputFormats().entrySet()){
 	    URL u = null;
 	    try{
@@ -283,40 +544,49 @@
 	    }
 	    secondaryTransformers.put(mapping.getKey(), transformer);
  	}
-	return ms;
     }
 
+     private String fixXPath(String xpath){
+	 //return xpath.replaceAll("/([a-zA-Z_0-9\\-]+)(?=/|$|\\[)", "/"+DEFAULT_NSPREFIX_4_XPATH+":$1");
+	return xpath.replaceAll("/([a-zA-Z_0-9\\-]+)(?=/|$)", "/*[local-name() = '$1']");
+     }
+
     public String createInputSpecString(WSDLConfig wsdl){
 	Map<String,String> params = wsdlConfig.getPrimaryInputs();
+	//System.err.println("Inputs: "+XHTMLForm.join(",", params.values().toArray(new String[params.size()])));
 	return XHTMLForm.join(",", params.values().toArray(new String[params.size()]));
     }
 
     public String createOutputSpecString(WSDLConfig form){
 	Map<String,String> params = wsdlConfig.getPrimaryOutputs();
+	//System.err.println("Outputs: "+XHTMLForm.join(",", params.values().toArray(new String[params.size()])));
 	return XHTMLForm.join(",", params.values().toArray(new String[params.size()]));
     }
 
     public String createSecondarySpecString(WSDLConfig form){
 	Map<String,String> params = wsdlConfig.getSecondaryInputs();
+	//System.err.println("Secondaries: "+XHTMLForm.join(",", params.values().toArray(new String[params.size()])));
 	return XHTMLForm.join(",", params.values().toArray(new String[params.size()]));
     }
 
-    private Map<String,Node> getResponseData(Source source) throws Exception{
+    private Map<String,Node> getResponseData(Node domNode) throws Exception{
+    //    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();
+	 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();
+	 Element responseElement = (Element) domNode;
 
 	NodeList responseParams = responseElement.getChildNodes();
 	for(int i = 0; i < responseParams.getLength(); i++){	    
@@ -338,9 +608,9 @@
 		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());
+// 	    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