[MOBY-guts] biomoby commit

Paul Gordon gordonp at dev.open-bio.org
Fri Apr 9 15:54:17 UTC 2010


gordonp
Fri Apr  9 11:54:16 EDT 2010
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui
In directory dev.open-bio.org:/tmp/cvs-serv1630/src/main/ca/ucalgary/seahawk/gui

Modified Files:
	MobyContentPane.java 
Log Message:
Fixes to highlighting, added case sensitive search, added 'previous input' service options (equivalent to an if condition in PbE)
moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.23,1.24
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java	2010/03/29 19:54:36	1.23
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java	2010/04/09 15:54:16	1.24
@@ -107,6 +107,7 @@
     private Document currentDoc; //the doc DOM being actively filtered
     private NodeList currentSelectedData = null;
     private String currentSelectionXPath = null;
+    private Map<String,Boolean> jobXPtrs = null;  // Map<xptr,has a HAS member>
     private List<String> filterableNodes = null;  // List<xptr>
     private List<AttributeSet> origStyles = null;
     private boolean firstDocRendering = true;
@@ -442,9 +443,6 @@
 	    srv.addServlet(servletPath, servlet); // our deployment
 	}
 	else if(contentGUI.getServletContainer().getServlet(servletPath) == null){
-	    PBERecorder recorder = new PBERecorder();
-	    recorder.setGUIMap(id2GuiMap);
-	    servlet.setRecorder(recorder);
 	    contentGUI.getServletContainer().addServlet(servletPath, servlet); 
 	}
 
@@ -742,6 +740,7 @@
 	    currentDoc = null;  // get rid of previous in-memory doc use for interactive filtering, if any
 	    currentSelectedData = null;
 	    currentSelectionXPath = null;
+	    jobXPtrs = null;
 	    filterableNodes = null;
 	    origStyles = null;
 	    firstDocRendering = true;
@@ -774,6 +773,13 @@
 	return history.elementAt(historyIndex);
     }
 
+    protected URL getPreviousURL(){
+	if(historyIndex < 1 || historyIndex > history.size()){
+	    return null;
+	}
+	return history.elementAt(historyIndex-1);
+    }
+
     public boolean canFilter(){
 	return hasXMLSource();
     }
@@ -809,6 +815,7 @@
 		xPtrsReferencedInNextService = DataUtils.getInputXPtrs(history.elementAt(historyIndex+1), history.elementAt(historyIndex));
 	    } catch(Exception e){
 		logger.error("Cannot get the provenance data from "+history.elementAt(historyIndex+1), e);
+                return false;
 	    }
 	    
 	}
@@ -1187,7 +1194,8 @@
 	    return DataUtils.loadMobyDataFromXPointer(targetURL, filterHistory.get(getCurrentURL()));
 	}
 
-	// Simple case, build the object using the values encoded in the URL itself
+	// Simple case, build the object using the values encoded in the URL itself.
+	// Currently this is not used because it messes up provenance tracking for PbE
 	else{
 	    return loadMobyDataFromURLQuery(targetURL);
 	}
@@ -1204,7 +1212,7 @@
 
 	JPopupMenu popup = new DynamicJPopupMenu();
 	popup.setName(MOBY_SERVICE_POPUP_NAME);
-	addExtraMobyOptions(popup, mobyData);
+	addExtraMobyOptions(popup, mobyData, targetURL);
 	JMenuItem checkingLinksPopupItem = new JMenuItem("Check for services...");
 	popup.add(checkingLinksPopupItem);
 	popup.show(this, lastClickX+editorPane.getX(), lastClickY+editorPane.getY());
@@ -1223,7 +1231,7 @@
     /**
      * Subclasses can use this method to expand the popup menu.  Be sure to call super.addExtraMobyOptions()
      */
