[MOBY-guts] biomoby commit

Paul Gordon gordonp at dev.open-bio.org
Mon Aug 17 21:17:13 UTC 2009


gordonp
Mon Aug 17 17:17:13 EDT 2009
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util
In directory dev.open-bio.org:/tmp/cvs-serv25823/src/main/ca/ucalgary/services/util

Modified Files:
	PBERecorder.java 
Log Message:
Refactoring to provide generic DataRecorder callbacks during SoapServlet execution, was PBERecorder hardcoded before
moby-live/Java/src/main/ca/ucalgary/services/util PBERecorder.java,1.1,1.2
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/PBERecorder.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/PBERecorder.java	2009/06/09 19:37:17	1.1
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/PBERecorder.java	2009/08/17 21:17:13	1.2
@@ -33,7 +33,7 @@
 /**
  * This class controls the interaction between the web browser and Seahawk via the pasting actions.
  */
-public class PBERecorder{
+public class PBERecorder implements DataRecorder{
     private Map<String,MobyContentGUI> sessionId2gui;  // link the http session with the GUI
     private Map<String,Node> sessionId2dom;  // link the http session with the results of the WSDL service
     private Map<String,String> sessionId2wsdlSpec;  // link the http session with the wsdl service/port/op def
@@ -218,6 +218,107 @@
 	transformer = t;
     }
 
+    public boolean shouldIntercept(HttpServletRequest request){
+	return request.getParameter(PBERecorder.RETURN_XPATH_PARAM) != null ||
+	    request.getParameter(PBERecorder.AUTOCOMPLETE_PARAM) != null ||
+	    request.getParameter(PBERecorder.RESOURCE_FILE_PARAM) != null ||
+	    request.getParameter(PBERecorder.RAW_XPATH_PARAM) != null;
+	// TODO: deal with wsdl-less POST, which need writeWrapperForm call
+    }
+
+    public void interceptRequest(HttpServletRequest request,
+				 HttpServletResponse response){
+
+	String xpath = request.getParameter(PBERecorder.RETURN_XPATH_PARAM);
+	String autocompleteRequest = request.getParameter(PBERecorder.AUTOCOMPLETE_PARAM);
+	String resource = request.getParameter(PBERecorder.RESOURCE_FILE_PARAM);
+	String raw = request.getParameter(PBERecorder.RAW_XPATH_PARAM);
+
+	if(raw != null && raw.trim().length() != 0){
+	    getRawXml(request, response);
+	}
+	else if(resource != null && resource.trim().length() != 0){
+	    getResource(request, response);
+	}
+	//AJAX call for autocomplete
+	else if(autocompleteRequest != null && autocompleteRequest.trim().length() != 0){
+	    writeAutocompleteReply(request, response, autocompleteRequest);
+	}
+	else if(xpath != null && xpath.trim().length() != 0){
+	    writeWrapperForm(request, response);
+	}
+	// TODO: deal with wsdl-less POST, which need writeWrapperForm call
+	else{
+	    // Shouldn't get here unless shouldIntercept() was not checked before calling this method, 
+	    // or the logic of shouldIntercept() is inconsistent with that of this method.
+	    
+	}
+    }
+
+    private void writeAutocompleteReply(HttpServletRequest request,
+					HttpServletResponse response,
+					String seed){
+	java.io.OutputStream out = null;
+	response.setContentType("text/plain");
+	try{
+	    out = response.getOutputStream();
+	}
+	catch(java.io.IOException ioe){
+	    logger.log(Level.SEVERE, "While getting servlet output stream (for HTML form response to client)", ioe);
+	    return;
+	}
+
+	String answer = "";
+	try{
+	    answer = autocomplete(request, seed);
+	} catch(Exception e){
+	    //todo: make pretty, more verbose, etc., fit on one line for AJAX client
+	    answer = e.toString();
+	}
+
+	try{
+	    out.write(answer.getBytes());
+	}
+	catch(java.io.IOException ioe){
+	    logger.log(Level.SEVERE, "While printing HTML form to servlet output stream", ioe);
+	    return;
+	}		
+    }
+
+    // This is called when the user has picked a part of the service response to return in the MOBY service being created
+    private void writeWrapperForm(HttpServletRequest request,
+				  HttpServletResponse response){
+	java.io.OutputStream out = null;
+	response.setContentType("text/html");
+	try{
+	    out = response.getOutputStream();
+	}
+	catch(java.io.IOException ioe){
+	    logger.log(Level.SEVERE, "While getting servlet output stream (for HTML form response to client)", ioe);
+	    return;
+	}
+	
+	String answer = "";
+	try{
+	    out.write(writeWrapperForm(request).getBytes());
+	    return;
+	} catch(Exception e){
+	    answer = "Error in PBE system:\n" + e.toString()+"\n";
+	    for(StackTraceElement ste: e.getStackTrace()){
+		answer += ste.toString()+"\n";
+	    }
+	}
+
+	try{
+	    out.write("<html><head><title>Service Definition Error</title></head>\n".getBytes());
+	    out.write(("<body>"+answer+"</body></html>").getBytes());
+	}
+	catch(java.io.IOException ioe){
+	    logger.log(Level.SEVERE, "While printing HTML form to servlet output stream", ioe);
+	    return;
+	}	
+    }
+
     /**
      * Called when data in a field is being updated via a paste event.
      */
@@ -227,7 +328,7 @@
 	MobyContentGUI gui = sessionId2gui.get(session.getId());
 
 	// datatype<->event unification for Seahawk->browser drag 'n' drop
-	String action = request.getParameter("seahawkAction");
+	String action = request.getParameter(DataRecorder.PASSTHROUGH_ACTION);
 	if(action.equals("pasteEvent")){
 	    dataPasted(request);
 	}
@@ -252,7 +353,8 @@
 	try{
 	    response.getOutputStream().write(statusMessage.getBytes());
 	} catch(Exception e){
-	    logger.log(Level.SEVERE, "Cannot write the response to a seahawkAction request", e);
+	    logger.log(Level.SEVERE, "Cannot write the response to a " + 
+		       DataRecorder.PASSTHROUGH_ACTION + " request", e);
 	}
     }
 
