[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