-    protected void addExtraMobyOptions(JPopupMenu popup, MobyDataInstance mdi){
+    protected void addExtraMobyOptions(JPopupMenu popup, MobyDataInstance mdi, URL srcURL){
 	// If we are wrapping a service, and you're getting the context menu, you must be 
 	// looking at service results, in which case let's give the option to create a service.
 	if(isWrapping){
@@ -1231,7 +1239,34 @@
 	    popup.add(createServicePopupItem);
 	    popup.setVisible(true);	    
 	}
+	// todo: 
+	// The item below is mainly to allow X to be used in service Y if running service Z on X meets some filter criteria.
+	// This is a common task in bioinformatics workflows.
+	// Backtrack from data to input used for service that generated the data.
+
+	// Here's an important point: if there is no filter on the current doc, we shouldn't be offering
+	// a "previous input" option, because the current doc's service contributed nothing to deciding 
+	// on how to proceed (no "if" conditon).
+	if(getFilter() == null){
+	    return;
+	}
+
+	//System.err.println("Should create a previous input menu item for " + mdi.getUserData());
+	try{
+	    Document srcDoc = docBuilder.parse(srcURL.openStream());
 
+	    // Get the input data for the *previous* service
+	    MobyDataJob inputData = DataUtils.getInputSample(srcDoc, SeahawkOptions.getRegistry());
+	    for(MobyDataInstance previousMDI: inputData.getPrimaryData()){		
+		// add conditional of the current service as a criteria in user data for each previousMDI, 
+		// so PbE will properly reflect the logic of if(f1(x) matches filter){f2(x)}
+		DataUtils.addUserData(previousMDI, srcURL, getFilter());
+
+		servicesGUI.addPopupOptions(previousMDI, popup, true, null, "previous input");
+	    }
+	} catch(Exception e){
+	    logger.warn("Could not load previous service info, 'previous input' option will not be displayed", e);
+	}
     }
 
     /**
@@ -1372,11 +1407,13 @@
 	}
 	// Filter out any moby jobs, parameters, collection members or HAS members that aren't in the matchingNodes
 	if(filterableNodes == null){
+	    jobXPtrs = new HashMap<String,Boolean>();
 	    filterableNodes = new Vector<String>();
 	    NodeList nodes = currentDoc.getElementsByTagNameNS(MobyTags.MOBY_XML_NS, MobyTags.MOBYDATA);
 	    for(int i = 0; i < nodes.getLength(); i++){
-		filterableNodes.add(getXPtr(nodes.item(i)));
-		addHASXPtrs(filterableNodes, (Element) nodes.item(i));
+		String jobXPtr = getXPtr(nodes.item(i));		
+		filterableNodes.add(jobXPtr);
+		jobXPtrs.put(jobXPtr, addHASXPtrs(filterableNodes, (Element) nodes.item(i)));
 	    }
 		
 	    // Collections
@@ -1429,26 +1466,43 @@
 	// Find just the data subset also matching the regex
 	Map<String,Boolean> matchingXPtrs = new LinkedHashMap<String,Boolean>();
 	// Build the FSA only once, for efficiency
-	Pattern regex = Pattern.compile(fs.getFilterRegex().toString(), Pattern.MULTILINE);
+	Pattern regex = Pattern.compile(fs.getFilterRegex().toString(), 
+                                        Pattern.MULTILINE | Pattern.DOTALL | 
+                                         (fs.getCaseSensitivity() ? 0 : Pattern.CASE_INSENSITIVE));
 	for(int i = 0; i < currentSelectedData.getLength(); i++){
 	    Node node = currentSelectedData.item(i);	    
 	    if(node instanceof Element){
-		if(regex.matcher(((Element) node).getTextContent()).find()){
-		    matchingXPtrs.put(getXPtr(node), Boolean.TRUE);
+		String elementXPtr = getXPtr(node);
+		if(matchingXPtrs.containsKey(elementXPtr) &&
+		   matchingXPtrs.get(elementXPtr).booleanValue()){
+		    	continue;  // already true, no 
+                    }
+		else if(regex.matcher(((Element) node).getTextContent()).find()){
+		    matchingXPtrs.put(elementXPtr, Boolean.TRUE);
+		    System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr));
 		}
 		else{
-		    matchingXPtrs.put(getXPtr(node), Boolean.FALSE);
+		    matchingXPtrs.put(elementXPtr, Boolean.FALSE);
+		    System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr));
 		}
-		//System.err.println("Adding " + getXPtr(node) + " as " + matchingXPtrs.get(getXPtr(node)));
 	    }
 	    else if(node instanceof Attr){
-		if(regex.matcher(((Attr) node).getValue()).find()){
+		String attrParentXPtr = getXPtr(((Attr) node).getOwnerElement());
+		if(matchingXPtrs.containsKey(attrParentXPtr) &&
+	 	   matchingXPtrs.get(attrParentXPtr).booleanValue()){
+		    continue;
+                }
+		else if(regex.matcher(((Attr) node).getValue()).find()){
 		    // Mark the element to which the attribute belongs
-		    matchingXPtrs.put(getXPtr(((Attr) node).getOwnerElement()), Boolean.TRUE);
+		    matchingXPtrs.put(attrParentXPtr, Boolean.TRUE);
+		    System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr));
 		}
-		else{
-		    matchingXPtrs.put(getXPtr(((Attr) node).getOwnerElement()), Boolean.FALSE);
+		// so false doesn't override true for multi-attr elements
+		else if(!matchingXPtrs.containsKey(attrParentXPtr)){ 
+		    matchingXPtrs.put(attrParentXPtr, Boolean.FALSE);
+		    System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr));
 		}
+		
 	    }
 	    else{
 		logger.warn("Found filter xpath result item that was not an Element or Attribute as expected ("+
@@ -1462,7 +1516,7 @@
 		if(matchingXPtr.getKey().startsWith(currXPtr+"/")){ // a parent of the matching data
 		    // No positive example yet?
 		    if(!parentMatchingXPtrs.containsKey(currXPtr) || !parentMatchingXPtrs.get(currXPtr).booleanValue()){
-			//System.err.println("Adding "+ matchingXPtr.getValue() + " for " + currXPtr);
+			System.err.println("Adding "+ matchingXPtr.getValue() + " for " + currXPtr);
 			parentMatchingXPtrs.put(currXPtr, matchingXPtr.getValue());
 		    }
 		}
@@ -1472,7 +1526,9 @@
 	matchingXPtrs.putAll(parentMatchingXPtrs);
 	for(String currXPtr: matchingXPtrs.keySet()){
 	    // Is part of the selection criteria, but doesn't match the regex
-	    if(!matchingXPtrs.get(currXPtr).booleanValue()){
+	    if(!matchingXPtrs.get(currXPtr).booleanValue() &&
+	       // special condition: if "entire document" xpath is given, filter only at the job level
+	       (!currentSelectionXPath.equals(FilterSearch.SELECT_ALL_XPATH) || jobXPtrs.containsKey(currXPtr))){
 		filteredData.put(currXPtr, "todo");
 	    }
 	}
@@ -1484,7 +1540,7 @@
     }
 
     // If any moby object member is in a HAS relationship, add it to the list of filterable items
-    private void addHASXPtrs(List<String> filterList, Element object){
+    private Boolean addHASXPtrs(List<String> filterList, Element object){
 	String tagName = object.getLocalName();
 	boolean isContainer = false;
 	MobyDataType mobyDataType = null;	
@@ -1496,10 +1552,11 @@
 	    mobyDataType = MobyDataType.getDataType(tagName, SeahawkOptions.getRegistry());
 	    if(mobyDataType == null){
 		logger.warn("Found datatype unknown to the registry ("+object.getLocalName()+")");
-		return;
+		return Boolean.FALSE;
 	    }
 	}
 
+	Boolean hasHAS = Boolean.FALSE; // does the object have a member with a HAS relationship?
 	NodeList members = object.getChildNodes();
 	for(int i = 0; i < members.getLength(); i++){
 	    if(!(members.item(i) instanceof Element)){
@@ -1516,9 +1573,13 @@
 		//		   " is " + (membership == null ? null : membership.getRelationshipType()));
 		if(membership != null && membership.getRelationshipType() == Central.iHAS){
 		    filterList.add(getXPtr(member));
+		    if(!hasHAS){
+			hasHAS = Boolean.TRUE;
+		    }
 		}
 	    }
 	}
+	return hasHAS;
     }
 
     // Recursively ascend the DOM tree and find out our place in its branching structure
@@ -1527,6 +1588,9 @@
 	    return "";
 	}
 	Node parent = n.getParentNode();
+        if(parent == null && n instanceof Attr){
+	    parent = ((Attr) n).getOwnerElement();
+	}
 
 	NodeList children = parent.getChildNodes();
 	int nonElementCnt = 0;
@@ -1624,19 +1688,27 @@
 	int matchCount = 0;
 	if(fs != null && fs.getFilterRegex().length() > 0){
 	    try{
+                Map<String,Boolean> highlights = new HashMap<String,Boolean>();
 		javax.swing.text.LayeredHighlighter.LayerPainter painter = 
 		    new DefaultHighlighter.DefaultHighlightPainter(Color.yellow);
-		Pattern p = Pattern.compile(fs.getFilterRegex().toString(), Pattern.MULTILINE);
+		Pattern p = Pattern.compile(fs.getFilterRegex().toString(), 
+				            Pattern.MULTILINE | Pattern.DOTALL | 
+                                             (fs.getCaseSensitivity() ? 0 : Pattern.CASE_INSENSITIVE));
 		for(String filterable: filterableNodes){
 		    javax.swing.text.Element el = d.getElement(filterable);
 		    String fragment = d.getText(el.getStartOffset(),
 						el.getEndOffset() - el.getStartOffset());
 		    Matcher matcher = p.matcher(fragment);
 		    while (matcher.find()) {
-			h.addHighlight(el.getStartOffset() + matcher.start(),
-				       el.getStartOffset() + matcher.end(),
-				       painter);
-			matchCount++;
+			// Only count match if not already highlighted in a containing filterable node
+			// todo: in future, avoid looking in text bits already checked, for efficiency
+			int hstart = el.getStartOffset() + matcher.start();
+                        int hend = el.getStartOffset() + matcher.end();
+			if(!highlights.containsKey(""+hstart+","+hend)){
+			    h.addHighlight(hstart, hend, painter);
+			    matchCount++;
+			    highlights.put(""+hstart+","+hend, Boolean.TRUE);
+                        }	
 		    }
 		}
 	    } catch(Exception e){
@@ -1687,6 +1759,7 @@
 	    searchPanel.add(filterSearchWidget);
 	    searchPanel.revalidate();
 	    revalidate(); // redo the panel layout
+	    applyFilter(true);
 	}
 	else{
 	    // have a backup, so if re-enabled the old search is restored
@@ -1768,6 +1841,11 @@
 		    }
 		}
 	    }
+	    // todo: If the selection was over the Moby XML display, harvest the set of data and show options for those
+	    // from experience, users try to highlight the whole data and send forward to the next service rather than
+	    // just picking an example value.
+
+	    // If display was not moby data links, but rather just text of some sort, do data recognition over it.
 	    MobyDataInstance[] mobyData = loadMobyDataFromString(selectedTextData);
 	    if(mobyData == null || mobyData.length == 0){
 		logger.warn("No MobyData could be made from the selected text");




More information about the MOBY-guts mailing list