@@ -391,7 +493,7 @@
 				"the service (probably an internal error): " + e);	    
 	}
 
-	System.err.println(stringResult.toString());
+	//System.err.println(stringResult.toString());
 	// Replace any enclosing tag with links that indicate the tag contents are of 
 	// interest based on tag or attribute name, or attribute value
 	String markup = stringResult.toString().replaceAll("</", "&lt;/");
@@ -400,8 +502,9 @@
 					       "=\"(.*?)#(.*?)\"", Pattern.MULTILINE | Pattern.DOTALL);
 	Pattern attributePattern = Pattern.compile("(\\S+)=\"([^\"]*)\"", Pattern.MULTILINE | Pattern.DOTALL);
 
-
+	StringBuilder newMarkup = new StringBuilder();
 	Matcher elementMatcher = elementPattern.matcher(markup);
+	int markupLengthRemoved = 0;
 	while(elementMatcher.find()){
 	    // These data structure keeps track changes we need to make to elementText
 	    Vector<int[]> ranges = new Vector<int[]>();
@@ -460,7 +563,13 @@
 		}
 		// literal string replacement
 		String linkedElement = applyEdits(elementText, ranges, replacements);
-		markup = markup.replace(elementText, linkedElement);
+		newMarkup.append(markup.substring(markupLengthRemoved, elementMatcher.start())); 
+		newMarkup.append(linkedElement);
+		//markup = elementMatcher.end() >= markup.length() ? "" :
+		//    markup.substring(elementMatcher.end()-markupLengthRemoved);
+		markupLengthRemoved = elementMatcher.end();
+		//elementMatcher = elementPattern.matcher(markup);
+		//markup = markup.replace(elementText, linkedElement);
 	    }
 	}
 
@@ -470,7 +579,7 @@
 	    "Below, click the most indented <b>element name</b>, <b>attribute name</b>, or <b>specific attribute value</b> "+
 	    "that you expect to be <b>always present</b> in a <b>successful</b> execution. You will then be taken to "+
 	    "a form asking you about how you want this data returned using the Moby data types." +
-	    "</td></tr></table>"+"<pre>"+markup+"</pre>";
+	    "</td></tr></table>"+"<pre>"+newMarkup+"</pre>";
     }
 
     private void addEdit(Vector<int[]> exciseRanges, int[] newRange, 
@@ -595,12 +704,16 @@
 
     // give surrounding words (numChars worth total) around targetWord in text
     private String getContext(String text, String targetWord, int numChars){
+	return getContext(text, targetWord, numChars, true); // true = use tool tips for ellipsis expansion
+    }
+
+    private String getContext(String text, String targetWord, int numChars, boolean useToolTip){
 	text = text.replaceAll("\n",""); //new-line obvious messes up ajax one-line per response format
 	
 	if(text.length() < numChars){
 	    return text;  //can fit the whole thing
 	}
-
+	
 	int start = 0;
 	if(targetWord.length() > 0){
 	    start = text.toLowerCase().indexOf(targetWord)-numChars/2;
@@ -628,8 +741,8 @@
 	    }
 	}
 	
-	String prefix = start == 0 ? "" : "<acronym title=\""+text.substring(0,start)+"\">...</acronym>";
-	String suffix = end == text.length() ? "" : "<acronym title=\""+text.substring(end)+"\">...</acronym>";
+	String prefix = start == 0 ? "" : (useToolTip ? "<acronym title=\""+text.substring(0,start)+"\">...</acronym>" : "...");
+	String suffix = end == text.length() ? "" : (useToolTip ? "<acronym title=\""+text.substring(end)+"\">...</acronym>" : "...");
 
 	return prefix+text.substring(start, end)+suffix;
     }
@@ -1228,15 +1341,30 @@
 
 	if(dataType.length() != 0){
 	    MobyDataType dt = MobyDataType.getDataType(dataType, SeahawkOptions.getRegistry());
-	    // xpaths should be called foo-memberName foo-otherMemberName etc.
-	    for(MobyRelationship relationship: dt.getAllChildren()){
-		String memberName = relationship.getName();
-		String memberXPath = request.getParameter(VALUE_XPATH_PARAM+memberName);
+	    String dataTypeName = dt.getName();
+	    if(dataTypeName.equals(MobyTags.MOBYSTRING) ||
+	       dataTypeName.equals(MobyTags.MOBYFLOAT) ||
+	       dataTypeName.equals(MobyTags.MOBYINTEGER) ||
+	       dataTypeName.equals(MobyTags.MOBYBOOLEAN) ||
+	       dataTypeName.equals(MobyTags.MOBYDATETIME)){  // is it a primitive? no suffix in that case...
+		String memberXPath = request.getParameter(VALUE_XPATH_PARAM);
 		if(memberXPath == null){
-		    throw new Exception("Cannot find XPath param ("+VALUE_XPATH_PARAM+memberName+
-					") for '"+dataType + "' data type's member " + memberName);
+		    throw new Exception("Cannot find XPath param ("+VALUE_XPATH_PARAM+
+					") for the '"+dataTypeName + "' primitive value ");
+		}
+		memberMap.put(MobyComplexBuilder.PRIMITIVE_VALUE_SENTINEL, fixXPath(memberXPath, request)); // "" is special member name key for primitives
+	    }
+	    else{
+		// xpaths should be called foo-memberName foo-otherMemberName etc.
+		for(MobyRelationship relationship: dt.getAllChildren()){
+		    String memberName = relationship.getName();
+		    String memberXPath = request.getParameter(VALUE_XPATH_PARAM+memberName);
+		    if(memberXPath == null){
+			throw new Exception("Cannot find XPath param ("+VALUE_XPATH_PARAM+memberName+
+					    ") for '"+dataType + "' data type's member " + memberName);
+		    }
+		    memberMap.put(memberName, fixXPath(memberXPath, request));
 		}
-		memberMap.put(memberName, memberXPath);
 	    }
 	}
 	else{
@@ -1496,12 +1624,12 @@
 		    ex.printStackTrace();
 		}
 	    }
-	    NodeList nl = e.getElementsByTagName("*");
-	    for(int i = 0; i < nl.getLength(); i++){
-		Element child = (Element) nl.item(i);
-		System.err.println("Element " + child.getNodeName() + " ns " + child.getNamespaceURI() + 
-				   " for prefix " + child.getPrefix());
-	    }
+	    // NodeList nl = e.getElementsByTagName("*");
+// 	    for(int i = 0; i < nl.getLength(); i++){
+// 		Element child = (Element) nl.item(i);
+// 		//System.err.println("Element " + child.getNodeName() + " ns " + child.getNamespaceURI() + 
+// 		//		   " for prefix " + child.getPrefix());
+// 	    }
 	}
 
 	// The namespace prefixes used in the selection xpath will use the following node's prefix:ns mappings
@@ -1528,7 +1656,7 @@
 	    xPathResults = (NodeList) xPathObj.evaluate(fixXPath(xPath, request), domNode, XPathConstants.NODESET);
 	    numResults = xPathResults.getLength();
 	    if(numResults == 0){
-		result.append("[<font color=\"red\" style=\"bold\">the selection XPath does " +
+		result.append("[<font color=\"red\" style=\"bold\">the selection XPath ("+fixXPath(xPath, request)+") does " +
 			      "not select any data, please modify</font>"+ 
 			      "]\n"); // <input type=\"submit\" value=\"Reselect\"/><br/>\n");
 	    }
@@ -1544,7 +1672,8 @@
 	}
 
 	//todo output xsd type:  xPathResults.item(0).getNamespaceURI(), xPathResults.item(0).getLocalName;
-	Vector<String> valXPathSuggestions = RuleCreator.suggestValueXPathsFromSelectionXPath(xPath, xPathResults.item(0));
+
+	Vector<String> valXPathSuggestions = (numResults == 0 ? new Vector<String>() : RuleCreator.suggestValueXPathsFromSelectionXPath(xPath, xPathResults.item(0)));
 	String valueXPath = getParam(request, VALUE_XPATH_PARAM);
 	String selectOptions = null;
 	boolean suggestable = false;
@@ -1567,9 +1696,14 @@
 
 	    // If no value already, let's suggest the first one
 	    if(valueXPath.length() == 0){
-		valueXPath = valXPathSuggestions.elementAt(0).replaceAll("(.*) -- .*", "$1");
-		valXPathSuggestions.removeElementAt(0);
-		suggestable = true;
+		if(valXPathSuggestions.size() == 0){
+		    valueXPath = "";
+		}
+		else{
+		    valueXPath = valXPathSuggestions.elementAt(0).replaceAll("(.*) -- .*", "$1");		    
+		    valXPathSuggestions.removeElementAt(0);
+		    suggestable = true;
+		}
 	    }
 	}
 	// a custom XPath
@@ -1799,7 +1933,8 @@
 	    // we do this here rather than on the referring page because the regex code
 	    // used to generate the referring page links can't make the prefixes easily
 	    //return xPath.replaceAll("/([a-zA-Z_0-9\\-]+)(?=/|$|\\[)", "/"+XPATH_DEFAULT_NS_PREFIX+":$1");
-	    return xPath.replaceAll("/([a-zA-Z_0-9\\-]+)(?=/|$)", "/*[local-name() = '$1']");
+	    return xPath.replaceAll("/([a-zA-Z_0-9\\-]+)(?=/|$)", "/*[local-name() = '$1']")
+		.replaceAll("/([a-zA-Z_0-9\\-]+)\\[", "/*[local-name() = '$1' and ");
 	}
 	else{
 	    return xPath;  //rpc nodes usually have no namespace
@@ -2179,13 +2314,13 @@
 			if(i == 0){
 			    MobyNamespace ns = obj.getPrimaryNamespace();
 			    if(ns != null){
-				result.append("<option title=\""+getContext(ns.getDescription(), "", 50)+
+				result.append("<option title=\""+getContext(ns.getDescription(), "", 50, false)+
 					      (partValue.equals(MobyTags.MOBYOBJECT+":"+ns.getName()) ? "\" selected=\"selected" : "") +
 					      "\">"+MobyTags.MOBYOBJECT+":"+ns.getName()+"</option>");
 			    }
 			}
 			else{
-			    result.append("<option title=\""+getContext(lineage[i].getDescription(),"", 50)+
+			    result.append("<option title=\""+getContext(lineage[i].getDescription(),"", 50, false)+
 					  (partValue.equals(lineage[i].getName()) ? "\" selected=\"selected" : "") +
 					  "\">"+lineage[i].getName()+"</option>");
 			}




More information about the MOBY-guts mailing list