From gordonp at dev.open-bio.org Thu Apr 8 22:23:15 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Thu, 8 Apr 2010 22:23:15 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004090223.o392NFDP006711@dev.open-bio.org> gordonp Thu Apr 8 22:23:15 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/images In directory dev.open-bio.org:/tmp/cvs-serv6679/src/main/ca/ucalgary/seahawk/resources/images Added Files: case_insensitive.png case_sensitive.png Log Message: Icon for search filter's case sensitivity moby-live/Java/src/main/ca/ucalgary/seahawk/resources/images case_insensitive.png,NONE,1.1 case_sensitive.png,NONE,1.1 From gordonp at dev.open-bio.org Fri Apr 9 11:47:04 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:47:04 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091547.o39Fl4m3001186@dev.open-bio.org> gordonp Fri Apr 9 11:47:03 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv1154/src/main/ca/ucalgary/seahawk/resources Added Files: PassFilterBeanShell FlattenListBeanShell Log Message: Taverna beanshells used in Seahawk's programming-by-example system moby-live/Java/src/main/ca/ucalgary/seahawk/resources PassFilterBeanShell,NONE,1.1 FlattenListBeanShell,NONE,1.1 From gordonp at dev.open-bio.org Fri Apr 9 11:48:19 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:48:19 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091548.o39FmJJf001286@dev.open-bio.org> gordonp Fri Apr 9 11:48:19 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv1250/src/main/ca/ucalgary/seahawk/util Modified Files: FilterSearch.java Log Message: Added case sensitivity, constant for select-all xpath moby-live/Java/src/main/ca/ucalgary/seahawk/util FilterSearch.java,1.2,1.3 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.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/seahawk/util/FilterSearch.java 2010/03/29 19:49:52 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/09 15:48:19 1.3 @@ -20,9 +20,11 @@ public class FilterSearch{ private URL docURL; + private boolean caseSensitivity = false; private StringBuffer filterRegex; private Vector xpathOptions; private int xpathSelected = 0; + public static final String SELECT_ALL_XPATH = "//* | //*/@*"; /** * @param docToFilter the document that will be used to determine what XPaths can be suggested @@ -34,7 +36,7 @@ docURL = docToFilter; filterRegex = new StringBuffer(); xpathOptions = new Vector(); - xpathOptions.add(new XPathOption("//*", "entire document")); + xpathOptions.add(new XPathOption(SELECT_ALL_XPATH, "entire response")); Document domDoc = docBuilder.parse(docURL.openStream()); // Get the moby jobs NodeList jobs = domDoc.getDocumentElement().getElementsByTagNameNS(MobyPrefixResolver.MOBY_XML_NAMESPACE, MobyTags.MOBYDATA); @@ -72,6 +74,14 @@ } } + public boolean getCaseSensitivity(){ + return caseSensitivity; + } + + public void setCaseSensitivity(boolean sensitivity){ + caseSensitivity = sensitivity; + } + public void setSelectedXPath(int cursor){ xpathSelected = cursor; } From gordonp at dev.open-bio.org Fri Apr 9 11:49:18 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:49:18 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091549.o39FnI8b001330@dev.open-bio.org> gordonp Fri Apr 9 11:49:18 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv1294/src/main/ca/ucalgary/seahawk/resources Modified Files: RegexFilterBeanShell Log Message: Added case sensitivity, eliminated auto-attr matching since select-all xpath has been fixed moby-live/Java/src/main/ca/ucalgary/seahawk/resources RegexFilterBeanShell,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/RegexFilterBeanShell,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/seahawk/resources/RegexFilterBeanShell 2010/03/17 20:03:06 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/RegexFilterBeanShell 2010/04/09 15:49:18 1.2 @@ -1,4 +1,5 @@ import java.util.*; +import java.util.regex.Pattern; import org.dom4j.*; import org.dom4j.io.SAXReader; @@ -13,24 +14,18 @@ int i = 1; Map collections = new LinkedHashMap(); Map collectionsEnd = new HashMap(); -select: for (Iterator iter = nodelist.iterator(); iter.hasNext();) { +Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL | (Boolean.parseBoolean(case_sensitive) ? 0 : Pattern.CASE_INSENSITIVE)); +for (Iterator iter = nodelist.iterator(); iter.hasNext();) { Node node = (Node) iter.next(); boolean match = false; switch(node.getNodeType()){ case Node.ELEMENT_NODE: - if(node.getText().matches(".*?"+regex+".*")){ + if(pattern.matcher(node.getText()).find()){ match = true; } - else{ - for(Object attr: ((Element) node).attributeIterator()){ - if(((Attribute) attr).getValue().matches(".*?"+regex+".*")){ - match = true; break; - } - } - } break; case Node.ATTRIBUTE_NODE: - if(node.getValue().matches(".*?"+regex+".*")){ + if(pattern.matcher(node.getValue()).find()){ match = true; } break; From gordonp at dev.open-bio.org Fri Apr 9 11:50:09 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:50:09 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091550.o39Fo903001396@dev.open-bio.org> gordonp Fri Apr 9 11:50:09 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv1360/src/main/ca/ucalgary/seahawk/gui Modified Files: FilterSearchWidget.java Log Message: Added case sensitivity moby-live/Java/src/main/ca/ucalgary/seahawk/gui FilterSearchWidget.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.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/seahawk/gui/FilterSearchWidget.java 2010/03/17 20:20:47 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/09 15:50:09 1.2 @@ -17,9 +17,13 @@ private FilterSearch currentFilterSearch; private JLabel closeIcon; + private JToggleButton caseButton; private JTextField searchField; private JComboBox docPartOptions; private MobyContentPane contentPane; + public static final String CASE_SENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_sensitive.png"; + public static final String CASE_INSENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_insensitive.png"; + private static final String CASE_BUTTON_NAME = "case_sensitivity_button"; private static Logger logger = Logger.getLogger(FilterSearchWidget.class.getName()); @@ -27,7 +31,8 @@ super(); contentPane = mcp; - URL u = Thread.currentThread().getContextClassLoader().getResource(CloseTabIcon.CLOSE_TAB_ICON_RESOURCE); + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + URL u = cl.getResource(CloseTabIcon.CLOSE_TAB_ICON_RESOURCE); if(u == null){ throw new Exception("Could not find icon resource " + CloseTabIcon.CLOSE_TAB_ICON_RESOURCE); } @@ -37,9 +42,22 @@ closeIcon.addMouseListener(new Closer(this)); closeIcon.setToolTipText("Remove filter criteria"); + Dimension buttonSize = new Dimension(24,24); + caseButton = new JToggleButton(new ImageIcon(cl.getResource(CASE_SENSITIVE_ICON_RESOURCE))); + caseButton.setDisabledIcon(new ImageIcon(cl.getResource(CASE_INSENSITIVE_ICON_RESOURCE))); + caseButton.setToolTipText("Toggles the case sensitivity of the filter"); + caseButton.setPreferredSize(buttonSize); + caseButton.setEnabled(true); + caseButton.setSelected(false); + caseButton.addActionListener(this); + caseButton.setMargin(new java.awt.Insets(2,2,2,2)); + caseButton.setName(CASE_BUTTON_NAME); // so test cases can find the component + setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); add(closeIcon); add(Box.createRigidArea(new Dimension(5,0))); + add(caseButton); + add(Box.createRigidArea(new Dimension(5,0))); add(new JLabel("Show data if ")); add(Box.createRigidArea(new Dimension(5,0))); searchField = new JTextField(25); @@ -62,11 +80,15 @@ public void setFilter(FilterSearch fs){ currentFilterSearch = null; if(fs == null){ + caseButton.setEnabled(false); searchField.setEnabled(false); docPartOptions.setEnabled(false); return; } + caseButton.setEnabled(true); + caseButton.setSelected(fs.getCaseSensitivity()); + searchField.setEnabled(true); searchField.setText(fs.getFilterRegex().toString()); @@ -79,7 +101,15 @@ * Called when the user has changed the xpath */ public void actionPerformed(ActionEvent e){ - if(currentFilterSearch == null || e.getSource() != docPartOptions){ + if(e.getSource() == caseButton){ + if(currentFilterSearch == null){ + return; + } + currentFilterSearch.setCaseSensitivity(caseButton.isSelected()); + contentPane.applyFilter(true); + return; + } + else if(currentFilterSearch == null || e.getSource() != docPartOptions){ return; } currentFilterSearch.setSelectedXPath(docPartOptions.getSelectedIndex()); From gordonp at dev.open-bio.org Fri Apr 9 11:51:53 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:51:53 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091551.o39FprFb001496@dev.open-bio.org> gordonp Fri Apr 9 11:51:53 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv1460/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentClipboard.java Log Message: data xml src passthrough to enable 'previous input' services moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentClipboard.java,1.8,1.9 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/03/29 19:47:02 1.8 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/09 15:51:53 1.9 @@ -113,8 +113,8 @@ return false; } - protected void addExtraMobyOptions(JPopupMenu popup, MobyDataInstance mdi){ - super.addExtraMobyOptions(popup, mdi); + protected void addExtraMobyOptions(JPopupMenu popup, MobyDataInstance mdi, URL srcURL){ + super.addExtraMobyOptions(popup, mdi, srcURL); // Only process if the passed in data is one of the top level collection elements // (i.e. don't delete subparts of object) From gordonp at dev.open-bio.org Fri Apr 9 11:54:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:54:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091554.o39FsHP8001666@dev.open-bio.org> 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 jobXPtrs = null; // Map private List filterableNodes = null; // List private List 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(); filterableNodes = new Vector(); 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 matchingXPtrs = new LinkedHashMap(); // 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 filterList, Element object){ + private Boolean addHASXPtrs(List 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 highlights = new HashMap(); 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"); From gordonp at dev.open-bio.org Fri Apr 9 11:55:49 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:55:49 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091555.o39FtnLh001766@dev.open-bio.org> gordonp Fri Apr 9 11:55:48 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv1730/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyServicesGUI.java Log Message: Added ability to customize top level menu items with extra text (used initially by 'previous input' feature) moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyServicesGUI.java,1.16,1.17 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2009/06/09 19:27:56 1.16 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/09 15:55:48 1.17 @@ -442,7 +442,7 @@ // Create the top level menu items for these moby objects right away submenus = new JMenu[mobyObjects.length]; for(int i = 0; i < mobyObjects.length; i++){ - JMenu submenu = createObjectSubMenu(mobyObjects[i]); + JMenu submenu = createObjectSubMenu(mobyObjects[i], null); if(submenu == null){ continue; } @@ -503,6 +503,7 @@ Node targetNode = null; MobyRequestEventHandler handler = null; MobyDataInstance mobyData = null; + String extraMenuText = null; JPopupMenu popupList; public OptionLoaderThread(Node targetNode, JPopupMenu popupList, MobyRequestEventHandler handler){ @@ -512,11 +513,12 @@ this.handler = handler; } - public OptionLoaderThread(MobyDataInstance mobyData, JPopupMenu popupList, MobyRequestEventHandler handler){ + public OptionLoaderThread(MobyDataInstance mobyData, JPopupMenu popupList, MobyRequestEventHandler handler, String extraMenuText){ super(); this.mobyData = mobyData; this.popupList = popupList; this.handler = handler; + this.extraMenuText = extraMenuText; } public void run(){ @@ -524,7 +526,7 @@ addPopupOptions(targetNode, popupList, false, handler); } else if(mobyData != null){ - addPopupOptions(mobyData, popupList, false, handler); + addPopupOptions(mobyData, popupList, false, handler, extraMenuText); } else{ logger.warn("Warning: OptionLoaderThread has no data to work with"); @@ -584,6 +586,13 @@ * Find the list of available services querying MobyCentral directly with a piece of data. */ public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous, MobyRequestEventHandler handler){ + addPopupOptions(mobyData, popupList, asynchronous, handler, null); + } + + /** + * Find the list of available services querying MobyCentral directly with a piece of data. + */ + public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous, MobyRequestEventHandler handler, String extraMenuText){ if(asynchronous){ //Show the user that we're doing something... @@ -596,13 +605,13 @@ } // Call this method synchronously in a different thread - OptionLoaderThread lt = new OptionLoaderThread(mobyData, popupList, handler); + OptionLoaderThread lt = new OptionLoaderThread(mobyData, popupList, handler, extraMenuText); lt.start(); return; } // Create submenu for this object - JMenu submenu = createObjectSubMenu(mobyData); + JMenu submenu = createObjectSubMenu(mobyData, extraMenuText); // Add option to copy object to clipboard. We don't need to wait until services are found. if(submenu == null){ return; @@ -1127,7 +1136,7 @@ return menu; } - public JMenu createObjectSubMenu(MobyDataInstance mdi){ + public JMenu createObjectSubMenu(MobyDataInstance mdi, String extraMenuText){ if(!(mdi instanceof MobyPrimaryData)){ logger.warn("Ignoring non-primary data object submitted to menu creation: " + mdi); return null; @@ -1205,7 +1214,7 @@ } } desc = "Record Identifier - " + mobydesc; - submenu = new JMenu("Services for " + datatype + ":" + id); + submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+datatype + ":" + id); assignMenuDataIndex(submenu); } else if("String".equals(mobyDataType.getName())){ @@ -1217,7 +1226,8 @@ sample = sample.substring(0, MAX_ID_LEN)+"..."; } desc = "A piece of text"; - submenu = new JMenu("Services for String \"" + sample + "\""); + submenu = new JMenu("Services for "+(extraMenuText == null ? "" : extraMenuText+" ")+ + "String \"" + sample + "\""); assignMenuDataIndex(submenu); } // Complex object @@ -1236,7 +1246,7 @@ else if(targetData instanceof MobyDataObjectSet){ objectLabel += " collection"; } - submenu = new JMenu("Services for " + objectLabel); + submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+objectLabel); assignMenuDataIndex(submenu); } desc = "Input data: " + desc; From gordonp at dev.open-bio.org Fri Apr 9 11:57:46 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:57:46 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091557.o39FvkSp001872@dev.open-bio.org> gordonp Fri Apr 9 11:57:46 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv1836/src/main/ca/ucalgary/seahawk/util Modified Files: DataUtils.java Log Message: Added support for case sensitive searches, and 'previous input' conditional service execution moby-live/Java/src/main/ca/ucalgary/seahawk/util DataUtils.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.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/seahawk/util/DataUtils.java 2010/03/29 19:58:17 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/09 15:57:46 1.2 @@ -117,7 +117,7 @@ if(newFilter != null){ XPathOption xsel = newFilter.getSelectedXPath(); newProvenanceData += "\t"+newFilter.getFilterRegex()+ - "\t"+xsel.getXPath()+"\t"+xsel.getDesc(); + "\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+newFilter.getCaseSensitivity(); } pi.setData(attr_val[0]+"=\""+newProvenanceData+"\""); } @@ -300,7 +300,7 @@ return temp.toURI().toURL(); } - private static URL getInputURL(Document responseDom) throws Exception{ + public static URL getInputURL(Document responseDom) throws Exception{ String inputAddr = getSeahawkAttrFromDoc(responseDom, SERVICEINPUT_ATTR); if(inputAddr == null){ return null; @@ -315,7 +315,11 @@ } } - private static Document getInputDoc(Document responseDom) throws Exception{ + public static Document getInputDoc(Document responseDom) throws Exception{ + URL inputURL = getInputURL(responseDom); + if(inputURL == null){ + return null; + } try{ return docBuilder.parse(getInputURL(responseDom).openStream()); } catch(org.xml.sax.SAXException saxe){ @@ -332,6 +336,9 @@ */ public static MobyDataJob getInputSample(Document responseDom, Registry registry) throws Exception{ Document inputDoc = getInputDoc(responseDom); + if(inputDoc == null){ + return null; + } MobyContentInstance inputPayload = MobyDataUtils.fromXMLDocument(inputDoc.getDocumentElement(), registry); if(inputPayload == null || inputPayload.size() == 0){ @@ -633,12 +640,30 @@ if(fs != null && fs.getFilterRegex().length() > 0){ XPathOption xsel = fs.getSelectedXPath(); - userData.append("\t"+fs.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()); + userData.append("\t"+fs.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+fs.getCaseSensitivity()); } mobyData.setUserData(userData.toString()); } /** + * Record a condition for data acceptability, + * another service call with an output filter criteria. i.e. records if(f1(x) matches f1's output filter){...} + */ + public static void addUserData(MobyDataInstance mdi, URL conditionalOutputURL, FilterSearch filter){ + String filterSpec = ""; + if(filter != null && filter.getFilterRegex().length() > 0){ + XPathOption xsel = filter.getSelectedXPath(); + filterSpec = "\t"+filter.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+filter.getCaseSensitivity(); + } + if(mdi.getUserData() != null){ + mdi.setUserData(mdi.getUserData().toString()+"\t"+conditionalOutputURL+filterSpec); + } + else{ + mdi.setUserData(conditionalOutputURL.toString()+filterSpec); + } + } + + /** * Retrieves processing instructions embedded in Moby XML docs if they have the for */ public static String getSeahawkAttrFromDoc(URL docURL, String attrName) throws Exception{ From gordonp at dev.open-bio.org Fri Apr 9 11:58:23 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:58:23 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091558.o39FwMVA001941@dev.open-bio.org> gordonp Fri Apr 9 11:58:22 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv1902/src/main/ca/ucalgary/seahawk/util Modified Files: DataFlowRecorder.java Log Message: Added support for case sensitive searches, and 'previous input' conditional service execution moby-live/Java/src/main/ca/ucalgary/seahawk/util DataFlowRecorder.java,1.2,1.3 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.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/seahawk/util/DataFlowRecorder.java 2010/03/29 20:53:04 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/09 15:58:22 1.3 @@ -31,6 +31,8 @@ public static final String T2FLOW_DISPATCHXML = "ca/ucalgary/seahawk/resources/t2flowDispatchStack.xml"; public static final String T2FLOW_REGEXFILTER_BEANSHELL = "ca/ucalgary/seahawk/resources/RegexFilterBeanShell"; public static final String T2FLOW_XPATHFILTER_BEANSHELL = "ca/ucalgary/seahawk/resources/XPathFilterBeanShell"; + public static final String T2FLOW_PASSFILTER_BEANSHELL = "ca/ucalgary/seahawk/resources/PassFilterBeanShell"; // = if condition + public static final String T2FLOW_LISTFLATTEN_BEANSHELL = "ca/ucalgary/seahawk/resources/FlattenListBeanShell"; private Central mobyCentral; private Map namesUsed; // keep count of workflow element name usage so as not to duplicate an ID @@ -39,9 +41,12 @@ // Value is processor and port names private Map filter2Processor; private Map decomp2Processor; // reuse decomposition processors if same decomp done more than once on a given doc + private Map input2Processor; // if same input use more than once, create only one input port private DocumentBuilder docBuilder; private static String regexFilterScript = null; private static String xpathFilterScript = null; + private static String passFilterScript = null; + private static String listFlattenScript = null; private static Element dispatchStack = null; private static Transformer nullTransformer = null; private static Logger logger = Logger.getLogger(DataFlowRecorder.class.getName()); @@ -57,8 +62,9 @@ namesUsed = new HashMap(); url2Processor = new HashMap(); - filter2Processor = new HashMap(); // key is compound: url \n regex \n xpath + filter2Processor = new HashMap(); // key is compound: url \n regex \n xpath \n caseSensitivity decomp2Processor = new HashMap(); // key is url with xpath attached as ref (the way Seahawk generates them) + input2Processor = new HashMap(); // key is input instance XML } /** @@ -154,6 +160,7 @@ url2Processor.clear(); // clear map of results already produced in backtracking (handling workflow forks) filter2Processor.clear(); // ditto decomp2Processor.clear(); // ditto + input2Processor.clear(); // ditto // Generate all of the outputs requested by the call. None should be intermediaries // of another (the backtracking done by addWorkflowElements will capture these). @@ -162,7 +169,7 @@ // Create the inputs, processors and data links required for the workflow to create the result doc String ultimateProcessorName = addWorkflowElements(result.getKey(), doc, inputPorts, processors, datalinks); - // If there is a filter active on the currently displyed doc, we need to apply it here + // If there is a filter active on the currently displayed doc, we need to apply it here FilterSearch filter = result.getValue(); String[] regexProcessorAndPorts = null; String filterKey = null; @@ -190,9 +197,11 @@ } else{ regexProcessorAndPorts = createRegexFilter(filter.getFilterRegex().toString(), - filter.getSelectedXPath(), + filter.getSelectedXPath(), + filter.getCaseSensitivity(), ultimateProcessorName, - getPortName(outputParam, true), + getPortName(outputParam, true), + 1, // desired list dpeth processors, datalinks, doc); filter2Processor.put(filterKey, regexProcessorAndPorts); } @@ -275,6 +284,9 @@ MobyService service = DataUtils.getService(resultDom); Registry registry = DataUtils.getRegistry(resultDom); MobyDataJob sampleJob = DataUtils.getInputSample(resultDom, registry); + if(sampleJob == null){ + return "foo"; //todo: doc was a loaded Moby XML, not a service output or recognized data + } Element processorElement = createProcessorElement(service, sampleJob, doc); // add processor to workflow @@ -297,111 +309,181 @@ MobyPrimaryData sampleData = (MobyPrimaryData) sd; // has provenance info? + String[] data = null; + String[] condPassProcessorAndPorts = null; //[procname, input port, outputport] if(sampleData.getUserData() != null){ - // User data has the form srcURL#generalSelectionXPath actualInputDataXptr regexFilter - // where the filter is optional - String[] data = sampleData.getUserData().toString().split("\t"); + // User data has the form + // srcURL#generalSelectionXPath actualInputDataXptr regexFilter conditionalURL + // where the filter and conditionalURL are optional + data = sampleData.getUserData().toString().split("\t"); + //options: selection + filter + cond, selection + cond, or cond only + if(data.length == 11 || data.length == 7 || data.length == 5){ + System.err.println("Adding conditional for " + resultURLString); + String conditionURL = data[data.length-5]; + String conditionRegex = data[data.length-4]; + XPathOption conditionXPath = new XPathOption(data[data.length-3], data[data.length-2]); + boolean caseSensitivity = Boolean.parseBoolean(data[data.length-1]); + condPassProcessorAndPorts = createServiceConditionFilter(new URL(conditionURL), conditionRegex, conditionXPath, caseSensitivity, + doc, inputPorts, processors, datalinks); + String[] conditionlessData = new String[data.length-5]; + System.arraycopy(data, 0, conditionlessData, 0, data.length-5); + data = conditionlessData; + } + else{ + System.err.println("Skipping conditional, only " + data.length + + "members in provenance data for " + resultURLString); + } + } + + // true means treat as a collection if that's what the sample data is + String sinkPortName = getPortName(sampleData, true); + if(data != null && data.length != 0){ URL dataSrcURL = null; try{ dataSrcURL = new URL(data[0]); } catch(Exception e){ logger.log(Level.WARNING, "Ignoring unexpected UserData in Moby DOM, was not " + "a provenance URL as expected URL (" + sampleData.getUserData().toString() + ")"); + continue; } - if(dataSrcURL != null){ - // recursion for workflow creation by backtracking service input provenance - String feedingProcessorName = null; - String feedingProcessorPort = null; - String dataSrcURLString = dataSrcURL.toString().replaceFirst("#.*$", ""); //get rid of ref part - if(url2Processor.containsKey(dataSrcURLString)){ - feedingProcessorName = url2Processor.get(dataSrcURLString); + // recursion for workflow creation by backtracking service input provenance + String feedingProcessorName = null; + String feedingProcessorPort = null; + String dataSrcURLString = dataSrcURL.toString().replaceFirst("#.*$", ""); //get rid of ref part + if(url2Processor.containsKey(dataSrcURLString)){ + feedingProcessorName = url2Processor.get(dataSrcURLString); + } + else{ + feedingProcessorName = addWorkflowElements(dataSrcURL, doc, inputPorts, processors, datalinks); + } + + // Take into account data[2..5] if they are present, + // which filter the data by a regex before any other activities happen + // Format of spec is regex xpath xpathTextDesc booleanForCaseSensitivity + if(data.length == 6){ + String[] origFeederProcessorAndPort = getPortFromURLRef(dataSrcURL, + sampleData, + feedingProcessorName, + null, + processors, + datalinks, + doc, + false); + + // Lookup key is url \n regex \n xpath \n caseSensitivity + String[] regexProcessorAndPorts = null; + String filterKey = dataSrcURLString+"\n"+data[2]+"\n"+data[3]+"\n"+data[5]; + if(filter2Processor.containsKey(filterKey)){ // filter already exists from another branch + regexProcessorAndPorts = filter2Processor.get(filterKey); } else{ - feedingProcessorName = addWorkflowElements(dataSrcURL, doc, inputPorts, processors, datalinks); - } - - // true means treat as a collection if that's what the sample data is - String sinkPortName = getPortName(sampleData, true); - - // Take into account data[2..4] if they are present, - // which filter the data by a regex before any other activities happen - // Format of spec is regex xpath xpathTextDesc, so the earlier split gives use indices 1..3 - if(data.length == 5){ - String[] origFeederProcessorAndPort = getPortFromURLRef(dataSrcURL, - sampleData, - feedingProcessorName, - null, - processors, - datalinks, - doc, - false); - - // Lookup key is url \n regex \n xpath - String[] regexProcessorAndPorts = null; - String filterKey = dataSrcURLString+"\n"+data[2]+"\n"+data[3]; - if(filter2Processor.containsKey(filterKey)){ // filter already exists from another branch - regexProcessorAndPorts = filter2Processor.get(filterKey); - } - else{ - regexProcessorAndPorts = createRegexFilter(data[2], - new XPathOption(data[3], data[4]), - origFeederProcessorAndPort[0], - origFeederProcessorAndPort[1], - processors, datalinks, doc); - // New filter is applied to just this branch from a service for the moment...record the filter - // so that if same filter criteria are applied to more than one branch, we only make one filter - filter2Processor.put(dataSrcURLString+"\n"+data[2]+"\n"+data[3], regexProcessorAndPorts); - } - feedingProcessorName = regexProcessorAndPorts[0]; - feedingProcessorPort = regexProcessorAndPorts[regexProcessorAndPorts.length-1]; //last one is output + regexProcessorAndPorts = createRegexFilter(data[2], + new XPathOption(data[3], data[4]), + Boolean.parseBoolean(data[5]), + origFeederProcessorAndPort[0], + origFeederProcessorAndPort[1], + 1, // desired list depth + processors, datalinks, doc); + // New filter is applied to just this branch from a service for the moment...record the filter + // so that if same filter criteria are applied to more than one branch, we only make one filter + filter2Processor.put(filterKey, regexProcessorAndPorts); } - - // getPortFromURLRef() may inject extra processors between the processorName and feedingProcessorName - // in order to maintain type safety, etc. so the data link may change (based on last arg being set to true). - String[] feederProcessorAndPort = getPortFromURLRef(dataSrcURL, - sampleData, - feedingProcessorName, - feedingProcessorPort, //if null, determined from urlref - processors, - datalinks, - doc, - true); - datalinks.appendChild(createDataLinkElement(feederProcessorAndPort[0], feederProcessorAndPort[1], - processorName, sinkPortName, + feedingProcessorName = regexProcessorAndPorts[0]; + feedingProcessorPort = regexProcessorAndPorts[regexProcessorAndPorts.length-1]; //last one is output + } + + // getPortFromURLRef() may inject extra processors between the processorName and feedingProcessorName + // in order to maintain type safety, etc. so the data link may change (based on last arg being set to true). + String[] feederProcessorAndPort = getPortFromURLRef(dataSrcURL, + sampleData, + feedingProcessorName, + feedingProcessorPort, //if null, determined from urlref + processors, + datalinks, + doc, + true); + if(condPassProcessorAndPorts != null){ + // inject condition filter between feeder service and current service + datalinks.appendChild(createDataLinkElement(feederProcessorAndPort[0], + feederProcessorAndPort[1], + condPassProcessorAndPorts[0], + condPassProcessorAndPorts[1], doc)); - + feederProcessorAndPort[0] = condPassProcessorAndPorts[0]; + feederProcessorAndPort[1] = condPassProcessorAndPorts[2]; } + + datalinks.appendChild(createDataLinkElement(feederProcessorAndPort[0], feederProcessorAndPort[1], + processorName, sinkPortName, + doc)); + } // Otherwise it's a workflow input the user will need to specify else{ - String uniqueInputName = createUniqueName(getInputName(sampleData)); - // todo: sample data may be of more specific type than service requires - inputPorts.appendChild(createWorkflowInputElement(uniqueInputName, sampleData, doc)); - if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT)){ - String mobifyingProcessorName = addIdMobifyingProcessor(processors, datalinks, - sampleData, processorName, - inputName, doc); - datalinks.appendChild(createWorkflowInputLinkElement(uniqueInputName, - mobifyingProcessorName, - "fileurl", - sampleData, - doc)); + // pName is editable name for input processor target... + // allows injection of condition without affecting method's return value + String pName = processorName; + if(condPassProcessorAndPorts != null){ + // inject condition filter between data creator and current service + datalinks.appendChild(createDataLinkElement(condPassProcessorAndPorts[0], + condPassProcessorAndPorts[2], + pName, + sinkPortName, + doc)); + pName = condPassProcessorAndPorts[0]; + sinkPortName = condPassProcessorAndPorts[1]; + } + // The sample data may be used in more than one branch of the flow...avoid duplication + // Get the real data XML, to see if we've encountered it before as input (it'd be in the hash) + // Remember that sd is the loop's original MobyDataInstance before it's been coerced into a MobyPrimaryData, + // which doesn't have XML modes, etc. + String inputKey = getInputKey(sd); + System.err.println("Input key for " + processorName + " is " + inputKey); + + String[] mobifyingProcessorNameAndPorts = null; + if(input2Processor.containsKey(inputKey)){ + mobifyingProcessorNameAndPorts = input2Processor.get(inputKey); } else{ - // TODO: Need to build complex input from MOB rule or spreadsheet fields? + if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT)){ + mobifyingProcessorNameAndPorts = addIdMobifyingProcessor(processors, datalinks, inputPorts, + sampleData, doc); + input2Processor.put(inputKey, mobifyingProcessorNameAndPorts); + } + else{ + // TODO: Need to build complex input from MOB rule or spreadsheet fields? + } } + // link the created data to the workflow service + datalinks.appendChild(createDataLinkElement(mobifyingProcessorNameAndPorts[0], + mobifyingProcessorNameAndPorts[1], + pName, sinkPortName, + doc)); } + } return processorName; } + // returns the same value for moby sample data instances containing the same data in XML form + private String getInputKey(MobyDataInstance sd){ + int oldXmlMode = sd.getXmlMode(); + sd.setXmlMode(MobyDataInstance.SERVICE_XML_MODE); + String inputKey = sd.toXML(); + sd.setXmlMode(oldXmlMode); + + // get rid of the top-level article name, as this is immaterial to the + // value equivalence of objects (only matters to the actual service call mechanism) + return inputKey.replaceFirst(MobyTags.ARTICLENAME+"\\s*=\\s*(['\"]).*?\\1", ""); + } + // Actually adds a few processors, but only one needs to be returned and connected to an input port. // The others are constant values. By default we assume that you want to run a bunch of IDs // in a file, we also link in a Taverna spreadsheet importer. - private String addIdMobifyingProcessor(Element processors, Element datalinks, - MobyPrimaryData sampleData, String targetProcessorName, - String targetProcessorPort, Document doc) throws Exception{ + // Returns [spreadsheetReadingProcName, outputPort] + private String[] addIdMobifyingProcessor(Element processors, Element datalinks, Element dataFlowInputPorts, + MobyPrimaryData sampleData, Document doc) throws Exception{ String processorName = "Create-" + sampleData.getDataType().getName(); MobyNamespace ns = null; MobyNamespace[] nss = ((MobyPrimaryData) sampleData).getNamespaces(); @@ -518,7 +600,7 @@ Map feeds = new HashMap(); //what port on data creator it maps to constants.put(ns.getName()+"-namespace-constant", ns.getName()); feeds.put(ns.getName()+"-namespace-constant", "namespace"); - constants.put("article_name-constant", targetProcessorPort); + constants.put("article_name-constant", "unimportant"); feeds.put("article_name-constant", "article name"); for(Map.Entry constant: constants.entrySet()){ @@ -632,19 +714,23 @@ port.setAttribute("name", "fileurl"); port.setAttribute("depth", "0"); + String uniqueInputName = createUniqueName(getInputName(sampleData)); + // todo: sample data may be of more specific type than service requires + dataFlowInputPorts.appendChild(createWorkflowInputElement(uniqueInputName, sampleData, doc)); + datalinks.appendChild(createWorkflowInputLinkElement(uniqueInputName, + importerName, + "fileurl", + sampleData, + doc)); + // link the spreadsheet reader to the Moby data creator datalinks.appendChild(createDataLinkElement(importerName, outputUniqueName, processorName, "id", doc)); - // link the created data to the first workflow service, which takes an id - datalinks.appendChild(createDataLinkElement(processorName, "mobyData", - targetProcessorName, "Object("+targetProcessorPort+")", - doc)); - - // return the name of the spreadsheet reading processor so it can be hooked up - // to an input port for a Moby service - return importerName; + // return the name of the spreadsheet reading processor and output port so it can be hooked up + // to input ports for Moby services + return new String[]{processorName, portNames[portNames.length-1]}; } private Element createConstantProcessor(String constantName, String constantValue, Document doc) @@ -884,15 +970,86 @@ processors, datalinks, doc); } - private String[] createRegexFilter(String regex, XPathOption xpath, String srcProcessor, String srcPort, + // Make the continued use of data X in the workflow conditional on the results of running X through service f + // and passing the filter condition set on f. Equivalent to if(f(X) matches f_filter){...} + // returns [proc name, input port, output port] + private String[] createServiceConditionFilter(URL conditionURL, String filterRegex, XPathOption filterXPath, + boolean caseSensitive, Document doc, + Element inputPorts, Element processors, Element datalinks) + throws Exception{ + + // Open the conditionURL, and find out what service result is used, and what filter applied + Document conditionDoc = docBuilder.parse(conditionURL.openStream()); + MobyService service = DataUtils.getService(conditionDoc); + Document condServiceOutputDoc = DataUtils.getInputDoc(conditionDoc); + + // The bits to run the service "f" + + String dataSrcURLString = conditionURL.toString().replaceFirst("#.*$", ""); //get rid of ref part + String processorName = null; + // See if the service creating the input for the conditional service has already been added to the workflow + if(url2Processor.containsKey(dataSrcURLString)){ + processorName = url2Processor.get(dataSrcURLString); + } + else{ + processorName = addWorkflowElements(conditionURL, doc, inputPorts, processors, datalinks); + } + + String filterKey = dataSrcURLString+"\n"+filterRegex+"\n"+filterXPath.getXPath()+"\n"+caseSensitive; + String[] regexFilterProcNameAndPort = null; + //todo: gimpy loop below, as more than one service output would cause a trampling of regex output ports + for(MobyPrimaryData outputParam: service.getPrimaryOutputs()){ + // See if the filter on the conditional service has already been used in the workflow + if(filter2Processor.containsKey(filterKey)){ + regexFilterProcNameAndPort = filter2Processor.get(filterKey); + } + else{ + regexFilterProcNameAndPort = createRegexFilter(filterRegex, + filterXPath, + caseSensitive, + processorName, + getPortName(outputParam, true), + 0, //depth of list desired (will return match count) + processors, datalinks, doc); + filter2Processor.put(filterKey, regexFilterProcNameAndPort); + } + } + + // We need to flatten the 2-deep list generated by the regex filter's cross product + String[] beanShellFlattenerProcNameAndPorts = addListFlattenBeanShell(processors, doc); + + datalinks.appendChild(createDataLinkElement(regexFilterProcNameAndPort[0], + regexFilterProcNameAndPort[1], + beanShellFlattenerProcNameAndPorts[0], + beanShellFlattenerProcNameAndPorts[1], + doc)); + + // Essentially an "if" condition, error if incoming value is empty, missing, or zero + String[] beanShellFilterProcNameAndPorts = addPassFilterBeanShell(processors, doc); + + datalinks.appendChild(createDataLinkElement(beanShellFlattenerProcNameAndPorts[0], + beanShellFlattenerProcNameAndPorts[2], + beanShellFilterProcNameAndPorts[0], + beanShellFilterProcNameAndPorts[2], + doc)); + + return new String[]{beanShellFilterProcNameAndPorts[0], + beanShellFilterProcNameAndPorts[1], + beanShellFilterProcNameAndPorts[3]}; + } + + private String[] createRegexFilter(String regex, XPathOption xpath, boolean caseSensitive, + String srcProcessor, String srcPort, int listDepth, Element processors, Element datalinks, Document doc) throws Exception{ String constantXPathName = createUniqueName(xpath.toString()); processors.appendChild(createConstantProcessor(constantXPathName, xpath.getXPath(), doc)); String constantRegexName = createUniqueName(regex); processors.appendChild(createConstantProcessor(constantRegexName, regex, doc)); + String constantCaseSensitivityName = createUniqueName("cs_"+caseSensitive); + processors.appendChild(createConstantProcessor(constantCaseSensitivityName, ""+caseSensitive, doc)); - String[] beanShellFilterProcNameAndPorts = addRegexFilterBeanShell(processors, doc); + String[] beanShellFilterProcNameAndPorts = addRegexFilterBeanShell(listDepth, processors, doc); datalinks.appendChild(createDataLinkElement(srcProcessor, srcPort, @@ -903,11 +1060,15 @@ beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[2], doc)); - datalinks.appendChild(createDataLinkElement(constantXPathName, "value", + datalinks.appendChild(createDataLinkElement(constantCaseSensitivityName, "value", beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[3], doc)); - return new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[4]}; + datalinks.appendChild(createDataLinkElement(constantXPathName, "value", + beanShellFilterProcNameAndPorts[0], + beanShellFilterProcNameAndPorts[4], + doc)); + return new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[5]}; } private String[] createXrefParser(MobyNamespace nsObj, String srcProcessor, String srcPort, @@ -1231,29 +1392,76 @@ } } + private String[] addListFlattenBeanShell(Element processors, Document doc) + throws Exception{ + String beanShellProcName = createUniqueName("Create_Pass_Fail_List"); + + // Now do all the param-specific stuff below (inserts into various parts of the elements defined above) + Map inputsMap = new LinkedHashMap(); + // linked because order is important to line up port connections + Map inputTypes = new LinkedHashMap(); + inputsMap.put("inputlist", "2"); + inputTypes.put("inputlist", "text/plain"); + Map outputsMap = new LinkedHashMap(); + outputsMap.put("outputlist", "1"); + + return addBeanShell(beanShellProcName, "dot", + inputsMap, inputTypes, outputsMap, + getListFlattenScript(), new String[]{}, + processors, doc); + } + + private String[] addPassFilterBeanShell(Element processors, Document doc) + throws Exception{ + String beanShellProcName = createUniqueName("IfPassesContentFilter"); + + // Now do all the param-specific stuff below (inserts into various parts of the elements defined above) + Map inputsMap = new LinkedHashMap(); + // linked because order is important to line up port connections + Map inputTypes = new LinkedHashMap(); + inputsMap.put("dataToPassThrough", "1"); + inputsMap.put("conditionResults", "1"); + inputTypes.put("dataToPassThrough", "text/xml"); + inputTypes.put("conditionResults", "text/plain"); + Map outputsMap = new LinkedHashMap(); + outputsMap.put("dataPassed", "1"); + + return addBeanShell(beanShellProcName, "cross", + inputsMap, inputTypes, outputsMap, + getPassFilterScript(), new String[]{}, + processors, doc); + } + // Returns the name of the bean shell processor and its ports, so we can create the data links in the caller // The input is the original moby xml, and the xpath to extract, and the regex to apply to the text contents of the xpath results. // The output is a list of moby xml docs, one for each mobyData that fit the xpath and regex criteria. - private String[] addRegexFilterBeanShell(Element processors, Document doc) + private String[] addRegexFilterBeanShell(int listDepth, Element processors, Document doc) throws Exception{ - String beanShellProcName = createUniqueName("Filter_By_Content"); + String beanShellProcName = createUniqueName("Filter"+(listDepth == 0 ? "_Match_Count" : "_By_Content")); // Now do all the param-specific stuff below (inserts into various parts of the elements defined above) Map inputsMap = new LinkedHashMap(); - // linked because order is importtant to line up port connections + // linked because order is important to line up port connections Map inputTypes = new LinkedHashMap(); inputsMap.put("xml_text", "0"); inputsMap.put("regex", "0"); + inputsMap.put("case_sensitive", "0"); inputsMap.put("xpath", "0"); inputTypes.put("xml_text", "text/xml"); inputTypes.put("xpath", "text/plain"); inputTypes.put("regex", "text/plain"); + inputTypes.put("case_sensitive", "text/plain"); Map outputsMap = new LinkedHashMap(); - outputsMap.put("nodelistAsXML", "1"); + if(listDepth == 0){ + outputsMap.put("matchCount", "0"); + } + else{ + outputsMap.put("nodelistAsXML", ""+listDepth); + } - return addBeanShell(beanShellProcName, + return addBeanShell(beanShellProcName, "cross", inputsMap, inputTypes, outputsMap, - getRegexFilterScript(), new String[]{"dom4j:dom4j:1.6"}, + getRegexFilterScript(listDepth), new String[]{"dom4j:dom4j:1.6"}, processors, doc); } @@ -1274,13 +1482,13 @@ Map outputsMap = new HashMap(); outputsMap.put("nodelistAsXML", "1"); - return addBeanShell(beanShellProcName, + return addBeanShell(beanShellProcName, "cross", inputsMap, inputTypes, outputsMap, getXPathFilterScript(), new String[]{"dom4j:dom4j:1.6"}, processors, doc); } - private String[] addBeanShell(String beanShellProcName, + private String[] addBeanShell(String beanShellProcName, String vectorComboOp, Map inputsMap, Map inputTypes, Map outputsMap, String script, String[] dependencySpecs, Element processors, Document doc) throws Exception{ @@ -1345,8 +1553,11 @@ iterationStrategyStack.appendChild(iteration); Element strategy = doc.createElementNS(T2FLOW_NS, "strategy"); iteration.appendChild(strategy); - Element cross = doc.createElementNS(T2FLOW_NS, "cross"); - strategy.appendChild(cross); + Element vectorOp = null; + if(vectorComboOp != null){ + vectorOp = doc.createElementNS(T2FLOW_NS, vectorComboOp); + strategy.appendChild(vectorOp); // either cross or dot + } // Lst processor name, input ports and output ports, in that order. Vector returnSpec = new Vector(); @@ -1370,7 +1581,9 @@ mimeTypes.appendChild(createElWithText(doc, "", "string", inputTypes.get(input.getKey()))); Element port = doc.createElementNS(T2FLOW_NS, "port"); - cross.appendChild(port); + if(vectorOp != null){ + vectorOp.appendChild(port); + } port.setAttribute("depth", input.getValue()); port.setAttribute("name", input.getKey()); } @@ -1517,7 +1730,7 @@ private String createUniqueName(String preferredName){ if(namesUsed.containsKey(preferredName)){ namesUsed.put(preferredName, namesUsed.get(preferredName).intValue()+1); //increment - preferredName += namesUsed.get(preferredName); + preferredName += "_"+namesUsed.get(preferredName); } else{ namesUsed.put(preferredName, 1); // will be auto-boxed to Integer @@ -1528,8 +1741,6 @@ // dataType(articleName) as required by the Taverna Moby plugin private String getPortName(MobyPrimaryData data, boolean asCollection){ if(data instanceof MobyPrimaryDataSet){ - // todo: Hmm...don't yet handle case where collections are passed from one service to another... - // here we assume iterating over the collection if(asCollection){ return data.getDataType().getName()+"(Collection - '"+data.getName()+"')"; } @@ -1680,7 +1891,7 @@ // Did we override the default value for the secondary param in the example input? Element stringValue = doc.createElementNS("", "string"); - if(sampleInput.containsKey(secParam.getName())){ + if(sampleInput != null && sampleInput.containsKey(secParam.getName())){ stringValue.appendChild(doc.createTextNode(((MobyDataSecondaryInstance) sampleInput.get(secParam.getName())).getValue())); } else{ // use the default defined in Moby Central @@ -1739,6 +1950,28 @@ return central; } + private synchronized String getListFlattenScript() throws Exception{ + if(listFlattenScript == null){ + URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_LISTFLATTEN_BEANSHELL); + if(scriptURL == null){ + throw new Exception("Cannot find resource " + T2FLOW_LISTFLATTEN_BEANSHELL); + } + listFlattenScript = HTMLUtils.getURLContents(scriptURL); + } + return listFlattenScript; + } + + private synchronized String getPassFilterScript() throws Exception{ + if(passFilterScript == null){ + URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_PASSFILTER_BEANSHELL); + if(scriptURL == null){ + throw new Exception("Cannot find resource " + T2FLOW_PASSFILTER_BEANSHELL); + } + passFilterScript = HTMLUtils.getURLContents(scriptURL); + } + return passFilterScript; + } + private synchronized String getXPathFilterScript() throws Exception{ if(xpathFilterScript == null){ URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_XPATHFILTER_BEANSHELL); @@ -1750,7 +1983,7 @@ return xpathFilterScript; } - private synchronized String getRegexFilterScript() throws Exception{ + private synchronized String getRegexFilterScript(int listDepth) throws Exception{ if(regexFilterScript == null){ URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_REGEXFILTER_BEANSHELL); if(scriptURL == null){ @@ -1758,7 +1991,12 @@ } regexFilterScript = HTMLUtils.getURLContents(scriptURL); } - return regexFilterScript; + if(listDepth == 0){// list to scalar conversion + return regexFilterScript+"\nString matchCount = \"\"+nodelistAsXML.size();"; + } + else{ + return regexFilterScript; + } } private synchronized Element getDispatchStack(Document newOwnerDoc) throws Exception{ From gordonp at dev.open-bio.org Fri Apr 9 12:58:14 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 12:58:14 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091658.o39GwEOB003781@dev.open-bio.org> gordonp Fri Apr 9 12:58:13 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow In directory dev.open-bio.org:/tmp/cvs-serv3745/src/main/ca/ucalgary/minnow Modified Files: MinJarMaker.java Log Message: got rid of annoying cvs-related files in secondary jars moby-live/Java/src/main/ca/ucalgary/minnow MinJarMaker.java,1.6,1.7 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow/MinJarMaker.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow/MinJarMaker.java 2010/03/30 19:14:04 1.6 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow/MinJarMaker.java 2010/04/09 16:58:13 1.7 @@ -812,7 +812,7 @@ relativePath.equals("META-INF") || //this one causes null pointers in jarsigner relativePath.equals("testdata") || relativePath.equals("deployment") || - relativePath.equals("CVS")){ + relativePath.endsWith("CVS")){ //System.err.println("Skipping " + relativePath); continue; } From gordonp at dev.open-bio.org Fri Apr 9 20:40:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 20:40:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004100040.o3A0eH2E014912@dev.open-bio.org> gordonp Fri Apr 9 20:40:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv14854/src/main/ca/ucalgary/seahawk/resources Modified Files: RegexFilterBeanShell Log Message: Added support for filter inversion (boolean negation) moby-live/Java/src/main/ca/ucalgary/seahawk/resources RegexFilterBeanShell,1.2,1.3 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/RegexFilterBeanShell,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/seahawk/resources/RegexFilterBeanShell 2010/04/09 15:49:18 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/RegexFilterBeanShell 2010/04/10 00:40:17 1.3 @@ -11,9 +11,12 @@ List nodelist = document.selectNodes(xpath); ArrayList outputXmlList = new ArrayList(); +ArrayList outputXmlList_false = new ArrayList(); int i = 1; Map collections = new LinkedHashMap(); Map collectionsEnd = new HashMap(); +Map collections_false = new LinkedHashMap(); +Map collectionsEnd_false = new HashMap(); Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL | (Boolean.parseBoolean(case_sensitive) ? 0 : Pattern.CASE_INSENSITIVE)); for (Iterator iter = nodelist.iterator(); iter.hasNext();) { Node node = (Node) iter.next(); @@ -31,10 +34,17 @@ break; default: break; } - if(!match){ - continue; - } + Map cs = null; + Map csEnd = null; + if(match){ + cs = collections; + csEnd = collectionsEnd; + } + else{ + cs = collections_false; + csEnd = collectionsEnd_false; + } //go up the tree until we hit a mobyData...this is the unit we can forward StringBuilder collection = null; StringBuilder collectionEnd = null; @@ -43,11 +53,11 @@ node.getParent().getName().equals("Collection")){ collection = new StringBuilder(); //start tracking parents collectionEnd = new StringBuilder(); - if(!collections.containsKey(collection)){ - collections.put(collection, new Vector()); - collectionsEnd.put(collection, collectionEnd); + if(!cs.containsKey(collection)){ + cs.put(collection, new Vector()); + csEnd.put(collection, collectionEnd); } - ((Vector)collections.get(collection)).add(node.asXML()); + ((Vector)cs.get(collection)).add(node.asXML()); } node = node.getParent(); if(node != null && collection != null){ @@ -61,14 +71,17 @@ collectionEnd.append(""); } } - if(node == null){ + if(node == null){ // wasn't part of a mobyData block continue; } - // At mobyData level if we got here + // At mobyData level if we got here, add if job not already present if(collection == null){ - outputXmlList.add( - ""+ - ""+node.asXML()+""); + String jobData = ""+ + ""+node.asXML()+""; + List list = (match ? outputXmlList : outputXmlList_false); + if(!list.contains(jobData)){ + list.add(jobData); + } } } @@ -83,6 +96,16 @@ } ((List) uniqueCollections.get(keyString)).addAll((List) collection.getValue()); } +Map uniqueCollections_false = new LinkedHashMap(); +Map uniqueCollectionsEnd_false = new LinkedHashMap(); +for(Map.Entry collection: collections_false.entrySet()){ + String keyString = collection.getKey().toString(); + if(!uniqueCollections_false.containsKey(keyString)){ + uniqueCollections_false.put(keyString, new Vector()); + uniqueCollectionsEnd_false.put(keyString, collectionsEnd_false.get(collection.getKey())); + } + ((List) uniqueCollections_false.get(keyString)).addAll((List) collection.getValue()); +} //Now concat the collection members that pass the filter for(Map.Entry collection: uniqueCollections.entrySet()){ @@ -99,6 +122,21 @@ outputXmlList.add(block.toString()); } +for(Map.Entry collection: uniqueCollections_false.entrySet()){ + StringBuilder block = new StringBuilder(); + block.append("\n"); + block.append("\n"); + block.append(collection.getKey().toString()); + for(String val: (List) collection.getValue()){ + block.append(val); + } + block.append(uniqueCollectionsEnd_false.get(collection.getKey().toString())); // closing tags + block.append("\n"); + block.append("\n"); + + outputXmlList_false.add(block.toString()); +} -List nodelistAsXML=outputXmlList; +List TRUE_nodelistAsXML=outputXmlList; +List FALSE_nodelistAsXML=outputXmlList_false; From gordonp at dev.open-bio.org Fri Apr 9 20:40:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 20:40:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004100040.o3A0eHik014894@dev.open-bio.org> gordonp Fri Apr 9 20:40:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv14854/src/main/ca/ucalgary/seahawk/gui Modified Files: FilterSearchWidget.java MobyContentPane.java Log Message: Added support for filter inversion (boolean negation) moby-live/Java/src/main/ca/ucalgary/seahawk/gui FilterSearchWidget.java,1.2,1.3 MobyContentPane.java,1.24,1.25 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.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/seahawk/gui/FilterSearchWidget.java 2010/04/09 15:50:09 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/10 00:40:17 1.3 @@ -18,12 +18,18 @@ private FilterSearch currentFilterSearch; private JLabel closeIcon; private JToggleButton caseButton; + private JButton inverseButton; // decides whether filter is "if" or "unless" private JTextField searchField; private JComboBox docPartOptions; private MobyContentPane contentPane; public static final String CASE_SENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_sensitive.png"; public static final String CASE_INSENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_insensitive.png"; + private static final String IF_TEXT = "if"; + private static final String UNLESS_TEXT = "unless"; + private static final String CASE_INSENSITIVE_MSG = "The filter is case insensitive,
click to make case sensitive"; + private static final String CASE_SENSITIVE_MSG = "The filter is case sensitive,
click to make case insensitive"; private static final String CASE_BUTTON_NAME = "case_sensitivity_button"; + private static final String INVERSE_BUTTON_NAME = "boolean_button"; private static Logger logger = Logger.getLogger(FilterSearchWidget.class.getName()); @@ -45,7 +51,7 @@ Dimension buttonSize = new Dimension(24,24); caseButton = new JToggleButton(new ImageIcon(cl.getResource(CASE_SENSITIVE_ICON_RESOURCE))); caseButton.setDisabledIcon(new ImageIcon(cl.getResource(CASE_INSENSITIVE_ICON_RESOURCE))); - caseButton.setToolTipText("Toggles the case sensitivity of the filter"); + caseButton.setToolTipText(CASE_INSENSITIVE_MSG); caseButton.setPreferredSize(buttonSize); caseButton.setEnabled(true); caseButton.setSelected(false); @@ -53,12 +59,20 @@ caseButton.setMargin(new java.awt.Insets(2,2,2,2)); caseButton.setName(CASE_BUTTON_NAME); // so test cases can find the component + inverseButton = new JButton(IF_TEXT); + inverseButton.setToolTipText("Click to invert the selection between \"if\" and \"unless\""); + inverseButton.setEnabled(true); + inverseButton.addActionListener(this); + inverseButton.setBorderPainted(false); // underline is hint enough that we can press it...looks cleaner + inverseButton.setName(INVERSE_BUTTON_NAME); // so test cases can find the component + setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); add(closeIcon); add(Box.createRigidArea(new Dimension(5,0))); add(caseButton); add(Box.createRigidArea(new Dimension(5,0))); - add(new JLabel("Show data if ")); + add(new JLabel("Show data ")); + add(inverseButton); add(Box.createRigidArea(new Dimension(5,0))); searchField = new JTextField(25); searchField.setToolTipText("A literal string, or a regular expression"); @@ -81,11 +95,15 @@ currentFilterSearch = null; if(fs == null){ caseButton.setEnabled(false); + inverseButton.setEnabled(false); searchField.setEnabled(false); docPartOptions.setEnabled(false); return; } + inverseButton.setEnabled(true); + inverseButton.setText(fs.getSelectionInversed() ? UNLESS_TEXT : IF_TEXT); + caseButton.setEnabled(true); caseButton.setSelected(fs.getCaseSensitivity()); @@ -101,11 +119,30 @@ * Called when the user has changed the xpath */ public void actionPerformed(ActionEvent e){ - if(e.getSource() == caseButton){ + if(e.getSource() == inverseButton){ + // Toggle the label for the if/unless button + if(inverseButton.getText().equals(IF_TEXT)){ + inverseButton.setText(UNLESS_TEXT); + currentFilterSearch.setSelectionInversed(true); + } + else{ + inverseButton.setText(IF_TEXT); + currentFilterSearch.setSelectionInversed(false); + } + contentPane.applyFilter(true); + return; + } + else if(e.getSource() == caseButton){ if(currentFilterSearch == null){ return; } currentFilterSearch.setCaseSensitivity(caseButton.isSelected()); + if(caseButton.isSelected()){ + caseButton.setToolTipText(CASE_SENSITIVE_MSG); + } + else{ + caseButton.setToolTipText(CASE_INSENSITIVE_MSG); + } contentPane.applyFilter(true); return; } @@ -127,6 +164,7 @@ sb.replace(0, sb.length(), searchField.getText()); contentPane.applyFilter(true); } + public void insertUpdate(DocumentEvent e){ if(currentFilterSearch == null){ return; =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.24 retrieving revision 1.25 diff -u -r1.24 -r1.25 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/09 15:54:16 1.24 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/10 00:40:17 1.25 @@ -1239,7 +1239,6 @@ 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. @@ -1510,12 +1509,15 @@ } } + boolean inversed = fs.getSelectionInversed(); Map parentMatchingXPtrs = new LinkedHashMap(); for(String currXPtr: filterableNodes){ for(Map.Entry matchingXPtr: matchingXPtrs.entrySet()){ if(matchingXPtr.getKey().startsWith(currXPtr+"/")){ // a parent of the matching data // No positive example yet? - if(!parentMatchingXPtrs.containsKey(currXPtr) || !parentMatchingXPtrs.get(currXPtr).booleanValue()){ + if(!parentMatchingXPtrs.containsKey(currXPtr) || + !inversed && !parentMatchingXPtrs.get(currXPtr).booleanValue() || + inversed && parentMatchingXPtrs.get(currXPtr).booleanValue()){ System.err.println("Adding "+ matchingXPtr.getValue() + " for " + currXPtr); parentMatchingXPtrs.put(currXPtr, matchingXPtr.getValue()); } @@ -1526,11 +1528,16 @@ matchingXPtrs.putAll(parentMatchingXPtrs); for(String currXPtr: matchingXPtrs.keySet()){ // Is part of the selection criteria, but doesn't match the regex + boolean shouldFilter = false; if(!matchingXPtrs.get(currXPtr).booleanValue() && - // special condition: if "entire document" xpath is given, filter only at the job level + // special condition: if "entire response" xpath is given, filter only at the job level (!currentSelectionXPath.equals(FilterSearch.SELECT_ALL_XPATH) || jobXPtrs.containsKey(currXPtr))){ - filteredData.put(currXPtr, "todo"); + shouldFilter = true; } + if(!inversed && shouldFilter || + inversed && !shouldFilter){ + filteredData.put(currXPtr, "todo"); + } } //todo: filter objects without the HAS field at all... From gordonp at dev.open-bio.org Fri Apr 9 20:40:18 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 20:40:18 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004100040.o3A0eIZb014938@dev.open-bio.org> gordonp Fri Apr 9 20:40:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv14854/src/main/ca/ucalgary/seahawk/util Modified Files: DataFlowRecorder.java DataUtils.java FilterSearch.java Log Message: Added support for filter inversion (boolean negation) moby-live/Java/src/main/ca/ucalgary/seahawk/util DataFlowRecorder.java,1.3,1.4 DataUtils.java,1.2,1.3 FilterSearch.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.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/seahawk/util/DataFlowRecorder.java 2010/04/09 15:58:22 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/10 00:40:17 1.4 @@ -174,7 +174,8 @@ String[] regexProcessorAndPorts = null; String filterKey = null; if(filter != null && filter.getFilterRegex().length() > 0){ - filterKey = result.getKey()+"\n"+filter.getFilterRegex()+"\n"+filter.getSelectedXPath().getXPath(); + filterKey = result.getKey()+"\n"+filter.getFilterRegex()+"\n"+ + filter.getSelectedXPath().getXPath()+"\n"+filter.getCaseSensitivity(); } // Create the workflow output and data links @@ -206,8 +207,10 @@ filter2Processor.put(filterKey, regexProcessorAndPorts); } + // The proc has an output port for non-matches (penultimate index) and matches (ultimate index) + int regexOutPort = regexProcessorAndPorts.length-(filter.getSelectionInversed() ? 2 : 1); datalinks.appendChild(createWorkflowOutputLinkElement(regexProcessorAndPorts[0], - regexProcessorAndPorts[regexProcessorAndPorts.length-1], + regexProcessorAndPorts[regexOutPort], uniqueOutputName, doc)); break; // only one output when filter is attached: the XML doc @@ -317,16 +320,18 @@ // where the filter and conditionalURL are optional data = sampleData.getUserData().toString().split("\t"); //options: selection + filter + cond, selection + cond, or cond only - if(data.length == 11 || data.length == 7 || data.length == 5){ + if(data.length == 14 || data.length == 8 || data.length == 6){ System.err.println("Adding conditional for " + resultURLString); - String conditionURL = data[data.length-5]; - String conditionRegex = data[data.length-4]; - XPathOption conditionXPath = new XPathOption(data[data.length-3], data[data.length-2]); - boolean caseSensitivity = Boolean.parseBoolean(data[data.length-1]); - condPassProcessorAndPorts = createServiceConditionFilter(new URL(conditionURL), conditionRegex, conditionXPath, caseSensitivity, + String conditionURL = data[data.length-6]; + String conditionRegex = data[data.length-5]; + XPathOption conditionXPath = new XPathOption(data[data.length-4], data[data.length-3]); + boolean caseSensitivity = Boolean.parseBoolean(data[data.length-2]); + boolean inverse = Boolean.parseBoolean(data[data.length-1]); + condPassProcessorAndPorts = createServiceConditionFilter(new URL(conditionURL), conditionRegex, + conditionXPath, caseSensitivity, inverse, doc, inputPorts, processors, datalinks); - String[] conditionlessData = new String[data.length-5]; - System.arraycopy(data, 0, conditionlessData, 0, data.length-5); + String[] conditionlessData = new String[data.length-6]; + System.arraycopy(data, 0, conditionlessData, 0, data.length-6); data = conditionlessData; } else{ @@ -357,10 +362,10 @@ feedingProcessorName = addWorkflowElements(dataSrcURL, doc, inputPorts, processors, datalinks); } - // Take into account data[2..5] if they are present, + // Take into account data[2..6] if they are present, // which filter the data by a regex before any other activities happen // Format of spec is regex xpath xpathTextDesc booleanForCaseSensitivity - if(data.length == 6){ + if(data.length == 7){ String[] origFeederProcessorAndPort = getPortFromURLRef(dataSrcURL, sampleData, feedingProcessorName, @@ -370,9 +375,11 @@ doc, false); - // Lookup key is url \n regex \n xpath \n caseSensitivity + // Lookup key is url \n regex \n xpath \n caseSensitivity + // (inverse selection uses same processor, different output port, so not part of the key) String[] regexProcessorAndPorts = null; String filterKey = dataSrcURLString+"\n"+data[2]+"\n"+data[3]+"\n"+data[5]; + boolean inversed = Boolean.parseBoolean(data[6]); if(filter2Processor.containsKey(filterKey)){ // filter already exists from another branch regexProcessorAndPorts = filter2Processor.get(filterKey); } @@ -389,7 +396,9 @@ filter2Processor.put(filterKey, regexProcessorAndPorts); } feedingProcessorName = regexProcessorAndPorts[0]; - feedingProcessorPort = regexProcessorAndPorts[regexProcessorAndPorts.length-1]; //last one is output + // The proc has an output port for non-matches (penultimate index) and matches (ultimate index) + int regexOutPort = regexProcessorAndPorts.length-(inversed ? 2 : 1); + feedingProcessorPort = regexProcessorAndPorts[regexOutPort]; } // getPortFromURLRef() may inject extra processors between the processorName and feedingProcessorName @@ -921,6 +930,7 @@ // supertype of the output from the other service! if(namespace != null){ MobyNamespace nsObj = MobyNamespace.getNamespace(namespace, getRegistryFromService(srcService)); + System.err.println("About to create namespace filter for "+ srcProcessor + " port " + portName + " when srcPort was " + srcPort); return createNamespaceFilter(nsObj, srcProcessor, portName, processors, datalinks, doc); } else if(xrefNs != null){ @@ -974,7 +984,7 @@ // and passing the filter condition set on f. Equivalent to if(f(X) matches f_filter){...} // returns [proc name, input port, output port] private String[] createServiceConditionFilter(URL conditionURL, String filterRegex, XPathOption filterXPath, - boolean caseSensitive, Document doc, + boolean caseSensitive, boolean inverse, Document doc, Element inputPorts, Element processors, Element datalinks) throws Exception{ @@ -996,30 +1006,31 @@ } String filterKey = dataSrcURLString+"\n"+filterRegex+"\n"+filterXPath.getXPath()+"\n"+caseSensitive; - String[] regexFilterProcNameAndPort = null; + String[] regexFilterProcNameAndPorts = null; //todo: gimpy loop below, as more than one service output would cause a trampling of regex output ports for(MobyPrimaryData outputParam: service.getPrimaryOutputs()){ // See if the filter on the conditional service has already been used in the workflow if(filter2Processor.containsKey(filterKey)){ - regexFilterProcNameAndPort = filter2Processor.get(filterKey); + regexFilterProcNameAndPorts = filter2Processor.get(filterKey); } else{ - regexFilterProcNameAndPort = createRegexFilter(filterRegex, + regexFilterProcNameAndPorts = createRegexFilter(filterRegex, filterXPath, caseSensitive, processorName, getPortName(outputParam, true), 0, //depth of list desired (will return match count) processors, datalinks, doc); - filter2Processor.put(filterKey, regexFilterProcNameAndPort); + filter2Processor.put(filterKey, regexFilterProcNameAndPorts); } } // We need to flatten the 2-deep list generated by the regex filter's cross product String[] beanShellFlattenerProcNameAndPorts = addListFlattenBeanShell(processors, doc); - datalinks.appendChild(createDataLinkElement(regexFilterProcNameAndPort[0], - regexFilterProcNameAndPort[1], + int regexOutPort = regexFilterProcNameAndPorts.length-(inverse ? 2 : 1); + datalinks.appendChild(createDataLinkElement(regexFilterProcNameAndPorts[0], + regexFilterProcNameAndPorts[regexOutPort], beanShellFlattenerProcNameAndPorts[0], beanShellFlattenerProcNameAndPorts[1], doc)); @@ -1068,7 +1079,9 @@ beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[4], doc)); - return new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[5]}; + return new String[]{beanShellFilterProcNameAndPorts[0], + beanShellFilterProcNameAndPorts[5], // false (non-matching) output + beanShellFilterProcNameAndPorts[6]}; // true (matching) output } private String[] createXrefParser(MobyNamespace nsObj, String srcProcessor, String srcPort, @@ -1090,6 +1103,7 @@ throws Exception{ String decompKey = srcProcessor+"\n"+srcPort+"\n"+xpath; + System.err.println("Decomp key is " + decompKey); // Has this decomp already been created in another branch? if(decomp2Processor.containsKey(decompKey)){ return decomp2Processor.get(decompKey); @@ -1108,7 +1122,7 @@ beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[2], doc)); - String[] procSpec = new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[3]}; + String[] procSpec = new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[3]}; decomp2Processor.put(decompKey, procSpec); //in case we need to reuse it in another branch return procSpec; } @@ -1453,10 +1467,12 @@ inputTypes.put("case_sensitive", "text/plain"); Map outputsMap = new LinkedHashMap(); if(listDepth == 0){ - outputsMap.put("matchCount", "0"); + outputsMap.put("FALSE_matchCount", "0"); + outputsMap.put("TRUE_matchCount", "0"); } else{ - outputsMap.put("nodelistAsXML", ""+listDepth); + outputsMap.put("FALSE_nodelistAsXML", ""+listDepth); + outputsMap.put("TRUE_nodelistAsXML", ""+listDepth); } return addBeanShell(beanShellProcName, "cross", @@ -1991,8 +2007,9 @@ } regexFilterScript = HTMLUtils.getURLContents(scriptURL); } - if(listDepth == 0){// list to scalar conversion - return regexFilterScript+"\nString matchCount = \"\"+nodelistAsXML.size();"; + if(listDepth == 0){// list to scalar conversions + return regexFilterScript+"\nString TRUE_matchCount = \"\"+TRUE_nodelistAsXML.size();\n"+ + "\nString FALSE_matchCount = \"\"+FALSE_nodelistAsXML.size();\n"; } else{ return regexFilterScript; =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.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/seahawk/util/DataUtils.java 2010/04/09 15:57:46 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/10 00:40:17 1.3 @@ -117,7 +117,8 @@ if(newFilter != null){ XPathOption xsel = newFilter.getSelectedXPath(); newProvenanceData += "\t"+newFilter.getFilterRegex()+ - "\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+newFilter.getCaseSensitivity(); + "\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+ + newFilter.getCaseSensitivity()+"\t"+newFilter.getSelectionInversed(); } pi.setData(attr_val[0]+"=\""+newProvenanceData+"\""); } @@ -640,7 +641,8 @@ if(fs != null && fs.getFilterRegex().length() > 0){ XPathOption xsel = fs.getSelectedXPath(); - userData.append("\t"+fs.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+fs.getCaseSensitivity()); + userData.append("\t"+fs.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+ + fs.getCaseSensitivity()+"\t"+fs.getSelectionInversed()); } mobyData.setUserData(userData.toString()); } @@ -653,7 +655,8 @@ String filterSpec = ""; if(filter != null && filter.getFilterRegex().length() > 0){ XPathOption xsel = filter.getSelectedXPath(); - filterSpec = "\t"+filter.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+filter.getCaseSensitivity(); + filterSpec = "\t"+filter.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+ + filter.getCaseSensitivity()+"\t"+filter.getSelectionInversed(); } if(mdi.getUserData() != null){ mdi.setUserData(mdi.getUserData().toString()+"\t"+conditionalOutputURL+filterSpec); =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.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/seahawk/util/FilterSearch.java 2010/04/09 15:48:19 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/10 00:40:17 1.4 @@ -21,6 +21,7 @@ private URL docURL; private boolean caseSensitivity = false; + private boolean inverseSelection = false; private StringBuffer filterRegex; private Vector xpathOptions; private int xpathSelected = 0; @@ -74,6 +75,14 @@ } } + public boolean getSelectionInversed(){ + return inverseSelection; + } + + public void setSelectionInversed(boolean inversed){ + inverseSelection = inversed; + } + public boolean getCaseSensitivity(){ return caseSensitivity; } From gordonp at dev.open-bio.org Sat Apr 10 18:42:09 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 18:42:09 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004102242.o3AMg9nE014502@dev.open-bio.org> gordonp Sat Apr 10 18:42:09 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data In directory dev.open-bio.org:/tmp/cvs-serv14466/src/main/org/biomoby/shared/data Modified Files: MobyDataObject.java Log Message: Improved equals() for base object equivalency...value not instance based moby-live/Java/src/main/org/biomoby/shared/data MobyDataObject.java,1.26,1.27 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyDataObject.java,v retrieving revision 1.26 retrieving revision 1.27 diff -u -r1.26 -r1.27 --- /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyDataObject.java 2008/01/07 22:11:36 1.26 +++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyDataObject.java 2010/04/10 22:42:09 1.27 @@ -302,7 +302,7 @@ public boolean equals(Object passedInObject) throws ClassCastException{ Object ourObject = getObject(); if(passedInObject != null && passedInObject instanceof MobyDataObject){ - if(((MobyDataObject) passedInObject).getDataType() == getDataType()){ + if(((MobyDataObject) passedInObject).getDataType().equals(getDataType())){ // An object of the same class. See if their XMLs are equivalent. int ourOldXMLMode = getXmlMode(); int itsOldXMLMode = ((MobyDataObject) passedInObject).getXmlMode(); From gordonp at dev.open-bio.org Sat Apr 10 21:58:05 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 21:58:05 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110158.o3B1w59N019017@dev.open-bio.org> gordonp Sat Apr 10 21:58:05 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services In directory dev.open-bio.org:/tmp/cvs-serv18981/src/main/ca/ucalgary/seahawk/services Modified Files: MobyClient.java Log Message: Added regex support for IUPAC monosacchride residues (\M) moby-live/Java/src/main/ca/ucalgary/seahawk/services MobyClient.java,1.25,1.26 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/03/17 20:21:55 1.25 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/11 01:58:05 1.26 @@ -1391,14 +1391,15 @@ /** * Converts seahawk-specific regex syntax into generic Java syntax (e.g \N becomes a - * match for any IUPAC DNA character, \P any amino acid). We pass in the member map so that + * match for any IUPAC DNA character, \P any amino acid, \M for any monosacchiride abbreviation). + * We pass in the member map so that * this method can populate the last field of rules that inherit complex members (by virtue * of using the capture group whose values is derived from \p{ruleName}), with ruleName */ protected String processRegExp(String regex, Map membersMap) throws Exception{ String returnValue = regex.replaceAll("\\\\N", "[acgtunxACGTUNX]") - .replaceAll("\\\\P", "[ARNDCQEGHILKMFPSTWYVBZXarndcqeghilkmfpstwyvbz*]"); - + .replaceAll("\\\\P", "[ARNDCQEGHILKMFPSTWYVBZXarndcqeghilkmfpstwyvbz*]") + .replaceAll("\\\\M", "(?:Abe|IdoA|All|Lyx|Alt|Man|Api|Mur|Ara|Neu|Ara-ol|Neu5Ac|dRib|Neu2en5Ac|Fru|Neu5Gc|Fuc|Kdo|Fuc-ol|Rha|Gal|Rha3,4Me2|GalN|Psi|GalNAc|Qui|B-D-Galp4S|Rib|Glc|Rib5P|GlcN|Ribulo|Rul|GlcN3N|Sor|Glc-ol|Tag|GlcNAc|Tal|GlcA|Xyl|GlcpA6Et|Xylulo|Xul|Gul|Xyl2CMe|Ido)"); // Now see if there are any references to other patterns (by rule name) // with the \p{} syntax specific to Seahawk Pattern charClassPattern = Pattern.compile("\\\\p\\{([A-Za-z0-9]+)\\}"); From gordonp at dev.open-bio.org Sat Apr 10 22:00:02 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 22:00:02 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110200.o3B202wI019153@dev.open-bio.org> gordonp Sat Apr 10 22:00:02 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv19034/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyObjectTransferHandler.java Log Message: Added native support for primitive datatype recognition in text transfers moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyObjectTransferHandler.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyObjectTransferHandler.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/seahawk/gui/MobyObjectTransferHandler.java 2007/12/17 18:44:13 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyObjectTransferHandler.java 2010/04/11 02:00:02 1.4 @@ -218,7 +218,30 @@ for(String fieldName: acceptableData.keySet()){ int itemCount = 1; MobyDataType desiredDataType = acceptableData.get(fieldName).getDataType(); + String dataTypeName = desiredDataType.getName(); System.err.println("Checking text for field " + fieldName+ ", data type " + desiredDataType.getName()); + + // trivial data creations first ... + if(dataTypeName.equals(MobyTags.MOBYSTRING)){ + foundData.put(fieldName+"#"+itemCount++, new MobyDataString(text)); + } + else if(dataTypeName.equals(MobyTags.MOBYBOOLEAN) && + text.matches("(true|True|TRUE|1|yes|Yes|YES|false|False|FALSE|0|no|No|NO)")){ + foundData.put(fieldName+"#"+itemCount++, + new MobyDataBoolean(text.matches("(true|True|TRUE|1|yes|Yes|YES)"))); + } + else if(dataTypeName.equals(MobyTags.MOBYINTEGER) && + text.matches("\\d+")){ + foundData.put(fieldName+"#"+itemCount++, new MobyDataInt("", text)); + } + else if(dataTypeName.equals(MobyTags.MOBYFLOAT) && + text.matches("\\d+(?:\\.\\d*)?(?:[eE][\\-\\+]?\\d+)?")){ + foundData.put(fieldName+"#"+itemCount++, new MobyDataFloat(text)); + } + else if(dataTypeName.equals(MobyTags.MOBYFLOAT) && + text.matches("(?:19|20)\\d\\d-(?:0[1-9]|1[012])-([012][1-9]|3[01])")){ + foundData.put(fieldName+"#"+itemCount++, new MobyDataDateTime(text)); + } MobyDataObject[] textData = client.getMobyObjects(text, desiredDataType); if(textData != null){ System.err.println("Found " + textData.length + " matches"); From gordonp at dev.open-bio.org Sat Apr 10 22:20:46 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 22:20:46 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110220.o3B2Kkwu020079@dev.open-bio.org> gordonp Sat Apr 10 22:20:46 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv20043/src/main/ca/ucalgary/seahawk/resources Modified Files: mobyBuilderRules.xml Log Message: Added LINUCS carbohydrate sequence recognition, for fun moby-live/Java/src/main/ca/ucalgary/seahawk/resources mobyBuilderRules.xml,1.10,1.11 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/mobyBuilderRules.xml,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/mobyBuilderRules.xml 2010/03/17 20:21:55 1.10 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/mobyBuilderRules.xml 2010/04/11 02:20:46 1.11 @@ -66,6 +66,16 @@ string-length('$1') + + + \[\]\[\\S+\]\{.*?(?:([ab]-D-)?\M.?[\x20\(\)\[\]\-\+0-9\{\}]+){3,} + + + '' + + $0 + + \AABIF.*\z From gordonp at dev.open-bio.org Sat Apr 10 22:22:07 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 22:22:07 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110222.o3B2M7Dc020123@dev.open-bio.org> gordonp Sat Apr 10 22:22:06 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv20087/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyDataObjectWidget.java Log Message: Better populated data field description moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyDataObjectWidget.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyDataObjectWidget.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/seahawk/gui/MobyDataObjectWidget.java 2007/12/06 17:26:26 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyDataObjectWidget.java 2010/04/11 02:22:06 1.4 @@ -18,6 +18,7 @@ */ public class MobyDataObjectWidget extends JLabel implements MobyObjectReceiver, MobyContentProducer{ public static final int PARAM_TOOLTIP_WIDTH = 50; + public static final int MAX_DATA_DESC = 30; public static final Color INSTANTIATED_FG_COLOUR = Color.DARK_GRAY; public static final Color UNINSTANTIATED_FG_COLOUR = Color.RED; public static final String INSTANTIATED_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/checkmark.gif"; @@ -150,7 +151,14 @@ labelText = name+": Collection("+dataType.getName()+") -- "+actualData.getName(); } else{ - labelText = name+": "+dataType.getName()+" -- "+actualData.getName(); + String display = actualData.getName(); + if(display == null || display.trim().length() == 0){ + display = ((MobyDataInstance) actualData).getObject().toString(); + } + if(display.length() > MAX_DATA_DESC){ + display = display.substring(0, MAX_DATA_DESC-3)+"..."; + } + labelText = name+": "+dataType.getName()+" -- "+display; } tipText = dataType.getDescription(); if(tipText == null || tipText.length() == 0){ From gordonp at dev.open-bio.org Sat Apr 10 22:25:03 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 22:25:03 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110225.o3B2P3eJ020209@dev.open-bio.org> gordonp Sat Apr 10 22:25:03 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv20173/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentClipboard.java Added Files: DataImportChoiceDialog.java DataImportChoiceListener.java Log Message: Improved data import to clipboard UI moby-live/Java/src/main/ca/ucalgary/seahawk/gui DataImportChoiceDialog.java,NONE,1.1 DataImportChoiceListener.java,NONE,1.1 MobyContentClipboard.java,1.9,1.10 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/09 15:51:53 1.9 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/11 02:25:03 1.10 @@ -6,6 +6,7 @@ import org.biomoby.client.MobyRequestEventHandler; import org.biomoby.shared.MobyDataType; +import org.biomoby.shared.MobyNamespace; import org.biomoby.shared.data.*; import org.biomoby.shared.parser.MobyTags; @@ -20,12 +21,13 @@ import java.io.FileOutputStream; import java.net.URL; import java.util.*; +import java.util.regex.Pattern; /** * The clipboard is a special tab that holds a query with a MOBY Collection * that the user can add and subtract MobyDataInstances from. */ -public class MobyContentClipboard extends MobyContentPane{ +public class MobyContentClipboard extends MobyContentPane implements DataImportChoiceListener{ public final static String CLEAR_CLIPBOARD_OPTION = "Clear Clipboard"; public final static String CLIPBOARD_FILE_NAME = "SeaHawkClipboard"; public final static String CLIPBOARD_COLLECTION_NAME = "Clipboard Collection"; @@ -41,7 +43,13 @@ private File clipboardFile; private MobyDataJob query; // lump all data into one query private MobyDataObjectSet collection; // lump all data into one collection - private String previousImportDataType = null; + private MobyDataType previousImportDataType = null; + private MobyNamespace previousImportNS = null; + + private Pattern commentRegex; + private Pattern scriptRegex; + private Pattern styleRegex; + private Pattern tagRegex; // Clipboard editing variables private JMenuItem deleteDataPopupItem; @@ -88,6 +96,12 @@ setTransferHandler(new FileAndTextTransferHandler(cGUI, false)); // false = open data in current tab editorPane.setTransferHandler(getTransferHandler()); + // Setup regexes used for stripping HTML docs of their markup (for data pasting ops) + commentRegex = Pattern.compile("", Pattern.MULTILINE | Pattern.DOTALL); + scriptRegex = Pattern.compile("", Pattern.MULTILINE | Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + styleRegex = Pattern.compile("", Pattern.MULTILINE | Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + tagRegex = Pattern.compile("<.*?>", Pattern.MULTILINE | Pattern.DOTALL); + sGUI.setClipboard(this); } @@ -248,7 +262,11 @@ logger.warn("Could not read contents of the URL to import to the clipboard ("+u+"):" +e); return; } - + if(urlContents.indexOf(" 1 - String[] selectionValues = new String[mobyDataFound.length]; - for(int i = 0; i < mobyDataFound.length; i++){ - selectionValues[i] = mobyDataFound[i].getDataType().getName(); - if(MobyTags.MOBYOBJECT.equals(selectionValues[i]) && - mobyDataFound[i].getPrimaryNamespace() != null){ - selectionValues[i] += " (" + mobyDataFound[i].getPrimaryNamespace().getName() + ")"; - } - } - // Sort alphabetically - //Arrays.sort(selectionValues); - String initialSelectionValue = selectionValues[0]; - if(previousImportDataType != null){ - for(String selectionValue: selectionValues){ - if(previousImportDataType.equals(selectionValue)){ - initialSelectionValue = selectionValue; - break; - } - } - } - String selection = (String) JOptionPane.showInputDialog(this, - "Paste data as...", - "Data import choice", - JOptionPane.PLAIN_MESSAGE, - (Icon) null, - selectionValues, - initialSelectionValue); - if(selection == null){ - logger.warn("No data type for import selected, abandoning import"); + + // Otherwise we need the user to choose + new DataImportChoiceDialog(contentGUI, mobyDataFound, previousImportDataType, previousImportNS, this); + } + + // Callback once user has selected the data to import from the DataImportChoiceDialog + public void importConfirmed(DataImportChoiceDialog dialog, MobyDataObject[] selectedData){ + if(selectedData == null){ + logger.warn("Got null for import selection, abandoning import"); return; } - for(int i = 0; i < selectionValues.length; i++){ - if(selection.equals(selectionValues[i])){ - addCollectionData(mobyDataFound[i]); - previousImportDataType = selection; - return; + for(int i = 0; i < selectedData.length; i++){ + addCollectionData(selectedData[i], i == selectedData.length-1); // only update display on last import + previousImportDataType = selectedData[i].getDataType(); + if(selectedData[i].getPrimaryNamespace() != null){ + previousImportNS = selectedData[i].getPrimaryNamespace(); } } } + public void importCanceled(DataImportChoiceDialog dialog){} + public boolean hasXMLSource(){ return true; } From gordonp at dev.open-bio.org Sun Apr 11 16:15:28 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sun, 11 Apr 2010 16:15:28 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004112015.o3BKFS3Y017966@dev.open-bio.org> gordonp Sun Apr 11 16:15:28 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv17912/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java Log Message: Updates for proper support of data filtering when submitting to forward services moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.25,1.26 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/10 00:40:17 1.25 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/11 20:15:28 1.26 @@ -532,7 +532,7 @@ isContentsXML = true; // Is it the second stage of wrapping, where data results are being seen? if(urlString.indexOf(WRAPPING_RESULTFILE_PREFIX) != -1){ - System.err.println("Wrapping service results"); + //System.err.println("Wrapping service results"); isWrapping = true; } else{ @@ -1191,7 +1191,7 @@ // Complex case, load the doc fragment from the MOBY XML source file if(docFragID != null && docFragID.length() > 0 && !targetURL.getHost().equals("moby")){ - return DataUtils.loadMobyDataFromXPointer(targetURL, filterHistory.get(getCurrentURL())); + return DataUtils.loadMobyDataFromXPointer(targetURL, filteredData, filterHistory.get(getCurrentURL())); } // Simple case, build the object using the values encoded in the URL itself. @@ -1256,8 +1256,13 @@ // Get the input data for the *previous* service MobyDataJob inputData = DataUtils.getInputSample(srcDoc, SeahawkOptions.getRegistry()); + if(inputData == null){ + // should only happen if Moby XML was loaded manually by a user, otherwise we've recorded this info... + logger.warn("No previous service info in Moby XML, 'previous input' option will not be displayed"); + return; + } for(MobyDataInstance previousMDI: inputData.getPrimaryData()){ - // add conditional of the current service as a criteria in user data for each previousMDI, + // 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()); @@ -1478,11 +1483,11 @@ } else if(regex.matcher(((Element) node).getTextContent()).find()){ matchingXPtrs.put(elementXPtr, Boolean.TRUE); - System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); + //System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); } else{ matchingXPtrs.put(elementXPtr, Boolean.FALSE); - System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); + //System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); } } else if(node instanceof Attr){ @@ -1494,12 +1499,12 @@ else if(regex.matcher(((Attr) node).getValue()).find()){ // Mark the element to which the attribute belongs matchingXPtrs.put(attrParentXPtr, Boolean.TRUE); - System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); + //System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); } // 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)); + //System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); } } @@ -1518,7 +1523,7 @@ if(!parentMatchingXPtrs.containsKey(currXPtr) || !inversed && !parentMatchingXPtrs.get(currXPtr).booleanValue() || inversed && 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()); } } @@ -1732,7 +1737,7 @@ List links = new Vector(); for(int i = 0; i < el.getElementCount(); i++){ javax.swing.text.Element childEl = el.getElement(i); - System.err.println("Found child element " + childEl.getName()); + //System.err.println("Found child element " + childEl.getName()); if(HTML.Tag.A.equals(childEl.getName())){ links.add(childEl); } @@ -1979,10 +1984,10 @@ // normally it'd go to mouseDragged, but sometimes that's flakey so check manually for the // mouse button being down here. if(overHyperlink && (e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == MouseEvent.BUTTON1_DOWN_MASK){ - System.err.println("Got wonky drag"); + //System.err.println("Got wonky drag"); lastHyperlinkDragged = lastHyperlinkHovered; status.setText("Drop the hyperlink onto a Web form field to populate it"); - System.err.println("Dragging "+lastHyperlinkDragged); + //System.err.println("Dragging "+lastHyperlinkDragged); getTransferHandler().exportAsDrag(this, e, TransferHandler.COPY); } else if(dragging){ @@ -1991,6 +1996,6 @@ } public void lostOwnership(Clipboard clipboard, Transferable contents){ - System.err.println("Lost clipboard ownership"); + //System.err.println("Lost clipboard ownership"); } } From gordonp at dev.open-bio.org Sun Apr 11 16:15:28 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sun, 11 Apr 2010 16:15:28 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004112015.o3BKFSqr017948@dev.open-bio.org> gordonp Sun Apr 11 16:15:28 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv17912/src/main/ca/ucalgary/seahawk/util Modified Files: DataUtils.java Added Files: XPointerResolver.java Log Message: Updates for proper support of data filtering when submitting to forward services moby-live/Java/src/main/ca/ucalgary/seahawk/util XPointerResolver.java,NONE,1.1 DataUtils.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.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/seahawk/util/DataUtils.java 2010/04/10 00:40:17 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/11 20:15:28 1.4 @@ -450,7 +450,14 @@ } } - public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, FilterSearch docFilter){ + /** + * Get the data instance object associated with a given XPointer into a Moby XML doc + * + * @param targetURL of the form URLpath#/1/1/2/1 where /1/1/2/1 is an XPointer, or an standard xpath, to the part of the Moby XML doc to deserialize + * @param filteredXPtrs a map of the xpointers to data that should NOT be deserialized if children of the targetURL XPointer + * @param docFilter the current filter applied to the document in targetURL + */ + public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, Map filteredXPtrs, FilterSearch docFilter){ // Are we dealing with a simple object or a complex one? MobyDataInstance mobyData = null; @@ -492,13 +499,35 @@ return null; } + // Remove the filtered data from the doc before deserializing to a moby data instance + // That way the request actually reflects what is shown on the screen to the user. + if(filteredXPtrs != null){ + // Mark and sweep (if we just deleted as we found node, the XPointers could be + // wrong as they refer to ordinality) + Vector nodesToDelete = new Vector(); + for(String xptr: filteredXPtrs.keySet()){ + nodesToDelete.add(XPointerResolver.getNodeFromXPointer(domDoc, xptr)); + } + + // Delete + for(Node nodeToDelete: nodesToDelete){ + Node parent = nodeToDelete.getParentNode(); + parent.removeChild(nodeToDelete); + // Get rid of Simple parents of deleted nodes, because empty Simple + // tags are not okay in Moby (causes parsing error) + if(MobyTags.SIMPLE.equals(parent.getLocalName())){ + parent.getParentNode().removeChild(parent); + } + } + } + // Build and run the XPath statement Element mobyObject = null; NodeList idSearchResult = null; Object xobject = null; try{ xobject = XPathFactory.newInstance().newXPath().evaluate(childXPath, - new InputSource(targetURL.openStream()), + domDoc, XPathConstants.NODESET); // Check the results From gordonp at dev.open-bio.org Wed Apr 14 18:02:05 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Wed, 14 Apr 2010 18:02:05 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004142202.o3EM252P007075@dev.open-bio.org> gordonp Wed Apr 14 18:02:04 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv7013/src/main/ca/ucalgary/seahawk/util Modified Files: DataUtils.java FilterSearch.java Added Files: MobyPayloadRequestListener.java MutableNodeList.java Log Message: Changes to implement explicit 'for each' loops over Seahawk data lists (not quite functional yet, but compiles) moby-live/Java/src/main/ca/ucalgary/seahawk/util MobyPayloadRequestListener.java,NONE,1.1 MutableNodeList.java,NONE,1.1 DataUtils.java,1.4,1.5 FilterSearch.java,1.4,1.5 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/11 20:15:28 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/14 22:02:04 1.5 @@ -4,6 +4,7 @@ import java.net.URL; import java.util.*; import java.util.logging.*; +import java.util.regex.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; @@ -34,8 +35,12 @@ public static final String TEMP_FILE_PREFIX = "seahawk"; private static final String OUTPUT_SUFFIX = ".out.xml"; private static final String INPUT_SUFFIX = ".in.xml"; - private static DocumentBuilder docBuilder; + public static DocumentBuilder docBuilder; private static Transformer identityTransform; + public static XPathFactory xPathFactory; + + public static final String ARTICLE_PEERS_MODE = "article_peers"; + public static final String DATATYPE_PEERS_MODE = "datatype_peers"; private static Logger logger = Logger.getLogger(DataUtils.class.getName()); @@ -54,6 +59,8 @@ } catch(Exception e){ logger.log(Level.SEVERE, "Cannot get identity XSLT transform from configuration", e); } + + xPathFactory = XPathFactory.newInstance(); } /** @@ -176,7 +183,7 @@ // User data has the form srcURL#XpathSelectCriteria xptrActualDataSubmitted regexFilter // where the filter is optional String[] data = sampleData.getUserData().toString().split("\t"); - System.err.println("Forward user data is " + sampleData.getUserData().toString()); + //System.err.println("Forward user data is " + sampleData.getUserData().toString()); URL dataSrcURL = null; try{ dataSrcURL = new URL(data[0]); @@ -437,7 +444,7 @@ "sync: the instance job '" + jobName + "' has no parameter '" + paramName + "'"); } - System.err.println("Setting user data val to " + attrValue + " for " + paramName); + //System.err.println("Setting user data val to " + attrValue + " for " + paramName); contentInstance.get(jobName).get(paramName).setUserData(attrValue); } else{ @@ -451,24 +458,47 @@ } /** - * Get the data instance object associated with a given XPointer into a Moby XML doc + * Loads targetURL, minus the nodes specified by the xpath keys in filteredXPtrs (map values are not currently used). + */ + public static void filterDoc(Document domDoc, Map filteredXPtrs){ + + if(domDoc == null){ + logger.log(Level.SEVERE, "Error: Could not get MOBY document as DOM (empty or malformed document?)"); + return; + } + + // Remove the filtered data from the doc before deserializing to a moby data instance + // That way the request actually reflects what is shown on the screen to the user. + if(filteredXPtrs != null){ + // Mark and sweep (if we just deleted as we found nodes, the XPointers could be + // wrong as they refer to ordinality) + Vector nodesToDelete = new Vector(); + for(String xptr: filteredXPtrs.keySet()){ + nodesToDelete.add(XPointerResolver.getNodeFromXPointer(domDoc, xptr)); + } + + // Delete + for(Node nodeToDelete: nodesToDelete){ + Node parent = nodeToDelete.getParentNode(); + parent.removeChild(nodeToDelete); + // Get rid of Simple parents of deleted nodes, because empty Simple + // tags are not okay in Moby (causes parsing error) + if(MobyTags.SIMPLE.equals(parent.getLocalName())){ + parent.getParentNode().removeChild(parent); + } + } + } + } + + /** + * Get the data instance object associated with a given XPointer in a Moby XML doc. * * @param targetURL of the form URLpath#/1/1/2/1 where /1/1/2/1 is an XPointer, or an standard xpath, to the part of the Moby XML doc to deserialize * @param filteredXPtrs a map of the xpointers to data that should NOT be deserialized if children of the targetURL XPointer * @param docFilter the current filter applied to the document in targetURL */ public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, Map filteredXPtrs, FilterSearch docFilter){ - // Are we dealing with a simple object or a complex one? - MobyDataInstance mobyData = null; - - // Find the DOM fragment corresponding to the MOBY ID anchor specified - // in the link URL by using an XPath statement on the source MOBY doc - //System.err.println("Retrieving complex object from XPointer " + targetURL); - - // A child Xpointer is of the form /1/2/1/1, specifying the DOM child - // descent path from the root node to get to the target node. The - // equivalent XPath is /*[1]/*[2]/*[1]/*[1] - String childXPath = targetURL.getRef().replaceAll("/(\\d+)", "/*[$1]"); + URL currentURL = null; try{currentURL = new URL(targetURL.toString().replaceAll("#"+targetURL.getRef(), ""));} catch(Exception e){ @@ -476,7 +506,6 @@ } // Build the DOM - Element mobyDOMRoot = null; Document domDoc = null; try{ domDoc = docBuilder.parse(targetURL.openStream()); @@ -489,46 +518,29 @@ " could not be read (from " + targetURL + ")", ioe); return null; } + // Does an in-place edit of domDoc + filterDoc(domDoc, filteredXPtrs); + + // Are we dealing with a simple object or a complex one? + MobyDataInstance mobyData = null; - if(domDoc != null){ - mobyDOMRoot = domDoc.getDocumentElement(); - } - if(mobyDOMRoot == null){ - logger.log(Level.SEVERE, "Error: Could not get MOBY document as DOM from source URL " + - targetURL + " (empty or malformed document?)"); - return null; - } + // Find the DOM fragment corresponding to the MOBY ID anchor specified + // in the link URL by using an XPath statement on the source MOBY doc + //System.err.println("Retrieving complex object from XPointer " + targetURL); - // Remove the filtered data from the doc before deserializing to a moby data instance - // That way the request actually reflects what is shown on the screen to the user. - if(filteredXPtrs != null){ - // Mark and sweep (if we just deleted as we found node, the XPointers could be - // wrong as they refer to ordinality) - Vector nodesToDelete = new Vector(); - for(String xptr: filteredXPtrs.keySet()){ - nodesToDelete.add(XPointerResolver.getNodeFromXPointer(domDoc, xptr)); - } - - // Delete - for(Node nodeToDelete: nodesToDelete){ - Node parent = nodeToDelete.getParentNode(); - parent.removeChild(nodeToDelete); - // Get rid of Simple parents of deleted nodes, because empty Simple - // tags are not okay in Moby (causes parsing error) - if(MobyTags.SIMPLE.equals(parent.getLocalName())){ - parent.getParentNode().removeChild(parent); - } - } - } + // A child Xpointer is of the form /1/2/1/1, specifying the DOM child + // descent path from the root node to get to the target node. The + // equivalent XPath is /*[1]/*[2]/*[1]/*[1] + String childXPath = targetURL.getRef().replaceAll("/(\\d+)", "/*[$1]"); // Build and run the XPath statement Element mobyObject = null; NodeList idSearchResult = null; Object xobject = null; try{ - xobject = XPathFactory.newInstance().newXPath().evaluate(childXPath, - domDoc, - XPathConstants.NODESET); + xobject = xPathFactory.newXPath().evaluate(childXPath, + domDoc, + XPathConstants.NODESET); // Check the results if(xobject != null){ @@ -603,7 +615,7 @@ * Generalizes the element instance into an XPath retrieving it and all * similarly nested elements (based on traversing the parent nodes and prepending their names) */ - protected static String elementInContextToNameBasedXPath(Element targetElement){ + public static String elementInContextToNameBasedXPath(Element targetElement){ String xpath = ""; for(Element currentElement = targetElement; @@ -630,22 +642,20 @@ xpath = "/*[@"+MobyTags.OBJ_NAMESPACE + " = '" + currentElement.getAttribute(MobyTags.OBJ_NAMESPACE)+"']" + xpath; } - else if(elName.equals(MobyTags.MOBYFLOAT) || - elName.equals(MobyTags.MOBYSTRING) || - elName.equals(MobyTags.MOBYBOOLEAN) || - elName.equals(MobyTags.MOBYINTEGER) || - elName.equals(MobyTags.MOBYDATETIME)){ +// else if(elName.equals(MobyTags.MOBYFLOAT) || +// elName.equals(MobyTags.MOBYSTRING) || +// elName.equals(MobyTags.MOBYBOOLEAN) || +// elName.equals(MobyTags.MOBYINTEGER) || +// elName.equals(MobyTags.MOBYDATETIME)){ // Assume that it isn't the primitive type, but rather the articleName // that makes it appropriate to use. - xpath = "/*[@"+MobyTags.ARTICLENAME + " = '" + - articleName+"']" + xpath; - } +// xpath = "/*[@"+MobyTags.ARTICLENAME + " = '" + +// articleName+"']" + xpath; +// } else{ // It's a complex type. Assume the type is why we are picking it. // TODO: In future we may want to check if a parent type is allowed in - // this slot, and generalize to that. May also want to check that there isn't more - // than one member of this type at this level in a HAS relationship... - // in that case we probably want to go by articleName to catch the full semantics + // this slot, and generalize to that. xpath = "/"+elName + xpath; } if(!(currentElement.getParentNode() instanceof Element)){ @@ -696,6 +706,12 @@ } /** + * Replace the selection xpath info in the data instance + */ + public static void replaceUserData(MobyDataInstance mdi, String selectionXPath){ + } + + /** * Retrieves processing instructions embedded in Moby XML docs if they have the for */ public static String getSeahawkAttrFromDoc(URL docURL, String attrName) throws Exception{ @@ -777,4 +793,328 @@ "any_namespace"); } + // Recursively ascend the DOM tree and find out our place in its branching structure + public static String getXPtr(Node n){ + if(n == null || n instanceof Document){ + return ""; + } + Node parent = n.getParentNode(); + if(parent == null && n instanceof Attr){ + parent = ((Attr) n).getOwnerElement(); + } + + NodeList children = parent.getChildNodes(); + int nonElementCnt = 0; + for(int i = 0; i < children.getLength(); i++){ + if(!(children.item(i) instanceof Element)){ + nonElementCnt++; + continue; + } + if(n == children.item(i)){ + return getXPtr(parent)+"/"+(i-nonElementCnt+1); + } + } + return null; + } + + /** + * If any moby object member is in a HAS relationship, add it to the list of filterable items + */ + public static Boolean addHASXPtrs(List filterList, Element object){ + String tagName = object.getLocalName(); + boolean isContainer = false; + MobyDataType mobyDataType = null; + if(tagName.equals(MobyTags.MOBYDATA) || tagName.equals(MobyTags.COLLECTION) || tagName.equals(MobyTags.SIMPLE) || + tagName.equals(MobyTags.CROSSREFERENCE)){ + isContainer = true; + } + else{ + mobyDataType = MobyDataType.getDataType(tagName, SeahawkOptions.getRegistry()); + if(mobyDataType == null){ + logger.log(Level.WARNING, + "Found datatype unknown to the registry ("+object.getLocalName()+")"); + 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)){ + continue; + } + + Element member = (Element) members.item(i); + addHASXPtrs(filterList, member); + + if(!isContainer){ + String memberName = member.getAttribute(MobyTags.ARTICLENAME); + MobyRelationship membership = mobyDataType.getChild(memberName); + //System.err.println("Relationship for " + tagName + " member " + memberName + + // " is " + (membership == null ? null : membership.getRelationshipType())); + if(membership != null && membership.getRelationshipType() == Central.iHAS){ + filterList.add(getXPtr(member)); + if(!hasHAS){ + hasHAS = Boolean.TRUE; + } + } + } + } + return hasHAS; + } + + /** + * For one-off filtering of a doc. Populates xPtrsToFilter, and returns the + * whole doc which you can manipulate yourself (e.g. removing the nodes identified). + */ + public static Document findFilteredNodes(URL targetURL, FilterSearch filter, + Map xPtrsToFilter){ + Document unfilteredDoc = null; + try{ + unfilteredDoc = docBuilder.parse(targetURL.openStream()); + } catch(Exception e){ + logger.log(Level.SEVERE, + "Could not parse Moby document " + targetURL, e); + return null; + } + findFilteredNodes(unfilteredDoc, filter, null, xPtrsToFilter, null, null, null, true); + return unfilteredDoc; + } + + /** + * Returns a list of xptrs to filterable nodes in the targetDoc, an populates the list of + * xptrs that should be filtered according to the provided filter. In-place edited fields are + * xPtrsToFilter, jobXPtrs, currentSelectedData, and currentSelectionXPath + * (for caching efficiency on multiple consecutive + * calls to this method, such as a live typed search in the UI). The latter three can be null if no caching is desired. + */ + public static List findFilteredNodes(Document targetDoc, FilterSearch filter, List filterableXPtrs, + Map xPtrsToFilter, Map jobXPtrs, + MutableNodeList currentSelectedData, StringBuffer currentSelectionXPath, + boolean apply){ + xPtrsToFilter.clear(); + + // Filter out any moby jobs, parameters, collection members or HAS members that aren't in the matchingNodes + if(filterableXPtrs == null){ + if(jobXPtrs == null){ + jobXPtrs = new HashMap(); + } + else{ + jobXPtrs.clear(); + } + filterableXPtrs = new Vector(); + NodeList nodes = targetDoc.getElementsByTagNameNS(MobyTags.MOBY_XML_NS, MobyTags.MOBYDATA); + for(int i = 0; i < nodes.getLength(); i++){ + String jobXPtr = getXPtr(nodes.item(i)); + filterableXPtrs.add(jobXPtr); + jobXPtrs.put(jobXPtr, addHASXPtrs(filterableXPtrs, (Element) nodes.item(i))); + } + + // Collections + nodes = targetDoc.getElementsByTagNameNS(MobyTags.MOBY_XML_NS, MobyTags.COLLECTION); + for(int i = 0; i < nodes.getLength(); i++){ + String collectionXPtr = getXPtr(nodes.item(i)); + NodeList collectionMembers = nodes.item(i).getChildNodes(); + int nonElementCnt = 0; + for(int j = 0; j < collectionMembers.getLength(); j++){ + if(!(collectionMembers.item(j) instanceof Element)){ + nonElementCnt++; + continue; + } + filterableXPtrs.add(collectionXPtr+"/"+(j-nonElementCnt+1)+"/1"); + } + } + } + + if(!apply || filter == null || filter.getFilterRegex().toString().length() == 0){ + return filterableXPtrs; + } + // Otherwise make a list of xpointers to data that should be filtered + XPathOption xsel = filter.getSelectedXPath(); + + // Find the applicable DOM nodes if not yet found, or if selection criteria have changed + if(currentSelectedData == null || currentSelectedData.isEmpty() || + currentSelectionXPath == null || !currentSelectionXPath.toString().equals(xsel.getXPath())){ + if(currentSelectionXPath == null){ + currentSelectionXPath = new StringBuffer(xsel.getXPath()); + } + else{ + currentSelectionXPath.replace(0, currentSelectionXPath.length(), xsel.getXPath()); + } + try{ + if(currentSelectedData == null){ + currentSelectedData = new MutableNodeList(); + } + else{ + currentSelectedData.clear(); + } + currentSelectedData.addAll((NodeList) xPathFactory.newXPath().evaluate(currentSelectionXPath.toString(), + targetDoc, + XPathConstants.NODESET)); + } catch(Exception e){ + logger.log(Level.SEVERE, + "Could not evaluate XPath (" + xsel.getXPath() + ")", e); + return filterableXPtrs; + } + // System.err.println("There are " + currentSelectedData.getLength() + + // " items selected in the document using XPath " + currentSelectionXPath); + } + + // Find just the data subset also matching the regex + Map matchingXPtrs = new LinkedHashMap(); + // Build the FSA only once, for efficiency + Pattern regex = Pattern.compile(filter.getFilterRegex().toString(), + Pattern.MULTILINE | Pattern.DOTALL | + (filter.getCaseSensitivity() ? 0 : Pattern.CASE_INSENSITIVE)); + for(int i = 0; i < currentSelectedData.getLength(); i++){ + Node node = currentSelectedData.item(i); + if(node instanceof Element){ + 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(elementXPtr, Boolean.FALSE); + //System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); + } + } + else if(node instanceof Attr){ + 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(attrParentXPtr, Boolean.TRUE); + //System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); + } + // 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.log(Level.WARNING, + "Found filter xpath result item that was not an Element or Attribute as expected ("+ + node.getClass().getName()+")"); + } + } + + boolean inversed = filter.getSelectionInversed(); + Map parentMatchingXPtrs = new LinkedHashMap(); + for(String currXPtr: filterableXPtrs){ + for(Map.Entry matchingXPtr: matchingXPtrs.entrySet()){ + if(matchingXPtr.getKey().startsWith(currXPtr+"/")){ // a parent of the matching data + // No positive example yet? + if(!parentMatchingXPtrs.containsKey(currXPtr) || + !inversed && !parentMatchingXPtrs.get(currXPtr).booleanValue() || + inversed && parentMatchingXPtrs.get(currXPtr).booleanValue()){ + //System.err.println("Adding "+ matchingXPtr.getValue() + " for " + currXPtr); + parentMatchingXPtrs.put(currXPtr, matchingXPtr.getValue()); + } + } + } + } + + matchingXPtrs.putAll(parentMatchingXPtrs); + for(String currXPtr: matchingXPtrs.keySet()){ + // Is part of the selection criteria, but doesn't match the regex + boolean shouldFilter = false; + if(!matchingXPtrs.get(currXPtr).booleanValue() && + // special condition: if "entire response" xpath is given, filter only at the job level + (!currentSelectionXPath.toString().equals(FilterSearch.SELECT_ALL_XPATH) || jobXPtrs.containsKey(currXPtr))){ + shouldFilter = true; + } + if(!inversed && shouldFilter || + inversed && !shouldFilter){ + xPtrsToFilter.put(currXPtr, "todo"); + } + } + + //todo: filter objects without the HAS field at all... + return filterableXPtrs; + } + // We need to enumerate the possible peer-sets for the selected data item. Is the user interested in + // items in the same namespace, same data type, or same article name? + public static NodeList getPeerElements(Document doc, MobyDataInstance mobyData, String peerMode){ + if(!(mobyData instanceof MobyPrimaryData)){ + logger.log(Level.WARNING, "Tried to get peers of data that was not an instanceof MobyPrimaryData (was " + + mobyData.getClass().getName()+ ")"); + return null; + } + MobyDataType dataTypeTemplate = ((MobyPrimaryData) mobyData).getDataType(); + + NodeList peerElements = null; + String peerGroupXPath = null; + if(mobyData.getUserData() != null){ + String[] userData = ((String) mobyData.getUserData()).split("\t"); + // first arg is url#nameBasedXPath + peerGroupXPath = userData[0].split("#", 2)[1]; + } + else{ + // Fallback is to get all nodes with the same name... + // warning: need to set this in the userdata sent to the job, to jibe with taverna workflow export selection of nodes! + logger.log(Level.WARNING, "No UserData for data instance, falling back to all peer elements of the same datatype"); + peerGroupXPath = "//"+dataTypeTemplate.getName(); + } + + // just look at data type tag, regardless of nesting + if(DATATYPE_PEERS_MODE.equals(peerMode)){ + peerGroupXPath = peerGroupXPath.replaceFirst("^.+/", "//"); + } + else if(ARTICLE_PEERS_MODE.equals(peerMode)){ + String xpathArticleCondition = "[@"+MobyTags.ARTICLENAME + "='" + mobyData.getName() +"']"; + // Pass back modified selection xpath for userdata (enables PBE to capture the additonal semantics) + // This is done by replacing first tab delimited field url#selectionXPath with url#newXPath + String newUserData = mobyData.getUserData().toString().replaceFirst("^(.*?)#.*?(?=\\t)", + "$1#"+peerGroupXPath+xpathArticleCondition); + mobyData.setUserData(newUserData); + + // keep from job article name down + peerGroupXPath = peerGroupXPath.replaceFirst("^.*/(Collection|Simple)", "//*"); + // we want to go by articleName too to catch the full semantics of the peer group definition + peerGroupXPath += xpathArticleCondition; + } + else{ + logger.log(Level.SEVERE, "Got unknown mode for peer selection, aborting (mode was "+peerMode+")"); + return null; + } + // For xpaths given above, MOBY namespace is problem in XPath evaluation. + // solution: eliminate Moby envelope path parts: full path doesn't resolve in xpath for unknown reasons + //.replaceAll("/(MOBY|mobyContent|mobyData|Collection|Simple)","/moby:$1"); //attempt 1 + //.replaceAll("/([a-zA-Z_0-9\\-]+)(?=/|$)", "/*[local-name() = '$1']") //attempt 2 + //.replaceAll("/([a-zA-Z_0-9\\-]+)\\[", "/*[local-name() = '$1' and "); //attempt 2 cont'd + + try{ + peerElements = (NodeList) xPathFactory.newXPath().evaluate(peerGroupXPath, + doc, + XPathConstants.NODESET); + } catch(Exception e){ + logger.log(Level.SEVERE, "Could not evaluate UserData XPath "+peerGroupXPath, e); + } + System.err.println("Got " + peerElements.getLength() + " peers for " + peerGroupXPath); + + return peerElements; + } + + // given a node from a Moby XML dom, find the name of the mobyData job that's its parent + public static String findMobyJobName(Node n){ + while(n != null && !n.getLocalName().equals(MobyTags.MOBYDATA)){ + n = n.getParentNode(); + } + if(n == null){ + return null; // no mobyData parent + } + else{ + return MobyPrefixResolver.getAttr((Element) n, MobyTags.QUERYID); + } + } } =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/10 00:40:17 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/14 22:02:04 1.5 @@ -28,6 +28,20 @@ public static final String SELECT_ALL_XPATH = "//* | //*/@*"; /** + * A c-tor to manually populate the filter with a specific set of filter criteria. + * No autopoulation of options is done. + */ + public FilterSearch(String regex, XPathOption xpath, boolean case_sensitive, boolean inverse_selection){ + filterRegex = new StringBuffer(regex); + xpathOptions = new Vector(); + xpathOptions.add(xpath); + setCaseSensitivity(case_sensitive); + setSelectionInversed(inverse_selection); + } + + /** + * Autopopulates the possible search field values based on the incoming doc + * * @param docToFilter the document that will be used to determine what XPaths can be suggested * @param docBuilder the xml parser to use on the document * @@ -106,4 +120,15 @@ public Vector getXPathOptions(){ return xpathOptions; } + + public boolean equals(Object o){ + if(o == null || !(o instanceof FilterSearch)){ + return false; + } + FilterSearch other = (FilterSearch) o; + return filterRegex.toString().equals(other.filterRegex.toString()) && + getSelectedXPath().getXPath().equals(other.getSelectedXPath().getXPath()) && + caseSensitivity == other.caseSensitivity && + inverseSelection == other.inverseSelection; + } } From gordonp at dev.open-bio.org Wed Apr 14 18:02:04 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Wed, 14 Apr 2010 18:02:04 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004142202.o3EM24JD007053@dev.open-bio.org> gordonp Wed Apr 14 18:02:04 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv7013/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java MobyServicesGUI.java Added Files: MobyPayloadCreator.java Log Message: Changes to implement explicit 'for each' loops over Seahawk data lists (not quite functional yet, but compiles) moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyPayloadCreator.java,NONE,1.1 MobyContentPane.java,1.26,1.27 MobyServicesGUI.java,1.17,1.18 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.26 retrieving revision 1.27 diff -u -r1.26 -r1.27 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/11 20:15:28 1.26 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/14 22:02:04 1.27 @@ -1,4 +1,3 @@ - package ca.ucalgary.seahawk.gui; // For external links @@ -72,8 +71,8 @@ public static final String SERVICE_CREATION_MSG = "Create a service returning this datatype"; private static final int TAB_ICON_SPACER = 2; - private static String SEARCH_VISIBLE = "Search visible"; - private static String SEARCH_HIDDEN = "Search hidden"; + private static final String SEARCH_VISIBLE = "Search visible"; + private static final String SEARCH_HIDDEN = "Search hidden"; private static ImageIcon hourglassIcon; private static ImageIcon failedIcon; @@ -105,10 +104,10 @@ private Map filteredData; //Map private boolean filterChanged; private Document currentDoc; //the doc DOM being actively filtered - private NodeList currentSelectedData = null; - private String currentSelectionXPath = null; - private Map jobXPtrs = null; // Map + private MutableNodeList currentSelectedData = null; + private StringBuffer currentSelectionXPath = null; private List filterableNodes = null; // List + private Map jobXPtrs = null; // Map private List origStyles = null; private boolean firstDocRendering = true; @@ -141,20 +140,6 @@ private final static String wsServletPath = "/SOAPServlet"; private static Acme.Serve.Serve servletContainer; private static Map id2GuiMap; - private static DocumentBuilder docBuilder; - private static XPathFactory xPathFactory; - - static{ - xPathFactory = XPathFactory.newInstance(); - - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - try{ - docBuilder = dbf.newDocumentBuilder(); - } catch(Exception e){ - logger.warn("Cannot get XML parser from configuration", e); - } - } public MobyContentPane(MobyContentGUI cGUI, MobyServicesGUI sGUI, JTabbedPane parentComponent, DataFlowRecorder recorder, JLabel statusBar){ tabbedPane = parentComponent; @@ -200,7 +185,9 @@ filterHistory = new HashMap(); deletedFilters = new HashMap(); xPtrsReferencedInNextService = new Vector(); + currentSelectedData = new MutableNodeList(); filteredData = new HashMap(); + jobXPtrs = new HashMap(); ClassLoader cl = getClass().getClassLoader(); if(cl == null){ @@ -738,9 +725,8 @@ // If this page has a filter associated with it before reload it try{ currentDoc = null; // get rid of previous in-memory doc use for interactive filtering, if any - currentSelectedData = null; - currentSelectionXPath = null; - jobXPtrs = null; + currentSelectedData.clear(); + currentSelectionXPath = new StringBuffer(); filterableNodes = null; origStyles = null; firstDocRendering = true; @@ -1209,14 +1195,54 @@ "not extract MOBY Data Object from " +targetURL); return; } + if(!(mobyData instanceof MobyPrimaryData)){ + logger.warn("Cannot create MOBY service list for non-primary " + + "MOBY Data (was " +mobyData.getClass().getName()+")"); + return; + } JPopupMenu popup = new DynamicJPopupMenu(); popup.setName(MOBY_SERVICE_POPUP_NAME); addExtraMobyOptions(popup, mobyData, targetURL); - JMenuItem checkingLinksPopupItem = new JMenuItem("Check for services..."); + JMenuItem checkingLinksPopupItem = new JMenuItem("Checking for services..."); popup.add(checkingLinksPopupItem); popup.show(this, lastClickX+editorPane.getX(), lastClickY+editorPane.getY()); servicesGUI.addPopupOptions(mobyData, popup, true, getDefaultHandler()); // true = asynchronous + + // It's possible that the current node clicked has peers that could also be submitted at the same time. + // In this case, create a "for each" option to submit all peers to the service. We don't actually build + // the input data, but provde a callback listener to create the full submission envelope if the user + // chooses the for each option. The Moby data instance's userData gives us the current context, enabling us + // to construct the correct payload in MobyPayloadCreator.createPayload() at any point in the future. + String origUserData = (String) mobyData.getUserData(); + MobyPayloadRequestListener payloadCreator = new MobyPayloadCreator(this); + for(String peerMode: new String[]{DataUtils.ARTICLE_PEERS_MODE, DataUtils.DATATYPE_PEERS_MODE}){ + // note that getPeerElements() will modify the userData to reflect the semantic of the requested peer mode + mobyData.setUserData(origUserData); + NodeList peerElements = DataUtils.getPeerElements(getCurrentDoc(), mobyData, peerMode); + if(peerElements.getLength() <= 1){ + continue; // no 'for each' option if only one to process... + } + String each = "each (" + peerElements.getLength() + " total)"; + if(peerMode.equals(DataUtils.ARTICLE_PEERS_MODE)){ + each += " '"+mobyData.getName()+"'"; + } + MobyDataType dataType = ((MobyPrimaryData) mobyData).getDataType(); + if(mobyData instanceof MobyPrimaryDataSet){ // Collection + servicesGUI.addPopupOptions((MobyPrimaryDataSet) mobyData, popup, true, getDefaultHandler(), payloadCreator, + (String) mobyData.getUserData(), each); + } + else if(MobyTags.MOBYOBJECT.equals(dataType.getName())){ + MobyNamespace namespace = null; + servicesGUI.addPopupOptions(namespace, popup, true, getDefaultHandler(), payloadCreator, + (String) mobyData.getUserData(), each); + } + else{ + servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), payloadCreator, + (String) mobyData.getUserData(), each); + } + } + status.setText("Shift+Click=Service in new tab, Ctrl+Click=Use default 2nd params"); if(popup.getSubElements().length > 0){ popup.setSelected(null); @@ -1228,6 +1254,15 @@ } } + Map getFilteredData(){ + return filteredData; + } + + Map getJobXPtrs(){ + return jobXPtrs; + } + + /** * Subclasses can use this method to expand the popup menu. Be sure to call super.addExtraMobyOptions() */ @@ -1252,7 +1287,7 @@ //System.err.println("Should create a previous input menu item for " + mdi.getUserData()); try{ - Document srcDoc = docBuilder.parse(srcURL.openStream()); + Document srcDoc = DataUtils.docBuilder.parse(srcURL.openStream()); // Get the input data for the *previous* service MobyDataJob inputData = DataUtils.getInputSample(srcDoc, SeahawkOptions.getRegistry()); @@ -1262,7 +1297,7 @@ return; } for(MobyDataInstance previousMDI: inputData.getPrimaryData()){ - // add conditional of the current service as a criteria in user data for each previousMDI, + // 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()); @@ -1271,6 +1306,7 @@ } catch(Exception e){ logger.warn("Could not load previous service info, 'previous input' option will not be displayed", e); } + } /** @@ -1392,231 +1428,41 @@ return null; } - /** - * Determine the parts of the XML document matching the FilterSearch criteria, and filter the view accordingly. - */ - public void applyFilter(boolean apply){ - if(!filterChanged){ - filterChanged = true; - } - filteredData.clear(); - + protected Document getCurrentDoc(){ if(currentDoc == null){ // parse the doc into memory if not already there try{ - currentDoc = docBuilder.parse(getCurrentURL().openStream()); + currentDoc = DataUtils.docBuilder.parse(getCurrentURL().openStream()); } catch(Exception e){ logger.error("Could not parse Moby document " + getCurrentURL(), e); - return; - } - } - // Filter out any moby jobs, parameters, collection members or HAS members that aren't in the matchingNodes - if(filterableNodes == null){ - jobXPtrs = new HashMap(); - filterableNodes = new Vector(); - NodeList nodes = currentDoc.getElementsByTagNameNS(MobyTags.MOBY_XML_NS, MobyTags.MOBYDATA); - for(int i = 0; i < nodes.getLength(); i++){ - String jobXPtr = getXPtr(nodes.item(i)); - filterableNodes.add(jobXPtr); - jobXPtrs.put(jobXPtr, addHASXPtrs(filterableNodes, (Element) nodes.item(i))); - } - - // Collections - nodes = currentDoc.getElementsByTagNameNS(MobyTags.MOBY_XML_NS, MobyTags.COLLECTION); - for(int i = 0; i < nodes.getLength(); i++){ - String collectionXPtr = getXPtr(nodes.item(i)); - NodeList collectionMembers = nodes.item(i).getChildNodes(); - int nonElementCnt = 0; - for(int j = 0; j < collectionMembers.getLength(); j++){ - if(!(collectionMembers.item(j) instanceof Element)){ - nonElementCnt++; - continue; - } - filterableNodes.add(collectionXPtr+"/"+(j-nonElementCnt+1)+"/1"); - } + return null; } } - - if(!apply || !filterHistory.containsKey(getCurrentURL()) || - (filterHistory.containsKey(getCurrentURL()) && - filterHistory.get(getCurrentURL()).getFilterRegex().toString().length() == 0)){ - // Show whole doc if no filter or if filter is blank, so nothing to do here - if(firstDocRendering){ - firstDocRendering = false; - } - else{ - displayFilterEffect(); //need to cleanup previous state - } - return; - } - // Otherwise make a list of xpointers to data that should be grayed out - FilterSearch fs = filterHistory.get(getCurrentURL()); - XPathOption xsel = fs.getSelectedXPath(); - - // Find all the matching data - XPath xpath = xPathFactory.newXPath(); - // Find the applicable DOM nodes if not yet found, or if selection criteria have changed - if(currentSelectedData == null || currentSelectionXPath == null || !currentSelectionXPath.equals(xsel.getXPath())){ - currentSelectionXPath = xsel.getXPath(); - try{ - currentSelectedData = (NodeList) xpath.evaluate(currentSelectionXPath, currentDoc, XPathConstants.NODESET); - } catch(Exception e){ - logger.error("Could not evaluate XPath (" + xsel.getXPath() + ") over " + getCurrentURL(), e); - return; - } - // System.err.println("There are " + currentSelectedData.getLength() + - // " items selected in the document using XPath " + currentSelectionXPath); - } - - // Find just the data subset also matching the regex - Map matchingXPtrs = new LinkedHashMap(); - // Build the FSA only once, for efficiency - 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){ - 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(elementXPtr, Boolean.FALSE); - //System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); - } - } - else if(node instanceof Attr){ - 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(attrParentXPtr, Boolean.TRUE); - //System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); - } - // 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 ("+ - node.getClass().getName()+")"); - } - } - - boolean inversed = fs.getSelectionInversed(); - Map parentMatchingXPtrs = new LinkedHashMap(); - for(String currXPtr: filterableNodes){ - for(Map.Entry matchingXPtr: matchingXPtrs.entrySet()){ - if(matchingXPtr.getKey().startsWith(currXPtr+"/")){ // a parent of the matching data - // No positive example yet? - if(!parentMatchingXPtrs.containsKey(currXPtr) || - !inversed && !parentMatchingXPtrs.get(currXPtr).booleanValue() || - inversed && parentMatchingXPtrs.get(currXPtr).booleanValue()){ - //System.err.println("Adding "+ matchingXPtr.getValue() + " for " + currXPtr); - parentMatchingXPtrs.put(currXPtr, matchingXPtr.getValue()); - } - } - } - } - - matchingXPtrs.putAll(parentMatchingXPtrs); - for(String currXPtr: matchingXPtrs.keySet()){ - // Is part of the selection criteria, but doesn't match the regex - boolean shouldFilter = false; - if(!matchingXPtrs.get(currXPtr).booleanValue() && - // special condition: if "entire response" xpath is given, filter only at the job level - (!currentSelectionXPath.equals(FilterSearch.SELECT_ALL_XPATH) || jobXPtrs.containsKey(currXPtr))){ - shouldFilter = true; - } - if(!inversed && shouldFilter || - inversed && !shouldFilter){ - filteredData.put(currXPtr, "todo"); - } - } - - //todo: filter objects without the HAS field at all... - - // apply gray out in the document display - displayFilterEffect(); + return currentDoc; } - // If any moby object member is in a HAS relationship, add it to the list of filterable items - private Boolean addHASXPtrs(List filterList, Element object){ - String tagName = object.getLocalName(); - boolean isContainer = false; - MobyDataType mobyDataType = null; - if(tagName.equals(MobyTags.MOBYDATA) || tagName.equals(MobyTags.COLLECTION) || tagName.equals(MobyTags.SIMPLE) || - tagName.equals(MobyTags.CROSSREFERENCE)){ - isContainer = true; - } - else{ - mobyDataType = MobyDataType.getDataType(tagName, SeahawkOptions.getRegistry()); - if(mobyDataType == null){ - logger.warn("Found datatype unknown to the registry ("+object.getLocalName()+")"); - return Boolean.FALSE; - } + /** + * Determine the parts of the XML document matching the FilterSearch criteria for the current doc, + * and filter the view accordingly. Used for interactive filtering in the display. + */ + protected void applyFilter(boolean apply){ + if(!filterChanged){ + filterChanged = true; } - 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)){ - continue; - } - - Element member = (Element) members.item(i); - addHASXPtrs(filterList, member); - - if(!isContainer){ - String memberName = member.getAttribute(MobyTags.ARTICLENAME); - MobyRelationship membership = mobyDataType.getChild(memberName); - //System.err.println("Relationship for " + tagName + " member " + memberName + - // " is " + (membership == null ? null : membership.getRelationshipType())); - if(membership != null && membership.getRelationshipType() == Central.iHAS){ - filterList.add(getXPtr(member)); - if(!hasHAS){ - hasHAS = Boolean.TRUE; - } - } - } + FilterSearch filter = filterHistory.get(getCurrentURL()); + filterableNodes = DataUtils.findFilteredNodes(getCurrentDoc(), filter, filterableNodes, filteredData, jobXPtrs, + currentSelectedData, currentSelectionXPath, apply); + + if((!apply || filter == null || filter.getFilterRegex().toString().length() == 0) && firstDocRendering){ + // Show whole doc if no filter or if filter is blank, so nothing to do here + firstDocRendering = false; } - return hasHAS; + // apply gray out in the document display, or need to cleanup previous state even if no filter now + else{ + displayFilterEffect(); + } } - // Recursively ascend the DOM tree and find out our place in its branching structure - private String getXPtr(Node n){ - if(n == null || n instanceof Document){ - return ""; - } - Node parent = n.getParentNode(); - if(parent == null && n instanceof Attr){ - parent = ((Attr) n).getOwnerElement(); - } - - NodeList children = parent.getChildNodes(); - int nonElementCnt = 0; - for(int i = 0; i < children.getLength(); i++){ - if(!(children.item(i) instanceof Element)){ - nonElementCnt++; - continue; - } - if(n == children.item(i)){ - return getXPtr(parent)+"/"+(i-nonElementCnt+1); - } - } - return null; - } /** * Gray out parts of the HTML view if they are part of the filtered data. @@ -1681,7 +1527,7 @@ // Gray out the mismatched textual data for(Map.Entry dataToFilter: filteredData.entrySet()){ - //System.err.println("Filtering "+dataToFilter.getKey()); + System.err.println("Filtering "+dataToFilter.getKey()); javax.swing.text.AbstractDocument.AbstractElement htmlDiv = (javax.swing.text.AbstractDocument.AbstractElement) d.getElement(dataToFilter.getKey()); if(htmlDiv == null){ @@ -1998,4 +1844,5 @@ public void lostOwnership(Clipboard clipboard, Transferable contents){ //System.err.println("Lost clipboard ownership"); } + } =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/09 15:55:48 1.17 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/14 22:02:04 1.18 @@ -1,11 +1,11 @@ package ca.ucalgary.seahawk.gui; import ca.ucalgary.seahawk.services.MobyClient; -import ca.ucalgary.seahawk.util.HTMLUtils; -import ca.ucalgary.seahawk.util.SeahawkOptions; +import ca.ucalgary.seahawk.util.*; import org.biomoby.shared.*; import org.biomoby.shared.data.*; +import org.biomoby.shared.parser.MobyTags; import org.biomoby.client.CentralImpl; import org.biomoby.client.MobyRequest; import org.biomoby.client.MobyRequestEventHandler; @@ -182,6 +182,7 @@ return handler; } + // synchronized so simultaneous requests don't get their input data mixed up public void setupServiceSecondaryData(MobyRequestEventHandler handler){ MobyDataInstance[] castInputs = new MobyDataInstance[primaryInput.length]; for(int i = 0; i < primaryInput.length; i++){ @@ -194,14 +195,17 @@ castInputs[i] = (MobyDataInstance) primaryInput[i]; } - try{ - mobyRequest.setInput(castInputs); - mobyRequest.setSecondaryInput(secondaryInputInstances); - } catch(MobyException me){ - me.printStackTrace(); - logger.warn("Error while trying to set service input: " + me); - } - executeService(handler); + // code from mobyRequest.setInput() to executeService() should always be synced to avoid input mixup between requests + synchronized(mobyRequest){ + try{ + mobyRequest.setInput(castInputs); + mobyRequest.setSecondaryInput(secondaryInputInstances); + } catch(MobyException me){ + me.printStackTrace(); + logger.warn("Error while trying to set service input: " + me); + } + executeService(handler); + } } protected void setupService(MobyService mobyService, MobyDataInstance mdi, int handlerHashCode, boolean useDefaultSecondaries){ @@ -217,18 +221,21 @@ System.arraycopy(primaryInputTemplate, 0, primaryInput, 0, primaryInput.length); if(!hasSecondaryInput(mobyService)){ - try{ - // Implement simple input (i.e. only one input argument) - mobyRequest.setInput(mdi, ""); - } - catch(MobyException me){ - logger.error("Failure in MOBY input, was not acceptable:" + me); - return; - } + // code from mobyRequest.setInput() to executeService() should always be synced to avoid input mixup between requests + synchronized(mobyRequest){ + try{ + // Implement simple input (i.e. only one input argument) + mobyRequest.setInput(mdi, ""); + } + catch(MobyException me){ + logger.error("Failure in MOBY input, was not acceptable:" + me); + return; + } - // No need for further info, just launch the request - removePopupOptions(); - executeService(getHandlerByHashCode(handlerHashCode)); + // No need for further info, just launch the request + removePopupOptions(); + executeService(getHandlerByHashCode(handlerHashCode)); + } } else{ // We need more info from the user to launch this service @@ -502,7 +509,8 @@ class OptionLoaderThread extends Thread{ Node targetNode = null; MobyRequestEventHandler handler = null; - MobyDataInstance mobyData = null; + MobyPayloadRequestListener payloadCreator = null; + Object mobyData = null; String extraMenuText = null; JPopupMenu popupList; @@ -513,11 +521,13 @@ this.handler = handler; } - public OptionLoaderThread(MobyDataInstance mobyData, JPopupMenu popupList, MobyRequestEventHandler handler, String extraMenuText){ + public OptionLoaderThread(Object mobyData, JPopupMenu popupList, MobyRequestEventHandler handler, + MobyPayloadRequestListener payloadCreator, String extraMenuText){ super(); this.mobyData = mobyData; this.popupList = popupList; this.handler = handler; + this.payloadCreator = payloadCreator; this.extraMenuText = extraMenuText; } @@ -526,7 +536,7 @@ addPopupOptions(targetNode, popupList, false, handler); } else if(mobyData != null){ - addPopupOptions(mobyData, popupList, false, handler, extraMenuText); + addPopupOptions(mobyData, popupList, false, handler, payloadCreator, extraMenuText); } else{ logger.warn("Warning: OptionLoaderThread has no data to work with"); @@ -576,6 +586,30 @@ } /** + * Creates a menu item based on the provided data type. If a service is selected from here, + * a callback will be made to the MobyPayloadRequestListener for the actual submission data. + * + * @param payloadKey a key that will be used in the callback so the listener knows what payload the create + */ + public void addPopupOptions(MobyDataType mobyDataType, JPopupMenu popupList, boolean asynchronous, + MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, + String payloadKey, String extraMenuText){ + addPopupOptions(mobyDataType, popupList, asynchronous, handler, payloadCreator, extraMenuText); + } + + public void addPopupOptions(MobyNamespace mobyNamespace, JPopupMenu popupList, boolean asynchronous, + MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, + String payloadKey, String extraMenuText){ + addPopupOptions(mobyNamespace, popupList, asynchronous, handler, payloadCreator, extraMenuText); + } + + public void addPopupOptions(MobyPrimaryDataSet collection, JPopupMenu popupList, boolean asynchronous, + MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, + String payloadKey, String extraMenuText){ + addPopupOptions(collection, popupList, asynchronous, handler, payloadCreator, extraMenuText); + } + + /** * Same as three arg addPopupOptions, but uses default response handler */ public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous){ @@ -586,13 +620,16 @@ * Find the list of available services querying MobyCentral directly with a piece of data. */ public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous, MobyRequestEventHandler handler){ - addPopupOptions(mobyData, popupList, asynchronous, handler, null); + addPopupOptions(mobyData, popupList, asynchronous, handler, null, null); } /** * Find the list of available services querying MobyCentral directly with a piece of data. + * + * @param mobyData a MobyDataInstance, or in the case of deferred data to be created by payloadCreator, a MobyDataType, MobyNamespace, or MobyPrimaryDataSet */ - public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous, MobyRequestEventHandler handler, String extraMenuText){ + public void addPopupOptions(Object mobyData, JPopupMenu popupList, boolean asynchronous, + MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, String extraMenuText){ if(asynchronous){ //Show the user that we're doing something... @@ -605,7 +642,7 @@ } // Call this method synchronously in a different thread - OptionLoaderThread lt = new OptionLoaderThread(mobyData, popupList, handler, extraMenuText); + OptionLoaderThread lt = new OptionLoaderThread(mobyData, popupList, handler, payloadCreator, extraMenuText); lt.start(); return; } @@ -625,7 +662,9 @@ popupList.setVisible(true); } - addClipboardItem(submenu, mobyData); + if(mobyData instanceof MobyDataInstance){ + addClipboardItem(submenu, (MobyDataInstance) mobyData); + } submenu.add(getWaitItem(submenu)); MobyDataServiceAssocInstance serviceAssocObject = null; @@ -637,6 +676,15 @@ else if(mobyData instanceof MobyDataObject){ serviceAssocObject = mobyClient.getServices((MobyDataObject) mobyData); } + // The data will be loaded later + else if(payloadCreator != null){ + if(mobyData instanceof MobyPrimaryDataSet){ + //serviceAssocObject = mobyClient.getServices(new MobyDataObjectSetDeferred(mobyData, payloadCreator, requestKey)); + } + else{ + //serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred(mobyData, payloadCreator, requestKey)); + } + } else{ logger.warn("Service options for objects other than MobyDataObject " + "and MobyDataObjectSet are not yet supported."); @@ -1136,51 +1184,50 @@ return menu; } - public JMenu createObjectSubMenu(MobyDataInstance mdi, String extraMenuText){ - if(!(mdi instanceof MobyPrimaryData)){ - logger.warn("Ignoring non-primary data object submitted to menu creation: " + mdi); - return null; - } - - MobyPrimaryData targetData = (MobyPrimaryData) mdi; - String id = targetData.getId(); - if(id == null){ - id = ""; - } - else if(id.length() > MAX_ID_LEN+3){ - id = id.substring(0, MAX_ID_LEN)+"..."; - } - - MobyDataType mobyDataType = targetData.getDataType(); - String name = null; - if(mobyDataType == null){ - logger.warn("PG: Warning: no datatype associated with service " + - targetData.getName()); - } - else{ - name = mobyDataType.getName(); - } - if("Object".equals(name)){ - MobyNamespace namespaces[] = targetData.getNamespaces(); - //System.err.println("Got base object with namespaces numbering " + namespaces.length); - if(namespaces != null && namespaces.length > 0 && namespaces[0] != null){ - //System.err.println("Checking namespace "+ namespaces[0].getName()); - name = namespaces[0].getName(); + /** + * Template object may be one of MobyPrimaryData, or in case of deferred content loading a + * MobyNamespace, MobyDataType, or MobyPrimaryDataSet. + */ + public JMenu createObjectSubMenu(Object templateObject, String extraMenuText){ + String id = null; + MobyDataType mobyDataType = null; + String name = null; + MobyNamespace[] namespaces = null; + if(templateObject instanceof MobyPrimaryData){ + MobyPrimaryData targetData = (MobyPrimaryData) templateObject; + mobyDataType = targetData.getDataType(); + namespaces = targetData.getNamespaces(); + id = targetData.getId(); + if(id == null){ + id = ""; } - } - else{ - //System.err.println("Got complex object with datatype name " + name); - } + else if(id.length() > MAX_ID_LEN+3){ + id = id.substring(0, MAX_ID_LEN)+"..."; + } + if(MobyTags.MOBYOBJECT.equals(mobyDataType.getName()) && + namespaces != null && namespaces.length > 0 && namespaces[0] != null){ + name = namespaces[0].getName(); + } + else{ + name = mobyDataType.getName(); + } + } + else if(templateObject instanceof MobyNamespace){ + namespaces = new MobyNamespace[]{(MobyNamespace) templateObject}; + mobyDataType = MobyDataType.getDataType(MobyTags.MOBYOBJECT, SeahawkOptions.getRegistry()); + name = ((MobyNamespace) templateObject).getName(); + } + else if(templateObject instanceof MobyDataType){ + mobyDataType = (MobyDataType) templateObject; + name = ((MobyDataType) templateObject).getName(); + } + else{ + logger.error("Could not create submenu for object of unaccepted type "+templateObject.getClass().getName()); + } - // Make sure we have a fully documented data type object - mobyDataType = MobyDataType.getDataType(targetData.getDataType().getName(), SeahawkOptions.getRegistry()); String desc = null; String datatype = null; - if(mobyDataType == null){ - logger.warn("PG: Warning (submenu): no datatype associated with service " + - targetData.getName()); - } - else{ + if(mobyDataType != null){ datatype = mobyDataType.getName(); desc = mobyDataType.getDescription(); if(desc == null || desc.length() == 0){ @@ -1189,19 +1236,12 @@ } if(datatype != null && datatype.indexOf("objectclass:") != -1){ //LSID type URN, truncate the prefix and keep the part a user would care about (last part, the class name) - datatype = datatype.substring(datatype.indexOf("objectclass:")+12); } JMenu submenu = null; - MobyNamespace[] namespaces = targetData.getNamespaces(); // If not defined, derive a description from the Data Namespace - if(mobyDataType == null){ - desc = "Unknown datatype"; - submenu = new JMenu("Services for unknown datatype"); - assignMenuDataIndex(submenu); - } - else if("Object".equals(mobyDataType.getName())){ + if(MobyTags.MOBYOBJECT.equals(mobyDataType.getName())){ String mobydesc = "?"; if(namespaces != null){ // Take the longest description @@ -1214,20 +1254,30 @@ } } desc = "Record Identifier - " + mobydesc; - submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+datatype + ":" + id); + if(templateObject instanceof MobyDataObjectSet){ + datatype += " collection"; + } + submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ") + + datatype + (id == null ? "" : ":" + id)+""); assignMenuDataIndex(submenu); } - else if("String".equals(mobyDataType.getName())){ - String sample = targetData.getName(); - if(sample == null){ - sample = targetData.toString(); + else if(MobyTags.MOBYSTRING.equals(mobyDataType.getName())){ + String sample = ""; + if(templateObject instanceof MobyDataInstance){ + sample = ((MobyDataInstance) templateObject).getName(); + if(sample == null){ + sample = "\""+((MobyDataInstance) templateObject).toString()+"\""; + } + } + if(templateObject instanceof MobyDataObjectSet){ + sample += " collection"; } if(sample.length() > MAX_ID_LEN+3){ - sample = sample.substring(0, MAX_ID_LEN)+"..."; + sample = "\""+sample.substring(0, MAX_ID_LEN)+"...\""; } desc = "A piece of text"; - submenu = new JMenu("Services for "+(extraMenuText == null ? "" : extraMenuText+" ")+ - "String \"" + sample + "\""); + submenu = new JMenu("Services for "+(extraMenuText == null ? "" : extraMenuText+" ")+ + "String " + sample+""); assignMenuDataIndex(submenu); } // Complex object @@ -1240,17 +1290,18 @@ desc += "["+namespaceDesc+"]"; } } - if(targetData instanceof MobyDataObject && id != null && id.length() > 0){ + if(templateObject instanceof MobyDataObject && id != null && id.length() > 0){ objectLabel += ":" + id; } - else if(targetData instanceof MobyDataObjectSet){ + else if(templateObject instanceof MobyDataObjectSet){ objectLabel += " collection"; } - submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+objectLabel); + submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+objectLabel+""); assignMenuDataIndex(submenu); } desc = "Input data: " + desc; desc = HTMLUtils.htmlifyToolTipText(desc, MAX_SERVICE_DESC_LEN); + System.err.println("New submenu has label " + submenu.getText()); submenu.setToolTipText(desc); submenu.setName(SERVICE_SUBMENU_NAME); return submenu; From gordonp at dev.open-bio.org Wed Apr 14 19:48:28 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Wed, 14 Apr 2010 19:48:28 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004142348.o3ENmSDf009599@dev.open-bio.org> gordonp Wed Apr 14 19:48:27 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv9535/src/main/ca/ucalgary/seahawk/util Modified Files: MobyPayloadRequestListener.java Added Files: MobyContentCreator.java MobyDataObjectDeferred.java MobyDataObjectSetDeferred.java Log Message: Additional commit related to initial implementation 'for each' in Seahawk service invocation moby-live/Java/src/main/ca/ucalgary/seahawk/util MobyContentCreator.java,NONE,1.1 MobyDataObjectDeferred.java,NONE,1.1 MobyDataObjectSetDeferred.java,NONE,1.1 MobyPayloadRequestListener.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/MobyPayloadRequestListener.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/seahawk/util/MobyPayloadRequestListener.java 2010/04/14 22:02:04 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/MobyPayloadRequestListener.java 2010/04/14 23:48:27 1.2 @@ -10,7 +10,10 @@ */ public interface MobyPayloadRequestListener{ /** - * @param requestKey the value given to the caller when the listener was registered (tells the listener what payload to create baesd on some internal naming convention for the listener) + * Assumes the listener knows what payload to create based on some internal context stored by the listener. + * (i.e. you need to create a new listener specific to each deferred payload. + * + * @param paramNameforJobs the name of the moby job parameter to which each value should be assigned */ - public org.biomoby.shared.data.MobyContentInstance createPayload(String requestKey, String paramNameforJobs); + public org.biomoby.shared.data.MobyContentInstance createPayload(String paramNameforJobs); } From gordonp at dev.open-bio.org Wed Apr 14 19:48:27 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Wed, 14 Apr 2010 19:48:27 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004142348.o3ENmRar009579@dev.open-bio.org> gordonp Wed Apr 14 19:48:27 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv9535/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java MobyPayloadCreator.java MobyServicesGUI.java Log Message: Additional commit related to initial implementation 'for each' in Seahawk service invocation moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.27,1.28 MobyPayloadCreator.java,1.1,1.2 MobyServicesGUI.java,1.18,1.19 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/14 22:02:04 1.27 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/14 23:48:27 1.28 @@ -1215,7 +1215,6 @@ // chooses the for each option. The Moby data instance's userData gives us the current context, enabling us // to construct the correct payload in MobyPayloadCreator.createPayload() at any point in the future. String origUserData = (String) mobyData.getUserData(); - MobyPayloadRequestListener payloadCreator = new MobyPayloadCreator(this); for(String peerMode: new String[]{DataUtils.ARTICLE_PEERS_MODE, DataUtils.DATATYPE_PEERS_MODE}){ // note that getPeerElements() will modify the userData to reflect the semantic of the requested peer mode mobyData.setUserData(origUserData); @@ -1229,17 +1228,20 @@ } MobyDataType dataType = ((MobyPrimaryData) mobyData).getDataType(); if(mobyData instanceof MobyPrimaryDataSet){ // Collection - servicesGUI.addPopupOptions((MobyPrimaryDataSet) mobyData, popup, true, getDefaultHandler(), payloadCreator, - (String) mobyData.getUserData(), each); + servicesGUI.addPopupOptions((MobyPrimaryDataSet) mobyData, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); } else if(MobyTags.MOBYOBJECT.equals(dataType.getName())){ MobyNamespace namespace = null; - servicesGUI.addPopupOptions(namespace, popup, true, getDefaultHandler(), payloadCreator, - (String) mobyData.getUserData(), each); + servicesGUI.addPopupOptions(namespace, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); } else{ - servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), payloadCreator, - (String) mobyData.getUserData(), each); + servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); } } @@ -1301,7 +1303,7 @@ // 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"); + servicesGUI.addPopupOptions(previousMDI, popup, true, null, null, "previous input"); } } catch(Exception e){ logger.warn("Could not load previous service info, 'previous input' option will not be displayed", e); =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.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/seahawk/gui/MobyPayloadCreator.java 2010/04/14 22:02:04 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/14 23:48:27 1.2 @@ -14,14 +14,16 @@ */ public class MobyPayloadCreator implements MobyPayloadRequestListener{ private MobyContentPane srcPane; + private String requestKey; private static Logger logger = Logger.getLogger(MobyPayloadCreator.class.getName()); - public MobyPayloadCreator(MobyContentPane pane){ + public MobyPayloadCreator(MobyContentPane pane, String requestKey){ srcPane = pane; + this.requestKey = requestKey; } - public MobyContentInstance createPayload(String requestKey, String targetJobArgName){ + public MobyContentInstance createPayload(String targetJobArgName){ // The request key is the sample data's app context: // url#xpath sample_xptr filter_regex filter_xpath xpath_desc case_sensitive_boolean inverse selection // from which we will build the peer dataset to submit. =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/14 22:02:04 1.18 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/14 23:48:27 1.19 @@ -586,30 +586,6 @@ } /** - * Creates a menu item based on the provided data type. If a service is selected from here, - * a callback will be made to the MobyPayloadRequestListener for the actual submission data. - * - * @param payloadKey a key that will be used in the callback so the listener knows what payload the create - */ - public void addPopupOptions(MobyDataType mobyDataType, JPopupMenu popupList, boolean asynchronous, - MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, - String payloadKey, String extraMenuText){ - addPopupOptions(mobyDataType, popupList, asynchronous, handler, payloadCreator, extraMenuText); - } - - public void addPopupOptions(MobyNamespace mobyNamespace, JPopupMenu popupList, boolean asynchronous, - MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, - String payloadKey, String extraMenuText){ - addPopupOptions(mobyNamespace, popupList, asynchronous, handler, payloadCreator, extraMenuText); - } - - public void addPopupOptions(MobyPrimaryDataSet collection, JPopupMenu popupList, boolean asynchronous, - MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, - String payloadKey, String extraMenuText){ - addPopupOptions(collection, popupList, asynchronous, handler, payloadCreator, extraMenuText); - } - - /** * Same as three arg addPopupOptions, but uses default response handler */ public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous){ @@ -678,16 +654,32 @@ } // The data will be loaded later else if(payloadCreator != null){ - if(mobyData instanceof MobyPrimaryDataSet){ - //serviceAssocObject = mobyClient.getServices(new MobyDataObjectSetDeferred(mobyData, payloadCreator, requestKey)); - } - else{ - //serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred(mobyData, payloadCreator, requestKey)); - } + try{ + if(mobyData instanceof MobyPrimaryDataSet){ + serviceAssocObject = mobyClient.getServices(new MobyDataObjectSetDeferred((MobyPrimaryDataSet) mobyData, + payloadCreator)); + } + else if(mobyData instanceof MobyNamespace){ + serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyNamespace) mobyData, + payloadCreator)); + } + else if(mobyData instanceof MobyDataType){ + serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyDataType) mobyData, + payloadCreator)); + } + else{ + logger.warn("Ignoring unrecognized template class (" + mobyData.getClass().getName()+ + ") for deferred data creation by a MobyPayloadRequestListener"); + return; + } + } catch(Exception e){ + logger.error("Could not create deferred Moby data object", e); + } } else{ logger.warn("Service options for objects other than MobyDataObject " + - "and MobyDataObjectSet are not yet supported."); + "and MobyDataObjectSet are not yet supported unless you " + + "have defined a MobyPayloadRequestListener."); return; } } catch(Exception mobye){ From gordonp at dev.open-bio.org Thu Apr 15 14:51:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Thu, 15 Apr 2010 14:51:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004151851.o3FIpHrB006441@dev.open-bio.org> gordonp Thu Apr 15 14:51:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data In directory dev.open-bio.org:/tmp/cvs-serv6403/src/main/org/biomoby/shared/data Modified Files: MobyContentInstance.java Log Message: Made contents maintain insertion order by switching to LinkedHashMap for underlying Map storage moby-live/Java/src/main/org/biomoby/shared/data MobyContentInstance.java,1.14,1.15 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyContentInstance.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyContentInstance.java 2008/01/14 22:54:19 1.14 +++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyContentInstance.java 2010/04/15 18:51:17 1.15 @@ -31,7 +31,7 @@ private String serviceAuthURI = null; private String serviceNotes = null; private int xmlMode = MobyDataInstance.SERVICE_XML_MODE; - private HashMap members; + private LinkedHashMap members; private int autoID = 1; // to name members without existing names private Vector exceptions; @@ -40,7 +40,7 @@ * Useful if you are a client composing a query, or a server composing a response. */ public MobyContentInstance(){ - members = new HashMap(); + members = new LinkedHashMap(); exceptions = new Vector(); } @@ -106,7 +106,7 @@ } } - members = new HashMap(); + members = new LinkedHashMap(); // If we got this far, we're in the clear for the single envelope // What we need to parse now is the one or more sets of data in the envelope From gordonp at dev.open-bio.org Fri Apr 16 13:29:21 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 13:29:21 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161729.o3GHTLfE014979@dev.open-bio.org> gordonp Fri Apr 16 13:29:21 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/client In directory dev.open-bio.org:/tmp/cvs-serv14943/src/main/org/biomoby/client Modified Files: MobyRequest.java Log Message: Fixed javadoc typo moby-live/Java/src/main/org/biomoby/client MobyRequest.java,1.46,1.47 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/MobyRequest.java,v retrieving revision 1.46 retrieving revision 1.47 diff -u -r1.46 -r1.47 --- /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/MobyRequest.java 2010/03/29 20:42:48 1.46 +++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/MobyRequest.java 2010/04/16 17:29:21 1.47 @@ -238,7 +238,7 @@ /** * This method will assign the provided secondary parameters to all primary input data currently - * in this object. This is covenient if you are running 100 seqs through BLAST and only want to set + * in this object. This is convenient if you are running 100 seqs through BLAST and only want to set * the parameters once. If you instead want to set secondary input differently for all primary inputs, you'll * need to create a custom MobyContentInstance as input to setInput(). * From gordonp at dev.open-bio.org Fri Apr 16 13:32:33 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 13:32:33 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161732.o3GHWXGF015279@dev.open-bio.org> gordonp Fri Apr 16 13:32:33 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services In directory dev.open-bio.org:/tmp/cvs-serv15243/src/main/ca/ucalgary/seahawk/services Modified Files: MobyClient.java Log Message: Implemented proper logging, account for deferred data objects moby-live/Java/src/main/ca/ucalgary/seahawk/services MobyClient.java,1.26,1.27 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java,v retrieving revision 1.26 retrieving revision 1.27 diff -u -r1.26 -r1.27 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/11 01:58:05 1.26 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/16 17:32:33 1.27 @@ -1,6 +1,6 @@ package ca.ucalgary.seahawk.services; -import ca.ucalgary.seahawk.util.SeahawkOptions; +import ca.ucalgary.seahawk.util.*; import org.biomoby.client.*; import org.biomoby.registry.meta.*; @@ -116,8 +116,8 @@ docBuilder = dbf.newDocumentBuilder(); } catch(ParserConfigurationException pce){ - System.err.println("Error: Could not find an XML parser, will not be able to use " + - "MOBY xpath and regex mapper default behaviors: " + pce); + logger.log(Level.SEVERE, "Error: Could not find an XML parser, will not be able to use " + + "MOBY xpath and regex mapper default behaviors: ", pce); } ClassLoader cl = getClass().getClassLoader(); if(cl == null){ @@ -138,8 +138,8 @@ } if(dataMappingXMLURL == null){ if(rulesResource.length() != 0){ // if not left intentionally blank - System.err.println("Could not find MOBY data mapping resource '"+ - rulesResource+"'"); + logger.log(Level.WARNING, "Could not find MOBY data mapping resource '"+ + rulesResource+"'"); } } else{ @@ -147,7 +147,7 @@ addMappingsFromURL(dataMappingXMLURL); } catch(Exception e){ - System.err.println("Error loading default data mapping rules ("+dataMappingXMLURL+"):" + e); + logger.log(Level.SEVERE, "Error loading default data mapping rules ("+dataMappingXMLURL+")", e); e.printStackTrace(); } } @@ -198,8 +198,8 @@ */ public void addMappingsFromURL(URL u) throws Exception{ if(docBuilder == null){ - System.err.println("Asked to add data mappings from file, " + - "but no XML parser is available"); + logger.log(Level.SEVERE, "Asked to add data mappings from file, " + + "but no XML parser is available"); return; } @@ -229,13 +229,13 @@ } if(nsContext.getNamespaceURI(prefix) != null){ - System.err.println("Prefix definition for " + prefix + " already exists, ignoring new definition"); + logger.log(Level.WARNING, "Prefix definition for " + prefix + " already exists, ignoring new definition"); return; } String nsURI = e.getTextContent(); if(nsURI == null || nsURI.length() == 0){ - System.err.println("Prefix definition for " + prefix + " has a blank URI rule, ignoring"); + logger.log(Level.WARNING, "Prefix definition for " + prefix + " has a blank URI rule, ignoring"); return; } nsContext.setPrefix(nsURI, prefix); @@ -264,7 +264,7 @@ } if(!RULE_SET_TAG.equals(ruleSet.getLocalName())){ - System.err.println("Skipping unexpected top level tag " + ruleSet.getLocalName()); + logger.log(Level.WARNING, "Skipping unexpected top level tag " + ruleSet.getLocalName()); continue; } @@ -304,18 +304,18 @@ } else if(isArticleNameRule(ruleMember)){ if(articleNameString != null && articleNameString.length() != 0){ - System.err.println("Skipping unexpected article name definition node, " + - "a valid article name rule has already been " + - "created for this ruleset"); + logger.log(Level.WARNING, "Skipping unexpected article name definition node, " + + "a valid article name rule has already been " + + "created for this ruleset"); continue; } articleNameString = ruleMember.getTextContent(); } else if(isDataTypeRule(ruleMember)){ if(dataTypeString != null && dataTypeString.length() != 0){ - System.err.println("Skipping unexpected datatype definition node, " + - "a valid datatype rule has already been " + - "created for this ruleset"); + logger.log(Level.WARNING, "Skipping unexpected datatype definition node, " + + "a valid datatype rule has already been " + + "created for this ruleset"); continue; } dataTypeString = getDataType(ruleMember); @@ -328,15 +328,15 @@ } // skip any Dublin Core metadata in validation else if(!MobyPrefixResolver.DUBLIN_CORE_NAMESPACE.equals(ruleMember.getNamespaceURI())){ - System.err.println("Skipping unexpected "+RULE_SET_TAG+ - " child node " + ruleMember.getLocalName()); + logger.log(Level.WARNING, "Skipping unexpected "+RULE_SET_TAG+ + " child node " + ruleMember.getLocalName()); continue; } } if(xpathStrings.size() == 0 && regexStrings.size() == 0 && urlRegexStrings.size() == 0){ - System.err.println("Skipping namespace rule that has no xpath " + - "url_regex or regex specs associated with it"); + logger.log(Level.WARNING, "Skipping namespace rule that has no xpath " + + "url_regex or regex specs associated with it"); // Next ruleset continue; } @@ -344,9 +344,9 @@ // Simple object with just namespace & ID if(dataTypeString == null || dataTypeString.length() == 0){ if(memberMap.size() != 0){ - System.err.println("Warning: ignoring member rules, since " + - "no datatype was defined for the ruleset " + - "(base Object will be created)"); + logger.log(Level.WARNING, "Warning: ignoring member rules, since " + + "no datatype was defined for the ruleset " + + "(base Object will be created)"); } for(int j = 0; j < xpathStrings.size(); j++){ @@ -362,8 +362,8 @@ // Build complex object else{ if(memberMap.size() == 0){ - System.err.println("Complex datatype (" + dataTypeString + " was defined " + - " in the ruleset, but no members were defined"); + logger.log(Level.WARNING, "Complex datatype (" + dataTypeString + " was defined " + + " in the ruleset, but no members were defined"); } for(int j = 0; j < xpathStrings.size(); j++){ @@ -465,7 +465,7 @@ regexStrings.add(str); } else{ - System.err.println("Skipping blank regex rule"); + logger.log(Level.WARNING, "Skipping blank regex rule"); } return str; @@ -483,7 +483,7 @@ urlRegexStrings.add(str); } else{ - System.err.println("Skipping blank url_regex rule"); + logger.log(Level.WARNING, "Skipping blank url_regex rule"); } return str; @@ -501,7 +501,7 @@ xPathStrings.add(str); } else{ - System.err.println("Skipping blank XPath rule"); + logger.log(Level.WARNING, "Skipping blank XPath rule"); } return str; @@ -524,7 +524,7 @@ String memberNameKey = isPrimitiveDataType(dataTypeName) ? MobyComplexBuilder.PRIMITIVE_VALUE_SENTINEL : memTag.getAttribute(DATATYPE_RULE_ATTR); if(ruleValue == null || ruleValue.length() == 0){ - System.err.println("Object member " + memberNameKey + " has a blank value rule"); + logger.log(Level.WARNING, "Object member " + memberNameKey + " has a blank value rule"); } String memberDataTypeSetting = memTag.getAttribute(DATATYPE_ATTR); @@ -574,10 +574,10 @@ !memberWhitespaceSetting.equals(WHITESPACE_ATTR_NORMALIZE_VAL) && !memberWhitespaceSetting.equals(WHITESPACE_ATTR_STRIP_FLANKING_VAL) && !memberWhitespaceSetting.equals(WHITESPACE_ATTR_STRIP_VAL)){ - System.err.println("Object member " + memberNameKey + - " has an unrecognized value for the " + WHITESPACE_ATTR + - " attribute (" + memberWhitespaceSetting + - "), overriding with default of " + WHITESPACE_ATTR_KEEP_VAL); + logger.log(Level.WARNING, "Object member " + memberNameKey + + " has an unrecognized value for the " + WHITESPACE_ATTR + + " attribute (" + memberWhitespaceSetting + + "), overriding with default of " + WHITESPACE_ATTR_KEEP_VAL); memberWhitespaceSetting = WHITESPACE_ATTR_KEEP_VAL; } @@ -587,14 +587,14 @@ } else if(!memberEncodingSetting.equals(ENCODING_ATTR_NONE_VAL) && !memberEncodingSetting.equals(ENCODING_ATTR_BASE64_VAL)){ - System.err.println("Object member " + memberNameKey + - " has an unrecognized value for the " + ENCODING_ATTR + - " attribute, overriding with default of " + ENCODING_ATTR_NONE_VAL); + logger.log(Level.WARNING, "Object member " + memberNameKey + + " has an unrecognized value for the " + ENCODING_ATTR + + " attribute, overriding with default of " + ENCODING_ATTR_NONE_VAL); memberWhitespaceSetting = ENCODING_ATTR_NONE_VAL; } if(membersMap.containsKey(memberNameKey)){ - System.err.println("Object member " + memberNameKey + " already exists, ignoring new definition"); + logger.log(Level.WARNING, "Object member " + memberNameKey + " already exists, ignoring new definition"); return; } @@ -637,8 +637,8 @@ " cannot have empty children"); } if(namespaceStrings.containsKey(keyName)){ - System.err.println("Ignoring duplicate namespace value rule for " + - "namespace '" + keyName + "'"); + logger.log(Level.WARNING, "Ignoring duplicate namespace value rule for " + + "namespace '" + keyName + "'"); continue; } if(keyName != null && keyName.length() != 0){ @@ -649,7 +649,7 @@ } } else{ - System.err.println("Skipping unexpected "+NAMESPACE_RULE_TAG+" child node " + specName); + logger.log(Level.WARNING, "Skipping unexpected "+NAMESPACE_RULE_TAG+" child node " + specName); continue; } } @@ -716,13 +716,11 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from match:" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from match", me); } } } catch(Throwable t){ // Principally stack overflows - System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text"); - t.printStackTrace(System.err); + logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text", t); } } } @@ -765,11 +763,11 @@ // have the exact same contents as the same members who are their // subtypes, as these are superfluous. - System.err.println("Multiple Moby objects were found in the text data, " + - "but the request was to return a simple. " + - "Only the first value in the collection has been returned."); + logger.log(Level.WARNING, "Multiple Moby objects were found in the text data, " + + "but the request was to return a simple. " + + "Only the first value in the collection has been returned."); for(MobyDataObject result: results){ - System.err.println("Found object: " + result.getDataType().getName()); + logger.log(Level.WARNING, "Found object: " + result.getDataType().getName()); } // TODO: should we instead return the one deepest in the hierarchy (or with the most members)? return results.elementAt(0); @@ -818,11 +816,11 @@ // have the exact same contents as the same members who are their // subtypes, as these are superfluous. - System.err.println("Multiple Moby objects were found in the text data, " + - "but the request was to return a simple. " + - "Only the first value in the collection has been returned."); + logger.log(Level.WARNING, "Multiple Moby objects were found in the text data, " + + "but the request was to return a simple. " + + "Only the first value in the collection has been returned."); for(MobyDataObject result: results){ - System.err.println("Found object: " + result.getDataType().getName()); + logger.log(Level.WARNING, "Found object: " + result.getDataType().getName()); } // TODO: should we instead return the one deepest in the hierarchy (or with the most members)? return results.elementAt(0); @@ -916,11 +914,11 @@ // have the exact same contents as the same members who are their // subtypes, as these are superfluous. - System.err.println("Multiple Moby objects were found in the text data, " + - "but the request was to return a simple. " + - "Only the first value in the collection has been returned."); + logger.log(Level.WARNING, "Multiple Moby objects were found in the text data, " + + "but the request was to return a simple. " + + "Only the first value in the collection has been returned."); for(MobyDataObject result: results){ - System.err.println("Found object: " + result.getDataType().getName()); + logger.log(Level.WARNING, "Found object: " + result.getDataType().getName()); } // TODO: should we instead return the one deepest in the hierarchy (or with the most members)? return results.elementAt(0); @@ -994,12 +992,11 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from match:" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from match", me); } } } catch(Throwable t){ // Principally stack overflows - System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to binary data"); + logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to binary data", t); } } } @@ -1050,7 +1047,7 @@ public Map getMobyObjectsURNMap(CharSequence textData, byte[] bytes){ Map results = new HashMap(); if(regexMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any regex->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any regex->moby data mappings!"); return results; } @@ -1069,12 +1066,11 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from match (rule "+urn+"):" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from match (rule "+urn+")", me); } } }catch(Throwable t){ // Principally stack overflows - System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary"); + logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary", t); } if(urn != null && !objectVector.isEmpty()){ results.put(urn, (MobyDataObject[]) objectVector.toArray(new MobyDataObject[objectVector.size()])); @@ -1086,7 +1082,7 @@ public MobyDataObject[] getMobyObjects(CharSequence textData, byte[] bytes){ if(regexMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any regex->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any regex->moby data mappings!"); return new MobyDataObject[0]; } @@ -1109,12 +1105,11 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from match:" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from match", me); } } }catch(Throwable t){ // Principally stack overflows - System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary"); + logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary", t); } } @@ -1142,7 +1137,7 @@ public MobyDataObject[] getMobyObjects(URL url, String linkText, MobyDataType targetDataType){ if(urlRegexMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any url regex->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any url regex->moby data mappings!"); return new MobyDataObject[0]; } @@ -1171,8 +1166,7 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from url regex match:" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from url regex match", me); } } } @@ -1188,7 +1182,7 @@ // No xpaths to check if(xpathMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any xpath->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any xpath->moby data mappings!"); return new MobyDataObject[0]; } @@ -1224,8 +1218,8 @@ } }catch(XPathExpressionException xpe2){ - System.err.println( "Warning: Cannot access resulting node list "+ - "due to exception in its retrieval: " + xpe2); + logger.log(Level.WARNING, "Warning: Cannot access resulting node list "+ + "due to exception in its retrieval: ", xpe2); return new Vector(); } } @@ -1241,9 +1235,9 @@ } } else{ //not a node sequence - System.out.println("Warning: the XPath expression ("+ xpath + - ") did not return a node set, cannot select document elements."+ - " The returned object was of type "+ result.getClass().getName() ); + logger.log(Level.WARNING, "Warning: the XPath expression ("+ xpath + + ") did not return a node set, cannot select document elements."+ + " The returned object was of type "+ result.getClass().getName() ); return new Vector(); } } @@ -1253,8 +1247,8 @@ //xpe.printStackTrace(); return new Vector(); }catch(MobyException me){ - System.err.println("Warning: Cannot create objects from select nodes due " + - " to exception in MOBY logic:" + me); + logger.log(Level.WARNING, "Warning: Cannot create objects from select nodes due " + + " to exception in MOBY logic:", me); return new Vector(); } @@ -1270,7 +1264,7 @@ // No xpaths to check if(xpathMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any xpath->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any xpath->moby data mappings!"); return results; } @@ -1340,14 +1334,24 @@ } if(mdos[i] instanceof MobyDataObject){ - mobyDataServiceAssocInstances[i] = new MobyDataObjectSAI((MobyDataObject) mdos[i], mService); + if(mdos[i] instanceof MobyDataObjectDeferred){ + mobyDataServiceAssocInstances[i] = new MobyDataObjectDeferredSAI((MobyDataObjectDeferred) mdos[i], mService); + } + else{ + mobyDataServiceAssocInstances[i] = new MobyDataObjectSAI((MobyDataObject) mdos[i], mService); + } } else if(mdos[i] instanceof MobyDataObjectSet){ - mobyDataServiceAssocInstances[i] = new MobyDataObjectSetSAI((MobyDataObjectSet) mdos[i], mService); + if(mdos[i] instanceof MobyDataObjectSetDeferred){ + mobyDataServiceAssocInstances[i] = new MobyDataObjectSetDeferredSAI((MobyDataObjectSetDeferred) mdos[i], mService); + } + else{ + mobyDataServiceAssocInstances[i] = new MobyDataObjectSetSAI((MobyDataObjectSet) mdos[i], mService); + } } else{ logger.log(Level.WARNING, "MobyClient could not handle service-associating an instance of " + mdos[i].getClass()); - System.err.println("MobyClient could not handle service-associating an instance of " + mdos[i].getClass()); + //System.err.println("MobyClient could not handle service-associating an instance of " + mdos[i].getClass()); } } return mobyDataServiceAssocInstances; @@ -1363,7 +1367,7 @@ public void addRegexMapping(String regexp, String[] mobyObj, String articleName, String urn){ //mobyObj<--mobyNamespaces if(mobyObj == null){ - System.err.println("Ignoring empty namespace-only regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only regex rule mappings"); return; } @@ -1377,7 +1381,7 @@ public void addURLRegexMapping(String url_regexp, String[] mobyObj, String articleName, String urn){ //mobyObj<--mobyNamespaces if(mobyObj == null){ - System.err.println("Ignoring empty namespace-only url regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only url regex rule mappings"); return; } @@ -1466,7 +1470,7 @@ protected void addRegexMapping(String regexp, Map nsRules, String articleName, String ruleName, String urn){ //nsRules = Map if(nsRules == null || nsRules.size() == 0){ - System.err.println("Ignoring empty namespace-only regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only regex rule mappings"); return; } @@ -1475,7 +1479,7 @@ protected void addURLRegexMapping(String url_regexp, Map url_nsRules, String articleName, String urn){ //nsRules = Map if(url_nsRules == null || url_nsRules.size() == 0){ - System.err.println("Ignoring empty namespace-only url regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only url regex rule mappings"); return; } @@ -1517,8 +1521,8 @@ if(memberRelationship.getRelationshipType() == Central.iHAS){ String[] rule = membersMap.get(memberRelationship.getName()); if(rule == null){ - System.err.println("Skipping HAS member "+memberRelationship.getName() + - " without an explicit rule (may be defined by inheritance?)"); + logger.log(Level.WARNING, "Skipping HAS member "+memberRelationship.getName() + + " without an explicit rule (may be defined by inheritance?)"); continue; } Pattern pattern = Pattern.compile(newRegexp, Pattern.DOTALL | Pattern.COMMENTS); @@ -1527,8 +1531,8 @@ if(captured.containsKey(i)){ //autoboxed int // Already encapsulated the capture group due to another // HAS member, don't need to add anything - System.err.println("Skipping processing of capture group "+i+ - ", it's already been processed by another member in this rule"); + logger.log(Level.WARNING, "Skipping processing of capture group "+i+ + ", it's already been processed by another member in this rule"); continue; } if(rule[0].matches("^.*\\$"+i+"(?=\\D.*|\\z)")){ @@ -1614,9 +1618,7 @@ } }catch(Exception e){ - System.err.println("Could not create regular expression statement from '" + - regexp + "': " + e); - e.printStackTrace(); + logger.log(Level.SEVERE, "Could not create regular expression statement from '" + regexp + "'", e); } } @@ -1651,15 +1653,15 @@ builderNameMap.put(urn, mcb); } }catch(Exception e){ - System.err.println("Could not create URL regular expression statement from '" + - url_regexp + "': " + e); + logger.log(Level.SEVERE, "Could not create URL regular expression statement from '" + + url_regexp + "': " + e); e.printStackTrace(); } } public void addXPathMapping(String xpath, String[] mobyObj){ //mobyObj<--mobyNamespaces if(mobyObj == null){ - System.err.println("Ignoring empty namespace-only regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only regex rule mappings"); return; } @@ -1707,10 +1709,7 @@ }catch(Exception e){ logger.log(Level.WARNING, "Could not create XPath select statement from '" + - xpath_exp + "': " + e.getMessage()); - System.err.println("Could not create XPath select statement from '" + - xpath_exp + "': " + e); - + xpath_exp + "': ", e); } } @@ -1773,8 +1772,8 @@ else if(line.indexOf("\t") == 0){ String[] fields = line.trim().split(","); if(fields.length != 2){ - System.err.println("Unrecognized line (not 2 comma delimited fields) " + - "from ValidateService: " + line.trim()); + logger.log(Level.WARNING, "Unrecognized line (not 2 comma delimited fields) " + + "from ValidateService: " + line.trim()); } else if(fields[1].equals("true")){ // service is okay, don't add to dead map @@ -1783,8 +1782,8 @@ isDeadMap.put(currentAuthority+":"+fields[0], "dead"); } else{ - System.err.println("Unrecognized line (second field not 'true' or 'false') " + - "from ValidateService: " + line.trim()); + logger.log(Level.WARNING, "Unrecognized line (second field not 'true' or 'false') " + + "from ValidateService: " + line.trim()); } } } From gordonp at dev.open-bio.org Fri Apr 16 13:33:26 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 13:33:26 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161733.o3GHXQBs015331@dev.open-bio.org> gordonp Fri Apr 16 13:33:25 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv15287/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java MobyPayloadCreator.java MobyServicesGUI.java Log Message: First fully functional version of 'for each' service invocation in Seahawk moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.28,1.29 MobyPayloadCreator.java,1.2,1.3 MobyServicesGUI.java,1.19,1.20 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.28 retrieving revision 1.29 diff -u -r1.28 -r1.29 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/14 23:48:27 1.28 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/16 17:33:25 1.29 @@ -1175,9 +1175,23 @@ String docFragID = targetURL.getRef(); // We store the xpath in the anchor part of the URL - // Complex case, load the doc fragment from the MOBY XML source file + // Complex case, load the doc fragment from the MOBY XML source file + // where the targetURL is url#xptr with xptr like /1/2/1/1 if(docFragID != null && docFragID.length() > 0 && !targetURL.getHost().equals("moby")){ - return DataUtils.loadMobyDataFromXPointer(targetURL, filteredData, filterHistory.get(getCurrentURL())); + URL currentURL = null; + try{currentURL = new URL(targetURL.toString().replaceAll("#"+targetURL.getRef(), ""));} + catch(Exception e){ + logger.error("Couldn't extract referenceless URL from " + targetURL, e); + } + // refers to currently loaded doc + if(currentURL.equals(getCurrentURL())){ + return DataUtils.loadMobyDataFromXPointer(currentURL, getCurrentDoc(), docFragID, + filteredData, filterHistory.get(getCurrentURL())); + } + // refers to another moby doc, let DataUtils resolve the doc for us + else{ + return DataUtils.loadMobyDataFromXPointer(targetURL, filteredData, filterHistory.get(getCurrentURL())); + } } // Simple case, build the object using the values encoded in the URL itself. @@ -1218,7 +1232,7 @@ for(String peerMode: new String[]{DataUtils.ARTICLE_PEERS_MODE, DataUtils.DATATYPE_PEERS_MODE}){ // note that getPeerElements() will modify the userData to reflect the semantic of the requested peer mode mobyData.setUserData(origUserData); - NodeList peerElements = DataUtils.getPeerElements(getCurrentDoc(), mobyData, peerMode); + NodeList peerElements = DataUtils.getPeerElements(getCurrentDoc(), mobyData, getFilteredData(), peerMode); if(peerElements.getLength() <= 1){ continue; // no 'for each' option if only one to process... } @@ -1227,21 +1241,33 @@ each += " '"+mobyData.getName()+"'"; } MobyDataType dataType = ((MobyPrimaryData) mobyData).getDataType(); + MobyNamespace[] namespaces = ((MobyPrimaryData) mobyData).getNamespaces(); if(mobyData instanceof MobyPrimaryDataSet){ // Collection servicesGUI.addPopupOptions((MobyPrimaryDataSet) mobyData, popup, true, getDefaultHandler(), new MobyPayloadCreator(this, (String) mobyData.getUserData()), each); } else if(MobyTags.MOBYOBJECT.equals(dataType.getName())){ - MobyNamespace namespace = null; - servicesGUI.addPopupOptions(namespace, popup, true, getDefaultHandler(), - new MobyPayloadCreator(this, (String) mobyData.getUserData()), - each); + if(namespaces != null && namespaces.length > 0){ + servicesGUI.addPopupOptions(namespaces[0], popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); + } + //else base object wth no namespace...useless! } else{ - servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), - new MobyPayloadCreator(this, (String) mobyData.getUserData()), - each); + // A non-base object, with a namespace too + if(namespaces != null && namespaces.length > 0){ + ((MobyPrimaryDataSimple) mobyData).setId(""); //anonymize + servicesGUI.addPopupOptions((MobyPrimaryDataSimple) mobyData, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); + } + else{ //just the data type useful + servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); + } } } @@ -1286,13 +1312,21 @@ if(getFilter() == null){ return; } + String[] userData = mdi.getUserData() == null ? null : + mdi.getUserData().toString().split("\t"); + // second user data arg is + Node mdiNode = userData == null || userData.length < 2 ? null : + XPointerResolver.getNodeFromXPointer(getCurrentDoc(), userData[1]); //System.err.println("Should create a previous input menu item for " + mdi.getUserData()); try{ Document srcDoc = DataUtils.docBuilder.parse(srcURL.openStream()); + //System.err.println("Context node is "+mdiNode+ " from user data" + mdi.getUserData()); // Get the input data for the *previous* service - MobyDataJob inputData = DataUtils.getInputSample(srcDoc, SeahawkOptions.getRegistry()); + MobyDataJob inputData = DataUtils.getInputSample(srcDoc, + DataUtils.findMobyJobName(mdiNode), + SeahawkOptions.getRegistry()); if(inputData == null){ // should only happen if Moby XML was loaded manually by a user, otherwise we've recorded this info... logger.warn("No previous service info in Moby XML, 'previous input' option will not be displayed"); @@ -1529,7 +1563,7 @@ // Gray out the mismatched textual data for(Map.Entry dataToFilter: filteredData.entrySet()){ - System.err.println("Filtering "+dataToFilter.getKey()); + //System.err.println("Filtering "+dataToFilter.getKey()); javax.swing.text.AbstractDocument.AbstractElement htmlDiv = (javax.swing.text.AbstractDocument.AbstractElement) d.getElement(dataToFilter.getKey()); if(htmlDiv == null){ =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.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/seahawk/gui/MobyPayloadCreator.java 2010/04/14 23:48:27 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/16 17:33:25 1.3 @@ -27,6 +27,7 @@ // The request key is the sample data's app context: // url#xpath sample_xptr filter_regex filter_xpath xpath_desc case_sensitive_boolean inverse selection // from which we will build the peer dataset to submit. + System.err.println("Request key is " + requestKey); String[] requestKeyFields = requestKey.split("\t"); String[] requestParts = requestKeyFields[0].split("#", 2); @@ -50,20 +51,24 @@ Map xptrsToFilter = new HashMap(); FilterSearch filter = null; // Was there a filter in the request? - if(requestKeyFields.length >= 6){ - filter = new FilterSearch(requestKeyFields[1], - new XPathOption(requestKeyFields[2], requestKeyFields[3]), - Boolean.parseBoolean(requestKeyFields[4]), - Boolean.parseBoolean(requestKeyFields[5])); + if(requestKeyFields.length >= 7){ + filter = new FilterSearch(requestKeyFields[2], + new XPathOption(requestKeyFields[3], requestKeyFields[4]), + Boolean.parseBoolean(requestKeyFields[5]), + Boolean.parseBoolean(requestKeyFields[6])); } Document doc = null; // Get the list of nodes to filter, using in-memory data if possible if(targetURL.equals(srcPane.getCurrentURL())){ doc = srcPane.getCurrentDoc(); - if(filter.equals(srcPane.getFilter())){ + if(filter == null){ + xptrsToFilter = null; + } + else if(filter.equals(srcPane.getFilter())){ // no need to redo the filtering, it's the current display's filtering - xptrsToFilter = srcPane.getFilteredData(); + System.err.println("Reusing current filter"); + xptrsToFilter = srcPane.getFilteredData(); } else{ // we have the doc loaded, but the filter has changed since @@ -75,44 +80,33 @@ doc = DataUtils.findFilteredNodes(targetURL, filter, xptrsToFilter); } - // Get the valid parts of the doc for forwarding. - if(!xptrsToFilter.isEmpty()){ - if(doc == srcPane.getCurrentDoc()){ - // clone, because it'll be edited below by the filter, and we don't want to mess up currentDoc... - doc = (Document) srcPane.getCurrentDoc().cloneNode(true); - } - DataUtils.filterDoc(doc, xptrsToFilter); - } + MobyDataInstance mobyDataContext = new MobyDataObject("whatever"); + mobyDataContext.setUserData(requestKey); + NodeList peerElements = DataUtils.getPeerElements(doc, mobyDataContext, + xptrsToFilter, DataUtils.DATATYPE_PEERS_MODE); - // find the peers of templateElement and put them into a MobyContentInstance + // find the peers of defined by the userData selection constraints and put them into a MobyContentInstance MobyContentInstance payload = new MobyContentInstance(); Map jobPrefixes = new LinkedHashMap(); - NodeList peerElements = null; - try{ - peerElements = (NodeList) DataUtils.xPathFactory.newXPath().evaluate(selectionXPath, - doc, - XPathConstants.NODESET); - } catch(Exception e){ - logger.log(Level.SEVERE, "Could not select nodes from "+targetURL+" with XPath " + selectionXPath, e); - return null; - } + System.err.println("Loading MobyContentInstance with "+peerElements.getLength()+" elements for xpath "+selectionXPath); for(int i = 0; i < peerElements.getLength(); i++){ Element peerElement = (Element) peerElements.item(i); // Try to make the job names trackable to the inputs: // Name the jobs according to their original job + a iterated number suffix, e.g. originatingJob_1, originatingJob_2 String jobKey = DataUtils.findMobyJobName(peerElement); if(!jobPrefixes.containsKey(jobKey)){ + jobPrefixes.put(jobKey, new Integer(1)); if(peerElements.getLength() > 1){ jobKey += "_1"; // only add a suffix if multiple loop members for the job } - jobPrefixes.put(jobKey, new Integer(1)); } else{ int suffixCount = jobPrefixes.get(jobKey).intValue(); - jobKey += "_"+suffixCount; jobPrefixes.put(jobKey, new Integer(suffixCount+1)); + jobKey += "_"+(suffixCount+1); } + System.err.println("Adding job "+jobKey+" for "+peerElement.getLocalName()); MobyDataInstance mdi = null; try{ mdi = MobyDataObject.createInstanceFromDOM(peerElement, SeahawkOptions.getRegistry()); =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/14 23:48:27 1.19 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/16 17:33:25 1.20 @@ -182,9 +182,13 @@ return handler; } - // synchronized so simultaneous requests don't get their input data mixed up + /** + * Called when the 'Execute Service' button in the secondary input dialog in pushed. + * Section synchronized so simultaneous requests don't get their input data mixed up + */ public void setupServiceSecondaryData(MobyRequestEventHandler handler){ MobyDataInstance[] castInputs = new MobyDataInstance[primaryInput.length]; + MobyContentInstance mci = null; for(int i = 0; i < primaryInput.length; i++){ if(!(primaryInput[i] instanceof MobyDataInstance)){ logger.warn("Warning: setupServiceSecondaryData was called before the primary input" + @@ -192,13 +196,34 @@ " of class "+primaryInput[i].getClass().getName()); return; } - castInputs[i] = (MobyDataInstance) primaryInput[i]; + // Is one of the params a 'for each' + if(primaryInput[i] instanceof MobyContentCreator){ + mci = ((MobyContentCreator) primaryInput[i]).getAllContents(primaryInput[i].getName()); + } + else{ + castInputs[i] = (MobyDataInstance) primaryInput[i]; + } + } + // Cross product of single value primary params with param that is a content creator array + if(mci != null){ + for(MobyDataJob job: mci.values()){ + for(int i = 0; i < castInputs.length; i++){ + if(castInputs[i] != null){ + job.put(castInputs[i].getName(), castInputs[i]); + } + } + } } // code from mobyRequest.setInput() to executeService() should always be synced to avoid input mixup between requests synchronized(mobyRequest){ try{ - mobyRequest.setInput(castInputs); + if(mci != null){ + mobyRequest.setInput(mci); + } + else{ + mobyRequest.setInput(castInputs); + } mobyRequest.setSecondaryInput(secondaryInputInstances); } catch(MobyException me){ me.printStackTrace(); @@ -224,8 +249,13 @@ // code from mobyRequest.setInput() to executeService() should always be synced to avoid input mixup between requests synchronized(mobyRequest){ try{ + if(mdi instanceof MobyContentCreator){ + mobyRequest.setInput(((MobyContentCreator) mdi).getAllContents(primaryInput[0].getName())); + } // Implement simple input (i.e. only one input argument) - mobyRequest.setInput(mdi, ""); + else{ + mobyRequest.setInput(mdi, ""); + } } catch(MobyException me){ logger.error("Failure in MOBY input, was not acceptable:" + me); @@ -539,7 +569,7 @@ addPopupOptions(mobyData, popupList, false, handler, payloadCreator, extraMenuText); } else{ - logger.warn("Warning: OptionLoaderThread has no data to work with"); + logger.warn("Warning: OptionLoaderThread has no data to work with", new Exception("Arrggh")); } } } @@ -646,27 +676,27 @@ MobyDataServiceAssocInstance serviceAssocObject = null; // //Services for only the one piece of data try{ - if(mobyData instanceof MobyDataObjectSet){ - serviceAssocObject = mobyClient.getServices((MobyDataObjectSet) mobyData); - } - else if(mobyData instanceof MobyDataObject){ - serviceAssocObject = mobyClient.getServices((MobyDataObject) mobyData); - } // The data will be loaded later - else if(payloadCreator != null){ + if(payloadCreator != null){ try{ if(mobyData instanceof MobyPrimaryDataSet){ serviceAssocObject = mobyClient.getServices(new MobyDataObjectSetDeferred((MobyPrimaryDataSet) mobyData, payloadCreator)); } - else if(mobyData instanceof MobyNamespace){ - serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyNamespace) mobyData, + else if(mobyData instanceof MobyPrimaryDataSimple){ // pass in if datatype and namespace are useful + serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred(((MobyPrimaryDataSimple) mobyData).getDataType(), + ((MobyPrimaryDataSimple) mobyData).getNamespaces()[0], payloadCreator)); } else if(mobyData instanceof MobyDataType){ serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyDataType) mobyData, payloadCreator)); } + else if(mobyData instanceof MobyNamespace){ + System.err.println("Creating deferred dataset payload"); + serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyNamespace) mobyData, + payloadCreator)); + } else{ logger.warn("Ignoring unrecognized template class (" + mobyData.getClass().getName()+ ") for deferred data creation by a MobyPayloadRequestListener"); @@ -675,6 +705,12 @@ } catch(Exception e){ logger.error("Could not create deferred Moby data object", e); } + } + else if(mobyData instanceof MobyDataObjectSet){ + serviceAssocObject = mobyClient.getServices((MobyDataObjectSet) mobyData); + } + else if(mobyData instanceof MobyDataObject){ + serviceAssocObject = mobyClient.getServices((MobyDataObject) mobyData); } else{ logger.warn("Service options for objects other than MobyDataObject " + @@ -730,9 +766,6 @@ logger.warn("Cannot add service options, cannot find " + "parent moby object index for submenu " + submenu.getText()); - System.err.println("Cannot add service options, cannot find " + - "parent moby object index for submenu " + - submenu.getText()); return; } dataIndex = ((Integer) submenu2msIndex.get(parent)).intValue(); @@ -1250,7 +1283,7 @@ datatype += " collection"; } submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ") + - datatype + (id == null ? "" : ":" + id)+""); + ""+datatype + "" + (id == null ? "" : ":" + id)+""); assignMenuDataIndex(submenu); } else if(MobyTags.MOBYSTRING.equals(mobyDataType.getName())){ @@ -1269,7 +1302,7 @@ } desc = "A piece of text"; submenu = new JMenu("Services for "+(extraMenuText == null ? "" : extraMenuText+" ")+ - "String " + sample+""); + "String " + sample+""); assignMenuDataIndex(submenu); } // Complex object @@ -1283,17 +1316,19 @@ } } if(templateObject instanceof MobyDataObject && id != null && id.length() > 0){ - objectLabel += ":" + id; + objectLabel += ""+objectLabel+":" + id; } else if(templateObject instanceof MobyDataObjectSet){ - objectLabel += " collection"; + objectLabel = ""+objectLabel+" collection"; + } + else{ + objectLabel = ""+objectLabel+""; } submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+objectLabel+""); assignMenuDataIndex(submenu); } desc = "Input data: " + desc; desc = HTMLUtils.htmlifyToolTipText(desc, MAX_SERVICE_DESC_LEN); - System.err.println("New submenu has label " + submenu.getText()); submenu.setToolTipText(desc); submenu.setName(SERVICE_SUBMENU_NAME); return submenu; From gordonp at dev.open-bio.org Fri Apr 16 13:33:26 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 13:33:26 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161733.o3GHXQvK015367@dev.open-bio.org> gordonp Fri Apr 16 13:33:26 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv15287/src/main/ca/ucalgary/seahawk/util Modified Files: DataFlowRecorder.java DataUtils.java FilterSearch.java MobyDataObjectDeferred.java XPointerResolver.java Added Files: MobyDataObjectDeferredSAI.java MobyDataObjectSetDeferredSAI.java Log Message: First fully functional version of 'for each' service invocation in Seahawk moby-live/Java/src/main/ca/ucalgary/seahawk/util MobyDataObjectDeferredSAI.java,NONE,1.1 MobyDataObjectSetDeferredSAI.java,NONE,1.1 DataFlowRecorder.java,1.4,1.5 DataUtils.java,1.5,1.6 FilterSearch.java,1.5,1.6 MobyDataObjectDeferred.java,1.1,1.2 XPointerResolver.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/10 00:40:17 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/16 17:33:26 1.5 @@ -321,7 +321,7 @@ data = sampleData.getUserData().toString().split("\t"); //options: selection + filter + cond, selection + cond, or cond only if(data.length == 14 || data.length == 8 || data.length == 6){ - System.err.println("Adding conditional for " + resultURLString); + // System.err.println("Adding conditional for " + resultURLString); String conditionURL = data[data.length-6]; String conditionRegex = data[data.length-5]; XPathOption conditionXPath = new XPathOption(data[data.length-4], data[data.length-3]); @@ -334,10 +334,10 @@ System.arraycopy(data, 0, conditionlessData, 0, data.length-6); data = conditionlessData; } - else{ - System.err.println("Skipping conditional, only " + data.length + - "members in provenance data for " + resultURLString); - } +// else{ +// System.err.println("Skipping conditional, only " + data.length + +// "members in provenance data for " + resultURLString); +// } } // true means treat as a collection if that's what the sample data is @@ -447,7 +447,7 @@ // Remember that sd is the loop's original MobyDataInstance before it's been coerced into a MobyPrimaryData, // which doesn't have XML modes, etc. String inputKey = getInputKey(sd); - System.err.println("Input key for " + processorName + " is " + inputKey); + // System.err.println("Input key for " + processorName + " is " + inputKey); String[] mobifyingProcessorNameAndPorts = null; if(input2Processor.containsKey(inputKey)){ @@ -930,7 +930,7 @@ // supertype of the output from the other service! if(namespace != null){ MobyNamespace nsObj = MobyNamespace.getNamespace(namespace, getRegistryFromService(srcService)); - System.err.println("About to create namespace filter for "+ srcProcessor + " port " + portName + " when srcPort was " + srcPort); + // System.err.println("About to create namespace filter for "+ srcProcessor + " port " + portName + " when srcPort was " + srcPort); return createNamespaceFilter(nsObj, srcProcessor, portName, processors, datalinks, doc); } else if(xrefNs != null){ @@ -1103,7 +1103,7 @@ throws Exception{ String decompKey = srcProcessor+"\n"+srcPort+"\n"+xpath; - System.err.println("Decomp key is " + decompKey); + // System.err.println("Decomp key is " + decompKey); // Has this decomp already been created in another branch? if(decomp2Processor.containsKey(decompKey)){ return decomp2Processor.get(decompKey); =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/14 22:02:04 1.5 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/16 17:33:26 1.6 @@ -166,6 +166,7 @@ Document resultDom = docBuilder.parse(serviceResultURL.openStream()); Registry registry = getRegistry(resultDom); + //todo: check all jobs, not just a sample MobyDataJob sampleJob = getInputSample(resultDom, registry); // Trace the inputs that came from the current document @@ -343,6 +344,13 @@ * @param responseDom the XML DOM for the answer from a Moby Web service called in Seahawk */ public static MobyDataJob getInputSample(Document responseDom, Registry registry) throws Exception{ + return getInputSample(responseDom, null, registry); + } + + /** + * Same as two-arg, but retrieves a specific job's input (or null if not a job name found in the doc). + */ + public static MobyDataJob getInputSample(Document responseDom, String jobName, Registry registry) throws Exception{ Document inputDoc = getInputDoc(responseDom); if(inputDoc == null){ return null; @@ -360,11 +368,14 @@ throw new Exception("Could not parse Moby output message from the given DOM"); } + if(jobName != null){ + return inputPayload.get(jobName); + } // Pick a job that produced output, if given the choice of more that one - for(String jobName: inputPayload.keySet()){ - if(outputPayload.containsKey(jobName) && - outputPayload.get(jobName).size() > 0){ - return inputPayload.get(jobName); + for(String jobID: inputPayload.keySet()){ + if(outputPayload.containsKey(jobID) && + outputPayload.get(jobID).size() > 0){ + return inputPayload.get(jobID); } } return (MobyDataJob) inputPayload.values().iterator().next(); @@ -460,9 +471,9 @@ /** * Loads targetURL, minus the nodes specified by the xpath keys in filteredXPtrs (map values are not currently used). */ - public static void filterDoc(Document domDoc, Map filteredXPtrs){ + public static void filterNodes(Node rootNode, Map filteredXPtrs){ - if(domDoc == null){ + if(rootNode == null){ logger.log(Level.SEVERE, "Error: Could not get MOBY document as DOM (empty or malformed document?)"); return; } @@ -474,7 +485,7 @@ // wrong as they refer to ordinality) Vector nodesToDelete = new Vector(); for(String xptr: filteredXPtrs.keySet()){ - nodesToDelete.add(XPointerResolver.getNodeFromXPointer(domDoc, xptr)); + nodesToDelete.add(XPointerResolver.getNodeFromXPointer(rootNode, xptr)); } // Delete @@ -497,86 +508,54 @@ * @param filteredXPtrs a map of the xpointers to data that should NOT be deserialized if children of the targetURL XPointer * @param docFilter the current filter applied to the document in targetURL */ - public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, Map filteredXPtrs, FilterSearch docFilter){ - - URL currentURL = null; - try{currentURL = new URL(targetURL.toString().replaceAll("#"+targetURL.getRef(), ""));} - catch(Exception e){ - logger.log(Level.SEVERE, "Couldn't extract referenceless URL from " + targetURL, e); - } - - // Build the DOM - Document domDoc = null; - try{ - domDoc = docBuilder.parse(targetURL.openStream()); - } catch(org.xml.sax.SAXException saxe){ - logger.log(Level.SEVERE, "The document defining the MOBY data " + - "could not be parsed", saxe); - return null; - } catch(java.io.IOException ioe){ - logger.log(Level.SEVERE, "The document defining the MOBY data " + - " could not be read (from " + targetURL + ")", ioe); - return null; - } - // Does an in-place edit of domDoc - filterDoc(domDoc, filteredXPtrs); - + public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, Map filteredXPtrs, + FilterSearch docFilter){ + + URL currentURL = null; + try{currentURL = new URL(targetURL.toString().replaceAll("#"+targetURL.getRef(), ""));} + catch(Exception e){ + logger.log(Level.SEVERE, "Couldn't extract referenceless URL from " + targetURL, e); + } + + // Build the DOM + Document domDoc = null; + try{ + domDoc = docBuilder.parse(targetURL.openStream()); + } catch(org.xml.sax.SAXException saxe){ + logger.log(Level.SEVERE, "The document defining the MOBY data " + + "could not be parsed", saxe); + return null; + } catch(java.io.IOException ioe){ + logger.log(Level.SEVERE, "The document defining the MOBY data " + + " could not be read (from " + targetURL + ")", ioe); + return null; + } + + return loadMobyDataFromXPointer(currentURL, domDoc, targetURL.getRef(), filteredXPtrs, docFilter); + } + + public static MobyDataInstance loadMobyDataFromXPointer(URL docURL, Document domDoc, String targetXptr, + Map filteredXPtrs, FilterSearch docFilter){ // Are we dealing with a simple object or a complex one? MobyDataInstance mobyData = null; // Find the DOM fragment corresponding to the MOBY ID anchor specified // in the link URL by using an XPath statement on the source MOBY doc - //System.err.println("Retrieving complex object from XPointer " + targetURL); // A child Xpointer is of the form /1/2/1/1, specifying the DOM child - // descent path from the root node to get to the target node. The - // equivalent XPath is /*[1]/*[2]/*[1]/*[1] - String childXPath = targetURL.getRef().replaceAll("/(\\d+)", "/*[$1]"); - - // Build and run the XPath statement - Element mobyObject = null; - NodeList idSearchResult = null; - Object xobject = null; - try{ - xobject = xPathFactory.newXPath().evaluate(childXPath, - domDoc, - XPathConstants.NODESET); - - // Check the results - if(xobject != null){ - idSearchResult = (NodeList) xobject; - } - else{ - logger.log(Level.WARNING,"Could not find Moby object in document " + currentURL + - ", referred to by the reference ID in Moby link " + targetURL + - " (document changed?)"); - return null; - } - } - catch(Exception e){// Syntax error - logger.log(Level.SEVERE, "Error: Could not search Moby data instance for XPath " + - childXPath + ")", e); - return null; - } + // descent path from the root node to get to the target node. + Element mobyObject = (Element) XPointerResolver.getNodeFromXPointer(domDoc, targetXptr); - if(idSearchResult.getLength() == 0){ - logger.log(Level.WARNING, "Error: Could not find Moby data instance with XPath (" + childXPath + - " in " + targetURL); - return null; - } - if(idSearchResult.getLength() > 1){ - logger.log(Level.WARNING, "Error: Moby data instance could not beresolved because " + - "there are multiple elements with XPath " + childXPath + " in " + - currentURL); - return null; - } - if(!(idSearchResult.item(0) instanceof Element)){ - logger.log(Level.WARNING, "Error: Moby data instance with XPath " + childXPath + " in " + - currentURL + " was not an element as required!"); - return null; + // Does an in-place edit of domDoc + // Check if the returned data was supposed to be filtered. If so, don't filter. + if(filteredXPtrs != null && !filteredXPtrs.isEmpty() && !filteredXPtrs.containsKey(targetXptr)){ + // Otherwise filter, so child elements of the data to return reflect the current filter conditions + // (e.g. a collection may be filtered to just a subset based on namespace, so retrieving the collection should only + // return that subset of children). + domDoc = (Document) domDoc.cloneNode(true); // true == deep + filterNodes(domDoc, filteredXPtrs); } - mobyObject = (Element) idSearchResult.item(0); - + // Create the Java MOBY API object based on the linked document DOM fragment try{ MobyDataInstance mdi = MobyDataObject.createInstanceFromDOM(mobyObject, SeahawkOptions.getRegistry()); @@ -587,8 +566,8 @@ mobyData = mdi; } else{ - logger.log(Level.WARNING, "Error: Moby data instance retrieved with XPath " + childXPath + " in " + - currentURL + " was not a primary MOBY input object as expected"); + logger.log(Level.WARNING, "Error: Moby data instance retrieved with XPath " + targetXptr + + " was not a primary MOBY input object as expected"); return null; } @@ -600,8 +579,8 @@ // For workflow creation, etc. associate the potential input data with its source generalized XPath // Also, if there is currently a filter on the doc, store it too as useful info for workflow creation. - setUserData(mobyData, currentURL, elementInContextToNameBasedXPath(mobyObject), - targetURL.getRef(), docFilter); + setUserData(mobyData, docURL, elementInContextToNameBasedXPath(mobyObject), + targetXptr, docFilter); } catch(MobyException mobye){ // Logic error logger.log(Level.SEVERE, "Error: Could not construct Moby data instance from document fragment: ", @@ -656,6 +635,7 @@ // It's a complex type. Assume the type is why we are picking it. // TODO: In future we may want to check if a parent type is allowed in // this slot, and generalize to that. + // Also, account for namespace if present? xpath = "/"+elName + xpath; } if(!(currentElement.getParentNode() instanceof Element)){ @@ -784,7 +764,7 @@ /** * Find out which registry the service that created the reponse is registered in. * - * @param responseURL the service response whose origin we should trace + * @param responseDoc the service response whose origin we should trace */ public static Registry getRegistry(Document responseDoc) throws Exception{ String endpointURL = getSeahawkAttrFromDoc(responseDoc, REGISTRY_ATTR); @@ -1035,16 +1015,20 @@ } if(!inversed && shouldFilter || inversed && !shouldFilter){ - xPtrsToFilter.put(currXPtr, "todo"); + xPtrsToFilter.put(currXPtr, "whatever"); } } //todo: filter objects without the HAS field at all... return filterableXPtrs; } - // We need to enumerate the possible peer-sets for the selected data item. Is the user interested in - // items in the same namespace, same data type, or same article name? - public static NodeList getPeerElements(Document doc, MobyDataInstance mobyData, String peerMode){ + + /** + * We need to enumerate the possible peer-sets for the selected data item. Is the user interested in + * items in the same namespace/data type, or same article name? + */ + public static NodeList getPeerElements(Document doc, MobyDataInstance mobyData, + Map xPtrsToFilter, String peerMode){ if(!(mobyData instanceof MobyPrimaryData)){ logger.log(Level.WARNING, "Tried to get peers of data that was not an instanceof MobyPrimaryData (was " + mobyData.getClass().getName()+ ")"); @@ -1054,10 +1038,13 @@ NodeList peerElements = null; String peerGroupXPath = null; + Node contextNode = null; if(mobyData.getUserData() != null){ String[] userData = ((String) mobyData.getUserData()).split("\t"); // first arg is url#nameBasedXPath peerGroupXPath = userData[0].split("#", 2)[1]; + contextNode = XPointerResolver.getNodeFromXPointer(doc, userData[1]); + //System.err.println("Loaded context node " + userData[1] + " as " + contextNode); } else{ // Fallback is to get all nodes with the same name... @@ -1079,7 +1066,7 @@ mobyData.setUserData(newUserData); // keep from job article name down - peerGroupXPath = peerGroupXPath.replaceFirst("^.*/(Collection|Simple)", "//*"); + //peerGroupXPath = peerGroupXPath.replaceFirst("^.*?/(Collection|Simple)", "//*"); // we want to go by articleName too to catch the full semantics of the peer group definition peerGroupXPath += xpathArticleCondition; } @@ -1090,17 +1077,58 @@ // For xpaths given above, MOBY namespace is problem in XPath evaluation. // solution: eliminate Moby envelope path parts: full path doesn't resolve in xpath for unknown reasons //.replaceAll("/(MOBY|mobyContent|mobyData|Collection|Simple)","/moby:$1"); //attempt 1 - //.replaceAll("/([a-zA-Z_0-9\\-]+)(?=/|$)", "/*[local-name() = '$1']") //attempt 2 - //.replaceAll("/([a-zA-Z_0-9\\-]+)\\[", "/*[local-name() = '$1' and "); //attempt 2 cont'd + peerGroupXPath = peerGroupXPath.replaceAll("/([a-zA-Z_0-9\\-]+)", "/d:$1"); try{ - peerElements = (NodeList) xPathFactory.newXPath().evaluate(peerGroupXPath, - doc, - XPathConstants.NODESET); + XPath xpath = xPathFactory.newXPath(); + if(contextNode != null){ + xpath.setNamespaceContext(new NamespaceContextImpl(contextNode, "d")); + } + peerElements = (NodeList) xpath.evaluate(peerGroupXPath, + doc, + XPathConstants.NODESET); } catch(Exception e){ logger.log(Level.SEVERE, "Could not evaluate UserData XPath "+peerGroupXPath, e); } - System.err.println("Got " + peerElements.getLength() + " peers for " + peerGroupXPath); + //System.err.println("Got " + peerElements.getLength() + " peers for " + peerGroupXPath); + + // Remove peers that are currently filtered. Seems to be quicker than cloning the doc, + // filtering the node, then running the xpath. Assumes you don't do much with peerElements + // afterwards, or you should apply the filter to remove errant children, etc.) + if(xPtrsToFilter != null && !xPtrsToFilter.isEmpty()){ + MutableNodeList filterPassedPeers = new MutableNodeList(); + for(int i = 0; i < peerElements.getLength(); i++){ + boolean filtered = false; + String peerXPtr = getXPtr(peerElements.item(i)); + // Check all ancestors to see if they are filtered + for(String ancestorXPtr = peerXPtr; + ancestorXPtr.length() > 0; + ancestorXPtr = ancestorXPtr.replaceFirst("/\\d+$", "")){ + if(xPtrsToFilter.containsKey(ancestorXPtr)){ + filtered = true; + break; + } + } + if(!filtered){ + Element peerElement = (Element) peerElements.item(i); + // Now check if any child nodes need to be filtered + Map childrenToDelete = new HashMap(); + for(String xptr: xPtrsToFilter.keySet()){ + // is it a child of the peer about to be put in the "passed filter" list? + if(xptr.indexOf(peerXPtr+"/") == 0){ + childrenToDelete.put(xptr.substring(peerXPtr.length()), "whatever"); + } + } + if(!childrenToDelete.isEmpty()){ + peerElement = (Element) peerElements.item(i).cloneNode(true); //true = deep copy + filterNodes(peerElement, childrenToDelete); + } + filterPassedPeers.add(peerElement); + } + } + peerElements = filterPassedPeers; + //System.err.println("Got " + peerElements.getLength() + " peers that passed the filter"); + } return peerElements; } =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/14 22:02:04 1.5 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/16 17:33:26 1.6 @@ -121,11 +121,17 @@ return xpathOptions; } + public String toString(){ + return filterRegex.toString()+"\t"+getSelectedXPath().getXPath()+"\t"+ + getSelectedXPath().getDesc()+"\t"+caseSensitivity+"\t"+inverseSelection; + } + public boolean equals(Object o){ if(o == null || !(o instanceof FilterSearch)){ return false; } FilterSearch other = (FilterSearch) o; + //System.err.println("Comparing "+this+"\n\nand\n\n"+o); return filterRegex.toString().equals(other.filterRegex.toString()) && getSelectedXPath().getXPath().equals(other.getSelectedXPath().getXPath()) && caseSensitivity == other.caseSensitivity && =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/MobyDataObjectDeferred.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/seahawk/util/MobyDataObjectDeferred.java 2010/04/14 23:48:27 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/MobyDataObjectDeferred.java 2010/04/16 17:33:26 1.2 @@ -15,8 +15,8 @@ super(MobyDataType.getDataType(MobyTags.MOBYOBJECT, SeahawkOptions.getRegistry()), ns, "any_id"); dataCreator = listener; } - public MobyDataObjectDeferred(MobyDataType dt, MobyPayloadRequestListener listener){ - super(dt); + public MobyDataObjectDeferred(MobyDataType dt, MobyPayloadRequestListener listener) throws Exception{ + super(dt, new MobyNamespace("unknown"), "any_id"); dataCreator = listener; } public MobyDataObjectDeferred(MobyDataType dt, MobyNamespace ns, MobyPayloadRequestListener listener) throws Exception{ =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/XPointerResolver.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/seahawk/util/XPointerResolver.java 2010/04/11 20:15:28 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/XPointerResolver.java 2010/04/16 17:33:26 1.2 @@ -15,20 +15,24 @@ * Note, this currently only works for stuff like /1/1/2/3/1/67, * not all XPointers, which includes functions, etc. */ - public static Node getNodeFromXPointer(Document d, String xptr){ - if(d == null || xptr == null || xptr.length() < 2 || !xptr.startsWith("/1")){ + public static Node getNodeFromXPointer(Node rootNode, String xptr){ + if(rootNode == null || xptr == null || xptr.length() < 2){ return null; } - Node currentNode = d.getDocumentElement(); + Node currentNode = rootNode; if(currentNode == null){ return null; } - if(xptr.equals("/1")){ - return currentNode; - } + if(rootNode instanceof Document){ + currentNode = ((Document) rootNode).getDocumentElement(); + if(xptr.equals("/1")){ + return currentNode; + } - // Get rid of leading "/1/" - String[] ordinal_steps = xptr.substring(3).split("/"); + // Get rid of leading "/1/" + xptr = xptr.substring(3); + } + String[] ordinal_steps = xptr.split("/"); if(ordinal_steps.length == 0){ return currentNode; } From gordonp at dev.open-bio.org Fri Apr 16 15:58:26 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 15:58:26 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161958.o3GJwQk7018588@dev.open-bio.org> gordonp Fri Apr 16 15:58:26 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services In directory dev.open-bio.org:/tmp/cvs-serv18552/src/main/ca/ucalgary/seahawk/services Modified Files: MobyClient.java Log Message: Fixed logging messaages moby-live/Java/src/main/ca/ucalgary/seahawk/services MobyClient.java,1.27,1.28 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/16 17:32:33 1.27 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/16 19:58:26 1.28 @@ -84,9 +84,7 @@ * new registry will NOT be reflected here. */ public MobyClient() throws MobyException{ - this(SeahawkOptions.getRegistry() == null ? - RegistryCache.getDefaultRegistry() : - SeahawkOptions.getRegistry()); + this(SeahawkOptions.getRegistry()); } /** From gordonp at dev.open-bio.org Fri Apr 16 15:59:01 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 15:59:01 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161959.o3GJx1sF018632@dev.open-bio.org> gordonp Fri Apr 16 15:59:01 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/client In directory dev.open-bio.org:/tmp/cvs-serv18596/src/main/org/biomoby/client Modified Files: CentralImpl.java Log Message: Fixed logging messages moby-live/Java/src/main/org/biomoby/client CentralImpl.java,1.64,1.65 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralImpl.java,v retrieving revision 1.64 retrieving revision 1.65 diff -u -r1.64 -r1.65 --- /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralImpl.java 2010/03/29 19:48:28 1.64 +++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralImpl.java 2010/04/16 19:59:01 1.65 @@ -131,7 +131,7 @@ public static final String CENTRAL_IMPL_RESOURCE_NAME = "org.biomoby.client.CentralImpl"; /** The class to use for getDefaultCentral if all else fails */ public static final String DEFAULT_CENTRAL_IMPL_CLASSNAME = "org.biomoby.client.CentralDigestCachedImpl"; - private static Logger logger = Logger.getLogger("org.biomoby.client.CentralImpl"); + private static Logger logger = Logger.getLogger(CentralImpl.class.getName()); /** * Thread local that gives each thread its own @@ -1888,7 +1888,7 @@ ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); URL resURL = classLoader.getResource("META-INF/services/"+CENTRAL_IMPL_RESOURCE_NAME); if(resURL != null){ - System.err.println("Loading "+resURL); + logger.log(Level.CONFIG, "Loading "+resURL); try{ LineNumberReader reader = new LineNumberReader(new InputStreamReader(resURL.openStream())); for(String line = reader.readLine(); line != null; line = reader.readLine()){ @@ -1904,9 +1904,7 @@ } } try{ - if(Boolean.getBoolean("moby.debug")){ - System.err.println("Central class is "+className+ " for " + reg); - } + logger.log(Level.CONFIG, "Central class is "+className+ " for " + reg); Class clazz = Class.forName(className); if(reg == null){ // should use default nullary c-tor defaultCentrals.put("", (CentralImpl) clazz.newInstance()); From gordonp at dev.open-bio.org Fri Apr 16 16:36:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 16:36:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004162036.o3GKaHua019856@dev.open-bio.org> gordonp Fri Apr 16 16:36:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv19820/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentClipboard.java Log Message: Switched to java.util.logging.* moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentClipboard.java,1.10,1.11 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/11 02:25:03 1.10 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/16 20:36:17 1.11 @@ -21,6 +21,7 @@ import java.io.FileOutputStream; import java.net.URL; import java.util.*; +import java.util.logging.*; import java.util.regex.Pattern; /** @@ -54,7 +55,8 @@ // Clipboard editing variables private JMenuItem deleteDataPopupItem; private MobyDataInstance itemToDelete; - private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(MobyContentClipboard.class); + private static Logger logger = Logger.getLogger(MobyContentClipboard.class.getName()); + public MobyContentClipboard(MobyContentGUI cGUI, MobyServicesGUI sGUI, JTabbedPane parentComponent, DataFlowRecorder recorder, JLabel statusBar){ super(cGUI, sGUI, parentComponent, recorder, statusBar); @@ -66,7 +68,7 @@ if(clipboardIcon == null){ URL u = cl.getResource(CLIPBOARD_TAB_ICON_RESOURCE); if(u == null){ - logger.warn("Could not find icon resource " + CLIPBOARD_TAB_ICON_RESOURCE); + logger.log(Level.WARNING, "Could not find icon resource " + CLIPBOARD_TAB_ICON_RESOURCE); } else{ clipboardIcon = new ImageIcon(u); @@ -86,7 +88,7 @@ clipboardFile = File.createTempFile(CLIPBOARD_FILE_NAME, ".xml"); } catch(Exception e){ - logger.error("Clipboard failed to initialize, cannot create temp file:" + e); + logger.log(Level.SEVERE, "Clipboard failed to initialize, cannot create temp file", e); return; } clipboardFile.deleteOnExit(); @@ -134,7 +136,7 @@ // (i.e. don't delete subparts of object) if(!(mdi instanceof MobyDataObject) || !collection.contains(mdi)){ mdi.setXmlMode(MobyDataInstance.SERVICE_XML_MODE); - System.err.println("Skipping " + mdi.toXML()); + logger.log(Level.WARNING, "Skipping " + mdi.toXML()); mdi.setXmlMode(MobyDataInstance.CENTRAL_XML_MODE); return; } @@ -160,7 +162,7 @@ } } else{ - logger.warn("Clipboard: ignoring unrecognized source of event " + e); + logger.log(Level.WARNING, "Clipboard: ignoring unrecognized source of event ", e); } } @@ -186,7 +188,7 @@ public void addCollectionData(MobyDataInstance mdi, boolean updateDisplay){ if(mdi == null){ - logger.warn("Cannot add null object to the clipboard."); + logger.log(Level.WARNING, "Cannot add null object to the clipboard."); return; } if(!query.containsKey(CLIPBOARD_COLLECTION_NAME)){ @@ -200,9 +202,9 @@ collection.add((MobyDataObject) mdi); } else{ - logger.warn("Cannot add object of class " + mdi.getClass() + - " to the clipboard, only MobyDataObject and MobyDataObjectSet" + - " are supported"); + logger.log(Level.WARNING, "Cannot add object of class " + mdi.getClass() + + " to the clipboard, only MobyDataObject and MobyDataObjectSet" + + " are supported"); return; } @@ -246,26 +248,26 @@ return; } } catch(Exception e){ - logger.warn("Could not transform binary file ("+u+"): " + e); + logger.log(Level.WARNING, "Could not transform binary file ("+u+")", e); } // Not binary, see if it's text that's convertible to MOBY data MobyClient client = servicesGUI.getMobyClient(); if(client == null){ - logger.warn("Could not get MOBY client from MOBY services GUI, " + - "cannot transform incoming clipboard data to MOBY objects"); + logger.log(Level.WARNING, "Could not get MOBY client from MOBY services GUI, " + + "cannot transform incoming clipboard data to MOBY objects"); } String urlContents = null; try{ urlContents = HTMLUtils.getURLContents(u); } catch(Exception e){ - logger.warn("Could not read contents of the URL to import to the clipboard ("+u+"):" +e); + logger.log(Level.WARNING, "Could not read contents of the URL to import to the clipboard ("+u+")", e); return; } if(urlContents.indexOf(" gordonp Sat Apr 17 20:23:42 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv27510/src/main/ca/ucalgary/seahawk/util Modified Files: DataFlowRecorder.java Log Message: Fixed so no problem when original data comes from the clipboard, or a saved moby xml file moby-live/Java/src/main/ca/ucalgary/seahawk/util DataFlowRecorder.java,1.5,1.6 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/16 17:33:26 1.5 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/18 00:23:42 1.6 @@ -342,6 +342,7 @@ // true means treat as a collection if that's what the sample data is String sinkPortName = getPortName(sampleData, true); + // No user data means non-moby origin...backtracking stops. if(data != null && data.length != 0){ URL dataSrcURL = null; try{ @@ -351,6 +352,16 @@ "a provenance URL as expected URL (" + sampleData.getUserData().toString() + ")"); continue; } + + // If srcService == null, the input source for this param was a Moby doc that wasn't a + // service output, e.g. the clipboard or an old doc loaded from file. + MobyService srcService = DataUtils.getService(dataSrcURL); + if(srcService == null){ + addWorkflowInput(processorName, condPassProcessorAndPorts, sinkPortName, sampleData, + datalinks, processors, inputPorts, doc); + continue; + } + // recursion for workflow creation by backtracking service input provenance String feedingProcessorName = null; String feedingProcessorPort = null; @@ -429,52 +440,57 @@ } // Otherwise it's a workflow input the user will need to specify else{ - // pName is editable name for input processor target... - // allows injection of condition without affecting method's return value - String pName = processorName; - if(condPassProcessorAndPorts != null){ - // inject condition filter between data creator and current service - datalinks.appendChild(createDataLinkElement(condPassProcessorAndPorts[0], - condPassProcessorAndPorts[2], - pName, - sinkPortName, - doc)); - pName = condPassProcessorAndPorts[0]; - sinkPortName = condPassProcessorAndPorts[1]; - } - // The sample data may be used in more than one branch of the flow...avoid duplication - // Get the real data XML, to see if we've encountered it before as input (it'd be in the hash) - // Remember that sd is the loop's original MobyDataInstance before it's been coerced into a MobyPrimaryData, - // which doesn't have XML modes, etc. - String inputKey = getInputKey(sd); - // System.err.println("Input key for " + processorName + " is " + inputKey); - - String[] mobifyingProcessorNameAndPorts = null; - if(input2Processor.containsKey(inputKey)){ - mobifyingProcessorNameAndPorts = input2Processor.get(inputKey); - } - else{ - if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT)){ - mobifyingProcessorNameAndPorts = addIdMobifyingProcessor(processors, datalinks, inputPorts, - sampleData, doc); - input2Processor.put(inputKey, mobifyingProcessorNameAndPorts); - } - else{ - // TODO: Need to build complex input from MOB rule or spreadsheet fields? - } - } - // link the created data to the workflow service - datalinks.appendChild(createDataLinkElement(mobifyingProcessorNameAndPorts[0], - mobifyingProcessorNameAndPorts[1], - pName, sinkPortName, - doc)); + addWorkflowInput(processorName, condPassProcessorAndPorts, sinkPortName, sampleData, + datalinks, processors, inputPorts, doc); } - } return processorName; } + private void addWorkflowInput(String pName, String[] condPassProcessorAndPorts, String sinkPortName, + MobyPrimaryData sampleData, Element datalinks, Element processors, + Element inputPorts, Document doc) throws Exception{ + // pName is editable name for input processor target... + // allows injection of condition without affecting method's return value + if(condPassProcessorAndPorts != null){ + // inject condition filter between data creator and current service + datalinks.appendChild(createDataLinkElement(condPassProcessorAndPorts[0], + condPassProcessorAndPorts[2], + pName, + sinkPortName, + doc)); + pName = condPassProcessorAndPorts[0]; + sinkPortName = condPassProcessorAndPorts[1]; + } + // The sample data may be used in more than one branch of the flow...avoid duplication + // Get the real data XML, to see if we've encountered it before as input (it'd be in the hash) + // Remember that sd is the loop's original MobyDataInstance before it's been coerced into a MobyPrimaryData, + // which doesn't have XML modes, etc. + String inputKey = getInputKey((MobyDataInstance) sampleData); + // System.err.println("Input key for " + processorName + " is " + inputKey); + + String[] mobifyingProcessorNameAndPorts = null; + if(input2Processor.containsKey(inputKey)){ + mobifyingProcessorNameAndPorts = input2Processor.get(inputKey); + } + else{ + if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT)){ + mobifyingProcessorNameAndPorts = addIdMobifyingProcessor(processors, datalinks, inputPorts, + sampleData, doc); + input2Processor.put(inputKey, mobifyingProcessorNameAndPorts); + } + else{ + // TODO: Need to build complex input from MOB rule or spreadsheet fields? + } + } + // link the created data to the workflow service + datalinks.appendChild(createDataLinkElement(mobifyingProcessorNameAndPorts[0], + mobifyingProcessorNameAndPorts[1], + pName, sinkPortName, + doc)); + } + // returns the same value for moby sample data instances containing the same data in XML form private String getInputKey(MobyDataInstance sd){ int oldXmlMode = sd.getXmlMode(); From gordonp at dev.open-bio.org Sat Apr 17 20:31:49 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 17 Apr 2010 20:31:49 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004180031.o3I0VnZ0028062@dev.open-bio.org> gordonp Sat Apr 17 20:31:49 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv28026/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyServicesGUI.java Log Message: Switched from Object to ID for basic object label, more intuitive for users moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyServicesGUI.java,1.20,1.21 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/16 17:33:25 1.20 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/18 00:31:49 1.21 @@ -693,7 +693,6 @@ payloadCreator)); } else if(mobyData instanceof MobyNamespace){ - System.err.println("Creating deferred dataset payload"); serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyNamespace) mobyData, payloadCreator)); } @@ -1175,7 +1174,7 @@ } public JMenu addOutputTypeSubMenu(JMenu parentMenu, MobyDataType type){ - JMenu menu = new JMenu("Result type: " + type.getName()); + JMenu menu = new JMenu("Result type: " + (type.getName().equals(MobyTags.MOBYOBJECT) ? "ID" : type.getName())); MobyDataType[] typeLineage = type.getLineage(); String commonAncestorDesc = ""; From gordonp at dev.open-bio.org Sat Apr 17 20:33:05 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 17 Apr 2010 20:33:05 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004180033.o3I0X5V4028106@dev.open-bio.org> gordonp Sat Apr 17 20:33:05 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv28070/src/main/ca/ucalgary/seahawk/gui Modified Files: MobySaveDialog.java Log Message: Stripped seahawk preocessing instructions from saved XML as they can confuse on reload. Workflow export is default save option now. moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobySaveDialog.java,1.8,1.9 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java 2010/03/29 19:53:16 1.8 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java 2010/04/18 00:33:05 1.9 @@ -92,11 +92,11 @@ fileChooser.setName(FILE_CHOOSER_SAVE_TITLE); fileChooser.setFileHidingEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(HTML_EXT, HTML_DESC)); if(document.hasXMLSource()){ fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(T2FLOW_EXT, T2FLOW_DESC)); fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(XML_EXT, XML_DESC)); } + fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(HTML_EXT, HTML_DESC)); fileChooser.setAcceptAllFileFilterUsed(false); if(lastDirOpened != null){ fileChooser.setCurrentDirectory(lastDirOpened); @@ -318,7 +318,9 @@ try { OutputStream ostream = new FileOutputStream(f); String xml = document.getXMLSource(); - ostream.write(xml.getBytes()); + // Before saving, strip out the Seahawk processing instructions, which will + // confuse Seahawk if we reload the XML doc later. + ostream.write(xml.replaceAll("<\\?"+DataUtils.PI_TARGET+".*?\\?>","").getBytes()); ostream.flush(); ostream.close(); } catch (Exception ex) { From gordonp at dev.open-bio.org Sat Apr 17 20:33:56 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 17 Apr 2010 20:33:56 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004180033.o3I0Xu7J028150@dev.open-bio.org> gordonp Sat Apr 17 20:33:56 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv28114/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyPayloadCreator.java Log Message: Cleaner logging moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyPayloadCreator.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.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/seahawk/gui/MobyPayloadCreator.java 2010/04/16 17:33:25 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/18 00:33:56 1.4 @@ -27,7 +27,7 @@ // The request key is the sample data's app context: // url#xpath sample_xptr filter_regex filter_xpath xpath_desc case_sensitive_boolean inverse selection // from which we will build the peer dataset to submit. - System.err.println("Request key is " + requestKey); + logger.log(Level.FINER, "Request key is " + requestKey); String[] requestKeyFields = requestKey.split("\t"); String[] requestParts = requestKeyFields[0].split("#", 2); @@ -67,7 +67,7 @@ } else if(filter.equals(srcPane.getFilter())){ // no need to redo the filtering, it's the current display's filtering - System.err.println("Reusing current filter"); + logger.log(Level.FINE, "Reusing current filter"); xptrsToFilter = srcPane.getFilteredData(); } else{ @@ -89,7 +89,7 @@ MobyContentInstance payload = new MobyContentInstance(); Map jobPrefixes = new LinkedHashMap(); - System.err.println("Loading MobyContentInstance with "+peerElements.getLength()+" elements for xpath "+selectionXPath); + logger.log(Level.FINE, "Loading MobyContentInstance with "+peerElements.getLength()+" elements for xpath "+selectionXPath); for(int i = 0; i < peerElements.getLength(); i++){ Element peerElement = (Element) peerElements.item(i); // Try to make the job names trackable to the inputs: @@ -106,7 +106,7 @@ jobPrefixes.put(jobKey, new Integer(suffixCount+1)); jobKey += "_"+(suffixCount+1); } - System.err.println("Adding job "+jobKey+" for "+peerElement.getLocalName()); + logger.log(Level.FINE, "Adding job "+jobKey+" for "+peerElement.getLocalName()); MobyDataInstance mdi = null; try{ mdi = MobyDataObject.createInstanceFromDOM(peerElement, SeahawkOptions.getRegistry()); From gordonp at dev.open-bio.org Fri Apr 23 01:15:42 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:15:42 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230515.o3N5FglD024507@dev.open-bio.org> gordonp Fri Apr 23 01:15:42 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util In directory dev.open-bio.org:/tmp/cvs-serv24471/src/main/ca/ucalgary/services/util Modified Files: PBERecorder.java Log Message: Truncate long example data abruptly if it has no whitespace moby-live/Java/src/main/ca/ucalgary/services/util PBERecorder.java,1.4,1.5 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/PBERecorder.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/PBERecorder.java 2010/03/29 20:59:54 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/PBERecorder.java 2010/04/23 05:15:41 1.5 @@ -795,7 +795,10 @@ } int end = text.length(); - if(start + targetWord.length() + numChars < text.length()){ + if(text.indexOf(" ") == -1){ + end = numChars; + } + else if(start + targetWord.length() + numChars < text.length()){ end = start + targetWord.length() + numChars; // break at a word boundary while(end < text.length() && !Character.isWhitespace(text.charAt(end))){ From gordonp at dev.open-bio.org Fri Apr 23 01:16:45 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:16:45 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230516.o3N5GjOm024551@dev.open-bio.org> gordonp Fri Apr 23 01:16:45 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services In directory dev.open-bio.org:/tmp/cvs-serv24515/src/main/ca/ucalgary/seahawk/services Modified Files: TextClient.java Log Message: Better Dublin Core support, added getPossibleTextTypes() for drag and drop export moby-live/Java/src/main/ca/ucalgary/seahawk/services TextClient.java,1.7,1.8 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/TextClient.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/TextClient.java 2009/06/09 19:22:21 1.7 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/TextClient.java 2010/04/23 05:16:45 1.8 @@ -8,13 +8,15 @@ import org.w3c.dom.*; -import javax.xml.transform.stream.*; -import javax.xml.transform.*; import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.*; import java.io.*; import java.net.URL; import java.util.*; +import java.util.logging.*; /** * This class uses XSLT rules to transform MOBY XML data representation @@ -24,20 +26,26 @@ */ public class TextClient{ + public static final String DATA_MAPPING_XSLT_RESOURCE = "ca/ucalgary/seahawk/resources/mobyRules.xsl"; + public static final String RESOURCE_SYSTEM_PROPERTY = "seahawk.textrules"; + public final static String XSLT_NS = "http://www.w3.org/1999/XSL/Transform"; public final static String XSLT_MODE_VAR = "selectedACDTypeTarget"; private Vector moby2textConverters; // XSLT engine private TransformerFactory transFactory; private DocumentBuilder docBuilder; + private URL dataMappingXSLTURL; //private Map id; //todo: unique xslt doc id (e.g. LSID or URL) -> transformer private Map> typeTemplates; //mobytype -> Vector(xsltrule1, xsltrule2,...) private Map> typeNsRestrictions; //mobytype -> Vector(mobynamespace1, ...) private Map templateMode; - private String id; + private Map templateIds; // template name -> URN private Registry registry; + private static Logger logger = Logger.getLogger(TextClient.class.getName()); + public TextClient() throws Exception{ this(SeahawkOptions.getRegistry() == null ? RegistryCache.getDefaultRegistry() : @@ -60,16 +68,95 @@ typeTemplates = new HashMap>(); typeNsRestrictions = new HashMap>(); templateMode = new HashMap(); + templateIds = new HashMap(); + + ClassLoader cl = getClass().getClassLoader(); + if(cl == null){ + cl = ClassLoader.getSystemClassLoader(); + } + String rulesResource = System.getProperty(RESOURCE_SYSTEM_PROPERTY); + if(rulesResource == null){ + dataMappingXSLTURL = cl.getResource(DATA_MAPPING_XSLT_RESOURCE); + } + else if(rulesResource.length() != 0){ + // See if it's a URL + try{ + dataMappingXSLTURL = new URL(rulesResource); + } + catch(Exception e){ + dataMappingXSLTURL = cl.getResource(rulesResource); + } + } + if(dataMappingXSLTURL == null){ + if(rulesResource.length() != 0){ // if not left intentionally blank + logger.log(Level.WARNING, "Could not find MOBY to text mapping resource '"+ + rulesResource+"'"); + } + } + else{ + try{ + addMappingsFromURL(dataMappingXSLTURL); + } + catch(Exception e){ + logger.log(Level.SEVERE, "Error loading default data mapping rules ("+dataMappingXSLTURL+")", e); + e.printStackTrace(); + } + } + } + + public String[] getPossibleTextTypes(MobyPrimaryData dataTemplate, boolean mustHaveURN){ + Vector possibleTypes = new Vector(); + // Search for templates matching the given type or one of its parent types, + // and see if they create the given text type (indicated by the template's mode attribute) + for(MobyDataType type = dataTemplate.getDataType(); + type != null; + type = type.getParent()){ + if(typeTemplates.containsKey(type.getName())){ + // These two vectors should be of the same length! + Vector templateNames = typeTemplates.get(type.getName()); + Vector nsRestrictions = typeNsRestrictions.get(type.getName()); + for(int i = 0; i < templateNames.size(); i++){ + String templateName = templateNames.elementAt(i); + if(mustHaveURN && getTemplateURN(templateName) == null){ + continue; + } + + // the template input moby datatype is the same type as we have an instance of + String textType = templateMode.get(templateName); // mode and text type name are one and the same + // does set-ness match? + if(dataTemplate instanceof MobyPrimaryDataSet){ + if(templateName.startsWith("Collection-")){ + possibleTypes.add(textType); + } + } + else{ + if(!templateName.startsWith("Collection-")){ + possibleTypes.add(textType); + } + } + // Is there a namespace restriction on the transformation rule? + MobyNamespace ns = nsRestrictions.elementAt(i); + if(ns != null){ + for(MobyNamespace n: dataTemplate.getNamespaces()){ + if(ns.equals(n)){ + possibleTypes.add(textType); + } + } + } + } + } + } + return possibleTypes.toArray(new String[possibleTypes.size()]); + } + + public String getTemplateURN(String templateName){ + return templateIds.get(templateName); } /** * @return the data format the xslt creates (the last template mode attribute in the file) */ public synchronized String addMappingsFromURL(URL xsltURL) throws Exception{ - StreamSource stylesheet = new StreamSource(xsltURL.toString()); - // Prepend to list, so later rules can override ones specified earlier - moby2textConverters.insertElementAt(transFactory.newTransformer(stylesheet), 0); - // We actually need to read in the XSLT file and keep track of the template // names, modes, etc.. Currently, this will not follow links that // import other stylesheets into the one being examined. @@ -80,7 +167,6 @@ throw new Exception("Error: Could not get XSLT document as DOM from source URL " + xsltURL + " (empty or malformed document?)"); } - getId(xsltDOMRoot); // retrieve the dublin core metadata String mode = null; // returned in the end @@ -93,6 +179,9 @@ continue; } String templateName = template.getAttribute("name"); + + templateIds.put(templateName, getId(template)); + String m = template.getAttribute("mode"); if(m != null && m.trim().length() > 0){ mode = template.getAttribute("mode"); @@ -150,12 +239,16 @@ typeNsRestrictions.get(templateNameParts[0]).insertElementAt(ns, 0); } + DOMSource stylesheet = new DOMSource(domDoc); + // Prepend to list, so later rules can override ones specified earlier + moby2textConverters.insertElementAt(transFactory.newTransformer(stylesheet), 0); + //System.err.println("Mode returned by " + xsltURL + " is " + mode); return mode; // return the last mode value in the file (useful when mapping XSLT -> data format) } // Looks for Dublin Core metadata - private void getId(Element xsltDOMRoot){ + private String getId(Element xsltDOMRoot){ NodeList idElements = xsltDOMRoot.getElementsByTagNameNS(MobyPrefixResolver.DUBLIN_CORE_NAMESPACE, "identifier"); if(idElements.getLength() == 0){ @@ -163,13 +256,17 @@ "source"); } if(idElements.getLength() == 0){ - return; + return null; } if(idElements.getLength() != 1){ System.err.println("More than one Dublin Core identifier was found, cannot disambiguate."); - return; + return null; } - id = idElements.item(0).getTextContent(); + String id = idElements.item(0).getTextContent(); + // remove child so id doesn't show up in the xslt output! + idElements.item(0).getParentNode().removeChild(idElements.item(0)); + System.err.println("Found and removed "+id); + return id; } /** @@ -374,17 +471,17 @@ e); } - if(client.id == null){ + if(client.templateIds.isEmpty()){ throw new Exception("Internal error: loaded the transformation rule (URI " + ruleURI + ") from " + ruleSource + " but could not retrieve it from TextClient " + "using the URI. Make sure the transformation rule contains a Dublin Core " + "identifier element specifying this URI."); } - else if(!client.id.equals(ruleURI)){ + else if(!client.templateIds.containsValue(ruleURI)){ throw new Exception("Internal error: loaded the transformation rule (URI " + ruleURI + ") from " + ruleSource + " but could not retrieve it from TextClient " + "using the URI. The given Dublin Core info for the rule actually loaded " + - "was " + client.id); + "was " + client.templateIds.values().iterator().next()); } else{ template = new MobyPrimaryDataSimple("templateRuleReturnedObject"); @@ -398,7 +495,7 @@ if(dataTypeNames.size() > 1){ throw new Exception("Multiple TextClient rules were loaded from " + ruleSource + ", please separate them out into separate XSLT files to ensure " + - "they can be referenced inidivudually and unambiguously."); + "they can be referenced indivudually and unambiguously."); } MobyDataType type = MobyDataType.getDataType(dataTypeNames.toArray()[0].toString(), client.getRegistry()); template.setDataType(type); From gordonp at dev.open-bio.org Fri Apr 23 01:17:28 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:17:28 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230517.o3N5HSKc024595@dev.open-bio.org> gordonp Fri Apr 23 01:17:28 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv24559/src/main/ca/ucalgary/seahawk/gui Modified Files: SeahawkTransferable.java Log Message: Better complex object drag and drop export support moby-live/Java/src/main/ca/ucalgary/seahawk/gui SeahawkTransferable.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/SeahawkTransferable.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/seahawk/gui/SeahawkTransferable.java 2009/06/09 19:46:48 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/SeahawkTransferable.java 2010/04/23 05:17:28 1.2 @@ -1,9 +1,15 @@ package ca.ucalgary.seahawk.gui; +import ca.ucalgary.seahawk.util.SeahawkOptions; +import ca.ucalgary.seahawk.services.TextClient; + +import org.biomoby.shared.MobyPrimaryData; import org.biomoby.shared.data.*; import java.awt.datatransfer.*; +import javax.swing.JOptionPane; import java.util.*; +import java.util.logging.*; /** * This class handles the export of data from the Seahawk interface into other applications, @@ -16,9 +22,20 @@ private String lastPastedValue; private String lastTransformRuleURI; + private static TextClient textClient; + private static Logger logger = Logger.getLogger(SeahawkTransferable.class.getName()); + public SeahawkTransferable(MobyContentPane p){ pane = p; } + + private synchronized TextClient getTextClient() throws Exception{ + if(textClient == null){ + textClient = new TextClient(SeahawkOptions.getRegistry()); + //auto populate the rules + } + return textClient; + } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, java.io.IOException{ @@ -28,7 +45,7 @@ Class clazz = flavor.getRepresentationClass(); // Essentially, we let the user drag Moby objects or submembers rather than substrings of members' text - // so that we can make simple rules for decomposition in programming-by-example. OR an XSLT "DEM" rulew + // so that we can make simple rules for decomposition in programming-by-example. OR an XSLT "DEM" rules // could be applied to provide a particular format e.g. DNASequence -> FastA String fieldString = null; String transformRuleURI = null; @@ -54,12 +71,38 @@ fieldString = ((MobyDataObject) field).getValue().toString(); transformRuleURI = "urn:lsid:bioxml.info:mobyLoweringSchemaMapping:DateTime2String"; } - else if(field instanceof MobyDataObjectVector){ - } - else if(field instanceof MobyDataObjectSet){ + else if(field instanceof MobyDataObjectVector){ + //todo? } else if(field instanceof MobyDataComposite){ - // todo: Is there a DEM rule we can use? + try{ + // Is there a DEM rule we can use? + boolean ONLY_IF_HAS_URN = true; + String[] formatChoices = getTextClient().getPossibleTextTypes((MobyPrimaryData) field, ONLY_IF_HAS_URN); + String targetTextType = null; + if(formatChoices != null && formatChoices.length != 0){ + if(formatChoices.length == 1){ + targetTextType = formatChoices[0]; + } + else{ + // Give the user a choice + targetTextType = formatChoices[0]; + logger.log(Level.INFO, "Chose "+formatChoices[0]+" instead of "+formatChoices[1]); +// targetTextType = (String) JOptionPane.showInputDialog(pane +// "Please select a text format to convert to", +// "Format choices available", +// JOptionPane.QUESTION_MESSAGE, +// null, +// formatChoices, +// formatChoices[0]); + } + } + fieldString = getTextClient().getText(field, targetTextType); + transformRuleURI = getTextClient().getTemplateURN(targetTextType); + } catch(Exception e){ + pane.setStatus("Could not transform Moby object to text: " + e.getMessage()); + logger.log(Level.SEVERE, "Could not transform Moby object to text: ", e); + } } else{ // Must be just a base MobyDataObject From gordonp at dev.open-bio.org Fri Apr 23 01:18:13 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:18:13 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230518.o3N5IDig024639@dev.open-bio.org> gordonp Fri Apr 23 01:18:13 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv24603/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyServicesGUI.java Log Message: Fixed duplication in complex object labels when they have namespaces too moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyServicesGUI.java,1.21,1.22 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.21 retrieving revision 1.22 diff -u -r1.21 -r1.22 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/18 00:31:49 1.21 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/23 05:18:13 1.22 @@ -1315,7 +1315,7 @@ } } if(templateObject instanceof MobyDataObject && id != null && id.length() > 0){ - objectLabel += ""+objectLabel+":" + id; + objectLabel = ""+objectLabel+":" + id; } else if(templateObject instanceof MobyDataObjectSet){ objectLabel = ""+objectLabel+" collection"; From gordonp at dev.open-bio.org Fri Apr 23 01:19:10 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:19:10 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230519.o3N5JAnp024685@dev.open-bio.org> gordonp Fri Apr 23 01:19:10 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv24649/src/main/ca/ucalgary/seahawk/gui Modified Files: MobySaveDialog.java Log Message: Removed redundant popup of single tab export if canceled moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobySaveDialog.java,1.9,1.10 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java 2010/04/18 00:33:05 1.9 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java 2010/04/23 05:19:10 1.10 @@ -92,11 +92,11 @@ fileChooser.setName(FILE_CHOOSER_SAVE_TITLE); fileChooser.setFileHidingEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(HTML_EXT, HTML_DESC)); if(document.hasXMLSource()){ - fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(T2FLOW_EXT, T2FLOW_DESC)); fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(XML_EXT, XML_DESC)); + fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(T2FLOW_EXT, T2FLOW_DESC)); } - fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(HTML_EXT, HTML_DESC)); fileChooser.setAcceptAllFileFilterUsed(false); if(lastDirOpened != null){ fileChooser.setCurrentDirectory(lastDirOpened); @@ -277,7 +277,8 @@ // Waits until workflowConfirmed or workflowCanceled is called by the preview dialog dialog.available.acquire(); - return dialog.exportConfirmed; + // Check choice, because if the user cancelled the dialog, don't show it again regardless + return choice == 1 ? true : dialog.exportConfirmed; } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(null, "Cannot save the Seahawk tab history as a Taverna workflow: "+ex, From gordonp at dev.open-bio.org Fri Apr 23 01:20:00 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:20:00 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230520.o3N5K0NK024729@dev.open-bio.org> gordonp Fri Apr 23 01:20:00 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv24693/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java Log Message: Fixed bug with support of plus sign in URLs to wrap as services moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.29,1.30 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.29 retrieving revision 1.30 diff -u -r1.29 -r1.30 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/16 17:33:25 1.29 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/23 05:20:00 1.30 @@ -273,6 +273,10 @@ } } + public void setStatus(String msg){ + status.setText(msg); + } + // servletPath is either the CGI or SOAP servlet private void createService(String servletPath){ // item name, set by MobyContentGUI's processResults(), is namedXPath#numericXPtr @@ -459,7 +463,7 @@ "Please manually launch a browser and go to the URL " + u); } - desktop.browse(u.toURI()); + desktop.browse(new java.net.URI(u.toURI().toString().replace("+", "%2B"))); } catch (java.net.URISyntaxException urise){ logger.error("Could not create URI from URL ("+u+"): " + urise); } catch (java.io.IOException ioe){ From gordonp at dev.open-bio.org Fri Apr 23 01:21:42 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:21:42 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230521.o3N5LgTu024871@dev.open-bio.org> gordonp Fri Apr 23 01:21:42 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv24839/src/main/ca/ucalgary/seahawk/resources Added Files: mobyRules.xsl Log Message: Sibling of mobyRules.xsl in src/main/ca/ucalgary/services/resources, but with nicer format names and Dublin Core IDs for Daggoo wrapping moby-live/Java/src/main/ca/ucalgary/seahawk/resources mobyRules.xsl,NONE,1.1 From gordonp at dev.open-bio.org Sat Apr 24 13:23:27 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 24 Apr 2010 13:23:27 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004241723.o3OHNRQZ007370@dev.open-bio.org> gordonp Sat Apr 24 13:23:27 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv7331/src/main/ca/ucalgary/seahawk/gui Modified Files: MobySecondaryInputGUI.java MobyServicesGUI.java Added Files: ServiceChoiceListener.java ServiceSearchDialog.java Log Message: Initial commit of service search dialog moby-live/Java/src/main/ca/ucalgary/seahawk/gui ServiceChoiceListener.java,NONE,1.1 ServiceSearchDialog.java,NONE,1.1 MobySecondaryInputGUI.java,1.7,1.8 MobyServicesGUI.java,1.22,1.23 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySecondaryInputGUI.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySecondaryInputGUI.java 2007/12/06 17:32:32 1.7 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySecondaryInputGUI.java 2010/04/24 17:23:26 1.8 @@ -1,4 +1,3 @@ - package ca.ucalgary.seahawk.gui; import ca.ucalgary.seahawk.services.MobyClient; =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/23 05:18:13 1.22 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/24 17:23:26 1.23 @@ -27,7 +27,7 @@ * Implementation of the actually popup menu that lists services available, and invokes them. */ -public class MobyServicesGUI implements ActionListener, Comparator, PopupMenuListener{ +public class MobyServicesGUI implements ActionListener, Comparator, PopupMenuListener, ServiceChoiceListener{ public final static int MAX_ID_LEN = 30; public final static String SERVICE_SUBMENU_NAME = "seahawkPopupSubMenuName"; @@ -35,6 +35,10 @@ public final static int MAX_SERVICES_PER_SUBMENU = 12; public final static int MAX_SERVICE_DESC_LEN = 50; public final static String CLIPBOARD_CMD = "clipboard"; + public final static String SERVICESEARCH_CMD = "service_search"; + public final static String SEARCH_LABEL = "Find service by keyword..."; + public final static String CLIPBOARD_LABEL = "Add to clipboard"; + /** Always spring MOBY response in a new window if this modifier is present for a click */ public final static int USE_DEFAULT_HANDLER_MASK = ActionEvent.SHIFT_MASK; public final static int USE_DEFAULT_SECONDARIES_MASK = ActionEvent.CTRL_MASK; @@ -57,6 +61,7 @@ int maxDataDesc = 22; // tracks nested submenus to root submenus of choices popup private Map service2submenu; + private Map search2submenu; private Map submenu2msIndex; private Map submenu2waitItem; // for storing callbacks to other than the default response handler @@ -75,6 +80,7 @@ submenu2msIndex = new HashMap(); submenu2waitItem = new HashMap(); service2submenu = new HashMap(); + search2submenu = new HashMap(); specificHandlers = new HashMap>(); } @@ -124,6 +130,20 @@ } return; } + if(service.equals(SERVICESEARCH_CMD)){ + synchronized(ms){ + if(ms[which_data] == null){ + logger.warn("Ignoring searvice search in " + getClass().getName() + + ", the data to add is currently null (index "+which_data+")"+ + ", from source " + e.getSource()); + removePopupOptions(e.getSource()); + return; + } + setupSearchData(search2submenu.get((JMenuItem) e.getSource()), ms[which_data]); + removePopupOptions(e.getSource()); + } + return; + } // Otherwise call a remote service int which_service = Integer.parseInt(service); @@ -322,7 +342,7 @@ } /** - * If the popup is cancelled, we want to remove any data we've stored, and kill any + * If the popup is canceled, we want to remove any data we've stored, and kill any * requests to MOBYCentral. */ public void popupMenuCanceled(PopupMenuEvent e){ @@ -533,6 +553,7 @@ for(int i = 0; i < submenus.length; i++){ addServicesToSubMenu(submenus[i], serviceAssocObjects[i], handler); + addSearchItem(submenus[i], 1); } } @@ -595,6 +616,7 @@ //}}.start(); } service2submenu.clear(); + search2submenu.clear(); submenu2msIndex.clear(); submenu2waitItem.clear(); ms = new MobyDataServiceAssocInstance[0]; @@ -732,6 +754,7 @@ } addServicesToSubMenu(submenu, serviceAssocObject, handler); + addSearchItem(submenu, 0); } protected synchronized void addServicesToSubMenu(JMenu submenu, MobyDataServiceAssocInstance msadi){ @@ -1333,6 +1356,15 @@ return submenu; } + public void serviceSelected(ServiceSearchDialog dialog, javax.swing.JMenuItem selectedServiceItem){ + actionPerformed(new ActionEvent(selectedServiceItem, 1, selectedServiceItem.getActionCommand())); + removePopupOptions(); + } + + public void selectionCanceled(ServiceSearchDialog dialog){ + removePopupOptions(); //cleanup stored data + } + private synchronized int assignMenuDataIndex(JMenu submenu){ // Make the services array bigger, then copy over existing data, // leaving a blank at the end to be filled in by addServicesToSubMenu @@ -1370,6 +1402,64 @@ } } + /** + * Removes the popup menu and replaces it with a window that has a filter widget + * over the list of services from the original popup. + */ + protected void setupSearchData(JMenu objectMenu, MobyDataInstance mobyData){ + // Setup the chooser dialog + ServiceSearchDialog searchDialog = new ServiceSearchDialog(null, + objectMenu.getText().replaceFirst("Services for", "Run "), + this); + addMenuOptionsToSearch(searchDialog, objectMenu); + + searchDialog.initializeList(); + searchDialog.pack(); + searchDialog.setVisible(true); + } + + private void addMenuOptionsToSearch(ServiceSearchDialog searchDialog, MenuElement menuElement){ + if(menuElement instanceof JPopupMenu || menuElement instanceof JMenu){ + for(MenuElement subMenuElement: menuElement.getSubElements()){ + addMenuOptionsToSearch(searchDialog, subMenuElement); + } + } + else if(menuElement instanceof JMenuItem){ // leaf defining a service + JMenuItem serviceItem = (JMenuItem) menuElement; + String label = serviceItem.getText(); + if(label.equals(SEARCH_LABEL) || label.equals(CLIPBOARD_LABEL)){ + return; // not real services + } + serviceItem.setText(label.replaceFirst("Run ", "")); + searchDialog.addOption(serviceItem, false); + } + else{ + System.err.println("Got dead end with "+menuElement.getClass().getName()); + } + } + + public void addSearchItem(JMenu menu, int location){ + if(menu == null){ + logger.warn("Cannot add service search option, menu reference passed in was null"); + return; + } + + if(!submenu2msIndex.containsKey(menu)){ + logger.warn("Cannot add service search option, cannot find " + + "moby object list index for menu " + + menu.getText()); + return; + } + + + int dataIndex = ((Integer) submenu2msIndex.get(menu)).intValue(); + JMenuItem searchItem = new JMenuItem(SEARCH_LABEL); + searchItem.setActionCommand("MOBY:"+dataIndex+":"+SERVICESEARCH_CMD); + searchItem.addActionListener(this); + menu.add(searchItem, location); + search2submenu.put(searchItem, menu); + } + public void addClipboardItem(JMenu menu, MobyDataInstance mobyData){ if(menu == null){ logger.warn("Cannot add clipboard option, menu reference passed in was null"); @@ -1408,11 +1498,11 @@ } else{ logger.warn("Clipboard option for objects other than MobyDataObject " + - "and MobyDataObjectSet are not yet supported:"+mobyData); + "and MobyDataObjectSet are not yet supported:"+mobyData); return; } - JMenuItem clipItem = new JMenuItem("Add to clipboard"); + JMenuItem clipItem = new JMenuItem(CLIPBOARD_LABEL); clipItem.setActionCommand("MOBY:"+dataIndex+":"+CLIPBOARD_CMD); clipItem.addActionListener(this); menu.add(clipItem); From gordonp at dev.open-bio.org Mon Apr 26 12:25:36 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:25:36 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261625.o3QGPasj025559@dev.open-bio.org> gordonp Mon Apr 26 12:25:36 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv25523/src/main/ca/ucalgary/seahawk/util Modified Files: DataUtils.java Log Message: Ensured that moby namepsace is defined for xpath moby-live/Java/src/main/ca/ucalgary/seahawk/util DataUtils.java,1.6,1.7 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/16 17:33:26 1.6 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/26 16:25:36 1.7 @@ -1044,7 +1044,7 @@ // first arg is url#nameBasedXPath peerGroupXPath = userData[0].split("#", 2)[1]; contextNode = XPointerResolver.getNodeFromXPointer(doc, userData[1]); - //System.err.println("Loaded context node " + userData[1] + " as " + contextNode); + System.err.println("Loaded context node " + userData[1] + " as " + contextNode); } else{ // Fallback is to get all nodes with the same name... @@ -1082,13 +1082,16 @@ try{ XPath xpath = xPathFactory.newXPath(); if(contextNode != null){ - xpath.setNamespaceContext(new NamespaceContextImpl(contextNode, "d")); + NamespaceContextImpl nsContext = new NamespaceContextImpl(contextNode, "d"); + nsContext.setPrefix(MobyPrefixResolver.MOBY_XML_NAMESPACE, "d"); + xpath.setNamespaceContext(nsContext); } peerElements = (NodeList) xpath.evaluate(peerGroupXPath, doc, XPathConstants.NODESET); } catch(Exception e){ logger.log(Level.SEVERE, "Could not evaluate UserData XPath "+peerGroupXPath, e); + return null; } //System.err.println("Got " + peerElements.getLength() + " peers for " + peerGroupXPath); From gordonp at dev.open-bio.org Mon Apr 26 12:26:18 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:26:18 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261626.o3QGQIZl025603@dev.open-bio.org> gordonp Mon Apr 26 12:26:18 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv25567/src/main/ca/ucalgary/seahawk/gui Modified Files: ServiceSearchDialog.java Log Message: Case insensitive service name highlighting during search moby-live/Java/src/main/ca/ucalgary/seahawk/gui ServiceSearchDialog.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/ServiceSearchDialog.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/seahawk/gui/ServiceSearchDialog.java 2010/04/24 17:23:27 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/ServiceSearchDialog.java 2010/04/26 16:26:18 1.2 @@ -127,6 +127,10 @@ Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); activeChoices.clear(); for(JMenuItem serviceChoice: serviceChoices){ + if(serviceChoice.getText() == null){ + continue; + } + String label = serviceChoice.getText().replaceAll("<.*?>", "").replaceAll("see description", ""); // get rid of any coloring @@ -134,12 +138,15 @@ if(searchTerm == null || searchTerm.trim().length() == 0){ serviceChoice.setText(label); activeChoices.addElement(serviceChoice); + continue; } + Matcher matcher = searchPattern.matcher(label); // In the label? - else if(serviceChoice.getText() != null && - searchPattern.matcher(label).find()){ - label = label.replaceAll("("+searchTerm+")", "$1"); - serviceChoice.setText(""+label+""); + if(matcher.find()){ + label = label.substring(0, matcher.start())+"" + + matcher.group(0) + "" + + (matcher.end() >= label.length() ? "" : label.substring(matcher.end())); + serviceChoice.setText("" + label + ""); activeChoices.addElement(serviceChoice); } // In the tooltip? From gordonp at dev.open-bio.org Mon Apr 26 12:27:31 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:27:31 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261627.o3QGRVV6025647@dev.open-bio.org> gordonp Mon Apr 26 12:27:31 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv25611/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyServicesGUI.java Log Message: Better UI refresh moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyServicesGUI.java,1.23,1.24 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.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/MobyServicesGUI.java 2010/04/24 17:23:26 1.23 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/26 16:27:31 1.24 @@ -554,6 +554,7 @@ for(int i = 0; i < submenus.length; i++){ addServicesToSubMenu(submenus[i], serviceAssocObjects[i], handler); addSearchItem(submenus[i], 1); + refreshMenu(submenus[i]); } } @@ -755,6 +756,7 @@ addServicesToSubMenu(submenu, serviceAssocObject, handler); addSearchItem(submenu, 0); + refreshMenu(submenu); } protected synchronized void addServicesToSubMenu(JMenu submenu, MobyDataServiceAssocInstance msadi){ @@ -1121,7 +1123,9 @@ } submenu.add(mobyItem); } + } + protected void refreshMenu(JMenu submenu){ // Causes resizing based on new items if(submenu.isPopupMenuVisible()){ submenu.setPopupMenuVisible(false); From gordonp at dev.open-bio.org Mon Apr 26 12:28:11 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:28:11 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261628.o3QGSB9E025691@dev.open-bio.org> gordonp Mon Apr 26 12:28:11 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv25655/src/main/ca/ucalgary/seahawk/gui Modified Files: FilterSearchWidget.java Log Message: Proper update of selected XPath when search restored moby-live/Java/src/main/ca/ucalgary/seahawk/gui FilterSearchWidget.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.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/seahawk/gui/FilterSearchWidget.java 2010/04/10 00:40:17 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/26 16:28:11 1.4 @@ -112,6 +112,7 @@ docPartOptions.setEnabled(true); docPartOptions.setModel(new DefaultComboBoxModel(fs.getXPathOptions())); + docPartOptions.setSelectedItem(fs.getSelectedXPath()); currentFilterSearch = fs; // done in this order so no feedback as DocumentEvents while setting fields programmatically } From gordonp at dev.open-bio.org Mon Apr 26 12:29:13 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:29:13 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261629.o3QGTD4M025779@dev.open-bio.org> gordonp Mon Apr 26 12:29:13 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv25739/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java MobyPayloadCreator.java Log Message: Account for possibility of null peer elements list moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.30,1.31 MobyPayloadCreator.java,1.4,1.5 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.30 retrieving revision 1.31 diff -u -r1.30 -r1.31 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/23 05:20:00 1.30 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/26 16:29:13 1.31 @@ -1237,7 +1237,7 @@ // note that getPeerElements() will modify the userData to reflect the semantic of the requested peer mode mobyData.setUserData(origUserData); NodeList peerElements = DataUtils.getPeerElements(getCurrentDoc(), mobyData, getFilteredData(), peerMode); - if(peerElements.getLength() <= 1){ + if(peerElements == null || peerElements.getLength() <= 1){ continue; // no 'for each' option if only one to process... } String each = "each (" + peerElements.getLength() + " total)"; =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/18 00:33:56 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/26 16:29:13 1.5 @@ -85,8 +85,12 @@ NodeList peerElements = DataUtils.getPeerElements(doc, mobyDataContext, xptrsToFilter, DataUtils.DATATYPE_PEERS_MODE); - // find the peers of defined by the userData selection constraints and put them into a MobyContentInstance MobyContentInstance payload = new MobyContentInstance(); + if(peerElements == null){ + return payload; + } + + // find the peers of defined by the userData selection constraints and put them into a MobyContentInstance Map jobPrefixes = new LinkedHashMap(); logger.log(Level.FINE, "Loading MobyContentInstance with "+peerElements.getLength()+" elements for xpath "+selectionXPath); From gordonp at dev.open-bio.org Mon Apr 26 13:50:34 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 13:50:34 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261750.o3QHoXg0029187@dev.open-bio.org> gordonp Mon Apr 26 13:50:33 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv29151/src/main/ca/ucalgary/seahawk/gui Modified Files: FilterSearchWidget.java Log Message: Kung foo with semaphores to let search filter only apply every 600ms or so when typing a longer string moby-live/Java/src/main/ca/ucalgary/seahawk/gui FilterSearchWidget.java,1.4,1.5 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/26 16:28:11 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/26 17:50:33 1.5 @@ -5,6 +5,7 @@ import java.awt.Dimension; import java.awt.event.*; import java.net.URL; +import java.util.concurrent.*; import java.util.logging.*; import javax.swing.*; import javax.swing.event.*; @@ -22,6 +23,8 @@ private JTextField searchField; private JComboBox docPartOptions; private MobyContentPane contentPane; + private Semaphore semaphore; // for search update delays in multikeystroke + public static final String CASE_SENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_sensitive.png"; public static final String CASE_INSENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_insensitive.png"; private static final String IF_TEXT = "if"; @@ -48,6 +51,8 @@ closeIcon.addMouseListener(new Closer(this)); closeIcon.setToolTipText("Remove filter criteria"); + semaphore = new Semaphore(1); //1 search update for a given timeframe + Dimension buttonSize = new Dimension(24,24); caseButton = new JToggleButton(new ImageIcon(cl.getResource(CASE_SENSITIVE_ICON_RESOURCE))); caseButton.setDisabledIcon(new ImageIcon(cl.getResource(CASE_INSENSITIVE_ICON_RESOURCE))); @@ -162,8 +167,10 @@ return; } StringBuffer sb = currentFilterSearch.getFilterRegex(); - sb.replace(0, sb.length(), searchField.getText()); - contentPane.applyFilter(true); + synchronized(searchField){ + sb.replace(0, sb.length(), searchField.getText()); + } + applyFilterWhenSuitable(); } public void insertUpdate(DocumentEvent e){ @@ -171,8 +178,10 @@ return; } StringBuffer sb = currentFilterSearch.getFilterRegex(); - sb.replace(0, sb.length(), searchField.getText()); - contentPane.applyFilter(true); + synchronized(searchField){ + sb.replace(0, sb.length(), searchField.getText()); + } + applyFilterWhenSuitable(); } public void removeUpdate(DocumentEvent e){ @@ -180,10 +189,53 @@ return; } StringBuffer sb = currentFilterSearch.getFilterRegex(); - sb.replace(0, sb.length(), searchField.getText()); - contentPane.applyFilter(true); + synchronized(searchField){ + sb.replace(0, sb.length(), searchField.getText()); + } + applyFilterWhenSuitable(); } + // Waits 600 milliseconds to see if the user is typing a phrase, rather than + // filtering for each letter added, which can be slow + private void applyFilterWhenSuitable(){ + try{ + final Semaphore sem = semaphore; + final MobyContentPane pane = contentPane; + final JTextField sf = searchField; + if(sem.tryAcquire()){ + new Thread(){ + public void run(){ + try{ + Thread.sleep(500); + } + catch(Exception e){ + logger.log(Level.WARNING, + "Delay less than 400ms on search input due to interrupt", + e); + } + synchronized(sf){ + try{ + // Give 100ms for other threads past sb.replace() in DocumentListener callbacks to + // try to acquire a permit, avoiding redundant applyFiolter call + Thread.sleep(100); + } + catch(Exception e){ + logger.log(Level.WARNING, + "Delay less than 100ms on search input due to interrupt", + e); + } + pane.applyFilter(true); + sem.release(); + } + } + }.start(); + } + }catch(Exception e){ + logger.log(Level.SEVERE, "Search result updater was interrupted while waiting for a semaphore," + + "GUI may not reflect search field", e); + } + // else, it's going to be updated soon anyway with the latest string buffer...just return + } class Closer extends MouseAdapter{ boolean active = false; From gordonp at dev.open-bio.org Fri Apr 9 02:23:15 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Thu, 8 Apr 2010 22:23:15 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004090223.o392NFDP006711@dev.open-bio.org> gordonp Thu Apr 8 22:23:15 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/images In directory dev.open-bio.org:/tmp/cvs-serv6679/src/main/ca/ucalgary/seahawk/resources/images Added Files: case_insensitive.png case_sensitive.png Log Message: Icon for search filter's case sensitivity moby-live/Java/src/main/ca/ucalgary/seahawk/resources/images case_insensitive.png,NONE,1.1 case_sensitive.png,NONE,1.1 From gordonp at dev.open-bio.org Fri Apr 9 15:47:04 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:47:04 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091547.o39Fl4m3001186@dev.open-bio.org> gordonp Fri Apr 9 11:47:03 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv1154/src/main/ca/ucalgary/seahawk/resources Added Files: PassFilterBeanShell FlattenListBeanShell Log Message: Taverna beanshells used in Seahawk's programming-by-example system moby-live/Java/src/main/ca/ucalgary/seahawk/resources PassFilterBeanShell,NONE,1.1 FlattenListBeanShell,NONE,1.1 From gordonp at dev.open-bio.org Fri Apr 9 15:48:19 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:48:19 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091548.o39FmJJf001286@dev.open-bio.org> gordonp Fri Apr 9 11:48:19 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv1250/src/main/ca/ucalgary/seahawk/util Modified Files: FilterSearch.java Log Message: Added case sensitivity, constant for select-all xpath moby-live/Java/src/main/ca/ucalgary/seahawk/util FilterSearch.java,1.2,1.3 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.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/seahawk/util/FilterSearch.java 2010/03/29 19:49:52 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/09 15:48:19 1.3 @@ -20,9 +20,11 @@ public class FilterSearch{ private URL docURL; + private boolean caseSensitivity = false; private StringBuffer filterRegex; private Vector xpathOptions; private int xpathSelected = 0; + public static final String SELECT_ALL_XPATH = "//* | //*/@*"; /** * @param docToFilter the document that will be used to determine what XPaths can be suggested @@ -34,7 +36,7 @@ docURL = docToFilter; filterRegex = new StringBuffer(); xpathOptions = new Vector(); - xpathOptions.add(new XPathOption("//*", "entire document")); + xpathOptions.add(new XPathOption(SELECT_ALL_XPATH, "entire response")); Document domDoc = docBuilder.parse(docURL.openStream()); // Get the moby jobs NodeList jobs = domDoc.getDocumentElement().getElementsByTagNameNS(MobyPrefixResolver.MOBY_XML_NAMESPACE, MobyTags.MOBYDATA); @@ -72,6 +74,14 @@ } } + public boolean getCaseSensitivity(){ + return caseSensitivity; + } + + public void setCaseSensitivity(boolean sensitivity){ + caseSensitivity = sensitivity; + } + public void setSelectedXPath(int cursor){ xpathSelected = cursor; } From gordonp at dev.open-bio.org Fri Apr 9 15:49:18 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:49:18 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091549.o39FnI8b001330@dev.open-bio.org> gordonp Fri Apr 9 11:49:18 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv1294/src/main/ca/ucalgary/seahawk/resources Modified Files: RegexFilterBeanShell Log Message: Added case sensitivity, eliminated auto-attr matching since select-all xpath has been fixed moby-live/Java/src/main/ca/ucalgary/seahawk/resources RegexFilterBeanShell,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/RegexFilterBeanShell,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/seahawk/resources/RegexFilterBeanShell 2010/03/17 20:03:06 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/RegexFilterBeanShell 2010/04/09 15:49:18 1.2 @@ -1,4 +1,5 @@ import java.util.*; +import java.util.regex.Pattern; import org.dom4j.*; import org.dom4j.io.SAXReader; @@ -13,24 +14,18 @@ int i = 1; Map collections = new LinkedHashMap(); Map collectionsEnd = new HashMap(); -select: for (Iterator iter = nodelist.iterator(); iter.hasNext();) { +Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL | (Boolean.parseBoolean(case_sensitive) ? 0 : Pattern.CASE_INSENSITIVE)); +for (Iterator iter = nodelist.iterator(); iter.hasNext();) { Node node = (Node) iter.next(); boolean match = false; switch(node.getNodeType()){ case Node.ELEMENT_NODE: - if(node.getText().matches(".*?"+regex+".*")){ + if(pattern.matcher(node.getText()).find()){ match = true; } - else{ - for(Object attr: ((Element) node).attributeIterator()){ - if(((Attribute) attr).getValue().matches(".*?"+regex+".*")){ - match = true; break; - } - } - } break; case Node.ATTRIBUTE_NODE: - if(node.getValue().matches(".*?"+regex+".*")){ + if(pattern.matcher(node.getValue()).find()){ match = true; } break; From gordonp at dev.open-bio.org Fri Apr 9 15:50:09 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:50:09 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091550.o39Fo903001396@dev.open-bio.org> gordonp Fri Apr 9 11:50:09 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv1360/src/main/ca/ucalgary/seahawk/gui Modified Files: FilterSearchWidget.java Log Message: Added case sensitivity moby-live/Java/src/main/ca/ucalgary/seahawk/gui FilterSearchWidget.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.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/seahawk/gui/FilterSearchWidget.java 2010/03/17 20:20:47 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/09 15:50:09 1.2 @@ -17,9 +17,13 @@ private FilterSearch currentFilterSearch; private JLabel closeIcon; + private JToggleButton caseButton; private JTextField searchField; private JComboBox docPartOptions; private MobyContentPane contentPane; + public static final String CASE_SENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_sensitive.png"; + public static final String CASE_INSENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_insensitive.png"; + private static final String CASE_BUTTON_NAME = "case_sensitivity_button"; private static Logger logger = Logger.getLogger(FilterSearchWidget.class.getName()); @@ -27,7 +31,8 @@ super(); contentPane = mcp; - URL u = Thread.currentThread().getContextClassLoader().getResource(CloseTabIcon.CLOSE_TAB_ICON_RESOURCE); + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + URL u = cl.getResource(CloseTabIcon.CLOSE_TAB_ICON_RESOURCE); if(u == null){ throw new Exception("Could not find icon resource " + CloseTabIcon.CLOSE_TAB_ICON_RESOURCE); } @@ -37,9 +42,22 @@ closeIcon.addMouseListener(new Closer(this)); closeIcon.setToolTipText("Remove filter criteria"); + Dimension buttonSize = new Dimension(24,24); + caseButton = new JToggleButton(new ImageIcon(cl.getResource(CASE_SENSITIVE_ICON_RESOURCE))); + caseButton.setDisabledIcon(new ImageIcon(cl.getResource(CASE_INSENSITIVE_ICON_RESOURCE))); + caseButton.setToolTipText("Toggles the case sensitivity of the filter"); + caseButton.setPreferredSize(buttonSize); + caseButton.setEnabled(true); + caseButton.setSelected(false); + caseButton.addActionListener(this); + caseButton.setMargin(new java.awt.Insets(2,2,2,2)); + caseButton.setName(CASE_BUTTON_NAME); // so test cases can find the component + setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); add(closeIcon); add(Box.createRigidArea(new Dimension(5,0))); + add(caseButton); + add(Box.createRigidArea(new Dimension(5,0))); add(new JLabel("Show data if ")); add(Box.createRigidArea(new Dimension(5,0))); searchField = new JTextField(25); @@ -62,11 +80,15 @@ public void setFilter(FilterSearch fs){ currentFilterSearch = null; if(fs == null){ + caseButton.setEnabled(false); searchField.setEnabled(false); docPartOptions.setEnabled(false); return; } + caseButton.setEnabled(true); + caseButton.setSelected(fs.getCaseSensitivity()); + searchField.setEnabled(true); searchField.setText(fs.getFilterRegex().toString()); @@ -79,7 +101,15 @@ * Called when the user has changed the xpath */ public void actionPerformed(ActionEvent e){ - if(currentFilterSearch == null || e.getSource() != docPartOptions){ + if(e.getSource() == caseButton){ + if(currentFilterSearch == null){ + return; + } + currentFilterSearch.setCaseSensitivity(caseButton.isSelected()); + contentPane.applyFilter(true); + return; + } + else if(currentFilterSearch == null || e.getSource() != docPartOptions){ return; } currentFilterSearch.setSelectedXPath(docPartOptions.getSelectedIndex()); From gordonp at dev.open-bio.org Fri Apr 9 15:51:53 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:51:53 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091551.o39FprFb001496@dev.open-bio.org> gordonp Fri Apr 9 11:51:53 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv1460/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentClipboard.java Log Message: data xml src passthrough to enable 'previous input' services moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentClipboard.java,1.8,1.9 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/03/29 19:47:02 1.8 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/09 15:51:53 1.9 @@ -113,8 +113,8 @@ return false; } - protected void addExtraMobyOptions(JPopupMenu popup, MobyDataInstance mdi){ - super.addExtraMobyOptions(popup, mdi); + protected void addExtraMobyOptions(JPopupMenu popup, MobyDataInstance mdi, URL srcURL){ + super.addExtraMobyOptions(popup, mdi, srcURL); // Only process if the passed in data is one of the top level collection elements // (i.e. don't delete subparts of object) From gordonp at dev.open-bio.org Fri Apr 9 15:54:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:54:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091554.o39FsHP8001666@dev.open-bio.org> 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 jobXPtrs = null; // Map private List filterableNodes = null; // List private List 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(); filterableNodes = new Vector(); 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 matchingXPtrs = new LinkedHashMap(); // 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 filterList, Element object){ + private Boolean addHASXPtrs(List 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 highlights = new HashMap(); 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"); From gordonp at dev.open-bio.org Fri Apr 9 15:55:49 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:55:49 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091555.o39FtnLh001766@dev.open-bio.org> gordonp Fri Apr 9 11:55:48 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv1730/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyServicesGUI.java Log Message: Added ability to customize top level menu items with extra text (used initially by 'previous input' feature) moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyServicesGUI.java,1.16,1.17 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2009/06/09 19:27:56 1.16 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/09 15:55:48 1.17 @@ -442,7 +442,7 @@ // Create the top level menu items for these moby objects right away submenus = new JMenu[mobyObjects.length]; for(int i = 0; i < mobyObjects.length; i++){ - JMenu submenu = createObjectSubMenu(mobyObjects[i]); + JMenu submenu = createObjectSubMenu(mobyObjects[i], null); if(submenu == null){ continue; } @@ -503,6 +503,7 @@ Node targetNode = null; MobyRequestEventHandler handler = null; MobyDataInstance mobyData = null; + String extraMenuText = null; JPopupMenu popupList; public OptionLoaderThread(Node targetNode, JPopupMenu popupList, MobyRequestEventHandler handler){ @@ -512,11 +513,12 @@ this.handler = handler; } - public OptionLoaderThread(MobyDataInstance mobyData, JPopupMenu popupList, MobyRequestEventHandler handler){ + public OptionLoaderThread(MobyDataInstance mobyData, JPopupMenu popupList, MobyRequestEventHandler handler, String extraMenuText){ super(); this.mobyData = mobyData; this.popupList = popupList; this.handler = handler; + this.extraMenuText = extraMenuText; } public void run(){ @@ -524,7 +526,7 @@ addPopupOptions(targetNode, popupList, false, handler); } else if(mobyData != null){ - addPopupOptions(mobyData, popupList, false, handler); + addPopupOptions(mobyData, popupList, false, handler, extraMenuText); } else{ logger.warn("Warning: OptionLoaderThread has no data to work with"); @@ -584,6 +586,13 @@ * Find the list of available services querying MobyCentral directly with a piece of data. */ public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous, MobyRequestEventHandler handler){ + addPopupOptions(mobyData, popupList, asynchronous, handler, null); + } + + /** + * Find the list of available services querying MobyCentral directly with a piece of data. + */ + public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous, MobyRequestEventHandler handler, String extraMenuText){ if(asynchronous){ //Show the user that we're doing something... @@ -596,13 +605,13 @@ } // Call this method synchronously in a different thread - OptionLoaderThread lt = new OptionLoaderThread(mobyData, popupList, handler); + OptionLoaderThread lt = new OptionLoaderThread(mobyData, popupList, handler, extraMenuText); lt.start(); return; } // Create submenu for this object - JMenu submenu = createObjectSubMenu(mobyData); + JMenu submenu = createObjectSubMenu(mobyData, extraMenuText); // Add option to copy object to clipboard. We don't need to wait until services are found. if(submenu == null){ return; @@ -1127,7 +1136,7 @@ return menu; } - public JMenu createObjectSubMenu(MobyDataInstance mdi){ + public JMenu createObjectSubMenu(MobyDataInstance mdi, String extraMenuText){ if(!(mdi instanceof MobyPrimaryData)){ logger.warn("Ignoring non-primary data object submitted to menu creation: " + mdi); return null; @@ -1205,7 +1214,7 @@ } } desc = "Record Identifier - " + mobydesc; - submenu = new JMenu("Services for " + datatype + ":" + id); + submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+datatype + ":" + id); assignMenuDataIndex(submenu); } else if("String".equals(mobyDataType.getName())){ @@ -1217,7 +1226,8 @@ sample = sample.substring(0, MAX_ID_LEN)+"..."; } desc = "A piece of text"; - submenu = new JMenu("Services for String \"" + sample + "\""); + submenu = new JMenu("Services for "+(extraMenuText == null ? "" : extraMenuText+" ")+ + "String \"" + sample + "\""); assignMenuDataIndex(submenu); } // Complex object @@ -1236,7 +1246,7 @@ else if(targetData instanceof MobyDataObjectSet){ objectLabel += " collection"; } - submenu = new JMenu("Services for " + objectLabel); + submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+objectLabel); assignMenuDataIndex(submenu); } desc = "Input data: " + desc; From gordonp at dev.open-bio.org Fri Apr 9 15:57:46 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:57:46 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091557.o39FvkSp001872@dev.open-bio.org> gordonp Fri Apr 9 11:57:46 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv1836/src/main/ca/ucalgary/seahawk/util Modified Files: DataUtils.java Log Message: Added support for case sensitive searches, and 'previous input' conditional service execution moby-live/Java/src/main/ca/ucalgary/seahawk/util DataUtils.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.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/seahawk/util/DataUtils.java 2010/03/29 19:58:17 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/09 15:57:46 1.2 @@ -117,7 +117,7 @@ if(newFilter != null){ XPathOption xsel = newFilter.getSelectedXPath(); newProvenanceData += "\t"+newFilter.getFilterRegex()+ - "\t"+xsel.getXPath()+"\t"+xsel.getDesc(); + "\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+newFilter.getCaseSensitivity(); } pi.setData(attr_val[0]+"=\""+newProvenanceData+"\""); } @@ -300,7 +300,7 @@ return temp.toURI().toURL(); } - private static URL getInputURL(Document responseDom) throws Exception{ + public static URL getInputURL(Document responseDom) throws Exception{ String inputAddr = getSeahawkAttrFromDoc(responseDom, SERVICEINPUT_ATTR); if(inputAddr == null){ return null; @@ -315,7 +315,11 @@ } } - private static Document getInputDoc(Document responseDom) throws Exception{ + public static Document getInputDoc(Document responseDom) throws Exception{ + URL inputURL = getInputURL(responseDom); + if(inputURL == null){ + return null; + } try{ return docBuilder.parse(getInputURL(responseDom).openStream()); } catch(org.xml.sax.SAXException saxe){ @@ -332,6 +336,9 @@ */ public static MobyDataJob getInputSample(Document responseDom, Registry registry) throws Exception{ Document inputDoc = getInputDoc(responseDom); + if(inputDoc == null){ + return null; + } MobyContentInstance inputPayload = MobyDataUtils.fromXMLDocument(inputDoc.getDocumentElement(), registry); if(inputPayload == null || inputPayload.size() == 0){ @@ -633,12 +640,30 @@ if(fs != null && fs.getFilterRegex().length() > 0){ XPathOption xsel = fs.getSelectedXPath(); - userData.append("\t"+fs.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()); + userData.append("\t"+fs.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+fs.getCaseSensitivity()); } mobyData.setUserData(userData.toString()); } /** + * Record a condition for data acceptability, + * another service call with an output filter criteria. i.e. records if(f1(x) matches f1's output filter){...} + */ + public static void addUserData(MobyDataInstance mdi, URL conditionalOutputURL, FilterSearch filter){ + String filterSpec = ""; + if(filter != null && filter.getFilterRegex().length() > 0){ + XPathOption xsel = filter.getSelectedXPath(); + filterSpec = "\t"+filter.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+filter.getCaseSensitivity(); + } + if(mdi.getUserData() != null){ + mdi.setUserData(mdi.getUserData().toString()+"\t"+conditionalOutputURL+filterSpec); + } + else{ + mdi.setUserData(conditionalOutputURL.toString()+filterSpec); + } + } + + /** * Retrieves processing instructions embedded in Moby XML docs if they have the for */ public static String getSeahawkAttrFromDoc(URL docURL, String attrName) throws Exception{ From gordonp at dev.open-bio.org Fri Apr 9 15:58:23 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 11:58:23 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091558.o39FwMVA001941@dev.open-bio.org> gordonp Fri Apr 9 11:58:22 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv1902/src/main/ca/ucalgary/seahawk/util Modified Files: DataFlowRecorder.java Log Message: Added support for case sensitive searches, and 'previous input' conditional service execution moby-live/Java/src/main/ca/ucalgary/seahawk/util DataFlowRecorder.java,1.2,1.3 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.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/seahawk/util/DataFlowRecorder.java 2010/03/29 20:53:04 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/09 15:58:22 1.3 @@ -31,6 +31,8 @@ public static final String T2FLOW_DISPATCHXML = "ca/ucalgary/seahawk/resources/t2flowDispatchStack.xml"; public static final String T2FLOW_REGEXFILTER_BEANSHELL = "ca/ucalgary/seahawk/resources/RegexFilterBeanShell"; public static final String T2FLOW_XPATHFILTER_BEANSHELL = "ca/ucalgary/seahawk/resources/XPathFilterBeanShell"; + public static final String T2FLOW_PASSFILTER_BEANSHELL = "ca/ucalgary/seahawk/resources/PassFilterBeanShell"; // = if condition + public static final String T2FLOW_LISTFLATTEN_BEANSHELL = "ca/ucalgary/seahawk/resources/FlattenListBeanShell"; private Central mobyCentral; private Map namesUsed; // keep count of workflow element name usage so as not to duplicate an ID @@ -39,9 +41,12 @@ // Value is processor and port names private Map filter2Processor; private Map decomp2Processor; // reuse decomposition processors if same decomp done more than once on a given doc + private Map input2Processor; // if same input use more than once, create only one input port private DocumentBuilder docBuilder; private static String regexFilterScript = null; private static String xpathFilterScript = null; + private static String passFilterScript = null; + private static String listFlattenScript = null; private static Element dispatchStack = null; private static Transformer nullTransformer = null; private static Logger logger = Logger.getLogger(DataFlowRecorder.class.getName()); @@ -57,8 +62,9 @@ namesUsed = new HashMap(); url2Processor = new HashMap(); - filter2Processor = new HashMap(); // key is compound: url \n regex \n xpath + filter2Processor = new HashMap(); // key is compound: url \n regex \n xpath \n caseSensitivity decomp2Processor = new HashMap(); // key is url with xpath attached as ref (the way Seahawk generates them) + input2Processor = new HashMap(); // key is input instance XML } /** @@ -154,6 +160,7 @@ url2Processor.clear(); // clear map of results already produced in backtracking (handling workflow forks) filter2Processor.clear(); // ditto decomp2Processor.clear(); // ditto + input2Processor.clear(); // ditto // Generate all of the outputs requested by the call. None should be intermediaries // of another (the backtracking done by addWorkflowElements will capture these). @@ -162,7 +169,7 @@ // Create the inputs, processors and data links required for the workflow to create the result doc String ultimateProcessorName = addWorkflowElements(result.getKey(), doc, inputPorts, processors, datalinks); - // If there is a filter active on the currently displyed doc, we need to apply it here + // If there is a filter active on the currently displayed doc, we need to apply it here FilterSearch filter = result.getValue(); String[] regexProcessorAndPorts = null; String filterKey = null; @@ -190,9 +197,11 @@ } else{ regexProcessorAndPorts = createRegexFilter(filter.getFilterRegex().toString(), - filter.getSelectedXPath(), + filter.getSelectedXPath(), + filter.getCaseSensitivity(), ultimateProcessorName, - getPortName(outputParam, true), + getPortName(outputParam, true), + 1, // desired list dpeth processors, datalinks, doc); filter2Processor.put(filterKey, regexProcessorAndPorts); } @@ -275,6 +284,9 @@ MobyService service = DataUtils.getService(resultDom); Registry registry = DataUtils.getRegistry(resultDom); MobyDataJob sampleJob = DataUtils.getInputSample(resultDom, registry); + if(sampleJob == null){ + return "foo"; //todo: doc was a loaded Moby XML, not a service output or recognized data + } Element processorElement = createProcessorElement(service, sampleJob, doc); // add processor to workflow @@ -297,111 +309,181 @@ MobyPrimaryData sampleData = (MobyPrimaryData) sd; // has provenance info? + String[] data = null; + String[] condPassProcessorAndPorts = null; //[procname, input port, outputport] if(sampleData.getUserData() != null){ - // User data has the form srcURL#generalSelectionXPath actualInputDataXptr regexFilter - // where the filter is optional - String[] data = sampleData.getUserData().toString().split("\t"); + // User data has the form + // srcURL#generalSelectionXPath actualInputDataXptr regexFilter conditionalURL + // where the filter and conditionalURL are optional + data = sampleData.getUserData().toString().split("\t"); + //options: selection + filter + cond, selection + cond, or cond only + if(data.length == 11 || data.length == 7 || data.length == 5){ + System.err.println("Adding conditional for " + resultURLString); + String conditionURL = data[data.length-5]; + String conditionRegex = data[data.length-4]; + XPathOption conditionXPath = new XPathOption(data[data.length-3], data[data.length-2]); + boolean caseSensitivity = Boolean.parseBoolean(data[data.length-1]); + condPassProcessorAndPorts = createServiceConditionFilter(new URL(conditionURL), conditionRegex, conditionXPath, caseSensitivity, + doc, inputPorts, processors, datalinks); + String[] conditionlessData = new String[data.length-5]; + System.arraycopy(data, 0, conditionlessData, 0, data.length-5); + data = conditionlessData; + } + else{ + System.err.println("Skipping conditional, only " + data.length + + "members in provenance data for " + resultURLString); + } + } + + // true means treat as a collection if that's what the sample data is + String sinkPortName = getPortName(sampleData, true); + if(data != null && data.length != 0){ URL dataSrcURL = null; try{ dataSrcURL = new URL(data[0]); } catch(Exception e){ logger.log(Level.WARNING, "Ignoring unexpected UserData in Moby DOM, was not " + "a provenance URL as expected URL (" + sampleData.getUserData().toString() + ")"); + continue; } - if(dataSrcURL != null){ - // recursion for workflow creation by backtracking service input provenance - String feedingProcessorName = null; - String feedingProcessorPort = null; - String dataSrcURLString = dataSrcURL.toString().replaceFirst("#.*$", ""); //get rid of ref part - if(url2Processor.containsKey(dataSrcURLString)){ - feedingProcessorName = url2Processor.get(dataSrcURLString); + // recursion for workflow creation by backtracking service input provenance + String feedingProcessorName = null; + String feedingProcessorPort = null; + String dataSrcURLString = dataSrcURL.toString().replaceFirst("#.*$", ""); //get rid of ref part + if(url2Processor.containsKey(dataSrcURLString)){ + feedingProcessorName = url2Processor.get(dataSrcURLString); + } + else{ + feedingProcessorName = addWorkflowElements(dataSrcURL, doc, inputPorts, processors, datalinks); + } + + // Take into account data[2..5] if they are present, + // which filter the data by a regex before any other activities happen + // Format of spec is regex xpath xpathTextDesc booleanForCaseSensitivity + if(data.length == 6){ + String[] origFeederProcessorAndPort = getPortFromURLRef(dataSrcURL, + sampleData, + feedingProcessorName, + null, + processors, + datalinks, + doc, + false); + + // Lookup key is url \n regex \n xpath \n caseSensitivity + String[] regexProcessorAndPorts = null; + String filterKey = dataSrcURLString+"\n"+data[2]+"\n"+data[3]+"\n"+data[5]; + if(filter2Processor.containsKey(filterKey)){ // filter already exists from another branch + regexProcessorAndPorts = filter2Processor.get(filterKey); } else{ - feedingProcessorName = addWorkflowElements(dataSrcURL, doc, inputPorts, processors, datalinks); - } - - // true means treat as a collection if that's what the sample data is - String sinkPortName = getPortName(sampleData, true); - - // Take into account data[2..4] if they are present, - // which filter the data by a regex before any other activities happen - // Format of spec is regex xpath xpathTextDesc, so the earlier split gives use indices 1..3 - if(data.length == 5){ - String[] origFeederProcessorAndPort = getPortFromURLRef(dataSrcURL, - sampleData, - feedingProcessorName, - null, - processors, - datalinks, - doc, - false); - - // Lookup key is url \n regex \n xpath - String[] regexProcessorAndPorts = null; - String filterKey = dataSrcURLString+"\n"+data[2]+"\n"+data[3]; - if(filter2Processor.containsKey(filterKey)){ // filter already exists from another branch - regexProcessorAndPorts = filter2Processor.get(filterKey); - } - else{ - regexProcessorAndPorts = createRegexFilter(data[2], - new XPathOption(data[3], data[4]), - origFeederProcessorAndPort[0], - origFeederProcessorAndPort[1], - processors, datalinks, doc); - // New filter is applied to just this branch from a service for the moment...record the filter - // so that if same filter criteria are applied to more than one branch, we only make one filter - filter2Processor.put(dataSrcURLString+"\n"+data[2]+"\n"+data[3], regexProcessorAndPorts); - } - feedingProcessorName = regexProcessorAndPorts[0]; - feedingProcessorPort = regexProcessorAndPorts[regexProcessorAndPorts.length-1]; //last one is output + regexProcessorAndPorts = createRegexFilter(data[2], + new XPathOption(data[3], data[4]), + Boolean.parseBoolean(data[5]), + origFeederProcessorAndPort[0], + origFeederProcessorAndPort[1], + 1, // desired list depth + processors, datalinks, doc); + // New filter is applied to just this branch from a service for the moment...record the filter + // so that if same filter criteria are applied to more than one branch, we only make one filter + filter2Processor.put(filterKey, regexProcessorAndPorts); } - - // getPortFromURLRef() may inject extra processors between the processorName and feedingProcessorName - // in order to maintain type safety, etc. so the data link may change (based on last arg being set to true). - String[] feederProcessorAndPort = getPortFromURLRef(dataSrcURL, - sampleData, - feedingProcessorName, - feedingProcessorPort, //if null, determined from urlref - processors, - datalinks, - doc, - true); - datalinks.appendChild(createDataLinkElement(feederProcessorAndPort[0], feederProcessorAndPort[1], - processorName, sinkPortName, + feedingProcessorName = regexProcessorAndPorts[0]; + feedingProcessorPort = regexProcessorAndPorts[regexProcessorAndPorts.length-1]; //last one is output + } + + // getPortFromURLRef() may inject extra processors between the processorName and feedingProcessorName + // in order to maintain type safety, etc. so the data link may change (based on last arg being set to true). + String[] feederProcessorAndPort = getPortFromURLRef(dataSrcURL, + sampleData, + feedingProcessorName, + feedingProcessorPort, //if null, determined from urlref + processors, + datalinks, + doc, + true); + if(condPassProcessorAndPorts != null){ + // inject condition filter between feeder service and current service + datalinks.appendChild(createDataLinkElement(feederProcessorAndPort[0], + feederProcessorAndPort[1], + condPassProcessorAndPorts[0], + condPassProcessorAndPorts[1], doc)); - + feederProcessorAndPort[0] = condPassProcessorAndPorts[0]; + feederProcessorAndPort[1] = condPassProcessorAndPorts[2]; } + + datalinks.appendChild(createDataLinkElement(feederProcessorAndPort[0], feederProcessorAndPort[1], + processorName, sinkPortName, + doc)); + } // Otherwise it's a workflow input the user will need to specify else{ - String uniqueInputName = createUniqueName(getInputName(sampleData)); - // todo: sample data may be of more specific type than service requires - inputPorts.appendChild(createWorkflowInputElement(uniqueInputName, sampleData, doc)); - if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT)){ - String mobifyingProcessorName = addIdMobifyingProcessor(processors, datalinks, - sampleData, processorName, - inputName, doc); - datalinks.appendChild(createWorkflowInputLinkElement(uniqueInputName, - mobifyingProcessorName, - "fileurl", - sampleData, - doc)); + // pName is editable name for input processor target... + // allows injection of condition without affecting method's return value + String pName = processorName; + if(condPassProcessorAndPorts != null){ + // inject condition filter between data creator and current service + datalinks.appendChild(createDataLinkElement(condPassProcessorAndPorts[0], + condPassProcessorAndPorts[2], + pName, + sinkPortName, + doc)); + pName = condPassProcessorAndPorts[0]; + sinkPortName = condPassProcessorAndPorts[1]; + } + // The sample data may be used in more than one branch of the flow...avoid duplication + // Get the real data XML, to see if we've encountered it before as input (it'd be in the hash) + // Remember that sd is the loop's original MobyDataInstance before it's been coerced into a MobyPrimaryData, + // which doesn't have XML modes, etc. + String inputKey = getInputKey(sd); + System.err.println("Input key for " + processorName + " is " + inputKey); + + String[] mobifyingProcessorNameAndPorts = null; + if(input2Processor.containsKey(inputKey)){ + mobifyingProcessorNameAndPorts = input2Processor.get(inputKey); } else{ - // TODO: Need to build complex input from MOB rule or spreadsheet fields? + if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT)){ + mobifyingProcessorNameAndPorts = addIdMobifyingProcessor(processors, datalinks, inputPorts, + sampleData, doc); + input2Processor.put(inputKey, mobifyingProcessorNameAndPorts); + } + else{ + // TODO: Need to build complex input from MOB rule or spreadsheet fields? + } } + // link the created data to the workflow service + datalinks.appendChild(createDataLinkElement(mobifyingProcessorNameAndPorts[0], + mobifyingProcessorNameAndPorts[1], + pName, sinkPortName, + doc)); } + } return processorName; } + // returns the same value for moby sample data instances containing the same data in XML form + private String getInputKey(MobyDataInstance sd){ + int oldXmlMode = sd.getXmlMode(); + sd.setXmlMode(MobyDataInstance.SERVICE_XML_MODE); + String inputKey = sd.toXML(); + sd.setXmlMode(oldXmlMode); + + // get rid of the top-level article name, as this is immaterial to the + // value equivalence of objects (only matters to the actual service call mechanism) + return inputKey.replaceFirst(MobyTags.ARTICLENAME+"\\s*=\\s*(['\"]).*?\\1", ""); + } + // Actually adds a few processors, but only one needs to be returned and connected to an input port. // The others are constant values. By default we assume that you want to run a bunch of IDs // in a file, we also link in a Taverna spreadsheet importer. - private String addIdMobifyingProcessor(Element processors, Element datalinks, - MobyPrimaryData sampleData, String targetProcessorName, - String targetProcessorPort, Document doc) throws Exception{ + // Returns [spreadsheetReadingProcName, outputPort] + private String[] addIdMobifyingProcessor(Element processors, Element datalinks, Element dataFlowInputPorts, + MobyPrimaryData sampleData, Document doc) throws Exception{ String processorName = "Create-" + sampleData.getDataType().getName(); MobyNamespace ns = null; MobyNamespace[] nss = ((MobyPrimaryData) sampleData).getNamespaces(); @@ -518,7 +600,7 @@ Map feeds = new HashMap(); //what port on data creator it maps to constants.put(ns.getName()+"-namespace-constant", ns.getName()); feeds.put(ns.getName()+"-namespace-constant", "namespace"); - constants.put("article_name-constant", targetProcessorPort); + constants.put("article_name-constant", "unimportant"); feeds.put("article_name-constant", "article name"); for(Map.Entry constant: constants.entrySet()){ @@ -632,19 +714,23 @@ port.setAttribute("name", "fileurl"); port.setAttribute("depth", "0"); + String uniqueInputName = createUniqueName(getInputName(sampleData)); + // todo: sample data may be of more specific type than service requires + dataFlowInputPorts.appendChild(createWorkflowInputElement(uniqueInputName, sampleData, doc)); + datalinks.appendChild(createWorkflowInputLinkElement(uniqueInputName, + importerName, + "fileurl", + sampleData, + doc)); + // link the spreadsheet reader to the Moby data creator datalinks.appendChild(createDataLinkElement(importerName, outputUniqueName, processorName, "id", doc)); - // link the created data to the first workflow service, which takes an id - datalinks.appendChild(createDataLinkElement(processorName, "mobyData", - targetProcessorName, "Object("+targetProcessorPort+")", - doc)); - - // return the name of the spreadsheet reading processor so it can be hooked up - // to an input port for a Moby service - return importerName; + // return the name of the spreadsheet reading processor and output port so it can be hooked up + // to input ports for Moby services + return new String[]{processorName, portNames[portNames.length-1]}; } private Element createConstantProcessor(String constantName, String constantValue, Document doc) @@ -884,15 +970,86 @@ processors, datalinks, doc); } - private String[] createRegexFilter(String regex, XPathOption xpath, String srcProcessor, String srcPort, + // Make the continued use of data X in the workflow conditional on the results of running X through service f + // and passing the filter condition set on f. Equivalent to if(f(X) matches f_filter){...} + // returns [proc name, input port, output port] + private String[] createServiceConditionFilter(URL conditionURL, String filterRegex, XPathOption filterXPath, + boolean caseSensitive, Document doc, + Element inputPorts, Element processors, Element datalinks) + throws Exception{ + + // Open the conditionURL, and find out what service result is used, and what filter applied + Document conditionDoc = docBuilder.parse(conditionURL.openStream()); + MobyService service = DataUtils.getService(conditionDoc); + Document condServiceOutputDoc = DataUtils.getInputDoc(conditionDoc); + + // The bits to run the service "f" + + String dataSrcURLString = conditionURL.toString().replaceFirst("#.*$", ""); //get rid of ref part + String processorName = null; + // See if the service creating the input for the conditional service has already been added to the workflow + if(url2Processor.containsKey(dataSrcURLString)){ + processorName = url2Processor.get(dataSrcURLString); + } + else{ + processorName = addWorkflowElements(conditionURL, doc, inputPorts, processors, datalinks); + } + + String filterKey = dataSrcURLString+"\n"+filterRegex+"\n"+filterXPath.getXPath()+"\n"+caseSensitive; + String[] regexFilterProcNameAndPort = null; + //todo: gimpy loop below, as more than one service output would cause a trampling of regex output ports + for(MobyPrimaryData outputParam: service.getPrimaryOutputs()){ + // See if the filter on the conditional service has already been used in the workflow + if(filter2Processor.containsKey(filterKey)){ + regexFilterProcNameAndPort = filter2Processor.get(filterKey); + } + else{ + regexFilterProcNameAndPort = createRegexFilter(filterRegex, + filterXPath, + caseSensitive, + processorName, + getPortName(outputParam, true), + 0, //depth of list desired (will return match count) + processors, datalinks, doc); + filter2Processor.put(filterKey, regexFilterProcNameAndPort); + } + } + + // We need to flatten the 2-deep list generated by the regex filter's cross product + String[] beanShellFlattenerProcNameAndPorts = addListFlattenBeanShell(processors, doc); + + datalinks.appendChild(createDataLinkElement(regexFilterProcNameAndPort[0], + regexFilterProcNameAndPort[1], + beanShellFlattenerProcNameAndPorts[0], + beanShellFlattenerProcNameAndPorts[1], + doc)); + + // Essentially an "if" condition, error if incoming value is empty, missing, or zero + String[] beanShellFilterProcNameAndPorts = addPassFilterBeanShell(processors, doc); + + datalinks.appendChild(createDataLinkElement(beanShellFlattenerProcNameAndPorts[0], + beanShellFlattenerProcNameAndPorts[2], + beanShellFilterProcNameAndPorts[0], + beanShellFilterProcNameAndPorts[2], + doc)); + + return new String[]{beanShellFilterProcNameAndPorts[0], + beanShellFilterProcNameAndPorts[1], + beanShellFilterProcNameAndPorts[3]}; + } + + private String[] createRegexFilter(String regex, XPathOption xpath, boolean caseSensitive, + String srcProcessor, String srcPort, int listDepth, Element processors, Element datalinks, Document doc) throws Exception{ String constantXPathName = createUniqueName(xpath.toString()); processors.appendChild(createConstantProcessor(constantXPathName, xpath.getXPath(), doc)); String constantRegexName = createUniqueName(regex); processors.appendChild(createConstantProcessor(constantRegexName, regex, doc)); + String constantCaseSensitivityName = createUniqueName("cs_"+caseSensitive); + processors.appendChild(createConstantProcessor(constantCaseSensitivityName, ""+caseSensitive, doc)); - String[] beanShellFilterProcNameAndPorts = addRegexFilterBeanShell(processors, doc); + String[] beanShellFilterProcNameAndPorts = addRegexFilterBeanShell(listDepth, processors, doc); datalinks.appendChild(createDataLinkElement(srcProcessor, srcPort, @@ -903,11 +1060,15 @@ beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[2], doc)); - datalinks.appendChild(createDataLinkElement(constantXPathName, "value", + datalinks.appendChild(createDataLinkElement(constantCaseSensitivityName, "value", beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[3], doc)); - return new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[4]}; + datalinks.appendChild(createDataLinkElement(constantXPathName, "value", + beanShellFilterProcNameAndPorts[0], + beanShellFilterProcNameAndPorts[4], + doc)); + return new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[5]}; } private String[] createXrefParser(MobyNamespace nsObj, String srcProcessor, String srcPort, @@ -1231,29 +1392,76 @@ } } + private String[] addListFlattenBeanShell(Element processors, Document doc) + throws Exception{ + String beanShellProcName = createUniqueName("Create_Pass_Fail_List"); + + // Now do all the param-specific stuff below (inserts into various parts of the elements defined above) + Map inputsMap = new LinkedHashMap(); + // linked because order is important to line up port connections + Map inputTypes = new LinkedHashMap(); + inputsMap.put("inputlist", "2"); + inputTypes.put("inputlist", "text/plain"); + Map outputsMap = new LinkedHashMap(); + outputsMap.put("outputlist", "1"); + + return addBeanShell(beanShellProcName, "dot", + inputsMap, inputTypes, outputsMap, + getListFlattenScript(), new String[]{}, + processors, doc); + } + + private String[] addPassFilterBeanShell(Element processors, Document doc) + throws Exception{ + String beanShellProcName = createUniqueName("IfPassesContentFilter"); + + // Now do all the param-specific stuff below (inserts into various parts of the elements defined above) + Map inputsMap = new LinkedHashMap(); + // linked because order is important to line up port connections + Map inputTypes = new LinkedHashMap(); + inputsMap.put("dataToPassThrough", "1"); + inputsMap.put("conditionResults", "1"); + inputTypes.put("dataToPassThrough", "text/xml"); + inputTypes.put("conditionResults", "text/plain"); + Map outputsMap = new LinkedHashMap(); + outputsMap.put("dataPassed", "1"); + + return addBeanShell(beanShellProcName, "cross", + inputsMap, inputTypes, outputsMap, + getPassFilterScript(), new String[]{}, + processors, doc); + } + // Returns the name of the bean shell processor and its ports, so we can create the data links in the caller // The input is the original moby xml, and the xpath to extract, and the regex to apply to the text contents of the xpath results. // The output is a list of moby xml docs, one for each mobyData that fit the xpath and regex criteria. - private String[] addRegexFilterBeanShell(Element processors, Document doc) + private String[] addRegexFilterBeanShell(int listDepth, Element processors, Document doc) throws Exception{ - String beanShellProcName = createUniqueName("Filter_By_Content"); + String beanShellProcName = createUniqueName("Filter"+(listDepth == 0 ? "_Match_Count" : "_By_Content")); // Now do all the param-specific stuff below (inserts into various parts of the elements defined above) Map inputsMap = new LinkedHashMap(); - // linked because order is importtant to line up port connections + // linked because order is important to line up port connections Map inputTypes = new LinkedHashMap(); inputsMap.put("xml_text", "0"); inputsMap.put("regex", "0"); + inputsMap.put("case_sensitive", "0"); inputsMap.put("xpath", "0"); inputTypes.put("xml_text", "text/xml"); inputTypes.put("xpath", "text/plain"); inputTypes.put("regex", "text/plain"); + inputTypes.put("case_sensitive", "text/plain"); Map outputsMap = new LinkedHashMap(); - outputsMap.put("nodelistAsXML", "1"); + if(listDepth == 0){ + outputsMap.put("matchCount", "0"); + } + else{ + outputsMap.put("nodelistAsXML", ""+listDepth); + } - return addBeanShell(beanShellProcName, + return addBeanShell(beanShellProcName, "cross", inputsMap, inputTypes, outputsMap, - getRegexFilterScript(), new String[]{"dom4j:dom4j:1.6"}, + getRegexFilterScript(listDepth), new String[]{"dom4j:dom4j:1.6"}, processors, doc); } @@ -1274,13 +1482,13 @@ Map outputsMap = new HashMap(); outputsMap.put("nodelistAsXML", "1"); - return addBeanShell(beanShellProcName, + return addBeanShell(beanShellProcName, "cross", inputsMap, inputTypes, outputsMap, getXPathFilterScript(), new String[]{"dom4j:dom4j:1.6"}, processors, doc); } - private String[] addBeanShell(String beanShellProcName, + private String[] addBeanShell(String beanShellProcName, String vectorComboOp, Map inputsMap, Map inputTypes, Map outputsMap, String script, String[] dependencySpecs, Element processors, Document doc) throws Exception{ @@ -1345,8 +1553,11 @@ iterationStrategyStack.appendChild(iteration); Element strategy = doc.createElementNS(T2FLOW_NS, "strategy"); iteration.appendChild(strategy); - Element cross = doc.createElementNS(T2FLOW_NS, "cross"); - strategy.appendChild(cross); + Element vectorOp = null; + if(vectorComboOp != null){ + vectorOp = doc.createElementNS(T2FLOW_NS, vectorComboOp); + strategy.appendChild(vectorOp); // either cross or dot + } // Lst processor name, input ports and output ports, in that order. Vector returnSpec = new Vector(); @@ -1370,7 +1581,9 @@ mimeTypes.appendChild(createElWithText(doc, "", "string", inputTypes.get(input.getKey()))); Element port = doc.createElementNS(T2FLOW_NS, "port"); - cross.appendChild(port); + if(vectorOp != null){ + vectorOp.appendChild(port); + } port.setAttribute("depth", input.getValue()); port.setAttribute("name", input.getKey()); } @@ -1517,7 +1730,7 @@ private String createUniqueName(String preferredName){ if(namesUsed.containsKey(preferredName)){ namesUsed.put(preferredName, namesUsed.get(preferredName).intValue()+1); //increment - preferredName += namesUsed.get(preferredName); + preferredName += "_"+namesUsed.get(preferredName); } else{ namesUsed.put(preferredName, 1); // will be auto-boxed to Integer @@ -1528,8 +1741,6 @@ // dataType(articleName) as required by the Taverna Moby plugin private String getPortName(MobyPrimaryData data, boolean asCollection){ if(data instanceof MobyPrimaryDataSet){ - // todo: Hmm...don't yet handle case where collections are passed from one service to another... - // here we assume iterating over the collection if(asCollection){ return data.getDataType().getName()+"(Collection - '"+data.getName()+"')"; } @@ -1680,7 +1891,7 @@ // Did we override the default value for the secondary param in the example input? Element stringValue = doc.createElementNS("", "string"); - if(sampleInput.containsKey(secParam.getName())){ + if(sampleInput != null && sampleInput.containsKey(secParam.getName())){ stringValue.appendChild(doc.createTextNode(((MobyDataSecondaryInstance) sampleInput.get(secParam.getName())).getValue())); } else{ // use the default defined in Moby Central @@ -1739,6 +1950,28 @@ return central; } + private synchronized String getListFlattenScript() throws Exception{ + if(listFlattenScript == null){ + URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_LISTFLATTEN_BEANSHELL); + if(scriptURL == null){ + throw new Exception("Cannot find resource " + T2FLOW_LISTFLATTEN_BEANSHELL); + } + listFlattenScript = HTMLUtils.getURLContents(scriptURL); + } + return listFlattenScript; + } + + private synchronized String getPassFilterScript() throws Exception{ + if(passFilterScript == null){ + URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_PASSFILTER_BEANSHELL); + if(scriptURL == null){ + throw new Exception("Cannot find resource " + T2FLOW_PASSFILTER_BEANSHELL); + } + passFilterScript = HTMLUtils.getURLContents(scriptURL); + } + return passFilterScript; + } + private synchronized String getXPathFilterScript() throws Exception{ if(xpathFilterScript == null){ URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_XPATHFILTER_BEANSHELL); @@ -1750,7 +1983,7 @@ return xpathFilterScript; } - private synchronized String getRegexFilterScript() throws Exception{ + private synchronized String getRegexFilterScript(int listDepth) throws Exception{ if(regexFilterScript == null){ URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_REGEXFILTER_BEANSHELL); if(scriptURL == null){ @@ -1758,7 +1991,12 @@ } regexFilterScript = HTMLUtils.getURLContents(scriptURL); } - return regexFilterScript; + if(listDepth == 0){// list to scalar conversion + return regexFilterScript+"\nString matchCount = \"\"+nodelistAsXML.size();"; + } + else{ + return regexFilterScript; + } } private synchronized Element getDispatchStack(Document newOwnerDoc) throws Exception{ From gordonp at dev.open-bio.org Fri Apr 9 16:58:14 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 12:58:14 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004091658.o39GwEOB003781@dev.open-bio.org> gordonp Fri Apr 9 12:58:13 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow In directory dev.open-bio.org:/tmp/cvs-serv3745/src/main/ca/ucalgary/minnow Modified Files: MinJarMaker.java Log Message: got rid of annoying cvs-related files in secondary jars moby-live/Java/src/main/ca/ucalgary/minnow MinJarMaker.java,1.6,1.7 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow/MinJarMaker.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow/MinJarMaker.java 2010/03/30 19:14:04 1.6 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/minnow/MinJarMaker.java 2010/04/09 16:58:13 1.7 @@ -812,7 +812,7 @@ relativePath.equals("META-INF") || //this one causes null pointers in jarsigner relativePath.equals("testdata") || relativePath.equals("deployment") || - relativePath.equals("CVS")){ + relativePath.endsWith("CVS")){ //System.err.println("Skipping " + relativePath); continue; } From gordonp at dev.open-bio.org Sat Apr 10 00:40:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 20:40:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004100040.o3A0eH2E014912@dev.open-bio.org> gordonp Fri Apr 9 20:40:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv14854/src/main/ca/ucalgary/seahawk/resources Modified Files: RegexFilterBeanShell Log Message: Added support for filter inversion (boolean negation) moby-live/Java/src/main/ca/ucalgary/seahawk/resources RegexFilterBeanShell,1.2,1.3 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/RegexFilterBeanShell,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/seahawk/resources/RegexFilterBeanShell 2010/04/09 15:49:18 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/RegexFilterBeanShell 2010/04/10 00:40:17 1.3 @@ -11,9 +11,12 @@ List nodelist = document.selectNodes(xpath); ArrayList outputXmlList = new ArrayList(); +ArrayList outputXmlList_false = new ArrayList(); int i = 1; Map collections = new LinkedHashMap(); Map collectionsEnd = new HashMap(); +Map collections_false = new LinkedHashMap(); +Map collectionsEnd_false = new HashMap(); Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL | (Boolean.parseBoolean(case_sensitive) ? 0 : Pattern.CASE_INSENSITIVE)); for (Iterator iter = nodelist.iterator(); iter.hasNext();) { Node node = (Node) iter.next(); @@ -31,10 +34,17 @@ break; default: break; } - if(!match){ - continue; - } + Map cs = null; + Map csEnd = null; + if(match){ + cs = collections; + csEnd = collectionsEnd; + } + else{ + cs = collections_false; + csEnd = collectionsEnd_false; + } //go up the tree until we hit a mobyData...this is the unit we can forward StringBuilder collection = null; StringBuilder collectionEnd = null; @@ -43,11 +53,11 @@ node.getParent().getName().equals("Collection")){ collection = new StringBuilder(); //start tracking parents collectionEnd = new StringBuilder(); - if(!collections.containsKey(collection)){ - collections.put(collection, new Vector()); - collectionsEnd.put(collection, collectionEnd); + if(!cs.containsKey(collection)){ + cs.put(collection, new Vector()); + csEnd.put(collection, collectionEnd); } - ((Vector)collections.get(collection)).add(node.asXML()); + ((Vector)cs.get(collection)).add(node.asXML()); } node = node.getParent(); if(node != null && collection != null){ @@ -61,14 +71,17 @@ collectionEnd.append(""); } } - if(node == null){ + if(node == null){ // wasn't part of a mobyData block continue; } - // At mobyData level if we got here + // At mobyData level if we got here, add if job not already present if(collection == null){ - outputXmlList.add( - ""+ - ""+node.asXML()+""); + String jobData = ""+ + ""+node.asXML()+""; + List list = (match ? outputXmlList : outputXmlList_false); + if(!list.contains(jobData)){ + list.add(jobData); + } } } @@ -83,6 +96,16 @@ } ((List) uniqueCollections.get(keyString)).addAll((List) collection.getValue()); } +Map uniqueCollections_false = new LinkedHashMap(); +Map uniqueCollectionsEnd_false = new LinkedHashMap(); +for(Map.Entry collection: collections_false.entrySet()){ + String keyString = collection.getKey().toString(); + if(!uniqueCollections_false.containsKey(keyString)){ + uniqueCollections_false.put(keyString, new Vector()); + uniqueCollectionsEnd_false.put(keyString, collectionsEnd_false.get(collection.getKey())); + } + ((List) uniqueCollections_false.get(keyString)).addAll((List) collection.getValue()); +} //Now concat the collection members that pass the filter for(Map.Entry collection: uniqueCollections.entrySet()){ @@ -99,6 +122,21 @@ outputXmlList.add(block.toString()); } +for(Map.Entry collection: uniqueCollections_false.entrySet()){ + StringBuilder block = new StringBuilder(); + block.append("\n"); + block.append("\n"); + block.append(collection.getKey().toString()); + for(String val: (List) collection.getValue()){ + block.append(val); + } + block.append(uniqueCollectionsEnd_false.get(collection.getKey().toString())); // closing tags + block.append("\n"); + block.append("\n"); + + outputXmlList_false.add(block.toString()); +} -List nodelistAsXML=outputXmlList; +List TRUE_nodelistAsXML=outputXmlList; +List FALSE_nodelistAsXML=outputXmlList_false; From gordonp at dev.open-bio.org Sat Apr 10 00:40:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 20:40:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004100040.o3A0eHik014894@dev.open-bio.org> gordonp Fri Apr 9 20:40:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv14854/src/main/ca/ucalgary/seahawk/gui Modified Files: FilterSearchWidget.java MobyContentPane.java Log Message: Added support for filter inversion (boolean negation) moby-live/Java/src/main/ca/ucalgary/seahawk/gui FilterSearchWidget.java,1.2,1.3 MobyContentPane.java,1.24,1.25 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.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/seahawk/gui/FilterSearchWidget.java 2010/04/09 15:50:09 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/10 00:40:17 1.3 @@ -18,12 +18,18 @@ private FilterSearch currentFilterSearch; private JLabel closeIcon; private JToggleButton caseButton; + private JButton inverseButton; // decides whether filter is "if" or "unless" private JTextField searchField; private JComboBox docPartOptions; private MobyContentPane contentPane; public static final String CASE_SENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_sensitive.png"; public static final String CASE_INSENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_insensitive.png"; + private static final String IF_TEXT = "if"; + private static final String UNLESS_TEXT = "unless"; + private static final String CASE_INSENSITIVE_MSG = "The filter is case insensitive,
click to make case sensitive"; + private static final String CASE_SENSITIVE_MSG = "The filter is case sensitive,
click to make case insensitive"; private static final String CASE_BUTTON_NAME = "case_sensitivity_button"; + private static final String INVERSE_BUTTON_NAME = "boolean_button"; private static Logger logger = Logger.getLogger(FilterSearchWidget.class.getName()); @@ -45,7 +51,7 @@ Dimension buttonSize = new Dimension(24,24); caseButton = new JToggleButton(new ImageIcon(cl.getResource(CASE_SENSITIVE_ICON_RESOURCE))); caseButton.setDisabledIcon(new ImageIcon(cl.getResource(CASE_INSENSITIVE_ICON_RESOURCE))); - caseButton.setToolTipText("Toggles the case sensitivity of the filter"); + caseButton.setToolTipText(CASE_INSENSITIVE_MSG); caseButton.setPreferredSize(buttonSize); caseButton.setEnabled(true); caseButton.setSelected(false); @@ -53,12 +59,20 @@ caseButton.setMargin(new java.awt.Insets(2,2,2,2)); caseButton.setName(CASE_BUTTON_NAME); // so test cases can find the component + inverseButton = new JButton(IF_TEXT); + inverseButton.setToolTipText("Click to invert the selection between \"if\" and \"unless\""); + inverseButton.setEnabled(true); + inverseButton.addActionListener(this); + inverseButton.setBorderPainted(false); // underline is hint enough that we can press it...looks cleaner + inverseButton.setName(INVERSE_BUTTON_NAME); // so test cases can find the component + setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS)); add(closeIcon); add(Box.createRigidArea(new Dimension(5,0))); add(caseButton); add(Box.createRigidArea(new Dimension(5,0))); - add(new JLabel("Show data if ")); + add(new JLabel("Show data ")); + add(inverseButton); add(Box.createRigidArea(new Dimension(5,0))); searchField = new JTextField(25); searchField.setToolTipText("A literal string, or a regular expression"); @@ -81,11 +95,15 @@ currentFilterSearch = null; if(fs == null){ caseButton.setEnabled(false); + inverseButton.setEnabled(false); searchField.setEnabled(false); docPartOptions.setEnabled(false); return; } + inverseButton.setEnabled(true); + inverseButton.setText(fs.getSelectionInversed() ? UNLESS_TEXT : IF_TEXT); + caseButton.setEnabled(true); caseButton.setSelected(fs.getCaseSensitivity()); @@ -101,11 +119,30 @@ * Called when the user has changed the xpath */ public void actionPerformed(ActionEvent e){ - if(e.getSource() == caseButton){ + if(e.getSource() == inverseButton){ + // Toggle the label for the if/unless button + if(inverseButton.getText().equals(IF_TEXT)){ + inverseButton.setText(UNLESS_TEXT); + currentFilterSearch.setSelectionInversed(true); + } + else{ + inverseButton.setText(IF_TEXT); + currentFilterSearch.setSelectionInversed(false); + } + contentPane.applyFilter(true); + return; + } + else if(e.getSource() == caseButton){ if(currentFilterSearch == null){ return; } currentFilterSearch.setCaseSensitivity(caseButton.isSelected()); + if(caseButton.isSelected()){ + caseButton.setToolTipText(CASE_SENSITIVE_MSG); + } + else{ + caseButton.setToolTipText(CASE_INSENSITIVE_MSG); + } contentPane.applyFilter(true); return; } @@ -127,6 +164,7 @@ sb.replace(0, sb.length(), searchField.getText()); contentPane.applyFilter(true); } + public void insertUpdate(DocumentEvent e){ if(currentFilterSearch == null){ return; =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.24 retrieving revision 1.25 diff -u -r1.24 -r1.25 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/09 15:54:16 1.24 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/10 00:40:17 1.25 @@ -1239,7 +1239,6 @@ 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. @@ -1510,12 +1509,15 @@ } } + boolean inversed = fs.getSelectionInversed(); Map parentMatchingXPtrs = new LinkedHashMap(); for(String currXPtr: filterableNodes){ for(Map.Entry matchingXPtr: matchingXPtrs.entrySet()){ if(matchingXPtr.getKey().startsWith(currXPtr+"/")){ // a parent of the matching data // No positive example yet? - if(!parentMatchingXPtrs.containsKey(currXPtr) || !parentMatchingXPtrs.get(currXPtr).booleanValue()){ + if(!parentMatchingXPtrs.containsKey(currXPtr) || + !inversed && !parentMatchingXPtrs.get(currXPtr).booleanValue() || + inversed && parentMatchingXPtrs.get(currXPtr).booleanValue()){ System.err.println("Adding "+ matchingXPtr.getValue() + " for " + currXPtr); parentMatchingXPtrs.put(currXPtr, matchingXPtr.getValue()); } @@ -1526,11 +1528,16 @@ matchingXPtrs.putAll(parentMatchingXPtrs); for(String currXPtr: matchingXPtrs.keySet()){ // Is part of the selection criteria, but doesn't match the regex + boolean shouldFilter = false; if(!matchingXPtrs.get(currXPtr).booleanValue() && - // special condition: if "entire document" xpath is given, filter only at the job level + // special condition: if "entire response" xpath is given, filter only at the job level (!currentSelectionXPath.equals(FilterSearch.SELECT_ALL_XPATH) || jobXPtrs.containsKey(currXPtr))){ - filteredData.put(currXPtr, "todo"); + shouldFilter = true; } + if(!inversed && shouldFilter || + inversed && !shouldFilter){ + filteredData.put(currXPtr, "todo"); + } } //todo: filter objects without the HAS field at all... From gordonp at dev.open-bio.org Sat Apr 10 00:40:18 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 9 Apr 2010 20:40:18 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004100040.o3A0eIZb014938@dev.open-bio.org> gordonp Fri Apr 9 20:40:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv14854/src/main/ca/ucalgary/seahawk/util Modified Files: DataFlowRecorder.java DataUtils.java FilterSearch.java Log Message: Added support for filter inversion (boolean negation) moby-live/Java/src/main/ca/ucalgary/seahawk/util DataFlowRecorder.java,1.3,1.4 DataUtils.java,1.2,1.3 FilterSearch.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.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/seahawk/util/DataFlowRecorder.java 2010/04/09 15:58:22 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/10 00:40:17 1.4 @@ -174,7 +174,8 @@ String[] regexProcessorAndPorts = null; String filterKey = null; if(filter != null && filter.getFilterRegex().length() > 0){ - filterKey = result.getKey()+"\n"+filter.getFilterRegex()+"\n"+filter.getSelectedXPath().getXPath(); + filterKey = result.getKey()+"\n"+filter.getFilterRegex()+"\n"+ + filter.getSelectedXPath().getXPath()+"\n"+filter.getCaseSensitivity(); } // Create the workflow output and data links @@ -206,8 +207,10 @@ filter2Processor.put(filterKey, regexProcessorAndPorts); } + // The proc has an output port for non-matches (penultimate index) and matches (ultimate index) + int regexOutPort = regexProcessorAndPorts.length-(filter.getSelectionInversed() ? 2 : 1); datalinks.appendChild(createWorkflowOutputLinkElement(regexProcessorAndPorts[0], - regexProcessorAndPorts[regexProcessorAndPorts.length-1], + regexProcessorAndPorts[regexOutPort], uniqueOutputName, doc)); break; // only one output when filter is attached: the XML doc @@ -317,16 +320,18 @@ // where the filter and conditionalURL are optional data = sampleData.getUserData().toString().split("\t"); //options: selection + filter + cond, selection + cond, or cond only - if(data.length == 11 || data.length == 7 || data.length == 5){ + if(data.length == 14 || data.length == 8 || data.length == 6){ System.err.println("Adding conditional for " + resultURLString); - String conditionURL = data[data.length-5]; - String conditionRegex = data[data.length-4]; - XPathOption conditionXPath = new XPathOption(data[data.length-3], data[data.length-2]); - boolean caseSensitivity = Boolean.parseBoolean(data[data.length-1]); - condPassProcessorAndPorts = createServiceConditionFilter(new URL(conditionURL), conditionRegex, conditionXPath, caseSensitivity, + String conditionURL = data[data.length-6]; + String conditionRegex = data[data.length-5]; + XPathOption conditionXPath = new XPathOption(data[data.length-4], data[data.length-3]); + boolean caseSensitivity = Boolean.parseBoolean(data[data.length-2]); + boolean inverse = Boolean.parseBoolean(data[data.length-1]); + condPassProcessorAndPorts = createServiceConditionFilter(new URL(conditionURL), conditionRegex, + conditionXPath, caseSensitivity, inverse, doc, inputPorts, processors, datalinks); - String[] conditionlessData = new String[data.length-5]; - System.arraycopy(data, 0, conditionlessData, 0, data.length-5); + String[] conditionlessData = new String[data.length-6]; + System.arraycopy(data, 0, conditionlessData, 0, data.length-6); data = conditionlessData; } else{ @@ -357,10 +362,10 @@ feedingProcessorName = addWorkflowElements(dataSrcURL, doc, inputPorts, processors, datalinks); } - // Take into account data[2..5] if they are present, + // Take into account data[2..6] if they are present, // which filter the data by a regex before any other activities happen // Format of spec is regex xpath xpathTextDesc booleanForCaseSensitivity - if(data.length == 6){ + if(data.length == 7){ String[] origFeederProcessorAndPort = getPortFromURLRef(dataSrcURL, sampleData, feedingProcessorName, @@ -370,9 +375,11 @@ doc, false); - // Lookup key is url \n regex \n xpath \n caseSensitivity + // Lookup key is url \n regex \n xpath \n caseSensitivity + // (inverse selection uses same processor, different output port, so not part of the key) String[] regexProcessorAndPorts = null; String filterKey = dataSrcURLString+"\n"+data[2]+"\n"+data[3]+"\n"+data[5]; + boolean inversed = Boolean.parseBoolean(data[6]); if(filter2Processor.containsKey(filterKey)){ // filter already exists from another branch regexProcessorAndPorts = filter2Processor.get(filterKey); } @@ -389,7 +396,9 @@ filter2Processor.put(filterKey, regexProcessorAndPorts); } feedingProcessorName = regexProcessorAndPorts[0]; - feedingProcessorPort = regexProcessorAndPorts[regexProcessorAndPorts.length-1]; //last one is output + // The proc has an output port for non-matches (penultimate index) and matches (ultimate index) + int regexOutPort = regexProcessorAndPorts.length-(inversed ? 2 : 1); + feedingProcessorPort = regexProcessorAndPorts[regexOutPort]; } // getPortFromURLRef() may inject extra processors between the processorName and feedingProcessorName @@ -921,6 +930,7 @@ // supertype of the output from the other service! if(namespace != null){ MobyNamespace nsObj = MobyNamespace.getNamespace(namespace, getRegistryFromService(srcService)); + System.err.println("About to create namespace filter for "+ srcProcessor + " port " + portName + " when srcPort was " + srcPort); return createNamespaceFilter(nsObj, srcProcessor, portName, processors, datalinks, doc); } else if(xrefNs != null){ @@ -974,7 +984,7 @@ // and passing the filter condition set on f. Equivalent to if(f(X) matches f_filter){...} // returns [proc name, input port, output port] private String[] createServiceConditionFilter(URL conditionURL, String filterRegex, XPathOption filterXPath, - boolean caseSensitive, Document doc, + boolean caseSensitive, boolean inverse, Document doc, Element inputPorts, Element processors, Element datalinks) throws Exception{ @@ -996,30 +1006,31 @@ } String filterKey = dataSrcURLString+"\n"+filterRegex+"\n"+filterXPath.getXPath()+"\n"+caseSensitive; - String[] regexFilterProcNameAndPort = null; + String[] regexFilterProcNameAndPorts = null; //todo: gimpy loop below, as more than one service output would cause a trampling of regex output ports for(MobyPrimaryData outputParam: service.getPrimaryOutputs()){ // See if the filter on the conditional service has already been used in the workflow if(filter2Processor.containsKey(filterKey)){ - regexFilterProcNameAndPort = filter2Processor.get(filterKey); + regexFilterProcNameAndPorts = filter2Processor.get(filterKey); } else{ - regexFilterProcNameAndPort = createRegexFilter(filterRegex, + regexFilterProcNameAndPorts = createRegexFilter(filterRegex, filterXPath, caseSensitive, processorName, getPortName(outputParam, true), 0, //depth of list desired (will return match count) processors, datalinks, doc); - filter2Processor.put(filterKey, regexFilterProcNameAndPort); + filter2Processor.put(filterKey, regexFilterProcNameAndPorts); } } // We need to flatten the 2-deep list generated by the regex filter's cross product String[] beanShellFlattenerProcNameAndPorts = addListFlattenBeanShell(processors, doc); - datalinks.appendChild(createDataLinkElement(regexFilterProcNameAndPort[0], - regexFilterProcNameAndPort[1], + int regexOutPort = regexFilterProcNameAndPorts.length-(inverse ? 2 : 1); + datalinks.appendChild(createDataLinkElement(regexFilterProcNameAndPorts[0], + regexFilterProcNameAndPorts[regexOutPort], beanShellFlattenerProcNameAndPorts[0], beanShellFlattenerProcNameAndPorts[1], doc)); @@ -1068,7 +1079,9 @@ beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[4], doc)); - return new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[5]}; + return new String[]{beanShellFilterProcNameAndPorts[0], + beanShellFilterProcNameAndPorts[5], // false (non-matching) output + beanShellFilterProcNameAndPorts[6]}; // true (matching) output } private String[] createXrefParser(MobyNamespace nsObj, String srcProcessor, String srcPort, @@ -1090,6 +1103,7 @@ throws Exception{ String decompKey = srcProcessor+"\n"+srcPort+"\n"+xpath; + System.err.println("Decomp key is " + decompKey); // Has this decomp already been created in another branch? if(decomp2Processor.containsKey(decompKey)){ return decomp2Processor.get(decompKey); @@ -1108,7 +1122,7 @@ beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[2], doc)); - String[] procSpec = new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[3]}; + String[] procSpec = new String[]{beanShellFilterProcNameAndPorts[0], beanShellFilterProcNameAndPorts[3]}; decomp2Processor.put(decompKey, procSpec); //in case we need to reuse it in another branch return procSpec; } @@ -1453,10 +1467,12 @@ inputTypes.put("case_sensitive", "text/plain"); Map outputsMap = new LinkedHashMap(); if(listDepth == 0){ - outputsMap.put("matchCount", "0"); + outputsMap.put("FALSE_matchCount", "0"); + outputsMap.put("TRUE_matchCount", "0"); } else{ - outputsMap.put("nodelistAsXML", ""+listDepth); + outputsMap.put("FALSE_nodelistAsXML", ""+listDepth); + outputsMap.put("TRUE_nodelistAsXML", ""+listDepth); } return addBeanShell(beanShellProcName, "cross", @@ -1991,8 +2007,9 @@ } regexFilterScript = HTMLUtils.getURLContents(scriptURL); } - if(listDepth == 0){// list to scalar conversion - return regexFilterScript+"\nString matchCount = \"\"+nodelistAsXML.size();"; + if(listDepth == 0){// list to scalar conversions + return regexFilterScript+"\nString TRUE_matchCount = \"\"+TRUE_nodelistAsXML.size();\n"+ + "\nString FALSE_matchCount = \"\"+FALSE_nodelistAsXML.size();\n"; } else{ return regexFilterScript; =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.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/seahawk/util/DataUtils.java 2010/04/09 15:57:46 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/10 00:40:17 1.3 @@ -117,7 +117,8 @@ if(newFilter != null){ XPathOption xsel = newFilter.getSelectedXPath(); newProvenanceData += "\t"+newFilter.getFilterRegex()+ - "\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+newFilter.getCaseSensitivity(); + "\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+ + newFilter.getCaseSensitivity()+"\t"+newFilter.getSelectionInversed(); } pi.setData(attr_val[0]+"=\""+newProvenanceData+"\""); } @@ -640,7 +641,8 @@ if(fs != null && fs.getFilterRegex().length() > 0){ XPathOption xsel = fs.getSelectedXPath(); - userData.append("\t"+fs.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+fs.getCaseSensitivity()); + userData.append("\t"+fs.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+ + fs.getCaseSensitivity()+"\t"+fs.getSelectionInversed()); } mobyData.setUserData(userData.toString()); } @@ -653,7 +655,8 @@ String filterSpec = ""; if(filter != null && filter.getFilterRegex().length() > 0){ XPathOption xsel = filter.getSelectedXPath(); - filterSpec = "\t"+filter.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+filter.getCaseSensitivity(); + filterSpec = "\t"+filter.getFilterRegex()+"\t"+xsel.getXPath()+"\t"+xsel.getDesc()+"\t"+ + filter.getCaseSensitivity()+"\t"+filter.getSelectionInversed(); } if(mdi.getUserData() != null){ mdi.setUserData(mdi.getUserData().toString()+"\t"+conditionalOutputURL+filterSpec); =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.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/seahawk/util/FilterSearch.java 2010/04/09 15:48:19 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/10 00:40:17 1.4 @@ -21,6 +21,7 @@ private URL docURL; private boolean caseSensitivity = false; + private boolean inverseSelection = false; private StringBuffer filterRegex; private Vector xpathOptions; private int xpathSelected = 0; @@ -74,6 +75,14 @@ } } + public boolean getSelectionInversed(){ + return inverseSelection; + } + + public void setSelectionInversed(boolean inversed){ + inverseSelection = inversed; + } + public boolean getCaseSensitivity(){ return caseSensitivity; } From gordonp at dev.open-bio.org Sat Apr 10 22:42:09 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 18:42:09 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004102242.o3AMg9nE014502@dev.open-bio.org> gordonp Sat Apr 10 18:42:09 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data In directory dev.open-bio.org:/tmp/cvs-serv14466/src/main/org/biomoby/shared/data Modified Files: MobyDataObject.java Log Message: Improved equals() for base object equivalency...value not instance based moby-live/Java/src/main/org/biomoby/shared/data MobyDataObject.java,1.26,1.27 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyDataObject.java,v retrieving revision 1.26 retrieving revision 1.27 diff -u -r1.26 -r1.27 --- /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyDataObject.java 2008/01/07 22:11:36 1.26 +++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyDataObject.java 2010/04/10 22:42:09 1.27 @@ -302,7 +302,7 @@ public boolean equals(Object passedInObject) throws ClassCastException{ Object ourObject = getObject(); if(passedInObject != null && passedInObject instanceof MobyDataObject){ - if(((MobyDataObject) passedInObject).getDataType() == getDataType()){ + if(((MobyDataObject) passedInObject).getDataType().equals(getDataType())){ // An object of the same class. See if their XMLs are equivalent. int ourOldXMLMode = getXmlMode(); int itsOldXMLMode = ((MobyDataObject) passedInObject).getXmlMode(); From gordonp at dev.open-bio.org Sun Apr 11 01:58:05 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 21:58:05 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110158.o3B1w59N019017@dev.open-bio.org> gordonp Sat Apr 10 21:58:05 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services In directory dev.open-bio.org:/tmp/cvs-serv18981/src/main/ca/ucalgary/seahawk/services Modified Files: MobyClient.java Log Message: Added regex support for IUPAC monosacchride residues (\M) moby-live/Java/src/main/ca/ucalgary/seahawk/services MobyClient.java,1.25,1.26 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/03/17 20:21:55 1.25 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/11 01:58:05 1.26 @@ -1391,14 +1391,15 @@ /** * Converts seahawk-specific regex syntax into generic Java syntax (e.g \N becomes a - * match for any IUPAC DNA character, \P any amino acid). We pass in the member map so that + * match for any IUPAC DNA character, \P any amino acid, \M for any monosacchiride abbreviation). + * We pass in the member map so that * this method can populate the last field of rules that inherit complex members (by virtue * of using the capture group whose values is derived from \p{ruleName}), with ruleName */ protected String processRegExp(String regex, Map membersMap) throws Exception{ String returnValue = regex.replaceAll("\\\\N", "[acgtunxACGTUNX]") - .replaceAll("\\\\P", "[ARNDCQEGHILKMFPSTWYVBZXarndcqeghilkmfpstwyvbz*]"); - + .replaceAll("\\\\P", "[ARNDCQEGHILKMFPSTWYVBZXarndcqeghilkmfpstwyvbz*]") + .replaceAll("\\\\M", "(?:Abe|IdoA|All|Lyx|Alt|Man|Api|Mur|Ara|Neu|Ara-ol|Neu5Ac|dRib|Neu2en5Ac|Fru|Neu5Gc|Fuc|Kdo|Fuc-ol|Rha|Gal|Rha3,4Me2|GalN|Psi|GalNAc|Qui|B-D-Galp4S|Rib|Glc|Rib5P|GlcN|Ribulo|Rul|GlcN3N|Sor|Glc-ol|Tag|GlcNAc|Tal|GlcA|Xyl|GlcpA6Et|Xylulo|Xul|Gul|Xyl2CMe|Ido)"); // Now see if there are any references to other patterns (by rule name) // with the \p{} syntax specific to Seahawk Pattern charClassPattern = Pattern.compile("\\\\p\\{([A-Za-z0-9]+)\\}"); From gordonp at dev.open-bio.org Sun Apr 11 02:00:02 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 22:00:02 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110200.o3B202wI019153@dev.open-bio.org> gordonp Sat Apr 10 22:00:02 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv19034/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyObjectTransferHandler.java Log Message: Added native support for primitive datatype recognition in text transfers moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyObjectTransferHandler.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyObjectTransferHandler.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/seahawk/gui/MobyObjectTransferHandler.java 2007/12/17 18:44:13 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyObjectTransferHandler.java 2010/04/11 02:00:02 1.4 @@ -218,7 +218,30 @@ for(String fieldName: acceptableData.keySet()){ int itemCount = 1; MobyDataType desiredDataType = acceptableData.get(fieldName).getDataType(); + String dataTypeName = desiredDataType.getName(); System.err.println("Checking text for field " + fieldName+ ", data type " + desiredDataType.getName()); + + // trivial data creations first ... + if(dataTypeName.equals(MobyTags.MOBYSTRING)){ + foundData.put(fieldName+"#"+itemCount++, new MobyDataString(text)); + } + else if(dataTypeName.equals(MobyTags.MOBYBOOLEAN) && + text.matches("(true|True|TRUE|1|yes|Yes|YES|false|False|FALSE|0|no|No|NO)")){ + foundData.put(fieldName+"#"+itemCount++, + new MobyDataBoolean(text.matches("(true|True|TRUE|1|yes|Yes|YES)"))); + } + else if(dataTypeName.equals(MobyTags.MOBYINTEGER) && + text.matches("\\d+")){ + foundData.put(fieldName+"#"+itemCount++, new MobyDataInt("", text)); + } + else if(dataTypeName.equals(MobyTags.MOBYFLOAT) && + text.matches("\\d+(?:\\.\\d*)?(?:[eE][\\-\\+]?\\d+)?")){ + foundData.put(fieldName+"#"+itemCount++, new MobyDataFloat(text)); + } + else if(dataTypeName.equals(MobyTags.MOBYFLOAT) && + text.matches("(?:19|20)\\d\\d-(?:0[1-9]|1[012])-([012][1-9]|3[01])")){ + foundData.put(fieldName+"#"+itemCount++, new MobyDataDateTime(text)); + } MobyDataObject[] textData = client.getMobyObjects(text, desiredDataType); if(textData != null){ System.err.println("Found " + textData.length + " matches"); From gordonp at dev.open-bio.org Sun Apr 11 02:20:46 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 22:20:46 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110220.o3B2Kkwu020079@dev.open-bio.org> gordonp Sat Apr 10 22:20:46 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv20043/src/main/ca/ucalgary/seahawk/resources Modified Files: mobyBuilderRules.xml Log Message: Added LINUCS carbohydrate sequence recognition, for fun moby-live/Java/src/main/ca/ucalgary/seahawk/resources mobyBuilderRules.xml,1.10,1.11 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/mobyBuilderRules.xml,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/mobyBuilderRules.xml 2010/03/17 20:21:55 1.10 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources/mobyBuilderRules.xml 2010/04/11 02:20:46 1.11 @@ -66,6 +66,16 @@ string-length('$1')
+ + + \[\]\[\\S+\]\{.*?(?:([ab]-D-)?\M.?[\x20\(\)\[\]\-\+0-9\{\}]+){3,} + + + '' + + $0 + + \AABIF.*\z From gordonp at dev.open-bio.org Sun Apr 11 02:22:07 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 22:22:07 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110222.o3B2M7Dc020123@dev.open-bio.org> gordonp Sat Apr 10 22:22:06 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv20087/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyDataObjectWidget.java Log Message: Better populated data field description moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyDataObjectWidget.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyDataObjectWidget.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/seahawk/gui/MobyDataObjectWidget.java 2007/12/06 17:26:26 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyDataObjectWidget.java 2010/04/11 02:22:06 1.4 @@ -18,6 +18,7 @@ */ public class MobyDataObjectWidget extends JLabel implements MobyObjectReceiver, MobyContentProducer{ public static final int PARAM_TOOLTIP_WIDTH = 50; + public static final int MAX_DATA_DESC = 30; public static final Color INSTANTIATED_FG_COLOUR = Color.DARK_GRAY; public static final Color UNINSTANTIATED_FG_COLOUR = Color.RED; public static final String INSTANTIATED_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/checkmark.gif"; @@ -150,7 +151,14 @@ labelText = name+": Collection("+dataType.getName()+") -- "+actualData.getName(); } else{ - labelText = name+": "+dataType.getName()+" -- "+actualData.getName(); + String display = actualData.getName(); + if(display == null || display.trim().length() == 0){ + display = ((MobyDataInstance) actualData).getObject().toString(); + } + if(display.length() > MAX_DATA_DESC){ + display = display.substring(0, MAX_DATA_DESC-3)+"..."; + } + labelText = name+": "+dataType.getName()+" -- "+display; } tipText = dataType.getDescription(); if(tipText == null || tipText.length() == 0){ From gordonp at dev.open-bio.org Sun Apr 11 02:25:03 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 10 Apr 2010 22:25:03 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004110225.o3B2P3eJ020209@dev.open-bio.org> gordonp Sat Apr 10 22:25:03 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv20173/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentClipboard.java Added Files: DataImportChoiceDialog.java DataImportChoiceListener.java Log Message: Improved data import to clipboard UI moby-live/Java/src/main/ca/ucalgary/seahawk/gui DataImportChoiceDialog.java,NONE,1.1 DataImportChoiceListener.java,NONE,1.1 MobyContentClipboard.java,1.9,1.10 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/09 15:51:53 1.9 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/11 02:25:03 1.10 @@ -6,6 +6,7 @@ import org.biomoby.client.MobyRequestEventHandler; import org.biomoby.shared.MobyDataType; +import org.biomoby.shared.MobyNamespace; import org.biomoby.shared.data.*; import org.biomoby.shared.parser.MobyTags; @@ -20,12 +21,13 @@ import java.io.FileOutputStream; import java.net.URL; import java.util.*; +import java.util.regex.Pattern; /** * The clipboard is a special tab that holds a query with a MOBY Collection * that the user can add and subtract MobyDataInstances from. */ -public class MobyContentClipboard extends MobyContentPane{ +public class MobyContentClipboard extends MobyContentPane implements DataImportChoiceListener{ public final static String CLEAR_CLIPBOARD_OPTION = "Clear Clipboard"; public final static String CLIPBOARD_FILE_NAME = "SeaHawkClipboard"; public final static String CLIPBOARD_COLLECTION_NAME = "Clipboard Collection"; @@ -41,7 +43,13 @@ private File clipboardFile; private MobyDataJob query; // lump all data into one query private MobyDataObjectSet collection; // lump all data into one collection - private String previousImportDataType = null; + private MobyDataType previousImportDataType = null; + private MobyNamespace previousImportNS = null; + + private Pattern commentRegex; + private Pattern scriptRegex; + private Pattern styleRegex; + private Pattern tagRegex; // Clipboard editing variables private JMenuItem deleteDataPopupItem; @@ -88,6 +96,12 @@ setTransferHandler(new FileAndTextTransferHandler(cGUI, false)); // false = open data in current tab editorPane.setTransferHandler(getTransferHandler()); + // Setup regexes used for stripping HTML docs of their markup (for data pasting ops) + commentRegex = Pattern.compile("", Pattern.MULTILINE | Pattern.DOTALL); + scriptRegex = Pattern.compile("", Pattern.MULTILINE | Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + styleRegex = Pattern.compile("", Pattern.MULTILINE | Pattern.DOTALL | Pattern.CASE_INSENSITIVE); + tagRegex = Pattern.compile("<.*?>", Pattern.MULTILINE | Pattern.DOTALL); + sGUI.setClipboard(this); } @@ -248,7 +262,11 @@ logger.warn("Could not read contents of the URL to import to the clipboard ("+u+"):" +e); return; } - + if(urlContents.indexOf(" 1 - String[] selectionValues = new String[mobyDataFound.length]; - for(int i = 0; i < mobyDataFound.length; i++){ - selectionValues[i] = mobyDataFound[i].getDataType().getName(); - if(MobyTags.MOBYOBJECT.equals(selectionValues[i]) && - mobyDataFound[i].getPrimaryNamespace() != null){ - selectionValues[i] += " (" + mobyDataFound[i].getPrimaryNamespace().getName() + ")"; - } - } - // Sort alphabetically - //Arrays.sort(selectionValues); - String initialSelectionValue = selectionValues[0]; - if(previousImportDataType != null){ - for(String selectionValue: selectionValues){ - if(previousImportDataType.equals(selectionValue)){ - initialSelectionValue = selectionValue; - break; - } - } - } - String selection = (String) JOptionPane.showInputDialog(this, - "Paste data as...", - "Data import choice", - JOptionPane.PLAIN_MESSAGE, - (Icon) null, - selectionValues, - initialSelectionValue); - if(selection == null){ - logger.warn("No data type for import selected, abandoning import"); + + // Otherwise we need the user to choose + new DataImportChoiceDialog(contentGUI, mobyDataFound, previousImportDataType, previousImportNS, this); + } + + // Callback once user has selected the data to import from the DataImportChoiceDialog + public void importConfirmed(DataImportChoiceDialog dialog, MobyDataObject[] selectedData){ + if(selectedData == null){ + logger.warn("Got null for import selection, abandoning import"); return; } - for(int i = 0; i < selectionValues.length; i++){ - if(selection.equals(selectionValues[i])){ - addCollectionData(mobyDataFound[i]); - previousImportDataType = selection; - return; + for(int i = 0; i < selectedData.length; i++){ + addCollectionData(selectedData[i], i == selectedData.length-1); // only update display on last import + previousImportDataType = selectedData[i].getDataType(); + if(selectedData[i].getPrimaryNamespace() != null){ + previousImportNS = selectedData[i].getPrimaryNamespace(); } } } + public void importCanceled(DataImportChoiceDialog dialog){} + public boolean hasXMLSource(){ return true; } From gordonp at dev.open-bio.org Sun Apr 11 20:15:28 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sun, 11 Apr 2010 16:15:28 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004112015.o3BKFS3Y017966@dev.open-bio.org> gordonp Sun Apr 11 16:15:28 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv17912/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java Log Message: Updates for proper support of data filtering when submitting to forward services moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.25,1.26 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/10 00:40:17 1.25 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/11 20:15:28 1.26 @@ -532,7 +532,7 @@ isContentsXML = true; // Is it the second stage of wrapping, where data results are being seen? if(urlString.indexOf(WRAPPING_RESULTFILE_PREFIX) != -1){ - System.err.println("Wrapping service results"); + //System.err.println("Wrapping service results"); isWrapping = true; } else{ @@ -1191,7 +1191,7 @@ // Complex case, load the doc fragment from the MOBY XML source file if(docFragID != null && docFragID.length() > 0 && !targetURL.getHost().equals("moby")){ - return DataUtils.loadMobyDataFromXPointer(targetURL, filterHistory.get(getCurrentURL())); + return DataUtils.loadMobyDataFromXPointer(targetURL, filteredData, filterHistory.get(getCurrentURL())); } // Simple case, build the object using the values encoded in the URL itself. @@ -1256,8 +1256,13 @@ // Get the input data for the *previous* service MobyDataJob inputData = DataUtils.getInputSample(srcDoc, SeahawkOptions.getRegistry()); + if(inputData == null){ + // should only happen if Moby XML was loaded manually by a user, otherwise we've recorded this info... + logger.warn("No previous service info in Moby XML, 'previous input' option will not be displayed"); + return; + } for(MobyDataInstance previousMDI: inputData.getPrimaryData()){ - // add conditional of the current service as a criteria in user data for each previousMDI, + // 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()); @@ -1478,11 +1483,11 @@ } else if(regex.matcher(((Element) node).getTextContent()).find()){ matchingXPtrs.put(elementXPtr, Boolean.TRUE); - System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); + //System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); } else{ matchingXPtrs.put(elementXPtr, Boolean.FALSE); - System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); + //System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); } } else if(node instanceof Attr){ @@ -1494,12 +1499,12 @@ else if(regex.matcher(((Attr) node).getValue()).find()){ // Mark the element to which the attribute belongs matchingXPtrs.put(attrParentXPtr, Boolean.TRUE); - System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); + //System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); } // 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)); + //System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); } } @@ -1518,7 +1523,7 @@ if(!parentMatchingXPtrs.containsKey(currXPtr) || !inversed && !parentMatchingXPtrs.get(currXPtr).booleanValue() || inversed && 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()); } } @@ -1732,7 +1737,7 @@ List links = new Vector(); for(int i = 0; i < el.getElementCount(); i++){ javax.swing.text.Element childEl = el.getElement(i); - System.err.println("Found child element " + childEl.getName()); + //System.err.println("Found child element " + childEl.getName()); if(HTML.Tag.A.equals(childEl.getName())){ links.add(childEl); } @@ -1979,10 +1984,10 @@ // normally it'd go to mouseDragged, but sometimes that's flakey so check manually for the // mouse button being down here. if(overHyperlink && (e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == MouseEvent.BUTTON1_DOWN_MASK){ - System.err.println("Got wonky drag"); + //System.err.println("Got wonky drag"); lastHyperlinkDragged = lastHyperlinkHovered; status.setText("Drop the hyperlink onto a Web form field to populate it"); - System.err.println("Dragging "+lastHyperlinkDragged); + //System.err.println("Dragging "+lastHyperlinkDragged); getTransferHandler().exportAsDrag(this, e, TransferHandler.COPY); } else if(dragging){ @@ -1991,6 +1996,6 @@ } public void lostOwnership(Clipboard clipboard, Transferable contents){ - System.err.println("Lost clipboard ownership"); + //System.err.println("Lost clipboard ownership"); } } From gordonp at dev.open-bio.org Sun Apr 11 20:15:28 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sun, 11 Apr 2010 16:15:28 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004112015.o3BKFSqr017948@dev.open-bio.org> gordonp Sun Apr 11 16:15:28 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv17912/src/main/ca/ucalgary/seahawk/util Modified Files: DataUtils.java Added Files: XPointerResolver.java Log Message: Updates for proper support of data filtering when submitting to forward services moby-live/Java/src/main/ca/ucalgary/seahawk/util XPointerResolver.java,NONE,1.1 DataUtils.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.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/seahawk/util/DataUtils.java 2010/04/10 00:40:17 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/11 20:15:28 1.4 @@ -450,7 +450,14 @@ } } - public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, FilterSearch docFilter){ + /** + * Get the data instance object associated with a given XPointer into a Moby XML doc + * + * @param targetURL of the form URLpath#/1/1/2/1 where /1/1/2/1 is an XPointer, or an standard xpath, to the part of the Moby XML doc to deserialize + * @param filteredXPtrs a map of the xpointers to data that should NOT be deserialized if children of the targetURL XPointer + * @param docFilter the current filter applied to the document in targetURL + */ + public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, Map filteredXPtrs, FilterSearch docFilter){ // Are we dealing with a simple object or a complex one? MobyDataInstance mobyData = null; @@ -492,13 +499,35 @@ return null; } + // Remove the filtered data from the doc before deserializing to a moby data instance + // That way the request actually reflects what is shown on the screen to the user. + if(filteredXPtrs != null){ + // Mark and sweep (if we just deleted as we found node, the XPointers could be + // wrong as they refer to ordinality) + Vector nodesToDelete = new Vector(); + for(String xptr: filteredXPtrs.keySet()){ + nodesToDelete.add(XPointerResolver.getNodeFromXPointer(domDoc, xptr)); + } + + // Delete + for(Node nodeToDelete: nodesToDelete){ + Node parent = nodeToDelete.getParentNode(); + parent.removeChild(nodeToDelete); + // Get rid of Simple parents of deleted nodes, because empty Simple + // tags are not okay in Moby (causes parsing error) + if(MobyTags.SIMPLE.equals(parent.getLocalName())){ + parent.getParentNode().removeChild(parent); + } + } + } + // Build and run the XPath statement Element mobyObject = null; NodeList idSearchResult = null; Object xobject = null; try{ xobject = XPathFactory.newInstance().newXPath().evaluate(childXPath, - new InputSource(targetURL.openStream()), + domDoc, XPathConstants.NODESET); // Check the results From gordonp at dev.open-bio.org Wed Apr 14 22:02:05 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Wed, 14 Apr 2010 18:02:05 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004142202.o3EM252P007075@dev.open-bio.org> gordonp Wed Apr 14 18:02:04 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv7013/src/main/ca/ucalgary/seahawk/util Modified Files: DataUtils.java FilterSearch.java Added Files: MobyPayloadRequestListener.java MutableNodeList.java Log Message: Changes to implement explicit 'for each' loops over Seahawk data lists (not quite functional yet, but compiles) moby-live/Java/src/main/ca/ucalgary/seahawk/util MobyPayloadRequestListener.java,NONE,1.1 MutableNodeList.java,NONE,1.1 DataUtils.java,1.4,1.5 FilterSearch.java,1.4,1.5 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/11 20:15:28 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/14 22:02:04 1.5 @@ -4,6 +4,7 @@ import java.net.URL; import java.util.*; import java.util.logging.*; +import java.util.regex.*; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; @@ -34,8 +35,12 @@ public static final String TEMP_FILE_PREFIX = "seahawk"; private static final String OUTPUT_SUFFIX = ".out.xml"; private static final String INPUT_SUFFIX = ".in.xml"; - private static DocumentBuilder docBuilder; + public static DocumentBuilder docBuilder; private static Transformer identityTransform; + public static XPathFactory xPathFactory; + + public static final String ARTICLE_PEERS_MODE = "article_peers"; + public static final String DATATYPE_PEERS_MODE = "datatype_peers"; private static Logger logger = Logger.getLogger(DataUtils.class.getName()); @@ -54,6 +59,8 @@ } catch(Exception e){ logger.log(Level.SEVERE, "Cannot get identity XSLT transform from configuration", e); } + + xPathFactory = XPathFactory.newInstance(); } /** @@ -176,7 +183,7 @@ // User data has the form srcURL#XpathSelectCriteria xptrActualDataSubmitted regexFilter // where the filter is optional String[] data = sampleData.getUserData().toString().split("\t"); - System.err.println("Forward user data is " + sampleData.getUserData().toString()); + //System.err.println("Forward user data is " + sampleData.getUserData().toString()); URL dataSrcURL = null; try{ dataSrcURL = new URL(data[0]); @@ -437,7 +444,7 @@ "sync: the instance job '" + jobName + "' has no parameter '" + paramName + "'"); } - System.err.println("Setting user data val to " + attrValue + " for " + paramName); + //System.err.println("Setting user data val to " + attrValue + " for " + paramName); contentInstance.get(jobName).get(paramName).setUserData(attrValue); } else{ @@ -451,24 +458,47 @@ } /** - * Get the data instance object associated with a given XPointer into a Moby XML doc + * Loads targetURL, minus the nodes specified by the xpath keys in filteredXPtrs (map values are not currently used). + */ + public static void filterDoc(Document domDoc, Map filteredXPtrs){ + + if(domDoc == null){ + logger.log(Level.SEVERE, "Error: Could not get MOBY document as DOM (empty or malformed document?)"); + return; + } + + // Remove the filtered data from the doc before deserializing to a moby data instance + // That way the request actually reflects what is shown on the screen to the user. + if(filteredXPtrs != null){ + // Mark and sweep (if we just deleted as we found nodes, the XPointers could be + // wrong as they refer to ordinality) + Vector nodesToDelete = new Vector(); + for(String xptr: filteredXPtrs.keySet()){ + nodesToDelete.add(XPointerResolver.getNodeFromXPointer(domDoc, xptr)); + } + + // Delete + for(Node nodeToDelete: nodesToDelete){ + Node parent = nodeToDelete.getParentNode(); + parent.removeChild(nodeToDelete); + // Get rid of Simple parents of deleted nodes, because empty Simple + // tags are not okay in Moby (causes parsing error) + if(MobyTags.SIMPLE.equals(parent.getLocalName())){ + parent.getParentNode().removeChild(parent); + } + } + } + } + + /** + * Get the data instance object associated with a given XPointer in a Moby XML doc. * * @param targetURL of the form URLpath#/1/1/2/1 where /1/1/2/1 is an XPointer, or an standard xpath, to the part of the Moby XML doc to deserialize * @param filteredXPtrs a map of the xpointers to data that should NOT be deserialized if children of the targetURL XPointer * @param docFilter the current filter applied to the document in targetURL */ public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, Map filteredXPtrs, FilterSearch docFilter){ - // Are we dealing with a simple object or a complex one? - MobyDataInstance mobyData = null; - - // Find the DOM fragment corresponding to the MOBY ID anchor specified - // in the link URL by using an XPath statement on the source MOBY doc - //System.err.println("Retrieving complex object from XPointer " + targetURL); - - // A child Xpointer is of the form /1/2/1/1, specifying the DOM child - // descent path from the root node to get to the target node. The - // equivalent XPath is /*[1]/*[2]/*[1]/*[1] - String childXPath = targetURL.getRef().replaceAll("/(\\d+)", "/*[$1]"); + URL currentURL = null; try{currentURL = new URL(targetURL.toString().replaceAll("#"+targetURL.getRef(), ""));} catch(Exception e){ @@ -476,7 +506,6 @@ } // Build the DOM - Element mobyDOMRoot = null; Document domDoc = null; try{ domDoc = docBuilder.parse(targetURL.openStream()); @@ -489,46 +518,29 @@ " could not be read (from " + targetURL + ")", ioe); return null; } + // Does an in-place edit of domDoc + filterDoc(domDoc, filteredXPtrs); + + // Are we dealing with a simple object or a complex one? + MobyDataInstance mobyData = null; - if(domDoc != null){ - mobyDOMRoot = domDoc.getDocumentElement(); - } - if(mobyDOMRoot == null){ - logger.log(Level.SEVERE, "Error: Could not get MOBY document as DOM from source URL " + - targetURL + " (empty or malformed document?)"); - return null; - } + // Find the DOM fragment corresponding to the MOBY ID anchor specified + // in the link URL by using an XPath statement on the source MOBY doc + //System.err.println("Retrieving complex object from XPointer " + targetURL); - // Remove the filtered data from the doc before deserializing to a moby data instance - // That way the request actually reflects what is shown on the screen to the user. - if(filteredXPtrs != null){ - // Mark and sweep (if we just deleted as we found node, the XPointers could be - // wrong as they refer to ordinality) - Vector nodesToDelete = new Vector(); - for(String xptr: filteredXPtrs.keySet()){ - nodesToDelete.add(XPointerResolver.getNodeFromXPointer(domDoc, xptr)); - } - - // Delete - for(Node nodeToDelete: nodesToDelete){ - Node parent = nodeToDelete.getParentNode(); - parent.removeChild(nodeToDelete); - // Get rid of Simple parents of deleted nodes, because empty Simple - // tags are not okay in Moby (causes parsing error) - if(MobyTags.SIMPLE.equals(parent.getLocalName())){ - parent.getParentNode().removeChild(parent); - } - } - } + // A child Xpointer is of the form /1/2/1/1, specifying the DOM child + // descent path from the root node to get to the target node. The + // equivalent XPath is /*[1]/*[2]/*[1]/*[1] + String childXPath = targetURL.getRef().replaceAll("/(\\d+)", "/*[$1]"); // Build and run the XPath statement Element mobyObject = null; NodeList idSearchResult = null; Object xobject = null; try{ - xobject = XPathFactory.newInstance().newXPath().evaluate(childXPath, - domDoc, - XPathConstants.NODESET); + xobject = xPathFactory.newXPath().evaluate(childXPath, + domDoc, + XPathConstants.NODESET); // Check the results if(xobject != null){ @@ -603,7 +615,7 @@ * Generalizes the element instance into an XPath retrieving it and all * similarly nested elements (based on traversing the parent nodes and prepending their names) */ - protected static String elementInContextToNameBasedXPath(Element targetElement){ + public static String elementInContextToNameBasedXPath(Element targetElement){ String xpath = ""; for(Element currentElement = targetElement; @@ -630,22 +642,20 @@ xpath = "/*[@"+MobyTags.OBJ_NAMESPACE + " = '" + currentElement.getAttribute(MobyTags.OBJ_NAMESPACE)+"']" + xpath; } - else if(elName.equals(MobyTags.MOBYFLOAT) || - elName.equals(MobyTags.MOBYSTRING) || - elName.equals(MobyTags.MOBYBOOLEAN) || - elName.equals(MobyTags.MOBYINTEGER) || - elName.equals(MobyTags.MOBYDATETIME)){ +// else if(elName.equals(MobyTags.MOBYFLOAT) || +// elName.equals(MobyTags.MOBYSTRING) || +// elName.equals(MobyTags.MOBYBOOLEAN) || +// elName.equals(MobyTags.MOBYINTEGER) || +// elName.equals(MobyTags.MOBYDATETIME)){ // Assume that it isn't the primitive type, but rather the articleName // that makes it appropriate to use. - xpath = "/*[@"+MobyTags.ARTICLENAME + " = '" + - articleName+"']" + xpath; - } +// xpath = "/*[@"+MobyTags.ARTICLENAME + " = '" + +// articleName+"']" + xpath; +// } else{ // It's a complex type. Assume the type is why we are picking it. // TODO: In future we may want to check if a parent type is allowed in - // this slot, and generalize to that. May also want to check that there isn't more - // than one member of this type at this level in a HAS relationship... - // in that case we probably want to go by articleName to catch the full semantics + // this slot, and generalize to that. xpath = "/"+elName + xpath; } if(!(currentElement.getParentNode() instanceof Element)){ @@ -696,6 +706,12 @@ } /** + * Replace the selection xpath info in the data instance + */ + public static void replaceUserData(MobyDataInstance mdi, String selectionXPath){ + } + + /** * Retrieves processing instructions embedded in Moby XML docs if they have the for */ public static String getSeahawkAttrFromDoc(URL docURL, String attrName) throws Exception{ @@ -777,4 +793,328 @@ "any_namespace"); } + // Recursively ascend the DOM tree and find out our place in its branching structure + public static String getXPtr(Node n){ + if(n == null || n instanceof Document){ + return ""; + } + Node parent = n.getParentNode(); + if(parent == null && n instanceof Attr){ + parent = ((Attr) n).getOwnerElement(); + } + + NodeList children = parent.getChildNodes(); + int nonElementCnt = 0; + for(int i = 0; i < children.getLength(); i++){ + if(!(children.item(i) instanceof Element)){ + nonElementCnt++; + continue; + } + if(n == children.item(i)){ + return getXPtr(parent)+"/"+(i-nonElementCnt+1); + } + } + return null; + } + + /** + * If any moby object member is in a HAS relationship, add it to the list of filterable items + */ + public static Boolean addHASXPtrs(List filterList, Element object){ + String tagName = object.getLocalName(); + boolean isContainer = false; + MobyDataType mobyDataType = null; + if(tagName.equals(MobyTags.MOBYDATA) || tagName.equals(MobyTags.COLLECTION) || tagName.equals(MobyTags.SIMPLE) || + tagName.equals(MobyTags.CROSSREFERENCE)){ + isContainer = true; + } + else{ + mobyDataType = MobyDataType.getDataType(tagName, SeahawkOptions.getRegistry()); + if(mobyDataType == null){ + logger.log(Level.WARNING, + "Found datatype unknown to the registry ("+object.getLocalName()+")"); + 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)){ + continue; + } + + Element member = (Element) members.item(i); + addHASXPtrs(filterList, member); + + if(!isContainer){ + String memberName = member.getAttribute(MobyTags.ARTICLENAME); + MobyRelationship membership = mobyDataType.getChild(memberName); + //System.err.println("Relationship for " + tagName + " member " + memberName + + // " is " + (membership == null ? null : membership.getRelationshipType())); + if(membership != null && membership.getRelationshipType() == Central.iHAS){ + filterList.add(getXPtr(member)); + if(!hasHAS){ + hasHAS = Boolean.TRUE; + } + } + } + } + return hasHAS; + } + + /** + * For one-off filtering of a doc. Populates xPtrsToFilter, and returns the + * whole doc which you can manipulate yourself (e.g. removing the nodes identified). + */ + public static Document findFilteredNodes(URL targetURL, FilterSearch filter, + Map xPtrsToFilter){ + Document unfilteredDoc = null; + try{ + unfilteredDoc = docBuilder.parse(targetURL.openStream()); + } catch(Exception e){ + logger.log(Level.SEVERE, + "Could not parse Moby document " + targetURL, e); + return null; + } + findFilteredNodes(unfilteredDoc, filter, null, xPtrsToFilter, null, null, null, true); + return unfilteredDoc; + } + + /** + * Returns a list of xptrs to filterable nodes in the targetDoc, an populates the list of + * xptrs that should be filtered according to the provided filter. In-place edited fields are + * xPtrsToFilter, jobXPtrs, currentSelectedData, and currentSelectionXPath + * (for caching efficiency on multiple consecutive + * calls to this method, such as a live typed search in the UI). The latter three can be null if no caching is desired. + */ + public static List findFilteredNodes(Document targetDoc, FilterSearch filter, List filterableXPtrs, + Map xPtrsToFilter, Map jobXPtrs, + MutableNodeList currentSelectedData, StringBuffer currentSelectionXPath, + boolean apply){ + xPtrsToFilter.clear(); + + // Filter out any moby jobs, parameters, collection members or HAS members that aren't in the matchingNodes + if(filterableXPtrs == null){ + if(jobXPtrs == null){ + jobXPtrs = new HashMap(); + } + else{ + jobXPtrs.clear(); + } + filterableXPtrs = new Vector(); + NodeList nodes = targetDoc.getElementsByTagNameNS(MobyTags.MOBY_XML_NS, MobyTags.MOBYDATA); + for(int i = 0; i < nodes.getLength(); i++){ + String jobXPtr = getXPtr(nodes.item(i)); + filterableXPtrs.add(jobXPtr); + jobXPtrs.put(jobXPtr, addHASXPtrs(filterableXPtrs, (Element) nodes.item(i))); + } + + // Collections + nodes = targetDoc.getElementsByTagNameNS(MobyTags.MOBY_XML_NS, MobyTags.COLLECTION); + for(int i = 0; i < nodes.getLength(); i++){ + String collectionXPtr = getXPtr(nodes.item(i)); + NodeList collectionMembers = nodes.item(i).getChildNodes(); + int nonElementCnt = 0; + for(int j = 0; j < collectionMembers.getLength(); j++){ + if(!(collectionMembers.item(j) instanceof Element)){ + nonElementCnt++; + continue; + } + filterableXPtrs.add(collectionXPtr+"/"+(j-nonElementCnt+1)+"/1"); + } + } + } + + if(!apply || filter == null || filter.getFilterRegex().toString().length() == 0){ + return filterableXPtrs; + } + // Otherwise make a list of xpointers to data that should be filtered + XPathOption xsel = filter.getSelectedXPath(); + + // Find the applicable DOM nodes if not yet found, or if selection criteria have changed + if(currentSelectedData == null || currentSelectedData.isEmpty() || + currentSelectionXPath == null || !currentSelectionXPath.toString().equals(xsel.getXPath())){ + if(currentSelectionXPath == null){ + currentSelectionXPath = new StringBuffer(xsel.getXPath()); + } + else{ + currentSelectionXPath.replace(0, currentSelectionXPath.length(), xsel.getXPath()); + } + try{ + if(currentSelectedData == null){ + currentSelectedData = new MutableNodeList(); + } + else{ + currentSelectedData.clear(); + } + currentSelectedData.addAll((NodeList) xPathFactory.newXPath().evaluate(currentSelectionXPath.toString(), + targetDoc, + XPathConstants.NODESET)); + } catch(Exception e){ + logger.log(Level.SEVERE, + "Could not evaluate XPath (" + xsel.getXPath() + ")", e); + return filterableXPtrs; + } + // System.err.println("There are " + currentSelectedData.getLength() + + // " items selected in the document using XPath " + currentSelectionXPath); + } + + // Find just the data subset also matching the regex + Map matchingXPtrs = new LinkedHashMap(); + // Build the FSA only once, for efficiency + Pattern regex = Pattern.compile(filter.getFilterRegex().toString(), + Pattern.MULTILINE | Pattern.DOTALL | + (filter.getCaseSensitivity() ? 0 : Pattern.CASE_INSENSITIVE)); + for(int i = 0; i < currentSelectedData.getLength(); i++){ + Node node = currentSelectedData.item(i); + if(node instanceof Element){ + 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(elementXPtr, Boolean.FALSE); + //System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); + } + } + else if(node instanceof Attr){ + 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(attrParentXPtr, Boolean.TRUE); + //System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); + } + // 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.log(Level.WARNING, + "Found filter xpath result item that was not an Element or Attribute as expected ("+ + node.getClass().getName()+")"); + } + } + + boolean inversed = filter.getSelectionInversed(); + Map parentMatchingXPtrs = new LinkedHashMap(); + for(String currXPtr: filterableXPtrs){ + for(Map.Entry matchingXPtr: matchingXPtrs.entrySet()){ + if(matchingXPtr.getKey().startsWith(currXPtr+"/")){ // a parent of the matching data + // No positive example yet? + if(!parentMatchingXPtrs.containsKey(currXPtr) || + !inversed && !parentMatchingXPtrs.get(currXPtr).booleanValue() || + inversed && parentMatchingXPtrs.get(currXPtr).booleanValue()){ + //System.err.println("Adding "+ matchingXPtr.getValue() + " for " + currXPtr); + parentMatchingXPtrs.put(currXPtr, matchingXPtr.getValue()); + } + } + } + } + + matchingXPtrs.putAll(parentMatchingXPtrs); + for(String currXPtr: matchingXPtrs.keySet()){ + // Is part of the selection criteria, but doesn't match the regex + boolean shouldFilter = false; + if(!matchingXPtrs.get(currXPtr).booleanValue() && + // special condition: if "entire response" xpath is given, filter only at the job level + (!currentSelectionXPath.toString().equals(FilterSearch.SELECT_ALL_XPATH) || jobXPtrs.containsKey(currXPtr))){ + shouldFilter = true; + } + if(!inversed && shouldFilter || + inversed && !shouldFilter){ + xPtrsToFilter.put(currXPtr, "todo"); + } + } + + //todo: filter objects without the HAS field at all... + return filterableXPtrs; + } + // We need to enumerate the possible peer-sets for the selected data item. Is the user interested in + // items in the same namespace, same data type, or same article name? + public static NodeList getPeerElements(Document doc, MobyDataInstance mobyData, String peerMode){ + if(!(mobyData instanceof MobyPrimaryData)){ + logger.log(Level.WARNING, "Tried to get peers of data that was not an instanceof MobyPrimaryData (was " + + mobyData.getClass().getName()+ ")"); + return null; + } + MobyDataType dataTypeTemplate = ((MobyPrimaryData) mobyData).getDataType(); + + NodeList peerElements = null; + String peerGroupXPath = null; + if(mobyData.getUserData() != null){ + String[] userData = ((String) mobyData.getUserData()).split("\t"); + // first arg is url#nameBasedXPath + peerGroupXPath = userData[0].split("#", 2)[1]; + } + else{ + // Fallback is to get all nodes with the same name... + // warning: need to set this in the userdata sent to the job, to jibe with taverna workflow export selection of nodes! + logger.log(Level.WARNING, "No UserData for data instance, falling back to all peer elements of the same datatype"); + peerGroupXPath = "//"+dataTypeTemplate.getName(); + } + + // just look at data type tag, regardless of nesting + if(DATATYPE_PEERS_MODE.equals(peerMode)){ + peerGroupXPath = peerGroupXPath.replaceFirst("^.+/", "//"); + } + else if(ARTICLE_PEERS_MODE.equals(peerMode)){ + String xpathArticleCondition = "[@"+MobyTags.ARTICLENAME + "='" + mobyData.getName() +"']"; + // Pass back modified selection xpath for userdata (enables PBE to capture the additonal semantics) + // This is done by replacing first tab delimited field url#selectionXPath with url#newXPath + String newUserData = mobyData.getUserData().toString().replaceFirst("^(.*?)#.*?(?=\\t)", + "$1#"+peerGroupXPath+xpathArticleCondition); + mobyData.setUserData(newUserData); + + // keep from job article name down + peerGroupXPath = peerGroupXPath.replaceFirst("^.*/(Collection|Simple)", "//*"); + // we want to go by articleName too to catch the full semantics of the peer group definition + peerGroupXPath += xpathArticleCondition; + } + else{ + logger.log(Level.SEVERE, "Got unknown mode for peer selection, aborting (mode was "+peerMode+")"); + return null; + } + // For xpaths given above, MOBY namespace is problem in XPath evaluation. + // solution: eliminate Moby envelope path parts: full path doesn't resolve in xpath for unknown reasons + //.replaceAll("/(MOBY|mobyContent|mobyData|Collection|Simple)","/moby:$1"); //attempt 1 + //.replaceAll("/([a-zA-Z_0-9\\-]+)(?=/|$)", "/*[local-name() = '$1']") //attempt 2 + //.replaceAll("/([a-zA-Z_0-9\\-]+)\\[", "/*[local-name() = '$1' and "); //attempt 2 cont'd + + try{ + peerElements = (NodeList) xPathFactory.newXPath().evaluate(peerGroupXPath, + doc, + XPathConstants.NODESET); + } catch(Exception e){ + logger.log(Level.SEVERE, "Could not evaluate UserData XPath "+peerGroupXPath, e); + } + System.err.println("Got " + peerElements.getLength() + " peers for " + peerGroupXPath); + + return peerElements; + } + + // given a node from a Moby XML dom, find the name of the mobyData job that's its parent + public static String findMobyJobName(Node n){ + while(n != null && !n.getLocalName().equals(MobyTags.MOBYDATA)){ + n = n.getParentNode(); + } + if(n == null){ + return null; // no mobyData parent + } + else{ + return MobyPrefixResolver.getAttr((Element) n, MobyTags.QUERYID); + } + } } =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/10 00:40:17 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/14 22:02:04 1.5 @@ -28,6 +28,20 @@ public static final String SELECT_ALL_XPATH = "//* | //*/@*"; /** + * A c-tor to manually populate the filter with a specific set of filter criteria. + * No autopoulation of options is done. + */ + public FilterSearch(String regex, XPathOption xpath, boolean case_sensitive, boolean inverse_selection){ + filterRegex = new StringBuffer(regex); + xpathOptions = new Vector(); + xpathOptions.add(xpath); + setCaseSensitivity(case_sensitive); + setSelectionInversed(inverse_selection); + } + + /** + * Autopopulates the possible search field values based on the incoming doc + * * @param docToFilter the document that will be used to determine what XPaths can be suggested * @param docBuilder the xml parser to use on the document * @@ -106,4 +120,15 @@ public Vector getXPathOptions(){ return xpathOptions; } + + public boolean equals(Object o){ + if(o == null || !(o instanceof FilterSearch)){ + return false; + } + FilterSearch other = (FilterSearch) o; + return filterRegex.toString().equals(other.filterRegex.toString()) && + getSelectedXPath().getXPath().equals(other.getSelectedXPath().getXPath()) && + caseSensitivity == other.caseSensitivity && + inverseSelection == other.inverseSelection; + } } From gordonp at dev.open-bio.org Wed Apr 14 22:02:04 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Wed, 14 Apr 2010 18:02:04 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004142202.o3EM24JD007053@dev.open-bio.org> gordonp Wed Apr 14 18:02:04 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv7013/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java MobyServicesGUI.java Added Files: MobyPayloadCreator.java Log Message: Changes to implement explicit 'for each' loops over Seahawk data lists (not quite functional yet, but compiles) moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyPayloadCreator.java,NONE,1.1 MobyContentPane.java,1.26,1.27 MobyServicesGUI.java,1.17,1.18 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.26 retrieving revision 1.27 diff -u -r1.26 -r1.27 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/11 20:15:28 1.26 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/14 22:02:04 1.27 @@ -1,4 +1,3 @@ - package ca.ucalgary.seahawk.gui; // For external links @@ -72,8 +71,8 @@ public static final String SERVICE_CREATION_MSG = "Create a service returning this datatype"; private static final int TAB_ICON_SPACER = 2; - private static String SEARCH_VISIBLE = "Search visible"; - private static String SEARCH_HIDDEN = "Search hidden"; + private static final String SEARCH_VISIBLE = "Search visible"; + private static final String SEARCH_HIDDEN = "Search hidden"; private static ImageIcon hourglassIcon; private static ImageIcon failedIcon; @@ -105,10 +104,10 @@ private Map filteredData; //Map private boolean filterChanged; private Document currentDoc; //the doc DOM being actively filtered - private NodeList currentSelectedData = null; - private String currentSelectionXPath = null; - private Map jobXPtrs = null; // Map + private MutableNodeList currentSelectedData = null; + private StringBuffer currentSelectionXPath = null; private List filterableNodes = null; // List + private Map jobXPtrs = null; // Map private List origStyles = null; private boolean firstDocRendering = true; @@ -141,20 +140,6 @@ private final static String wsServletPath = "/SOAPServlet"; private static Acme.Serve.Serve servletContainer; private static Map id2GuiMap; - private static DocumentBuilder docBuilder; - private static XPathFactory xPathFactory; - - static{ - xPathFactory = XPathFactory.newInstance(); - - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - dbf.setNamespaceAware(true); - try{ - docBuilder = dbf.newDocumentBuilder(); - } catch(Exception e){ - logger.warn("Cannot get XML parser from configuration", e); - } - } public MobyContentPane(MobyContentGUI cGUI, MobyServicesGUI sGUI, JTabbedPane parentComponent, DataFlowRecorder recorder, JLabel statusBar){ tabbedPane = parentComponent; @@ -200,7 +185,9 @@ filterHistory = new HashMap(); deletedFilters = new HashMap(); xPtrsReferencedInNextService = new Vector(); + currentSelectedData = new MutableNodeList(); filteredData = new HashMap(); + jobXPtrs = new HashMap(); ClassLoader cl = getClass().getClassLoader(); if(cl == null){ @@ -738,9 +725,8 @@ // If this page has a filter associated with it before reload it try{ currentDoc = null; // get rid of previous in-memory doc use for interactive filtering, if any - currentSelectedData = null; - currentSelectionXPath = null; - jobXPtrs = null; + currentSelectedData.clear(); + currentSelectionXPath = new StringBuffer(); filterableNodes = null; origStyles = null; firstDocRendering = true; @@ -1209,14 +1195,54 @@ "not extract MOBY Data Object from " +targetURL); return; } + if(!(mobyData instanceof MobyPrimaryData)){ + logger.warn("Cannot create MOBY service list for non-primary " + + "MOBY Data (was " +mobyData.getClass().getName()+")"); + return; + } JPopupMenu popup = new DynamicJPopupMenu(); popup.setName(MOBY_SERVICE_POPUP_NAME); addExtraMobyOptions(popup, mobyData, targetURL); - JMenuItem checkingLinksPopupItem = new JMenuItem("Check for services..."); + JMenuItem checkingLinksPopupItem = new JMenuItem("Checking for services..."); popup.add(checkingLinksPopupItem); popup.show(this, lastClickX+editorPane.getX(), lastClickY+editorPane.getY()); servicesGUI.addPopupOptions(mobyData, popup, true, getDefaultHandler()); // true = asynchronous + + // It's possible that the current node clicked has peers that could also be submitted at the same time. + // In this case, create a "for each" option to submit all peers to the service. We don't actually build + // the input data, but provde a callback listener to create the full submission envelope if the user + // chooses the for each option. The Moby data instance's userData gives us the current context, enabling us + // to construct the correct payload in MobyPayloadCreator.createPayload() at any point in the future. + String origUserData = (String) mobyData.getUserData(); + MobyPayloadRequestListener payloadCreator = new MobyPayloadCreator(this); + for(String peerMode: new String[]{DataUtils.ARTICLE_PEERS_MODE, DataUtils.DATATYPE_PEERS_MODE}){ + // note that getPeerElements() will modify the userData to reflect the semantic of the requested peer mode + mobyData.setUserData(origUserData); + NodeList peerElements = DataUtils.getPeerElements(getCurrentDoc(), mobyData, peerMode); + if(peerElements.getLength() <= 1){ + continue; // no 'for each' option if only one to process... + } + String each = "each (" + peerElements.getLength() + " total)"; + if(peerMode.equals(DataUtils.ARTICLE_PEERS_MODE)){ + each += " '"+mobyData.getName()+"'"; + } + MobyDataType dataType = ((MobyPrimaryData) mobyData).getDataType(); + if(mobyData instanceof MobyPrimaryDataSet){ // Collection + servicesGUI.addPopupOptions((MobyPrimaryDataSet) mobyData, popup, true, getDefaultHandler(), payloadCreator, + (String) mobyData.getUserData(), each); + } + else if(MobyTags.MOBYOBJECT.equals(dataType.getName())){ + MobyNamespace namespace = null; + servicesGUI.addPopupOptions(namespace, popup, true, getDefaultHandler(), payloadCreator, + (String) mobyData.getUserData(), each); + } + else{ + servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), payloadCreator, + (String) mobyData.getUserData(), each); + } + } + status.setText("Shift+Click=Service in new tab, Ctrl+Click=Use default 2nd params"); if(popup.getSubElements().length > 0){ popup.setSelected(null); @@ -1228,6 +1254,15 @@ } } + Map getFilteredData(){ + return filteredData; + } + + Map getJobXPtrs(){ + return jobXPtrs; + } + + /** * Subclasses can use this method to expand the popup menu. Be sure to call super.addExtraMobyOptions() */ @@ -1252,7 +1287,7 @@ //System.err.println("Should create a previous input menu item for " + mdi.getUserData()); try{ - Document srcDoc = docBuilder.parse(srcURL.openStream()); + Document srcDoc = DataUtils.docBuilder.parse(srcURL.openStream()); // Get the input data for the *previous* service MobyDataJob inputData = DataUtils.getInputSample(srcDoc, SeahawkOptions.getRegistry()); @@ -1262,7 +1297,7 @@ return; } for(MobyDataInstance previousMDI: inputData.getPrimaryData()){ - // add conditional of the current service as a criteria in user data for each previousMDI, + // 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()); @@ -1271,6 +1306,7 @@ } catch(Exception e){ logger.warn("Could not load previous service info, 'previous input' option will not be displayed", e); } + } /** @@ -1392,231 +1428,41 @@ return null; } - /** - * Determine the parts of the XML document matching the FilterSearch criteria, and filter the view accordingly. - */ - public void applyFilter(boolean apply){ - if(!filterChanged){ - filterChanged = true; - } - filteredData.clear(); - + protected Document getCurrentDoc(){ if(currentDoc == null){ // parse the doc into memory if not already there try{ - currentDoc = docBuilder.parse(getCurrentURL().openStream()); + currentDoc = DataUtils.docBuilder.parse(getCurrentURL().openStream()); } catch(Exception e){ logger.error("Could not parse Moby document " + getCurrentURL(), e); - return; - } - } - // Filter out any moby jobs, parameters, collection members or HAS members that aren't in the matchingNodes - if(filterableNodes == null){ - jobXPtrs = new HashMap(); - filterableNodes = new Vector(); - NodeList nodes = currentDoc.getElementsByTagNameNS(MobyTags.MOBY_XML_NS, MobyTags.MOBYDATA); - for(int i = 0; i < nodes.getLength(); i++){ - String jobXPtr = getXPtr(nodes.item(i)); - filterableNodes.add(jobXPtr); - jobXPtrs.put(jobXPtr, addHASXPtrs(filterableNodes, (Element) nodes.item(i))); - } - - // Collections - nodes = currentDoc.getElementsByTagNameNS(MobyTags.MOBY_XML_NS, MobyTags.COLLECTION); - for(int i = 0; i < nodes.getLength(); i++){ - String collectionXPtr = getXPtr(nodes.item(i)); - NodeList collectionMembers = nodes.item(i).getChildNodes(); - int nonElementCnt = 0; - for(int j = 0; j < collectionMembers.getLength(); j++){ - if(!(collectionMembers.item(j) instanceof Element)){ - nonElementCnt++; - continue; - } - filterableNodes.add(collectionXPtr+"/"+(j-nonElementCnt+1)+"/1"); - } + return null; } } - - if(!apply || !filterHistory.containsKey(getCurrentURL()) || - (filterHistory.containsKey(getCurrentURL()) && - filterHistory.get(getCurrentURL()).getFilterRegex().toString().length() == 0)){ - // Show whole doc if no filter or if filter is blank, so nothing to do here - if(firstDocRendering){ - firstDocRendering = false; - } - else{ - displayFilterEffect(); //need to cleanup previous state - } - return; - } - // Otherwise make a list of xpointers to data that should be grayed out - FilterSearch fs = filterHistory.get(getCurrentURL()); - XPathOption xsel = fs.getSelectedXPath(); - - // Find all the matching data - XPath xpath = xPathFactory.newXPath(); - // Find the applicable DOM nodes if not yet found, or if selection criteria have changed - if(currentSelectedData == null || currentSelectionXPath == null || !currentSelectionXPath.equals(xsel.getXPath())){ - currentSelectionXPath = xsel.getXPath(); - try{ - currentSelectedData = (NodeList) xpath.evaluate(currentSelectionXPath, currentDoc, XPathConstants.NODESET); - } catch(Exception e){ - logger.error("Could not evaluate XPath (" + xsel.getXPath() + ") over " + getCurrentURL(), e); - return; - } - // System.err.println("There are " + currentSelectedData.getLength() + - // " items selected in the document using XPath " + currentSelectionXPath); - } - - // Find just the data subset also matching the regex - Map matchingXPtrs = new LinkedHashMap(); - // Build the FSA only once, for efficiency - 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){ - 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(elementXPtr, Boolean.FALSE); - //System.err.println("Adding " + elementXPtr + " as " + matchingXPtrs.get(elementXPtr)); - } - } - else if(node instanceof Attr){ - 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(attrParentXPtr, Boolean.TRUE); - //System.err.println("Adding " + attrParentXPtr + " attr parent as " + matchingXPtrs.get(attrParentXPtr)); - } - // 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 ("+ - node.getClass().getName()+")"); - } - } - - boolean inversed = fs.getSelectionInversed(); - Map parentMatchingXPtrs = new LinkedHashMap(); - for(String currXPtr: filterableNodes){ - for(Map.Entry matchingXPtr: matchingXPtrs.entrySet()){ - if(matchingXPtr.getKey().startsWith(currXPtr+"/")){ // a parent of the matching data - // No positive example yet? - if(!parentMatchingXPtrs.containsKey(currXPtr) || - !inversed && !parentMatchingXPtrs.get(currXPtr).booleanValue() || - inversed && parentMatchingXPtrs.get(currXPtr).booleanValue()){ - //System.err.println("Adding "+ matchingXPtr.getValue() + " for " + currXPtr); - parentMatchingXPtrs.put(currXPtr, matchingXPtr.getValue()); - } - } - } - } - - matchingXPtrs.putAll(parentMatchingXPtrs); - for(String currXPtr: matchingXPtrs.keySet()){ - // Is part of the selection criteria, but doesn't match the regex - boolean shouldFilter = false; - if(!matchingXPtrs.get(currXPtr).booleanValue() && - // special condition: if "entire response" xpath is given, filter only at the job level - (!currentSelectionXPath.equals(FilterSearch.SELECT_ALL_XPATH) || jobXPtrs.containsKey(currXPtr))){ - shouldFilter = true; - } - if(!inversed && shouldFilter || - inversed && !shouldFilter){ - filteredData.put(currXPtr, "todo"); - } - } - - //todo: filter objects without the HAS field at all... - - // apply gray out in the document display - displayFilterEffect(); + return currentDoc; } - // If any moby object member is in a HAS relationship, add it to the list of filterable items - private Boolean addHASXPtrs(List filterList, Element object){ - String tagName = object.getLocalName(); - boolean isContainer = false; - MobyDataType mobyDataType = null; - if(tagName.equals(MobyTags.MOBYDATA) || tagName.equals(MobyTags.COLLECTION) || tagName.equals(MobyTags.SIMPLE) || - tagName.equals(MobyTags.CROSSREFERENCE)){ - isContainer = true; - } - else{ - mobyDataType = MobyDataType.getDataType(tagName, SeahawkOptions.getRegistry()); - if(mobyDataType == null){ - logger.warn("Found datatype unknown to the registry ("+object.getLocalName()+")"); - return Boolean.FALSE; - } + /** + * Determine the parts of the XML document matching the FilterSearch criteria for the current doc, + * and filter the view accordingly. Used for interactive filtering in the display. + */ + protected void applyFilter(boolean apply){ + if(!filterChanged){ + filterChanged = true; } - 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)){ - continue; - } - - Element member = (Element) members.item(i); - addHASXPtrs(filterList, member); - - if(!isContainer){ - String memberName = member.getAttribute(MobyTags.ARTICLENAME); - MobyRelationship membership = mobyDataType.getChild(memberName); - //System.err.println("Relationship for " + tagName + " member " + memberName + - // " is " + (membership == null ? null : membership.getRelationshipType())); - if(membership != null && membership.getRelationshipType() == Central.iHAS){ - filterList.add(getXPtr(member)); - if(!hasHAS){ - hasHAS = Boolean.TRUE; - } - } - } + FilterSearch filter = filterHistory.get(getCurrentURL()); + filterableNodes = DataUtils.findFilteredNodes(getCurrentDoc(), filter, filterableNodes, filteredData, jobXPtrs, + currentSelectedData, currentSelectionXPath, apply); + + if((!apply || filter == null || filter.getFilterRegex().toString().length() == 0) && firstDocRendering){ + // Show whole doc if no filter or if filter is blank, so nothing to do here + firstDocRendering = false; } - return hasHAS; + // apply gray out in the document display, or need to cleanup previous state even if no filter now + else{ + displayFilterEffect(); + } } - // Recursively ascend the DOM tree and find out our place in its branching structure - private String getXPtr(Node n){ - if(n == null || n instanceof Document){ - return ""; - } - Node parent = n.getParentNode(); - if(parent == null && n instanceof Attr){ - parent = ((Attr) n).getOwnerElement(); - } - - NodeList children = parent.getChildNodes(); - int nonElementCnt = 0; - for(int i = 0; i < children.getLength(); i++){ - if(!(children.item(i) instanceof Element)){ - nonElementCnt++; - continue; - } - if(n == children.item(i)){ - return getXPtr(parent)+"/"+(i-nonElementCnt+1); - } - } - return null; - } /** * Gray out parts of the HTML view if they are part of the filtered data. @@ -1681,7 +1527,7 @@ // Gray out the mismatched textual data for(Map.Entry dataToFilter: filteredData.entrySet()){ - //System.err.println("Filtering "+dataToFilter.getKey()); + System.err.println("Filtering "+dataToFilter.getKey()); javax.swing.text.AbstractDocument.AbstractElement htmlDiv = (javax.swing.text.AbstractDocument.AbstractElement) d.getElement(dataToFilter.getKey()); if(htmlDiv == null){ @@ -1998,4 +1844,5 @@ public void lostOwnership(Clipboard clipboard, Transferable contents){ //System.err.println("Lost clipboard ownership"); } + } =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/09 15:55:48 1.17 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/14 22:02:04 1.18 @@ -1,11 +1,11 @@ package ca.ucalgary.seahawk.gui; import ca.ucalgary.seahawk.services.MobyClient; -import ca.ucalgary.seahawk.util.HTMLUtils; -import ca.ucalgary.seahawk.util.SeahawkOptions; +import ca.ucalgary.seahawk.util.*; import org.biomoby.shared.*; import org.biomoby.shared.data.*; +import org.biomoby.shared.parser.MobyTags; import org.biomoby.client.CentralImpl; import org.biomoby.client.MobyRequest; import org.biomoby.client.MobyRequestEventHandler; @@ -182,6 +182,7 @@ return handler; } + // synchronized so simultaneous requests don't get their input data mixed up public void setupServiceSecondaryData(MobyRequestEventHandler handler){ MobyDataInstance[] castInputs = new MobyDataInstance[primaryInput.length]; for(int i = 0; i < primaryInput.length; i++){ @@ -194,14 +195,17 @@ castInputs[i] = (MobyDataInstance) primaryInput[i]; } - try{ - mobyRequest.setInput(castInputs); - mobyRequest.setSecondaryInput(secondaryInputInstances); - } catch(MobyException me){ - me.printStackTrace(); - logger.warn("Error while trying to set service input: " + me); - } - executeService(handler); + // code from mobyRequest.setInput() to executeService() should always be synced to avoid input mixup between requests + synchronized(mobyRequest){ + try{ + mobyRequest.setInput(castInputs); + mobyRequest.setSecondaryInput(secondaryInputInstances); + } catch(MobyException me){ + me.printStackTrace(); + logger.warn("Error while trying to set service input: " + me); + } + executeService(handler); + } } protected void setupService(MobyService mobyService, MobyDataInstance mdi, int handlerHashCode, boolean useDefaultSecondaries){ @@ -217,18 +221,21 @@ System.arraycopy(primaryInputTemplate, 0, primaryInput, 0, primaryInput.length); if(!hasSecondaryInput(mobyService)){ - try{ - // Implement simple input (i.e. only one input argument) - mobyRequest.setInput(mdi, ""); - } - catch(MobyException me){ - logger.error("Failure in MOBY input, was not acceptable:" + me); - return; - } + // code from mobyRequest.setInput() to executeService() should always be synced to avoid input mixup between requests + synchronized(mobyRequest){ + try{ + // Implement simple input (i.e. only one input argument) + mobyRequest.setInput(mdi, ""); + } + catch(MobyException me){ + logger.error("Failure in MOBY input, was not acceptable:" + me); + return; + } - // No need for further info, just launch the request - removePopupOptions(); - executeService(getHandlerByHashCode(handlerHashCode)); + // No need for further info, just launch the request + removePopupOptions(); + executeService(getHandlerByHashCode(handlerHashCode)); + } } else{ // We need more info from the user to launch this service @@ -502,7 +509,8 @@ class OptionLoaderThread extends Thread{ Node targetNode = null; MobyRequestEventHandler handler = null; - MobyDataInstance mobyData = null; + MobyPayloadRequestListener payloadCreator = null; + Object mobyData = null; String extraMenuText = null; JPopupMenu popupList; @@ -513,11 +521,13 @@ this.handler = handler; } - public OptionLoaderThread(MobyDataInstance mobyData, JPopupMenu popupList, MobyRequestEventHandler handler, String extraMenuText){ + public OptionLoaderThread(Object mobyData, JPopupMenu popupList, MobyRequestEventHandler handler, + MobyPayloadRequestListener payloadCreator, String extraMenuText){ super(); this.mobyData = mobyData; this.popupList = popupList; this.handler = handler; + this.payloadCreator = payloadCreator; this.extraMenuText = extraMenuText; } @@ -526,7 +536,7 @@ addPopupOptions(targetNode, popupList, false, handler); } else if(mobyData != null){ - addPopupOptions(mobyData, popupList, false, handler, extraMenuText); + addPopupOptions(mobyData, popupList, false, handler, payloadCreator, extraMenuText); } else{ logger.warn("Warning: OptionLoaderThread has no data to work with"); @@ -576,6 +586,30 @@ } /** + * Creates a menu item based on the provided data type. If a service is selected from here, + * a callback will be made to the MobyPayloadRequestListener for the actual submission data. + * + * @param payloadKey a key that will be used in the callback so the listener knows what payload the create + */ + public void addPopupOptions(MobyDataType mobyDataType, JPopupMenu popupList, boolean asynchronous, + MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, + String payloadKey, String extraMenuText){ + addPopupOptions(mobyDataType, popupList, asynchronous, handler, payloadCreator, extraMenuText); + } + + public void addPopupOptions(MobyNamespace mobyNamespace, JPopupMenu popupList, boolean asynchronous, + MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, + String payloadKey, String extraMenuText){ + addPopupOptions(mobyNamespace, popupList, asynchronous, handler, payloadCreator, extraMenuText); + } + + public void addPopupOptions(MobyPrimaryDataSet collection, JPopupMenu popupList, boolean asynchronous, + MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, + String payloadKey, String extraMenuText){ + addPopupOptions(collection, popupList, asynchronous, handler, payloadCreator, extraMenuText); + } + + /** * Same as three arg addPopupOptions, but uses default response handler */ public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous){ @@ -586,13 +620,16 @@ * Find the list of available services querying MobyCentral directly with a piece of data. */ public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous, MobyRequestEventHandler handler){ - addPopupOptions(mobyData, popupList, asynchronous, handler, null); + addPopupOptions(mobyData, popupList, asynchronous, handler, null, null); } /** * Find the list of available services querying MobyCentral directly with a piece of data. + * + * @param mobyData a MobyDataInstance, or in the case of deferred data to be created by payloadCreator, a MobyDataType, MobyNamespace, or MobyPrimaryDataSet */ - public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous, MobyRequestEventHandler handler, String extraMenuText){ + public void addPopupOptions(Object mobyData, JPopupMenu popupList, boolean asynchronous, + MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, String extraMenuText){ if(asynchronous){ //Show the user that we're doing something... @@ -605,7 +642,7 @@ } // Call this method synchronously in a different thread - OptionLoaderThread lt = new OptionLoaderThread(mobyData, popupList, handler, extraMenuText); + OptionLoaderThread lt = new OptionLoaderThread(mobyData, popupList, handler, payloadCreator, extraMenuText); lt.start(); return; } @@ -625,7 +662,9 @@ popupList.setVisible(true); } - addClipboardItem(submenu, mobyData); + if(mobyData instanceof MobyDataInstance){ + addClipboardItem(submenu, (MobyDataInstance) mobyData); + } submenu.add(getWaitItem(submenu)); MobyDataServiceAssocInstance serviceAssocObject = null; @@ -637,6 +676,15 @@ else if(mobyData instanceof MobyDataObject){ serviceAssocObject = mobyClient.getServices((MobyDataObject) mobyData); } + // The data will be loaded later + else if(payloadCreator != null){ + if(mobyData instanceof MobyPrimaryDataSet){ + //serviceAssocObject = mobyClient.getServices(new MobyDataObjectSetDeferred(mobyData, payloadCreator, requestKey)); + } + else{ + //serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred(mobyData, payloadCreator, requestKey)); + } + } else{ logger.warn("Service options for objects other than MobyDataObject " + "and MobyDataObjectSet are not yet supported."); @@ -1136,51 +1184,50 @@ return menu; } - public JMenu createObjectSubMenu(MobyDataInstance mdi, String extraMenuText){ - if(!(mdi instanceof MobyPrimaryData)){ - logger.warn("Ignoring non-primary data object submitted to menu creation: " + mdi); - return null; - } - - MobyPrimaryData targetData = (MobyPrimaryData) mdi; - String id = targetData.getId(); - if(id == null){ - id = ""; - } - else if(id.length() > MAX_ID_LEN+3){ - id = id.substring(0, MAX_ID_LEN)+"..."; - } - - MobyDataType mobyDataType = targetData.getDataType(); - String name = null; - if(mobyDataType == null){ - logger.warn("PG: Warning: no datatype associated with service " + - targetData.getName()); - } - else{ - name = mobyDataType.getName(); - } - if("Object".equals(name)){ - MobyNamespace namespaces[] = targetData.getNamespaces(); - //System.err.println("Got base object with namespaces numbering " + namespaces.length); - if(namespaces != null && namespaces.length > 0 && namespaces[0] != null){ - //System.err.println("Checking namespace "+ namespaces[0].getName()); - name = namespaces[0].getName(); + /** + * Template object may be one of MobyPrimaryData, or in case of deferred content loading a + * MobyNamespace, MobyDataType, or MobyPrimaryDataSet. + */ + public JMenu createObjectSubMenu(Object templateObject, String extraMenuText){ + String id = null; + MobyDataType mobyDataType = null; + String name = null; + MobyNamespace[] namespaces = null; + if(templateObject instanceof MobyPrimaryData){ + MobyPrimaryData targetData = (MobyPrimaryData) templateObject; + mobyDataType = targetData.getDataType(); + namespaces = targetData.getNamespaces(); + id = targetData.getId(); + if(id == null){ + id = ""; } - } - else{ - //System.err.println("Got complex object with datatype name " + name); - } + else if(id.length() > MAX_ID_LEN+3){ + id = id.substring(0, MAX_ID_LEN)+"..."; + } + if(MobyTags.MOBYOBJECT.equals(mobyDataType.getName()) && + namespaces != null && namespaces.length > 0 && namespaces[0] != null){ + name = namespaces[0].getName(); + } + else{ + name = mobyDataType.getName(); + } + } + else if(templateObject instanceof MobyNamespace){ + namespaces = new MobyNamespace[]{(MobyNamespace) templateObject}; + mobyDataType = MobyDataType.getDataType(MobyTags.MOBYOBJECT, SeahawkOptions.getRegistry()); + name = ((MobyNamespace) templateObject).getName(); + } + else if(templateObject instanceof MobyDataType){ + mobyDataType = (MobyDataType) templateObject; + name = ((MobyDataType) templateObject).getName(); + } + else{ + logger.error("Could not create submenu for object of unaccepted type "+templateObject.getClass().getName()); + } - // Make sure we have a fully documented data type object - mobyDataType = MobyDataType.getDataType(targetData.getDataType().getName(), SeahawkOptions.getRegistry()); String desc = null; String datatype = null; - if(mobyDataType == null){ - logger.warn("PG: Warning (submenu): no datatype associated with service " + - targetData.getName()); - } - else{ + if(mobyDataType != null){ datatype = mobyDataType.getName(); desc = mobyDataType.getDescription(); if(desc == null || desc.length() == 0){ @@ -1189,19 +1236,12 @@ } if(datatype != null && datatype.indexOf("objectclass:") != -1){ //LSID type URN, truncate the prefix and keep the part a user would care about (last part, the class name) - datatype = datatype.substring(datatype.indexOf("objectclass:")+12); } JMenu submenu = null; - MobyNamespace[] namespaces = targetData.getNamespaces(); // If not defined, derive a description from the Data Namespace - if(mobyDataType == null){ - desc = "Unknown datatype"; - submenu = new JMenu("Services for unknown datatype"); - assignMenuDataIndex(submenu); - } - else if("Object".equals(mobyDataType.getName())){ + if(MobyTags.MOBYOBJECT.equals(mobyDataType.getName())){ String mobydesc = "?"; if(namespaces != null){ // Take the longest description @@ -1214,20 +1254,30 @@ } } desc = "Record Identifier - " + mobydesc; - submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+datatype + ":" + id); + if(templateObject instanceof MobyDataObjectSet){ + datatype += " collection"; + } + submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ") + + datatype + (id == null ? "" : ":" + id)+""); assignMenuDataIndex(submenu); } - else if("String".equals(mobyDataType.getName())){ - String sample = targetData.getName(); - if(sample == null){ - sample = targetData.toString(); + else if(MobyTags.MOBYSTRING.equals(mobyDataType.getName())){ + String sample = ""; + if(templateObject instanceof MobyDataInstance){ + sample = ((MobyDataInstance) templateObject).getName(); + if(sample == null){ + sample = "\""+((MobyDataInstance) templateObject).toString()+"\""; + } + } + if(templateObject instanceof MobyDataObjectSet){ + sample += " collection"; } if(sample.length() > MAX_ID_LEN+3){ - sample = sample.substring(0, MAX_ID_LEN)+"..."; + sample = "\""+sample.substring(0, MAX_ID_LEN)+"...\""; } desc = "A piece of text"; - submenu = new JMenu("Services for "+(extraMenuText == null ? "" : extraMenuText+" ")+ - "String \"" + sample + "\""); + submenu = new JMenu("Services for "+(extraMenuText == null ? "" : extraMenuText+" ")+ + "String " + sample+""); assignMenuDataIndex(submenu); } // Complex object @@ -1240,17 +1290,18 @@ desc += "["+namespaceDesc+"]"; } } - if(targetData instanceof MobyDataObject && id != null && id.length() > 0){ + if(templateObject instanceof MobyDataObject && id != null && id.length() > 0){ objectLabel += ":" + id; } - else if(targetData instanceof MobyDataObjectSet){ + else if(templateObject instanceof MobyDataObjectSet){ objectLabel += " collection"; } - submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+objectLabel); + submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+objectLabel+""); assignMenuDataIndex(submenu); } desc = "Input data: " + desc; desc = HTMLUtils.htmlifyToolTipText(desc, MAX_SERVICE_DESC_LEN); + System.err.println("New submenu has label " + submenu.getText()); submenu.setToolTipText(desc); submenu.setName(SERVICE_SUBMENU_NAME); return submenu; From gordonp at dev.open-bio.org Wed Apr 14 23:48:28 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Wed, 14 Apr 2010 19:48:28 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004142348.o3ENmSDf009599@dev.open-bio.org> gordonp Wed Apr 14 19:48:27 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv9535/src/main/ca/ucalgary/seahawk/util Modified Files: MobyPayloadRequestListener.java Added Files: MobyContentCreator.java MobyDataObjectDeferred.java MobyDataObjectSetDeferred.java Log Message: Additional commit related to initial implementation 'for each' in Seahawk service invocation moby-live/Java/src/main/ca/ucalgary/seahawk/util MobyContentCreator.java,NONE,1.1 MobyDataObjectDeferred.java,NONE,1.1 MobyDataObjectSetDeferred.java,NONE,1.1 MobyPayloadRequestListener.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/MobyPayloadRequestListener.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/seahawk/util/MobyPayloadRequestListener.java 2010/04/14 22:02:04 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/MobyPayloadRequestListener.java 2010/04/14 23:48:27 1.2 @@ -10,7 +10,10 @@ */ public interface MobyPayloadRequestListener{ /** - * @param requestKey the value given to the caller when the listener was registered (tells the listener what payload to create baesd on some internal naming convention for the listener) + * Assumes the listener knows what payload to create based on some internal context stored by the listener. + * (i.e. you need to create a new listener specific to each deferred payload. + * + * @param paramNameforJobs the name of the moby job parameter to which each value should be assigned */ - public org.biomoby.shared.data.MobyContentInstance createPayload(String requestKey, String paramNameforJobs); + public org.biomoby.shared.data.MobyContentInstance createPayload(String paramNameforJobs); } From gordonp at dev.open-bio.org Wed Apr 14 23:48:27 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Wed, 14 Apr 2010 19:48:27 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004142348.o3ENmRar009579@dev.open-bio.org> gordonp Wed Apr 14 19:48:27 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv9535/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java MobyPayloadCreator.java MobyServicesGUI.java Log Message: Additional commit related to initial implementation 'for each' in Seahawk service invocation moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.27,1.28 MobyPayloadCreator.java,1.1,1.2 MobyServicesGUI.java,1.18,1.19 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/14 22:02:04 1.27 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/14 23:48:27 1.28 @@ -1215,7 +1215,6 @@ // chooses the for each option. The Moby data instance's userData gives us the current context, enabling us // to construct the correct payload in MobyPayloadCreator.createPayload() at any point in the future. String origUserData = (String) mobyData.getUserData(); - MobyPayloadRequestListener payloadCreator = new MobyPayloadCreator(this); for(String peerMode: new String[]{DataUtils.ARTICLE_PEERS_MODE, DataUtils.DATATYPE_PEERS_MODE}){ // note that getPeerElements() will modify the userData to reflect the semantic of the requested peer mode mobyData.setUserData(origUserData); @@ -1229,17 +1228,20 @@ } MobyDataType dataType = ((MobyPrimaryData) mobyData).getDataType(); if(mobyData instanceof MobyPrimaryDataSet){ // Collection - servicesGUI.addPopupOptions((MobyPrimaryDataSet) mobyData, popup, true, getDefaultHandler(), payloadCreator, - (String) mobyData.getUserData(), each); + servicesGUI.addPopupOptions((MobyPrimaryDataSet) mobyData, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); } else if(MobyTags.MOBYOBJECT.equals(dataType.getName())){ MobyNamespace namespace = null; - servicesGUI.addPopupOptions(namespace, popup, true, getDefaultHandler(), payloadCreator, - (String) mobyData.getUserData(), each); + servicesGUI.addPopupOptions(namespace, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); } else{ - servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), payloadCreator, - (String) mobyData.getUserData(), each); + servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); } } @@ -1301,7 +1303,7 @@ // 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"); + servicesGUI.addPopupOptions(previousMDI, popup, true, null, null, "previous input"); } } catch(Exception e){ logger.warn("Could not load previous service info, 'previous input' option will not be displayed", e); =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.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/seahawk/gui/MobyPayloadCreator.java 2010/04/14 22:02:04 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/14 23:48:27 1.2 @@ -14,14 +14,16 @@ */ public class MobyPayloadCreator implements MobyPayloadRequestListener{ private MobyContentPane srcPane; + private String requestKey; private static Logger logger = Logger.getLogger(MobyPayloadCreator.class.getName()); - public MobyPayloadCreator(MobyContentPane pane){ + public MobyPayloadCreator(MobyContentPane pane, String requestKey){ srcPane = pane; + this.requestKey = requestKey; } - public MobyContentInstance createPayload(String requestKey, String targetJobArgName){ + public MobyContentInstance createPayload(String targetJobArgName){ // The request key is the sample data's app context: // url#xpath sample_xptr filter_regex filter_xpath xpath_desc case_sensitive_boolean inverse selection // from which we will build the peer dataset to submit. =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.18 retrieving revision 1.19 diff -u -r1.18 -r1.19 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/14 22:02:04 1.18 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/14 23:48:27 1.19 @@ -586,30 +586,6 @@ } /** - * Creates a menu item based on the provided data type. If a service is selected from here, - * a callback will be made to the MobyPayloadRequestListener for the actual submission data. - * - * @param payloadKey a key that will be used in the callback so the listener knows what payload the create - */ - public void addPopupOptions(MobyDataType mobyDataType, JPopupMenu popupList, boolean asynchronous, - MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, - String payloadKey, String extraMenuText){ - addPopupOptions(mobyDataType, popupList, asynchronous, handler, payloadCreator, extraMenuText); - } - - public void addPopupOptions(MobyNamespace mobyNamespace, JPopupMenu popupList, boolean asynchronous, - MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, - String payloadKey, String extraMenuText){ - addPopupOptions(mobyNamespace, popupList, asynchronous, handler, payloadCreator, extraMenuText); - } - - public void addPopupOptions(MobyPrimaryDataSet collection, JPopupMenu popupList, boolean asynchronous, - MobyRequestEventHandler handler, MobyPayloadRequestListener payloadCreator, - String payloadKey, String extraMenuText){ - addPopupOptions(collection, popupList, asynchronous, handler, payloadCreator, extraMenuText); - } - - /** * Same as three arg addPopupOptions, but uses default response handler */ public void addPopupOptions(MobyDataInstance mobyData, JPopupMenu popupList, boolean asynchronous){ @@ -678,16 +654,32 @@ } // The data will be loaded later else if(payloadCreator != null){ - if(mobyData instanceof MobyPrimaryDataSet){ - //serviceAssocObject = mobyClient.getServices(new MobyDataObjectSetDeferred(mobyData, payloadCreator, requestKey)); - } - else{ - //serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred(mobyData, payloadCreator, requestKey)); - } + try{ + if(mobyData instanceof MobyPrimaryDataSet){ + serviceAssocObject = mobyClient.getServices(new MobyDataObjectSetDeferred((MobyPrimaryDataSet) mobyData, + payloadCreator)); + } + else if(mobyData instanceof MobyNamespace){ + serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyNamespace) mobyData, + payloadCreator)); + } + else if(mobyData instanceof MobyDataType){ + serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyDataType) mobyData, + payloadCreator)); + } + else{ + logger.warn("Ignoring unrecognized template class (" + mobyData.getClass().getName()+ + ") for deferred data creation by a MobyPayloadRequestListener"); + return; + } + } catch(Exception e){ + logger.error("Could not create deferred Moby data object", e); + } } else{ logger.warn("Service options for objects other than MobyDataObject " + - "and MobyDataObjectSet are not yet supported."); + "and MobyDataObjectSet are not yet supported unless you " + + "have defined a MobyPayloadRequestListener."); return; } } catch(Exception mobye){ From gordonp at dev.open-bio.org Thu Apr 15 18:51:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Thu, 15 Apr 2010 14:51:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004151851.o3FIpHrB006441@dev.open-bio.org> gordonp Thu Apr 15 14:51:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data In directory dev.open-bio.org:/tmp/cvs-serv6403/src/main/org/biomoby/shared/data Modified Files: MobyContentInstance.java Log Message: Made contents maintain insertion order by switching to LinkedHashMap for underlying Map storage moby-live/Java/src/main/org/biomoby/shared/data MobyContentInstance.java,1.14,1.15 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyContentInstance.java,v retrieving revision 1.14 retrieving revision 1.15 diff -u -r1.14 -r1.15 --- /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyContentInstance.java 2008/01/14 22:54:19 1.14 +++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/shared/data/MobyContentInstance.java 2010/04/15 18:51:17 1.15 @@ -31,7 +31,7 @@ private String serviceAuthURI = null; private String serviceNotes = null; private int xmlMode = MobyDataInstance.SERVICE_XML_MODE; - private HashMap members; + private LinkedHashMap members; private int autoID = 1; // to name members without existing names private Vector exceptions; @@ -40,7 +40,7 @@ * Useful if you are a client composing a query, or a server composing a response. */ public MobyContentInstance(){ - members = new HashMap(); + members = new LinkedHashMap(); exceptions = new Vector(); } @@ -106,7 +106,7 @@ } } - members = new HashMap(); + members = new LinkedHashMap(); // If we got this far, we're in the clear for the single envelope // What we need to parse now is the one or more sets of data in the envelope From gordonp at dev.open-bio.org Fri Apr 16 17:29:21 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 13:29:21 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161729.o3GHTLfE014979@dev.open-bio.org> gordonp Fri Apr 16 13:29:21 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/client In directory dev.open-bio.org:/tmp/cvs-serv14943/src/main/org/biomoby/client Modified Files: MobyRequest.java Log Message: Fixed javadoc typo moby-live/Java/src/main/org/biomoby/client MobyRequest.java,1.46,1.47 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/MobyRequest.java,v retrieving revision 1.46 retrieving revision 1.47 diff -u -r1.46 -r1.47 --- /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/MobyRequest.java 2010/03/29 20:42:48 1.46 +++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/MobyRequest.java 2010/04/16 17:29:21 1.47 @@ -238,7 +238,7 @@ /** * This method will assign the provided secondary parameters to all primary input data currently - * in this object. This is covenient if you are running 100 seqs through BLAST and only want to set + * in this object. This is convenient if you are running 100 seqs through BLAST and only want to set * the parameters once. If you instead want to set secondary input differently for all primary inputs, you'll * need to create a custom MobyContentInstance as input to setInput(). * From gordonp at dev.open-bio.org Fri Apr 16 17:32:33 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 13:32:33 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161732.o3GHWXGF015279@dev.open-bio.org> gordonp Fri Apr 16 13:32:33 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services In directory dev.open-bio.org:/tmp/cvs-serv15243/src/main/ca/ucalgary/seahawk/services Modified Files: MobyClient.java Log Message: Implemented proper logging, account for deferred data objects moby-live/Java/src/main/ca/ucalgary/seahawk/services MobyClient.java,1.26,1.27 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java,v retrieving revision 1.26 retrieving revision 1.27 diff -u -r1.26 -r1.27 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/11 01:58:05 1.26 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/16 17:32:33 1.27 @@ -1,6 +1,6 @@ package ca.ucalgary.seahawk.services; -import ca.ucalgary.seahawk.util.SeahawkOptions; +import ca.ucalgary.seahawk.util.*; import org.biomoby.client.*; import org.biomoby.registry.meta.*; @@ -116,8 +116,8 @@ docBuilder = dbf.newDocumentBuilder(); } catch(ParserConfigurationException pce){ - System.err.println("Error: Could not find an XML parser, will not be able to use " + - "MOBY xpath and regex mapper default behaviors: " + pce); + logger.log(Level.SEVERE, "Error: Could not find an XML parser, will not be able to use " + + "MOBY xpath and regex mapper default behaviors: ", pce); } ClassLoader cl = getClass().getClassLoader(); if(cl == null){ @@ -138,8 +138,8 @@ } if(dataMappingXMLURL == null){ if(rulesResource.length() != 0){ // if not left intentionally blank - System.err.println("Could not find MOBY data mapping resource '"+ - rulesResource+"'"); + logger.log(Level.WARNING, "Could not find MOBY data mapping resource '"+ + rulesResource+"'"); } } else{ @@ -147,7 +147,7 @@ addMappingsFromURL(dataMappingXMLURL); } catch(Exception e){ - System.err.println("Error loading default data mapping rules ("+dataMappingXMLURL+"):" + e); + logger.log(Level.SEVERE, "Error loading default data mapping rules ("+dataMappingXMLURL+")", e); e.printStackTrace(); } } @@ -198,8 +198,8 @@ */ public void addMappingsFromURL(URL u) throws Exception{ if(docBuilder == null){ - System.err.println("Asked to add data mappings from file, " + - "but no XML parser is available"); + logger.log(Level.SEVERE, "Asked to add data mappings from file, " + + "but no XML parser is available"); return; } @@ -229,13 +229,13 @@ } if(nsContext.getNamespaceURI(prefix) != null){ - System.err.println("Prefix definition for " + prefix + " already exists, ignoring new definition"); + logger.log(Level.WARNING, "Prefix definition for " + prefix + " already exists, ignoring new definition"); return; } String nsURI = e.getTextContent(); if(nsURI == null || nsURI.length() == 0){ - System.err.println("Prefix definition for " + prefix + " has a blank URI rule, ignoring"); + logger.log(Level.WARNING, "Prefix definition for " + prefix + " has a blank URI rule, ignoring"); return; } nsContext.setPrefix(nsURI, prefix); @@ -264,7 +264,7 @@ } if(!RULE_SET_TAG.equals(ruleSet.getLocalName())){ - System.err.println("Skipping unexpected top level tag " + ruleSet.getLocalName()); + logger.log(Level.WARNING, "Skipping unexpected top level tag " + ruleSet.getLocalName()); continue; } @@ -304,18 +304,18 @@ } else if(isArticleNameRule(ruleMember)){ if(articleNameString != null && articleNameString.length() != 0){ - System.err.println("Skipping unexpected article name definition node, " + - "a valid article name rule has already been " + - "created for this ruleset"); + logger.log(Level.WARNING, "Skipping unexpected article name definition node, " + + "a valid article name rule has already been " + + "created for this ruleset"); continue; } articleNameString = ruleMember.getTextContent(); } else if(isDataTypeRule(ruleMember)){ if(dataTypeString != null && dataTypeString.length() != 0){ - System.err.println("Skipping unexpected datatype definition node, " + - "a valid datatype rule has already been " + - "created for this ruleset"); + logger.log(Level.WARNING, "Skipping unexpected datatype definition node, " + + "a valid datatype rule has already been " + + "created for this ruleset"); continue; } dataTypeString = getDataType(ruleMember); @@ -328,15 +328,15 @@ } // skip any Dublin Core metadata in validation else if(!MobyPrefixResolver.DUBLIN_CORE_NAMESPACE.equals(ruleMember.getNamespaceURI())){ - System.err.println("Skipping unexpected "+RULE_SET_TAG+ - " child node " + ruleMember.getLocalName()); + logger.log(Level.WARNING, "Skipping unexpected "+RULE_SET_TAG+ + " child node " + ruleMember.getLocalName()); continue; } } if(xpathStrings.size() == 0 && regexStrings.size() == 0 && urlRegexStrings.size() == 0){ - System.err.println("Skipping namespace rule that has no xpath " + - "url_regex or regex specs associated with it"); + logger.log(Level.WARNING, "Skipping namespace rule that has no xpath " + + "url_regex or regex specs associated with it"); // Next ruleset continue; } @@ -344,9 +344,9 @@ // Simple object with just namespace & ID if(dataTypeString == null || dataTypeString.length() == 0){ if(memberMap.size() != 0){ - System.err.println("Warning: ignoring member rules, since " + - "no datatype was defined for the ruleset " + - "(base Object will be created)"); + logger.log(Level.WARNING, "Warning: ignoring member rules, since " + + "no datatype was defined for the ruleset " + + "(base Object will be created)"); } for(int j = 0; j < xpathStrings.size(); j++){ @@ -362,8 +362,8 @@ // Build complex object else{ if(memberMap.size() == 0){ - System.err.println("Complex datatype (" + dataTypeString + " was defined " + - " in the ruleset, but no members were defined"); + logger.log(Level.WARNING, "Complex datatype (" + dataTypeString + " was defined " + + " in the ruleset, but no members were defined"); } for(int j = 0; j < xpathStrings.size(); j++){ @@ -465,7 +465,7 @@ regexStrings.add(str); } else{ - System.err.println("Skipping blank regex rule"); + logger.log(Level.WARNING, "Skipping blank regex rule"); } return str; @@ -483,7 +483,7 @@ urlRegexStrings.add(str); } else{ - System.err.println("Skipping blank url_regex rule"); + logger.log(Level.WARNING, "Skipping blank url_regex rule"); } return str; @@ -501,7 +501,7 @@ xPathStrings.add(str); } else{ - System.err.println("Skipping blank XPath rule"); + logger.log(Level.WARNING, "Skipping blank XPath rule"); } return str; @@ -524,7 +524,7 @@ String memberNameKey = isPrimitiveDataType(dataTypeName) ? MobyComplexBuilder.PRIMITIVE_VALUE_SENTINEL : memTag.getAttribute(DATATYPE_RULE_ATTR); if(ruleValue == null || ruleValue.length() == 0){ - System.err.println("Object member " + memberNameKey + " has a blank value rule"); + logger.log(Level.WARNING, "Object member " + memberNameKey + " has a blank value rule"); } String memberDataTypeSetting = memTag.getAttribute(DATATYPE_ATTR); @@ -574,10 +574,10 @@ !memberWhitespaceSetting.equals(WHITESPACE_ATTR_NORMALIZE_VAL) && !memberWhitespaceSetting.equals(WHITESPACE_ATTR_STRIP_FLANKING_VAL) && !memberWhitespaceSetting.equals(WHITESPACE_ATTR_STRIP_VAL)){ - System.err.println("Object member " + memberNameKey + - " has an unrecognized value for the " + WHITESPACE_ATTR + - " attribute (" + memberWhitespaceSetting + - "), overriding with default of " + WHITESPACE_ATTR_KEEP_VAL); + logger.log(Level.WARNING, "Object member " + memberNameKey + + " has an unrecognized value for the " + WHITESPACE_ATTR + + " attribute (" + memberWhitespaceSetting + + "), overriding with default of " + WHITESPACE_ATTR_KEEP_VAL); memberWhitespaceSetting = WHITESPACE_ATTR_KEEP_VAL; } @@ -587,14 +587,14 @@ } else if(!memberEncodingSetting.equals(ENCODING_ATTR_NONE_VAL) && !memberEncodingSetting.equals(ENCODING_ATTR_BASE64_VAL)){ - System.err.println("Object member " + memberNameKey + - " has an unrecognized value for the " + ENCODING_ATTR + - " attribute, overriding with default of " + ENCODING_ATTR_NONE_VAL); + logger.log(Level.WARNING, "Object member " + memberNameKey + + " has an unrecognized value for the " + ENCODING_ATTR + + " attribute, overriding with default of " + ENCODING_ATTR_NONE_VAL); memberWhitespaceSetting = ENCODING_ATTR_NONE_VAL; } if(membersMap.containsKey(memberNameKey)){ - System.err.println("Object member " + memberNameKey + " already exists, ignoring new definition"); + logger.log(Level.WARNING, "Object member " + memberNameKey + " already exists, ignoring new definition"); return; } @@ -637,8 +637,8 @@ " cannot have empty children"); } if(namespaceStrings.containsKey(keyName)){ - System.err.println("Ignoring duplicate namespace value rule for " + - "namespace '" + keyName + "'"); + logger.log(Level.WARNING, "Ignoring duplicate namespace value rule for " + + "namespace '" + keyName + "'"); continue; } if(keyName != null && keyName.length() != 0){ @@ -649,7 +649,7 @@ } } else{ - System.err.println("Skipping unexpected "+NAMESPACE_RULE_TAG+" child node " + specName); + logger.log(Level.WARNING, "Skipping unexpected "+NAMESPACE_RULE_TAG+" child node " + specName); continue; } } @@ -716,13 +716,11 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from match:" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from match", me); } } } catch(Throwable t){ // Principally stack overflows - System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text"); - t.printStackTrace(System.err); + logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text", t); } } } @@ -765,11 +763,11 @@ // have the exact same contents as the same members who are their // subtypes, as these are superfluous. - System.err.println("Multiple Moby objects were found in the text data, " + - "but the request was to return a simple. " + - "Only the first value in the collection has been returned."); + logger.log(Level.WARNING, "Multiple Moby objects were found in the text data, " + + "but the request was to return a simple. " + + "Only the first value in the collection has been returned."); for(MobyDataObject result: results){ - System.err.println("Found object: " + result.getDataType().getName()); + logger.log(Level.WARNING, "Found object: " + result.getDataType().getName()); } // TODO: should we instead return the one deepest in the hierarchy (or with the most members)? return results.elementAt(0); @@ -818,11 +816,11 @@ // have the exact same contents as the same members who are their // subtypes, as these are superfluous. - System.err.println("Multiple Moby objects were found in the text data, " + - "but the request was to return a simple. " + - "Only the first value in the collection has been returned."); + logger.log(Level.WARNING, "Multiple Moby objects were found in the text data, " + + "but the request was to return a simple. " + + "Only the first value in the collection has been returned."); for(MobyDataObject result: results){ - System.err.println("Found object: " + result.getDataType().getName()); + logger.log(Level.WARNING, "Found object: " + result.getDataType().getName()); } // TODO: should we instead return the one deepest in the hierarchy (or with the most members)? return results.elementAt(0); @@ -916,11 +914,11 @@ // have the exact same contents as the same members who are their // subtypes, as these are superfluous. - System.err.println("Multiple Moby objects were found in the text data, " + - "but the request was to return a simple. " + - "Only the first value in the collection has been returned."); + logger.log(Level.WARNING, "Multiple Moby objects were found in the text data, " + + "but the request was to return a simple. " + + "Only the first value in the collection has been returned."); for(MobyDataObject result: results){ - System.err.println("Found object: " + result.getDataType().getName()); + logger.log(Level.WARNING, "Found object: " + result.getDataType().getName()); } // TODO: should we instead return the one deepest in the hierarchy (or with the most members)? return results.elementAt(0); @@ -994,12 +992,11 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from match:" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from match", me); } } } catch(Throwable t){ // Principally stack overflows - System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to binary data"); + logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to binary data", t); } } } @@ -1050,7 +1047,7 @@ public Map getMobyObjectsURNMap(CharSequence textData, byte[] bytes){ Map results = new HashMap(); if(regexMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any regex->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any regex->moby data mappings!"); return results; } @@ -1069,12 +1066,11 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from match (rule "+urn+"):" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from match (rule "+urn+")", me); } } }catch(Throwable t){ // Principally stack overflows - System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary"); + logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary", t); } if(urn != null && !objectVector.isEmpty()){ results.put(urn, (MobyDataObject[]) objectVector.toArray(new MobyDataObject[objectVector.size()])); @@ -1086,7 +1082,7 @@ public MobyDataObject[] getMobyObjects(CharSequence textData, byte[] bytes){ if(regexMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any regex->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any regex->moby data mappings!"); return new MobyDataObject[0]; } @@ -1109,12 +1105,11 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from match:" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from match", me); } } }catch(Throwable t){ // Principally stack overflows - System.err.println("Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary"); + logger.log(Level.SEVERE, "Exception/Error ("+t+") while applying regex '"+pattern.pattern()+"' to text/binary", t); } } @@ -1142,7 +1137,7 @@ public MobyDataObject[] getMobyObjects(URL url, String linkText, MobyDataType targetDataType){ if(urlRegexMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any url regex->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any url regex->moby data mappings!"); return new MobyDataObject[0]; } @@ -1171,8 +1166,7 @@ } } catch(MobyException me){ - System.err.println("Could not build Moby object from url regex match:" + me); - me.printStackTrace(); + logger.log(Level.SEVERE, "Could not build Moby object from url regex match", me); } } } @@ -1188,7 +1182,7 @@ // No xpaths to check if(xpathMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any xpath->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any xpath->moby data mappings!"); return new MobyDataObject[0]; } @@ -1224,8 +1218,8 @@ } }catch(XPathExpressionException xpe2){ - System.err.println( "Warning: Cannot access resulting node list "+ - "due to exception in its retrieval: " + xpe2); + logger.log(Level.WARNING, "Warning: Cannot access resulting node list "+ + "due to exception in its retrieval: ", xpe2); return new Vector(); } } @@ -1241,9 +1235,9 @@ } } else{ //not a node sequence - System.out.println("Warning: the XPath expression ("+ xpath + - ") did not return a node set, cannot select document elements."+ - " The returned object was of type "+ result.getClass().getName() ); + logger.log(Level.WARNING, "Warning: the XPath expression ("+ xpath + + ") did not return a node set, cannot select document elements."+ + " The returned object was of type "+ result.getClass().getName() ); return new Vector(); } } @@ -1253,8 +1247,8 @@ //xpe.printStackTrace(); return new Vector(); }catch(MobyException me){ - System.err.println("Warning: Cannot create objects from select nodes due " + - " to exception in MOBY logic:" + me); + logger.log(Level.WARNING, "Warning: Cannot create objects from select nodes due " + + " to exception in MOBY logic:", me); return new Vector(); } @@ -1270,7 +1264,7 @@ // No xpaths to check if(xpathMap.isEmpty()){ - System.out.println("The MOBY Client has not been provided any xpath->moby data mappings!"); + logger.log(Level.WARNING, "The MOBY Client has not been provided any xpath->moby data mappings!"); return results; } @@ -1340,14 +1334,24 @@ } if(mdos[i] instanceof MobyDataObject){ - mobyDataServiceAssocInstances[i] = new MobyDataObjectSAI((MobyDataObject) mdos[i], mService); + if(mdos[i] instanceof MobyDataObjectDeferred){ + mobyDataServiceAssocInstances[i] = new MobyDataObjectDeferredSAI((MobyDataObjectDeferred) mdos[i], mService); + } + else{ + mobyDataServiceAssocInstances[i] = new MobyDataObjectSAI((MobyDataObject) mdos[i], mService); + } } else if(mdos[i] instanceof MobyDataObjectSet){ - mobyDataServiceAssocInstances[i] = new MobyDataObjectSetSAI((MobyDataObjectSet) mdos[i], mService); + if(mdos[i] instanceof MobyDataObjectSetDeferred){ + mobyDataServiceAssocInstances[i] = new MobyDataObjectSetDeferredSAI((MobyDataObjectSetDeferred) mdos[i], mService); + } + else{ + mobyDataServiceAssocInstances[i] = new MobyDataObjectSetSAI((MobyDataObjectSet) mdos[i], mService); + } } else{ logger.log(Level.WARNING, "MobyClient could not handle service-associating an instance of " + mdos[i].getClass()); - System.err.println("MobyClient could not handle service-associating an instance of " + mdos[i].getClass()); + //System.err.println("MobyClient could not handle service-associating an instance of " + mdos[i].getClass()); } } return mobyDataServiceAssocInstances; @@ -1363,7 +1367,7 @@ public void addRegexMapping(String regexp, String[] mobyObj, String articleName, String urn){ //mobyObj<--mobyNamespaces if(mobyObj == null){ - System.err.println("Ignoring empty namespace-only regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only regex rule mappings"); return; } @@ -1377,7 +1381,7 @@ public void addURLRegexMapping(String url_regexp, String[] mobyObj, String articleName, String urn){ //mobyObj<--mobyNamespaces if(mobyObj == null){ - System.err.println("Ignoring empty namespace-only url regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only url regex rule mappings"); return; } @@ -1466,7 +1470,7 @@ protected void addRegexMapping(String regexp, Map nsRules, String articleName, String ruleName, String urn){ //nsRules = Map if(nsRules == null || nsRules.size() == 0){ - System.err.println("Ignoring empty namespace-only regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only regex rule mappings"); return; } @@ -1475,7 +1479,7 @@ protected void addURLRegexMapping(String url_regexp, Map url_nsRules, String articleName, String urn){ //nsRules = Map if(url_nsRules == null || url_nsRules.size() == 0){ - System.err.println("Ignoring empty namespace-only url regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only url regex rule mappings"); return; } @@ -1517,8 +1521,8 @@ if(memberRelationship.getRelationshipType() == Central.iHAS){ String[] rule = membersMap.get(memberRelationship.getName()); if(rule == null){ - System.err.println("Skipping HAS member "+memberRelationship.getName() + - " without an explicit rule (may be defined by inheritance?)"); + logger.log(Level.WARNING, "Skipping HAS member "+memberRelationship.getName() + + " without an explicit rule (may be defined by inheritance?)"); continue; } Pattern pattern = Pattern.compile(newRegexp, Pattern.DOTALL | Pattern.COMMENTS); @@ -1527,8 +1531,8 @@ if(captured.containsKey(i)){ //autoboxed int // Already encapsulated the capture group due to another // HAS member, don't need to add anything - System.err.println("Skipping processing of capture group "+i+ - ", it's already been processed by another member in this rule"); + logger.log(Level.WARNING, "Skipping processing of capture group "+i+ + ", it's already been processed by another member in this rule"); continue; } if(rule[0].matches("^.*\\$"+i+"(?=\\D.*|\\z)")){ @@ -1614,9 +1618,7 @@ } }catch(Exception e){ - System.err.println("Could not create regular expression statement from '" + - regexp + "': " + e); - e.printStackTrace(); + logger.log(Level.SEVERE, "Could not create regular expression statement from '" + regexp + "'", e); } } @@ -1651,15 +1653,15 @@ builderNameMap.put(urn, mcb); } }catch(Exception e){ - System.err.println("Could not create URL regular expression statement from '" + - url_regexp + "': " + e); + logger.log(Level.SEVERE, "Could not create URL regular expression statement from '" + + url_regexp + "': " + e); e.printStackTrace(); } } public void addXPathMapping(String xpath, String[] mobyObj){ //mobyObj<--mobyNamespaces if(mobyObj == null){ - System.err.println("Ignoring empty namespace-only regex rule mappings"); + logger.log(Level.WARNING, "Ignoring empty namespace-only regex rule mappings"); return; } @@ -1707,10 +1709,7 @@ }catch(Exception e){ logger.log(Level.WARNING, "Could not create XPath select statement from '" + - xpath_exp + "': " + e.getMessage()); - System.err.println("Could not create XPath select statement from '" + - xpath_exp + "': " + e); - + xpath_exp + "': ", e); } } @@ -1773,8 +1772,8 @@ else if(line.indexOf("\t") == 0){ String[] fields = line.trim().split(","); if(fields.length != 2){ - System.err.println("Unrecognized line (not 2 comma delimited fields) " + - "from ValidateService: " + line.trim()); + logger.log(Level.WARNING, "Unrecognized line (not 2 comma delimited fields) " + + "from ValidateService: " + line.trim()); } else if(fields[1].equals("true")){ // service is okay, don't add to dead map @@ -1783,8 +1782,8 @@ isDeadMap.put(currentAuthority+":"+fields[0], "dead"); } else{ - System.err.println("Unrecognized line (second field not 'true' or 'false') " + - "from ValidateService: " + line.trim()); + logger.log(Level.WARNING, "Unrecognized line (second field not 'true' or 'false') " + + "from ValidateService: " + line.trim()); } } } From gordonp at dev.open-bio.org Fri Apr 16 17:33:26 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 13:33:26 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161733.o3GHXQBs015331@dev.open-bio.org> gordonp Fri Apr 16 13:33:25 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv15287/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java MobyPayloadCreator.java MobyServicesGUI.java Log Message: First fully functional version of 'for each' service invocation in Seahawk moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.28,1.29 MobyPayloadCreator.java,1.2,1.3 MobyServicesGUI.java,1.19,1.20 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.28 retrieving revision 1.29 diff -u -r1.28 -r1.29 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/14 23:48:27 1.28 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/16 17:33:25 1.29 @@ -1175,9 +1175,23 @@ String docFragID = targetURL.getRef(); // We store the xpath in the anchor part of the URL - // Complex case, load the doc fragment from the MOBY XML source file + // Complex case, load the doc fragment from the MOBY XML source file + // where the targetURL is url#xptr with xptr like /1/2/1/1 if(docFragID != null && docFragID.length() > 0 && !targetURL.getHost().equals("moby")){ - return DataUtils.loadMobyDataFromXPointer(targetURL, filteredData, filterHistory.get(getCurrentURL())); + URL currentURL = null; + try{currentURL = new URL(targetURL.toString().replaceAll("#"+targetURL.getRef(), ""));} + catch(Exception e){ + logger.error("Couldn't extract referenceless URL from " + targetURL, e); + } + // refers to currently loaded doc + if(currentURL.equals(getCurrentURL())){ + return DataUtils.loadMobyDataFromXPointer(currentURL, getCurrentDoc(), docFragID, + filteredData, filterHistory.get(getCurrentURL())); + } + // refers to another moby doc, let DataUtils resolve the doc for us + else{ + return DataUtils.loadMobyDataFromXPointer(targetURL, filteredData, filterHistory.get(getCurrentURL())); + } } // Simple case, build the object using the values encoded in the URL itself. @@ -1218,7 +1232,7 @@ for(String peerMode: new String[]{DataUtils.ARTICLE_PEERS_MODE, DataUtils.DATATYPE_PEERS_MODE}){ // note that getPeerElements() will modify the userData to reflect the semantic of the requested peer mode mobyData.setUserData(origUserData); - NodeList peerElements = DataUtils.getPeerElements(getCurrentDoc(), mobyData, peerMode); + NodeList peerElements = DataUtils.getPeerElements(getCurrentDoc(), mobyData, getFilteredData(), peerMode); if(peerElements.getLength() <= 1){ continue; // no 'for each' option if only one to process... } @@ -1227,21 +1241,33 @@ each += " '"+mobyData.getName()+"'"; } MobyDataType dataType = ((MobyPrimaryData) mobyData).getDataType(); + MobyNamespace[] namespaces = ((MobyPrimaryData) mobyData).getNamespaces(); if(mobyData instanceof MobyPrimaryDataSet){ // Collection servicesGUI.addPopupOptions((MobyPrimaryDataSet) mobyData, popup, true, getDefaultHandler(), new MobyPayloadCreator(this, (String) mobyData.getUserData()), each); } else if(MobyTags.MOBYOBJECT.equals(dataType.getName())){ - MobyNamespace namespace = null; - servicesGUI.addPopupOptions(namespace, popup, true, getDefaultHandler(), - new MobyPayloadCreator(this, (String) mobyData.getUserData()), - each); + if(namespaces != null && namespaces.length > 0){ + servicesGUI.addPopupOptions(namespaces[0], popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); + } + //else base object wth no namespace...useless! } else{ - servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), - new MobyPayloadCreator(this, (String) mobyData.getUserData()), - each); + // A non-base object, with a namespace too + if(namespaces != null && namespaces.length > 0){ + ((MobyPrimaryDataSimple) mobyData).setId(""); //anonymize + servicesGUI.addPopupOptions((MobyPrimaryDataSimple) mobyData, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); + } + else{ //just the data type useful + servicesGUI.addPopupOptions(dataType, popup, true, getDefaultHandler(), + new MobyPayloadCreator(this, (String) mobyData.getUserData()), + each); + } } } @@ -1286,13 +1312,21 @@ if(getFilter() == null){ return; } + String[] userData = mdi.getUserData() == null ? null : + mdi.getUserData().toString().split("\t"); + // second user data arg is + Node mdiNode = userData == null || userData.length < 2 ? null : + XPointerResolver.getNodeFromXPointer(getCurrentDoc(), userData[1]); //System.err.println("Should create a previous input menu item for " + mdi.getUserData()); try{ Document srcDoc = DataUtils.docBuilder.parse(srcURL.openStream()); + //System.err.println("Context node is "+mdiNode+ " from user data" + mdi.getUserData()); // Get the input data for the *previous* service - MobyDataJob inputData = DataUtils.getInputSample(srcDoc, SeahawkOptions.getRegistry()); + MobyDataJob inputData = DataUtils.getInputSample(srcDoc, + DataUtils.findMobyJobName(mdiNode), + SeahawkOptions.getRegistry()); if(inputData == null){ // should only happen if Moby XML was loaded manually by a user, otherwise we've recorded this info... logger.warn("No previous service info in Moby XML, 'previous input' option will not be displayed"); @@ -1529,7 +1563,7 @@ // Gray out the mismatched textual data for(Map.Entry dataToFilter: filteredData.entrySet()){ - System.err.println("Filtering "+dataToFilter.getKey()); + //System.err.println("Filtering "+dataToFilter.getKey()); javax.swing.text.AbstractDocument.AbstractElement htmlDiv = (javax.swing.text.AbstractDocument.AbstractElement) d.getElement(dataToFilter.getKey()); if(htmlDiv == null){ =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.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/seahawk/gui/MobyPayloadCreator.java 2010/04/14 23:48:27 1.2 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/16 17:33:25 1.3 @@ -27,6 +27,7 @@ // The request key is the sample data's app context: // url#xpath sample_xptr filter_regex filter_xpath xpath_desc case_sensitive_boolean inverse selection // from which we will build the peer dataset to submit. + System.err.println("Request key is " + requestKey); String[] requestKeyFields = requestKey.split("\t"); String[] requestParts = requestKeyFields[0].split("#", 2); @@ -50,20 +51,24 @@ Map xptrsToFilter = new HashMap(); FilterSearch filter = null; // Was there a filter in the request? - if(requestKeyFields.length >= 6){ - filter = new FilterSearch(requestKeyFields[1], - new XPathOption(requestKeyFields[2], requestKeyFields[3]), - Boolean.parseBoolean(requestKeyFields[4]), - Boolean.parseBoolean(requestKeyFields[5])); + if(requestKeyFields.length >= 7){ + filter = new FilterSearch(requestKeyFields[2], + new XPathOption(requestKeyFields[3], requestKeyFields[4]), + Boolean.parseBoolean(requestKeyFields[5]), + Boolean.parseBoolean(requestKeyFields[6])); } Document doc = null; // Get the list of nodes to filter, using in-memory data if possible if(targetURL.equals(srcPane.getCurrentURL())){ doc = srcPane.getCurrentDoc(); - if(filter.equals(srcPane.getFilter())){ + if(filter == null){ + xptrsToFilter = null; + } + else if(filter.equals(srcPane.getFilter())){ // no need to redo the filtering, it's the current display's filtering - xptrsToFilter = srcPane.getFilteredData(); + System.err.println("Reusing current filter"); + xptrsToFilter = srcPane.getFilteredData(); } else{ // we have the doc loaded, but the filter has changed since @@ -75,44 +80,33 @@ doc = DataUtils.findFilteredNodes(targetURL, filter, xptrsToFilter); } - // Get the valid parts of the doc for forwarding. - if(!xptrsToFilter.isEmpty()){ - if(doc == srcPane.getCurrentDoc()){ - // clone, because it'll be edited below by the filter, and we don't want to mess up currentDoc... - doc = (Document) srcPane.getCurrentDoc().cloneNode(true); - } - DataUtils.filterDoc(doc, xptrsToFilter); - } + MobyDataInstance mobyDataContext = new MobyDataObject("whatever"); + mobyDataContext.setUserData(requestKey); + NodeList peerElements = DataUtils.getPeerElements(doc, mobyDataContext, + xptrsToFilter, DataUtils.DATATYPE_PEERS_MODE); - // find the peers of templateElement and put them into a MobyContentInstance + // find the peers of defined by the userData selection constraints and put them into a MobyContentInstance MobyContentInstance payload = new MobyContentInstance(); Map jobPrefixes = new LinkedHashMap(); - NodeList peerElements = null; - try{ - peerElements = (NodeList) DataUtils.xPathFactory.newXPath().evaluate(selectionXPath, - doc, - XPathConstants.NODESET); - } catch(Exception e){ - logger.log(Level.SEVERE, "Could not select nodes from "+targetURL+" with XPath " + selectionXPath, e); - return null; - } + System.err.println("Loading MobyContentInstance with "+peerElements.getLength()+" elements for xpath "+selectionXPath); for(int i = 0; i < peerElements.getLength(); i++){ Element peerElement = (Element) peerElements.item(i); // Try to make the job names trackable to the inputs: // Name the jobs according to their original job + a iterated number suffix, e.g. originatingJob_1, originatingJob_2 String jobKey = DataUtils.findMobyJobName(peerElement); if(!jobPrefixes.containsKey(jobKey)){ + jobPrefixes.put(jobKey, new Integer(1)); if(peerElements.getLength() > 1){ jobKey += "_1"; // only add a suffix if multiple loop members for the job } - jobPrefixes.put(jobKey, new Integer(1)); } else{ int suffixCount = jobPrefixes.get(jobKey).intValue(); - jobKey += "_"+suffixCount; jobPrefixes.put(jobKey, new Integer(suffixCount+1)); + jobKey += "_"+(suffixCount+1); } + System.err.println("Adding job "+jobKey+" for "+peerElement.getLocalName()); MobyDataInstance mdi = null; try{ mdi = MobyDataObject.createInstanceFromDOM(peerElement, SeahawkOptions.getRegistry()); =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.19 retrieving revision 1.20 diff -u -r1.19 -r1.20 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/14 23:48:27 1.19 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/16 17:33:25 1.20 @@ -182,9 +182,13 @@ return handler; } - // synchronized so simultaneous requests don't get their input data mixed up + /** + * Called when the 'Execute Service' button in the secondary input dialog in pushed. + * Section synchronized so simultaneous requests don't get their input data mixed up + */ public void setupServiceSecondaryData(MobyRequestEventHandler handler){ MobyDataInstance[] castInputs = new MobyDataInstance[primaryInput.length]; + MobyContentInstance mci = null; for(int i = 0; i < primaryInput.length; i++){ if(!(primaryInput[i] instanceof MobyDataInstance)){ logger.warn("Warning: setupServiceSecondaryData was called before the primary input" + @@ -192,13 +196,34 @@ " of class "+primaryInput[i].getClass().getName()); return; } - castInputs[i] = (MobyDataInstance) primaryInput[i]; + // Is one of the params a 'for each' + if(primaryInput[i] instanceof MobyContentCreator){ + mci = ((MobyContentCreator) primaryInput[i]).getAllContents(primaryInput[i].getName()); + } + else{ + castInputs[i] = (MobyDataInstance) primaryInput[i]; + } + } + // Cross product of single value primary params with param that is a content creator array + if(mci != null){ + for(MobyDataJob job: mci.values()){ + for(int i = 0; i < castInputs.length; i++){ + if(castInputs[i] != null){ + job.put(castInputs[i].getName(), castInputs[i]); + } + } + } } // code from mobyRequest.setInput() to executeService() should always be synced to avoid input mixup between requests synchronized(mobyRequest){ try{ - mobyRequest.setInput(castInputs); + if(mci != null){ + mobyRequest.setInput(mci); + } + else{ + mobyRequest.setInput(castInputs); + } mobyRequest.setSecondaryInput(secondaryInputInstances); } catch(MobyException me){ me.printStackTrace(); @@ -224,8 +249,13 @@ // code from mobyRequest.setInput() to executeService() should always be synced to avoid input mixup between requests synchronized(mobyRequest){ try{ + if(mdi instanceof MobyContentCreator){ + mobyRequest.setInput(((MobyContentCreator) mdi).getAllContents(primaryInput[0].getName())); + } // Implement simple input (i.e. only one input argument) - mobyRequest.setInput(mdi, ""); + else{ + mobyRequest.setInput(mdi, ""); + } } catch(MobyException me){ logger.error("Failure in MOBY input, was not acceptable:" + me); @@ -539,7 +569,7 @@ addPopupOptions(mobyData, popupList, false, handler, payloadCreator, extraMenuText); } else{ - logger.warn("Warning: OptionLoaderThread has no data to work with"); + logger.warn("Warning: OptionLoaderThread has no data to work with", new Exception("Arrggh")); } } } @@ -646,27 +676,27 @@ MobyDataServiceAssocInstance serviceAssocObject = null; // //Services for only the one piece of data try{ - if(mobyData instanceof MobyDataObjectSet){ - serviceAssocObject = mobyClient.getServices((MobyDataObjectSet) mobyData); - } - else if(mobyData instanceof MobyDataObject){ - serviceAssocObject = mobyClient.getServices((MobyDataObject) mobyData); - } // The data will be loaded later - else if(payloadCreator != null){ + if(payloadCreator != null){ try{ if(mobyData instanceof MobyPrimaryDataSet){ serviceAssocObject = mobyClient.getServices(new MobyDataObjectSetDeferred((MobyPrimaryDataSet) mobyData, payloadCreator)); } - else if(mobyData instanceof MobyNamespace){ - serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyNamespace) mobyData, + else if(mobyData instanceof MobyPrimaryDataSimple){ // pass in if datatype and namespace are useful + serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred(((MobyPrimaryDataSimple) mobyData).getDataType(), + ((MobyPrimaryDataSimple) mobyData).getNamespaces()[0], payloadCreator)); } else if(mobyData instanceof MobyDataType){ serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyDataType) mobyData, payloadCreator)); } + else if(mobyData instanceof MobyNamespace){ + System.err.println("Creating deferred dataset payload"); + serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyNamespace) mobyData, + payloadCreator)); + } else{ logger.warn("Ignoring unrecognized template class (" + mobyData.getClass().getName()+ ") for deferred data creation by a MobyPayloadRequestListener"); @@ -675,6 +705,12 @@ } catch(Exception e){ logger.error("Could not create deferred Moby data object", e); } + } + else if(mobyData instanceof MobyDataObjectSet){ + serviceAssocObject = mobyClient.getServices((MobyDataObjectSet) mobyData); + } + else if(mobyData instanceof MobyDataObject){ + serviceAssocObject = mobyClient.getServices((MobyDataObject) mobyData); } else{ logger.warn("Service options for objects other than MobyDataObject " + @@ -730,9 +766,6 @@ logger.warn("Cannot add service options, cannot find " + "parent moby object index for submenu " + submenu.getText()); - System.err.println("Cannot add service options, cannot find " + - "parent moby object index for submenu " + - submenu.getText()); return; } dataIndex = ((Integer) submenu2msIndex.get(parent)).intValue(); @@ -1250,7 +1283,7 @@ datatype += " collection"; } submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ") + - datatype + (id == null ? "" : ":" + id)+""); + ""+datatype + "" + (id == null ? "" : ":" + id)+""); assignMenuDataIndex(submenu); } else if(MobyTags.MOBYSTRING.equals(mobyDataType.getName())){ @@ -1269,7 +1302,7 @@ } desc = "A piece of text"; submenu = new JMenu("Services for "+(extraMenuText == null ? "" : extraMenuText+" ")+ - "String " + sample+""); + "String " + sample+""); assignMenuDataIndex(submenu); } // Complex object @@ -1283,17 +1316,19 @@ } } if(templateObject instanceof MobyDataObject && id != null && id.length() > 0){ - objectLabel += ":" + id; + objectLabel += ""+objectLabel+":" + id; } else if(templateObject instanceof MobyDataObjectSet){ - objectLabel += " collection"; + objectLabel = ""+objectLabel+" collection"; + } + else{ + objectLabel = ""+objectLabel+""; } submenu = new JMenu("Services for " + (extraMenuText == null ? "" : extraMenuText+" ")+objectLabel+""); assignMenuDataIndex(submenu); } desc = "Input data: " + desc; desc = HTMLUtils.htmlifyToolTipText(desc, MAX_SERVICE_DESC_LEN); - System.err.println("New submenu has label " + submenu.getText()); submenu.setToolTipText(desc); submenu.setName(SERVICE_SUBMENU_NAME); return submenu; From gordonp at dev.open-bio.org Fri Apr 16 17:33:26 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 13:33:26 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161733.o3GHXQvK015367@dev.open-bio.org> gordonp Fri Apr 16 13:33:26 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv15287/src/main/ca/ucalgary/seahawk/util Modified Files: DataFlowRecorder.java DataUtils.java FilterSearch.java MobyDataObjectDeferred.java XPointerResolver.java Added Files: MobyDataObjectDeferredSAI.java MobyDataObjectSetDeferredSAI.java Log Message: First fully functional version of 'for each' service invocation in Seahawk moby-live/Java/src/main/ca/ucalgary/seahawk/util MobyDataObjectDeferredSAI.java,NONE,1.1 MobyDataObjectSetDeferredSAI.java,NONE,1.1 DataFlowRecorder.java,1.4,1.5 DataUtils.java,1.5,1.6 FilterSearch.java,1.5,1.6 MobyDataObjectDeferred.java,1.1,1.2 XPointerResolver.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/10 00:40:17 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/16 17:33:26 1.5 @@ -321,7 +321,7 @@ data = sampleData.getUserData().toString().split("\t"); //options: selection + filter + cond, selection + cond, or cond only if(data.length == 14 || data.length == 8 || data.length == 6){ - System.err.println("Adding conditional for " + resultURLString); + // System.err.println("Adding conditional for " + resultURLString); String conditionURL = data[data.length-6]; String conditionRegex = data[data.length-5]; XPathOption conditionXPath = new XPathOption(data[data.length-4], data[data.length-3]); @@ -334,10 +334,10 @@ System.arraycopy(data, 0, conditionlessData, 0, data.length-6); data = conditionlessData; } - else{ - System.err.println("Skipping conditional, only " + data.length + - "members in provenance data for " + resultURLString); - } +// else{ +// System.err.println("Skipping conditional, only " + data.length + +// "members in provenance data for " + resultURLString); +// } } // true means treat as a collection if that's what the sample data is @@ -447,7 +447,7 @@ // Remember that sd is the loop's original MobyDataInstance before it's been coerced into a MobyPrimaryData, // which doesn't have XML modes, etc. String inputKey = getInputKey(sd); - System.err.println("Input key for " + processorName + " is " + inputKey); + // System.err.println("Input key for " + processorName + " is " + inputKey); String[] mobifyingProcessorNameAndPorts = null; if(input2Processor.containsKey(inputKey)){ @@ -930,7 +930,7 @@ // supertype of the output from the other service! if(namespace != null){ MobyNamespace nsObj = MobyNamespace.getNamespace(namespace, getRegistryFromService(srcService)); - System.err.println("About to create namespace filter for "+ srcProcessor + " port " + portName + " when srcPort was " + srcPort); + // System.err.println("About to create namespace filter for "+ srcProcessor + " port " + portName + " when srcPort was " + srcPort); return createNamespaceFilter(nsObj, srcProcessor, portName, processors, datalinks, doc); } else if(xrefNs != null){ @@ -1103,7 +1103,7 @@ throws Exception{ String decompKey = srcProcessor+"\n"+srcPort+"\n"+xpath; - System.err.println("Decomp key is " + decompKey); + // System.err.println("Decomp key is " + decompKey); // Has this decomp already been created in another branch? if(decomp2Processor.containsKey(decompKey)){ return decomp2Processor.get(decompKey); =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/14 22:02:04 1.5 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/16 17:33:26 1.6 @@ -166,6 +166,7 @@ Document resultDom = docBuilder.parse(serviceResultURL.openStream()); Registry registry = getRegistry(resultDom); + //todo: check all jobs, not just a sample MobyDataJob sampleJob = getInputSample(resultDom, registry); // Trace the inputs that came from the current document @@ -343,6 +344,13 @@ * @param responseDom the XML DOM for the answer from a Moby Web service called in Seahawk */ public static MobyDataJob getInputSample(Document responseDom, Registry registry) throws Exception{ + return getInputSample(responseDom, null, registry); + } + + /** + * Same as two-arg, but retrieves a specific job's input (or null if not a job name found in the doc). + */ + public static MobyDataJob getInputSample(Document responseDom, String jobName, Registry registry) throws Exception{ Document inputDoc = getInputDoc(responseDom); if(inputDoc == null){ return null; @@ -360,11 +368,14 @@ throw new Exception("Could not parse Moby output message from the given DOM"); } + if(jobName != null){ + return inputPayload.get(jobName); + } // Pick a job that produced output, if given the choice of more that one - for(String jobName: inputPayload.keySet()){ - if(outputPayload.containsKey(jobName) && - outputPayload.get(jobName).size() > 0){ - return inputPayload.get(jobName); + for(String jobID: inputPayload.keySet()){ + if(outputPayload.containsKey(jobID) && + outputPayload.get(jobID).size() > 0){ + return inputPayload.get(jobID); } } return (MobyDataJob) inputPayload.values().iterator().next(); @@ -460,9 +471,9 @@ /** * Loads targetURL, minus the nodes specified by the xpath keys in filteredXPtrs (map values are not currently used). */ - public static void filterDoc(Document domDoc, Map filteredXPtrs){ + public static void filterNodes(Node rootNode, Map filteredXPtrs){ - if(domDoc == null){ + if(rootNode == null){ logger.log(Level.SEVERE, "Error: Could not get MOBY document as DOM (empty or malformed document?)"); return; } @@ -474,7 +485,7 @@ // wrong as they refer to ordinality) Vector nodesToDelete = new Vector(); for(String xptr: filteredXPtrs.keySet()){ - nodesToDelete.add(XPointerResolver.getNodeFromXPointer(domDoc, xptr)); + nodesToDelete.add(XPointerResolver.getNodeFromXPointer(rootNode, xptr)); } // Delete @@ -497,86 +508,54 @@ * @param filteredXPtrs a map of the xpointers to data that should NOT be deserialized if children of the targetURL XPointer * @param docFilter the current filter applied to the document in targetURL */ - public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, Map filteredXPtrs, FilterSearch docFilter){ - - URL currentURL = null; - try{currentURL = new URL(targetURL.toString().replaceAll("#"+targetURL.getRef(), ""));} - catch(Exception e){ - logger.log(Level.SEVERE, "Couldn't extract referenceless URL from " + targetURL, e); - } - - // Build the DOM - Document domDoc = null; - try{ - domDoc = docBuilder.parse(targetURL.openStream()); - } catch(org.xml.sax.SAXException saxe){ - logger.log(Level.SEVERE, "The document defining the MOBY data " + - "could not be parsed", saxe); - return null; - } catch(java.io.IOException ioe){ - logger.log(Level.SEVERE, "The document defining the MOBY data " + - " could not be read (from " + targetURL + ")", ioe); - return null; - } - // Does an in-place edit of domDoc - filterDoc(domDoc, filteredXPtrs); - + public static MobyDataInstance loadMobyDataFromXPointer(URL targetURL, Map filteredXPtrs, + FilterSearch docFilter){ + + URL currentURL = null; + try{currentURL = new URL(targetURL.toString().replaceAll("#"+targetURL.getRef(), ""));} + catch(Exception e){ + logger.log(Level.SEVERE, "Couldn't extract referenceless URL from " + targetURL, e); + } + + // Build the DOM + Document domDoc = null; + try{ + domDoc = docBuilder.parse(targetURL.openStream()); + } catch(org.xml.sax.SAXException saxe){ + logger.log(Level.SEVERE, "The document defining the MOBY data " + + "could not be parsed", saxe); + return null; + } catch(java.io.IOException ioe){ + logger.log(Level.SEVERE, "The document defining the MOBY data " + + " could not be read (from " + targetURL + ")", ioe); + return null; + } + + return loadMobyDataFromXPointer(currentURL, domDoc, targetURL.getRef(), filteredXPtrs, docFilter); + } + + public static MobyDataInstance loadMobyDataFromXPointer(URL docURL, Document domDoc, String targetXptr, + Map filteredXPtrs, FilterSearch docFilter){ // Are we dealing with a simple object or a complex one? MobyDataInstance mobyData = null; // Find the DOM fragment corresponding to the MOBY ID anchor specified // in the link URL by using an XPath statement on the source MOBY doc - //System.err.println("Retrieving complex object from XPointer " + targetURL); // A child Xpointer is of the form /1/2/1/1, specifying the DOM child - // descent path from the root node to get to the target node. The - // equivalent XPath is /*[1]/*[2]/*[1]/*[1] - String childXPath = targetURL.getRef().replaceAll("/(\\d+)", "/*[$1]"); - - // Build and run the XPath statement - Element mobyObject = null; - NodeList idSearchResult = null; - Object xobject = null; - try{ - xobject = xPathFactory.newXPath().evaluate(childXPath, - domDoc, - XPathConstants.NODESET); - - // Check the results - if(xobject != null){ - idSearchResult = (NodeList) xobject; - } - else{ - logger.log(Level.WARNING,"Could not find Moby object in document " + currentURL + - ", referred to by the reference ID in Moby link " + targetURL + - " (document changed?)"); - return null; - } - } - catch(Exception e){// Syntax error - logger.log(Level.SEVERE, "Error: Could not search Moby data instance for XPath " + - childXPath + ")", e); - return null; - } + // descent path from the root node to get to the target node. + Element mobyObject = (Element) XPointerResolver.getNodeFromXPointer(domDoc, targetXptr); - if(idSearchResult.getLength() == 0){ - logger.log(Level.WARNING, "Error: Could not find Moby data instance with XPath (" + childXPath + - " in " + targetURL); - return null; - } - if(idSearchResult.getLength() > 1){ - logger.log(Level.WARNING, "Error: Moby data instance could not beresolved because " + - "there are multiple elements with XPath " + childXPath + " in " + - currentURL); - return null; - } - if(!(idSearchResult.item(0) instanceof Element)){ - logger.log(Level.WARNING, "Error: Moby data instance with XPath " + childXPath + " in " + - currentURL + " was not an element as required!"); - return null; + // Does an in-place edit of domDoc + // Check if the returned data was supposed to be filtered. If so, don't filter. + if(filteredXPtrs != null && !filteredXPtrs.isEmpty() && !filteredXPtrs.containsKey(targetXptr)){ + // Otherwise filter, so child elements of the data to return reflect the current filter conditions + // (e.g. a collection may be filtered to just a subset based on namespace, so retrieving the collection should only + // return that subset of children). + domDoc = (Document) domDoc.cloneNode(true); // true == deep + filterNodes(domDoc, filteredXPtrs); } - mobyObject = (Element) idSearchResult.item(0); - + // Create the Java MOBY API object based on the linked document DOM fragment try{ MobyDataInstance mdi = MobyDataObject.createInstanceFromDOM(mobyObject, SeahawkOptions.getRegistry()); @@ -587,8 +566,8 @@ mobyData = mdi; } else{ - logger.log(Level.WARNING, "Error: Moby data instance retrieved with XPath " + childXPath + " in " + - currentURL + " was not a primary MOBY input object as expected"); + logger.log(Level.WARNING, "Error: Moby data instance retrieved with XPath " + targetXptr + + " was not a primary MOBY input object as expected"); return null; } @@ -600,8 +579,8 @@ // For workflow creation, etc. associate the potential input data with its source generalized XPath // Also, if there is currently a filter on the doc, store it too as useful info for workflow creation. - setUserData(mobyData, currentURL, elementInContextToNameBasedXPath(mobyObject), - targetURL.getRef(), docFilter); + setUserData(mobyData, docURL, elementInContextToNameBasedXPath(mobyObject), + targetXptr, docFilter); } catch(MobyException mobye){ // Logic error logger.log(Level.SEVERE, "Error: Could not construct Moby data instance from document fragment: ", @@ -656,6 +635,7 @@ // It's a complex type. Assume the type is why we are picking it. // TODO: In future we may want to check if a parent type is allowed in // this slot, and generalize to that. + // Also, account for namespace if present? xpath = "/"+elName + xpath; } if(!(currentElement.getParentNode() instanceof Element)){ @@ -784,7 +764,7 @@ /** * Find out which registry the service that created the reponse is registered in. * - * @param responseURL the service response whose origin we should trace + * @param responseDoc the service response whose origin we should trace */ public static Registry getRegistry(Document responseDoc) throws Exception{ String endpointURL = getSeahawkAttrFromDoc(responseDoc, REGISTRY_ATTR); @@ -1035,16 +1015,20 @@ } if(!inversed && shouldFilter || inversed && !shouldFilter){ - xPtrsToFilter.put(currXPtr, "todo"); + xPtrsToFilter.put(currXPtr, "whatever"); } } //todo: filter objects without the HAS field at all... return filterableXPtrs; } - // We need to enumerate the possible peer-sets for the selected data item. Is the user interested in - // items in the same namespace, same data type, or same article name? - public static NodeList getPeerElements(Document doc, MobyDataInstance mobyData, String peerMode){ + + /** + * We need to enumerate the possible peer-sets for the selected data item. Is the user interested in + * items in the same namespace/data type, or same article name? + */ + public static NodeList getPeerElements(Document doc, MobyDataInstance mobyData, + Map xPtrsToFilter, String peerMode){ if(!(mobyData instanceof MobyPrimaryData)){ logger.log(Level.WARNING, "Tried to get peers of data that was not an instanceof MobyPrimaryData (was " + mobyData.getClass().getName()+ ")"); @@ -1054,10 +1038,13 @@ NodeList peerElements = null; String peerGroupXPath = null; + Node contextNode = null; if(mobyData.getUserData() != null){ String[] userData = ((String) mobyData.getUserData()).split("\t"); // first arg is url#nameBasedXPath peerGroupXPath = userData[0].split("#", 2)[1]; + contextNode = XPointerResolver.getNodeFromXPointer(doc, userData[1]); + //System.err.println("Loaded context node " + userData[1] + " as " + contextNode); } else{ // Fallback is to get all nodes with the same name... @@ -1079,7 +1066,7 @@ mobyData.setUserData(newUserData); // keep from job article name down - peerGroupXPath = peerGroupXPath.replaceFirst("^.*/(Collection|Simple)", "//*"); + //peerGroupXPath = peerGroupXPath.replaceFirst("^.*?/(Collection|Simple)", "//*"); // we want to go by articleName too to catch the full semantics of the peer group definition peerGroupXPath += xpathArticleCondition; } @@ -1090,17 +1077,58 @@ // For xpaths given above, MOBY namespace is problem in XPath evaluation. // solution: eliminate Moby envelope path parts: full path doesn't resolve in xpath for unknown reasons //.replaceAll("/(MOBY|mobyContent|mobyData|Collection|Simple)","/moby:$1"); //attempt 1 - //.replaceAll("/([a-zA-Z_0-9\\-]+)(?=/|$)", "/*[local-name() = '$1']") //attempt 2 - //.replaceAll("/([a-zA-Z_0-9\\-]+)\\[", "/*[local-name() = '$1' and "); //attempt 2 cont'd + peerGroupXPath = peerGroupXPath.replaceAll("/([a-zA-Z_0-9\\-]+)", "/d:$1"); try{ - peerElements = (NodeList) xPathFactory.newXPath().evaluate(peerGroupXPath, - doc, - XPathConstants.NODESET); + XPath xpath = xPathFactory.newXPath(); + if(contextNode != null){ + xpath.setNamespaceContext(new NamespaceContextImpl(contextNode, "d")); + } + peerElements = (NodeList) xpath.evaluate(peerGroupXPath, + doc, + XPathConstants.NODESET); } catch(Exception e){ logger.log(Level.SEVERE, "Could not evaluate UserData XPath "+peerGroupXPath, e); } - System.err.println("Got " + peerElements.getLength() + " peers for " + peerGroupXPath); + //System.err.println("Got " + peerElements.getLength() + " peers for " + peerGroupXPath); + + // Remove peers that are currently filtered. Seems to be quicker than cloning the doc, + // filtering the node, then running the xpath. Assumes you don't do much with peerElements + // afterwards, or you should apply the filter to remove errant children, etc.) + if(xPtrsToFilter != null && !xPtrsToFilter.isEmpty()){ + MutableNodeList filterPassedPeers = new MutableNodeList(); + for(int i = 0; i < peerElements.getLength(); i++){ + boolean filtered = false; + String peerXPtr = getXPtr(peerElements.item(i)); + // Check all ancestors to see if they are filtered + for(String ancestorXPtr = peerXPtr; + ancestorXPtr.length() > 0; + ancestorXPtr = ancestorXPtr.replaceFirst("/\\d+$", "")){ + if(xPtrsToFilter.containsKey(ancestorXPtr)){ + filtered = true; + break; + } + } + if(!filtered){ + Element peerElement = (Element) peerElements.item(i); + // Now check if any child nodes need to be filtered + Map childrenToDelete = new HashMap(); + for(String xptr: xPtrsToFilter.keySet()){ + // is it a child of the peer about to be put in the "passed filter" list? + if(xptr.indexOf(peerXPtr+"/") == 0){ + childrenToDelete.put(xptr.substring(peerXPtr.length()), "whatever"); + } + } + if(!childrenToDelete.isEmpty()){ + peerElement = (Element) peerElements.item(i).cloneNode(true); //true = deep copy + filterNodes(peerElement, childrenToDelete); + } + filterPassedPeers.add(peerElement); + } + } + peerElements = filterPassedPeers; + //System.err.println("Got " + peerElements.getLength() + " peers that passed the filter"); + } return peerElements; } =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/14 22:02:04 1.5 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/FilterSearch.java 2010/04/16 17:33:26 1.6 @@ -121,11 +121,17 @@ return xpathOptions; } + public String toString(){ + return filterRegex.toString()+"\t"+getSelectedXPath().getXPath()+"\t"+ + getSelectedXPath().getDesc()+"\t"+caseSensitivity+"\t"+inverseSelection; + } + public boolean equals(Object o){ if(o == null || !(o instanceof FilterSearch)){ return false; } FilterSearch other = (FilterSearch) o; + //System.err.println("Comparing "+this+"\n\nand\n\n"+o); return filterRegex.toString().equals(other.filterRegex.toString()) && getSelectedXPath().getXPath().equals(other.getSelectedXPath().getXPath()) && caseSensitivity == other.caseSensitivity && =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/MobyDataObjectDeferred.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/seahawk/util/MobyDataObjectDeferred.java 2010/04/14 23:48:27 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/MobyDataObjectDeferred.java 2010/04/16 17:33:26 1.2 @@ -15,8 +15,8 @@ super(MobyDataType.getDataType(MobyTags.MOBYOBJECT, SeahawkOptions.getRegistry()), ns, "any_id"); dataCreator = listener; } - public MobyDataObjectDeferred(MobyDataType dt, MobyPayloadRequestListener listener){ - super(dt); + public MobyDataObjectDeferred(MobyDataType dt, MobyPayloadRequestListener listener) throws Exception{ + super(dt, new MobyNamespace("unknown"), "any_id"); dataCreator = listener; } public MobyDataObjectDeferred(MobyDataType dt, MobyNamespace ns, MobyPayloadRequestListener listener) throws Exception{ =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/XPointerResolver.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/seahawk/util/XPointerResolver.java 2010/04/11 20:15:28 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/XPointerResolver.java 2010/04/16 17:33:26 1.2 @@ -15,20 +15,24 @@ * Note, this currently only works for stuff like /1/1/2/3/1/67, * not all XPointers, which includes functions, etc. */ - public static Node getNodeFromXPointer(Document d, String xptr){ - if(d == null || xptr == null || xptr.length() < 2 || !xptr.startsWith("/1")){ + public static Node getNodeFromXPointer(Node rootNode, String xptr){ + if(rootNode == null || xptr == null || xptr.length() < 2){ return null; } - Node currentNode = d.getDocumentElement(); + Node currentNode = rootNode; if(currentNode == null){ return null; } - if(xptr.equals("/1")){ - return currentNode; - } + if(rootNode instanceof Document){ + currentNode = ((Document) rootNode).getDocumentElement(); + if(xptr.equals("/1")){ + return currentNode; + } - // Get rid of leading "/1/" - String[] ordinal_steps = xptr.substring(3).split("/"); + // Get rid of leading "/1/" + xptr = xptr.substring(3); + } + String[] ordinal_steps = xptr.split("/"); if(ordinal_steps.length == 0){ return currentNode; } From gordonp at dev.open-bio.org Fri Apr 16 19:58:26 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 15:58:26 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161958.o3GJwQk7018588@dev.open-bio.org> gordonp Fri Apr 16 15:58:26 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services In directory dev.open-bio.org:/tmp/cvs-serv18552/src/main/ca/ucalgary/seahawk/services Modified Files: MobyClient.java Log Message: Fixed logging messaages moby-live/Java/src/main/ca/ucalgary/seahawk/services MobyClient.java,1.27,1.28 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/16 17:32:33 1.27 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/MobyClient.java 2010/04/16 19:58:26 1.28 @@ -84,9 +84,7 @@ * new registry will NOT be reflected here. */ public MobyClient() throws MobyException{ - this(SeahawkOptions.getRegistry() == null ? - RegistryCache.getDefaultRegistry() : - SeahawkOptions.getRegistry()); + this(SeahawkOptions.getRegistry()); } /** From gordonp at dev.open-bio.org Fri Apr 16 19:59:01 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 15:59:01 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004161959.o3GJx1sF018632@dev.open-bio.org> gordonp Fri Apr 16 15:59:01 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/client In directory dev.open-bio.org:/tmp/cvs-serv18596/src/main/org/biomoby/client Modified Files: CentralImpl.java Log Message: Fixed logging messages moby-live/Java/src/main/org/biomoby/client CentralImpl.java,1.64,1.65 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralImpl.java,v retrieving revision 1.64 retrieving revision 1.65 diff -u -r1.64 -r1.65 --- /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralImpl.java 2010/03/29 19:48:28 1.64 +++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralImpl.java 2010/04/16 19:59:01 1.65 @@ -131,7 +131,7 @@ public static final String CENTRAL_IMPL_RESOURCE_NAME = "org.biomoby.client.CentralImpl"; /** The class to use for getDefaultCentral if all else fails */ public static final String DEFAULT_CENTRAL_IMPL_CLASSNAME = "org.biomoby.client.CentralDigestCachedImpl"; - private static Logger logger = Logger.getLogger("org.biomoby.client.CentralImpl"); + private static Logger logger = Logger.getLogger(CentralImpl.class.getName()); /** * Thread local that gives each thread its own @@ -1888,7 +1888,7 @@ ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); URL resURL = classLoader.getResource("META-INF/services/"+CENTRAL_IMPL_RESOURCE_NAME); if(resURL != null){ - System.err.println("Loading "+resURL); + logger.log(Level.CONFIG, "Loading "+resURL); try{ LineNumberReader reader = new LineNumberReader(new InputStreamReader(resURL.openStream())); for(String line = reader.readLine(); line != null; line = reader.readLine()){ @@ -1904,9 +1904,7 @@ } } try{ - if(Boolean.getBoolean("moby.debug")){ - System.err.println("Central class is "+className+ " for " + reg); - } + logger.log(Level.CONFIG, "Central class is "+className+ " for " + reg); Class clazz = Class.forName(className); if(reg == null){ // should use default nullary c-tor defaultCentrals.put("", (CentralImpl) clazz.newInstance()); From gordonp at dev.open-bio.org Fri Apr 16 20:36:17 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 16 Apr 2010 16:36:17 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004162036.o3GKaHua019856@dev.open-bio.org> gordonp Fri Apr 16 16:36:17 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv19820/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentClipboard.java Log Message: Switched to java.util.logging.* moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentClipboard.java,1.10,1.11 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/11 02:25:03 1.10 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentClipboard.java 2010/04/16 20:36:17 1.11 @@ -21,6 +21,7 @@ import java.io.FileOutputStream; import java.net.URL; import java.util.*; +import java.util.logging.*; import java.util.regex.Pattern; /** @@ -54,7 +55,8 @@ // Clipboard editing variables private JMenuItem deleteDataPopupItem; private MobyDataInstance itemToDelete; - private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(MobyContentClipboard.class); + private static Logger logger = Logger.getLogger(MobyContentClipboard.class.getName()); + public MobyContentClipboard(MobyContentGUI cGUI, MobyServicesGUI sGUI, JTabbedPane parentComponent, DataFlowRecorder recorder, JLabel statusBar){ super(cGUI, sGUI, parentComponent, recorder, statusBar); @@ -66,7 +68,7 @@ if(clipboardIcon == null){ URL u = cl.getResource(CLIPBOARD_TAB_ICON_RESOURCE); if(u == null){ - logger.warn("Could not find icon resource " + CLIPBOARD_TAB_ICON_RESOURCE); + logger.log(Level.WARNING, "Could not find icon resource " + CLIPBOARD_TAB_ICON_RESOURCE); } else{ clipboardIcon = new ImageIcon(u); @@ -86,7 +88,7 @@ clipboardFile = File.createTempFile(CLIPBOARD_FILE_NAME, ".xml"); } catch(Exception e){ - logger.error("Clipboard failed to initialize, cannot create temp file:" + e); + logger.log(Level.SEVERE, "Clipboard failed to initialize, cannot create temp file", e); return; } clipboardFile.deleteOnExit(); @@ -134,7 +136,7 @@ // (i.e. don't delete subparts of object) if(!(mdi instanceof MobyDataObject) || !collection.contains(mdi)){ mdi.setXmlMode(MobyDataInstance.SERVICE_XML_MODE); - System.err.println("Skipping " + mdi.toXML()); + logger.log(Level.WARNING, "Skipping " + mdi.toXML()); mdi.setXmlMode(MobyDataInstance.CENTRAL_XML_MODE); return; } @@ -160,7 +162,7 @@ } } else{ - logger.warn("Clipboard: ignoring unrecognized source of event " + e); + logger.log(Level.WARNING, "Clipboard: ignoring unrecognized source of event ", e); } } @@ -186,7 +188,7 @@ public void addCollectionData(MobyDataInstance mdi, boolean updateDisplay){ if(mdi == null){ - logger.warn("Cannot add null object to the clipboard."); + logger.log(Level.WARNING, "Cannot add null object to the clipboard."); return; } if(!query.containsKey(CLIPBOARD_COLLECTION_NAME)){ @@ -200,9 +202,9 @@ collection.add((MobyDataObject) mdi); } else{ - logger.warn("Cannot add object of class " + mdi.getClass() + - " to the clipboard, only MobyDataObject and MobyDataObjectSet" + - " are supported"); + logger.log(Level.WARNING, "Cannot add object of class " + mdi.getClass() + + " to the clipboard, only MobyDataObject and MobyDataObjectSet" + + " are supported"); return; } @@ -246,26 +248,26 @@ return; } } catch(Exception e){ - logger.warn("Could not transform binary file ("+u+"): " + e); + logger.log(Level.WARNING, "Could not transform binary file ("+u+")", e); } // Not binary, see if it's text that's convertible to MOBY data MobyClient client = servicesGUI.getMobyClient(); if(client == null){ - logger.warn("Could not get MOBY client from MOBY services GUI, " + - "cannot transform incoming clipboard data to MOBY objects"); + logger.log(Level.WARNING, "Could not get MOBY client from MOBY services GUI, " + + "cannot transform incoming clipboard data to MOBY objects"); } String urlContents = null; try{ urlContents = HTMLUtils.getURLContents(u); } catch(Exception e){ - logger.warn("Could not read contents of the URL to import to the clipboard ("+u+"):" +e); + logger.log(Level.WARNING, "Could not read contents of the URL to import to the clipboard ("+u+")", e); return; } if(urlContents.indexOf(" gordonp Sat Apr 17 20:23:42 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv27510/src/main/ca/ucalgary/seahawk/util Modified Files: DataFlowRecorder.java Log Message: Fixed so no problem when original data comes from the clipboard, or a saved moby xml file moby-live/Java/src/main/ca/ucalgary/seahawk/util DataFlowRecorder.java,1.5,1.6 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/16 17:33:26 1.5 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java 2010/04/18 00:23:42 1.6 @@ -342,6 +342,7 @@ // true means treat as a collection if that's what the sample data is String sinkPortName = getPortName(sampleData, true); + // No user data means non-moby origin...backtracking stops. if(data != null && data.length != 0){ URL dataSrcURL = null; try{ @@ -351,6 +352,16 @@ "a provenance URL as expected URL (" + sampleData.getUserData().toString() + ")"); continue; } + + // If srcService == null, the input source for this param was a Moby doc that wasn't a + // service output, e.g. the clipboard or an old doc loaded from file. + MobyService srcService = DataUtils.getService(dataSrcURL); + if(srcService == null){ + addWorkflowInput(processorName, condPassProcessorAndPorts, sinkPortName, sampleData, + datalinks, processors, inputPorts, doc); + continue; + } + // recursion for workflow creation by backtracking service input provenance String feedingProcessorName = null; String feedingProcessorPort = null; @@ -429,52 +440,57 @@ } // Otherwise it's a workflow input the user will need to specify else{ - // pName is editable name for input processor target... - // allows injection of condition without affecting method's return value - String pName = processorName; - if(condPassProcessorAndPorts != null){ - // inject condition filter between data creator and current service - datalinks.appendChild(createDataLinkElement(condPassProcessorAndPorts[0], - condPassProcessorAndPorts[2], - pName, - sinkPortName, - doc)); - pName = condPassProcessorAndPorts[0]; - sinkPortName = condPassProcessorAndPorts[1]; - } - // The sample data may be used in more than one branch of the flow...avoid duplication - // Get the real data XML, to see if we've encountered it before as input (it'd be in the hash) - // Remember that sd is the loop's original MobyDataInstance before it's been coerced into a MobyPrimaryData, - // which doesn't have XML modes, etc. - String inputKey = getInputKey(sd); - // System.err.println("Input key for " + processorName + " is " + inputKey); - - String[] mobifyingProcessorNameAndPorts = null; - if(input2Processor.containsKey(inputKey)){ - mobifyingProcessorNameAndPorts = input2Processor.get(inputKey); - } - else{ - if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT)){ - mobifyingProcessorNameAndPorts = addIdMobifyingProcessor(processors, datalinks, inputPorts, - sampleData, doc); - input2Processor.put(inputKey, mobifyingProcessorNameAndPorts); - } - else{ - // TODO: Need to build complex input from MOB rule or spreadsheet fields? - } - } - // link the created data to the workflow service - datalinks.appendChild(createDataLinkElement(mobifyingProcessorNameAndPorts[0], - mobifyingProcessorNameAndPorts[1], - pName, sinkPortName, - doc)); + addWorkflowInput(processorName, condPassProcessorAndPorts, sinkPortName, sampleData, + datalinks, processors, inputPorts, doc); } - } return processorName; } + private void addWorkflowInput(String pName, String[] condPassProcessorAndPorts, String sinkPortName, + MobyPrimaryData sampleData, Element datalinks, Element processors, + Element inputPorts, Document doc) throws Exception{ + // pName is editable name for input processor target... + // allows injection of condition without affecting method's return value + if(condPassProcessorAndPorts != null){ + // inject condition filter between data creator and current service + datalinks.appendChild(createDataLinkElement(condPassProcessorAndPorts[0], + condPassProcessorAndPorts[2], + pName, + sinkPortName, + doc)); + pName = condPassProcessorAndPorts[0]; + sinkPortName = condPassProcessorAndPorts[1]; + } + // The sample data may be used in more than one branch of the flow...avoid duplication + // Get the real data XML, to see if we've encountered it before as input (it'd be in the hash) + // Remember that sd is the loop's original MobyDataInstance before it's been coerced into a MobyPrimaryData, + // which doesn't have XML modes, etc. + String inputKey = getInputKey((MobyDataInstance) sampleData); + // System.err.println("Input key for " + processorName + " is " + inputKey); + + String[] mobifyingProcessorNameAndPorts = null; + if(input2Processor.containsKey(inputKey)){ + mobifyingProcessorNameAndPorts = input2Processor.get(inputKey); + } + else{ + if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT)){ + mobifyingProcessorNameAndPorts = addIdMobifyingProcessor(processors, datalinks, inputPorts, + sampleData, doc); + input2Processor.put(inputKey, mobifyingProcessorNameAndPorts); + } + else{ + // TODO: Need to build complex input from MOB rule or spreadsheet fields? + } + } + // link the created data to the workflow service + datalinks.appendChild(createDataLinkElement(mobifyingProcessorNameAndPorts[0], + mobifyingProcessorNameAndPorts[1], + pName, sinkPortName, + doc)); + } + // returns the same value for moby sample data instances containing the same data in XML form private String getInputKey(MobyDataInstance sd){ int oldXmlMode = sd.getXmlMode(); From gordonp at dev.open-bio.org Sun Apr 18 00:31:49 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 17 Apr 2010 20:31:49 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004180031.o3I0VnZ0028062@dev.open-bio.org> gordonp Sat Apr 17 20:31:49 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv28026/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyServicesGUI.java Log Message: Switched from Object to ID for basic object label, more intuitive for users moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyServicesGUI.java,1.20,1.21 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/16 17:33:25 1.20 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/18 00:31:49 1.21 @@ -693,7 +693,6 @@ payloadCreator)); } else if(mobyData instanceof MobyNamespace){ - System.err.println("Creating deferred dataset payload"); serviceAssocObject = mobyClient.getServices(new MobyDataObjectDeferred((MobyNamespace) mobyData, payloadCreator)); } @@ -1175,7 +1174,7 @@ } public JMenu addOutputTypeSubMenu(JMenu parentMenu, MobyDataType type){ - JMenu menu = new JMenu("Result type: " + type.getName()); + JMenu menu = new JMenu("Result type: " + (type.getName().equals(MobyTags.MOBYOBJECT) ? "ID" : type.getName())); MobyDataType[] typeLineage = type.getLineage(); String commonAncestorDesc = ""; From gordonp at dev.open-bio.org Sun Apr 18 00:33:05 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 17 Apr 2010 20:33:05 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004180033.o3I0X5V4028106@dev.open-bio.org> gordonp Sat Apr 17 20:33:05 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv28070/src/main/ca/ucalgary/seahawk/gui Modified Files: MobySaveDialog.java Log Message: Stripped seahawk preocessing instructions from saved XML as they can confuse on reload. Workflow export is default save option now. moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobySaveDialog.java,1.8,1.9 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java 2010/03/29 19:53:16 1.8 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java 2010/04/18 00:33:05 1.9 @@ -92,11 +92,11 @@ fileChooser.setName(FILE_CHOOSER_SAVE_TITLE); fileChooser.setFileHidingEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); - fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(HTML_EXT, HTML_DESC)); if(document.hasXMLSource()){ fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(T2FLOW_EXT, T2FLOW_DESC)); fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(XML_EXT, XML_DESC)); } + fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(HTML_EXT, HTML_DESC)); fileChooser.setAcceptAllFileFilterUsed(false); if(lastDirOpened != null){ fileChooser.setCurrentDirectory(lastDirOpened); @@ -318,7 +318,9 @@ try { OutputStream ostream = new FileOutputStream(f); String xml = document.getXMLSource(); - ostream.write(xml.getBytes()); + // Before saving, strip out the Seahawk processing instructions, which will + // confuse Seahawk if we reload the XML doc later. + ostream.write(xml.replaceAll("<\\?"+DataUtils.PI_TARGET+".*?\\?>","").getBytes()); ostream.flush(); ostream.close(); } catch (Exception ex) { From gordonp at dev.open-bio.org Sun Apr 18 00:33:56 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 17 Apr 2010 20:33:56 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004180033.o3I0Xu7J028150@dev.open-bio.org> gordonp Sat Apr 17 20:33:56 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv28114/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyPayloadCreator.java Log Message: Cleaner logging moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyPayloadCreator.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.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/seahawk/gui/MobyPayloadCreator.java 2010/04/16 17:33:25 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/18 00:33:56 1.4 @@ -27,7 +27,7 @@ // The request key is the sample data's app context: // url#xpath sample_xptr filter_regex filter_xpath xpath_desc case_sensitive_boolean inverse selection // from which we will build the peer dataset to submit. - System.err.println("Request key is " + requestKey); + logger.log(Level.FINER, "Request key is " + requestKey); String[] requestKeyFields = requestKey.split("\t"); String[] requestParts = requestKeyFields[0].split("#", 2); @@ -67,7 +67,7 @@ } else if(filter.equals(srcPane.getFilter())){ // no need to redo the filtering, it's the current display's filtering - System.err.println("Reusing current filter"); + logger.log(Level.FINE, "Reusing current filter"); xptrsToFilter = srcPane.getFilteredData(); } else{ @@ -89,7 +89,7 @@ MobyContentInstance payload = new MobyContentInstance(); Map jobPrefixes = new LinkedHashMap(); - System.err.println("Loading MobyContentInstance with "+peerElements.getLength()+" elements for xpath "+selectionXPath); + logger.log(Level.FINE, "Loading MobyContentInstance with "+peerElements.getLength()+" elements for xpath "+selectionXPath); for(int i = 0; i < peerElements.getLength(); i++){ Element peerElement = (Element) peerElements.item(i); // Try to make the job names trackable to the inputs: @@ -106,7 +106,7 @@ jobPrefixes.put(jobKey, new Integer(suffixCount+1)); jobKey += "_"+(suffixCount+1); } - System.err.println("Adding job "+jobKey+" for "+peerElement.getLocalName()); + logger.log(Level.FINE, "Adding job "+jobKey+" for "+peerElement.getLocalName()); MobyDataInstance mdi = null; try{ mdi = MobyDataObject.createInstanceFromDOM(peerElement, SeahawkOptions.getRegistry()); From gordonp at dev.open-bio.org Fri Apr 23 05:15:42 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:15:42 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230515.o3N5FglD024507@dev.open-bio.org> gordonp Fri Apr 23 01:15:42 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util In directory dev.open-bio.org:/tmp/cvs-serv24471/src/main/ca/ucalgary/services/util Modified Files: PBERecorder.java Log Message: Truncate long example data abruptly if it has no whitespace moby-live/Java/src/main/ca/ucalgary/services/util PBERecorder.java,1.4,1.5 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/PBERecorder.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/PBERecorder.java 2010/03/29 20:59:54 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/services/util/PBERecorder.java 2010/04/23 05:15:41 1.5 @@ -795,7 +795,10 @@ } int end = text.length(); - if(start + targetWord.length() + numChars < text.length()){ + if(text.indexOf(" ") == -1){ + end = numChars; + } + else if(start + targetWord.length() + numChars < text.length()){ end = start + targetWord.length() + numChars; // break at a word boundary while(end < text.length() && !Character.isWhitespace(text.charAt(end))){ From gordonp at dev.open-bio.org Fri Apr 23 05:16:45 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:16:45 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230516.o3N5GjOm024551@dev.open-bio.org> gordonp Fri Apr 23 01:16:45 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services In directory dev.open-bio.org:/tmp/cvs-serv24515/src/main/ca/ucalgary/seahawk/services Modified Files: TextClient.java Log Message: Better Dublin Core support, added getPossibleTextTypes() for drag and drop export moby-live/Java/src/main/ca/ucalgary/seahawk/services TextClient.java,1.7,1.8 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/TextClient.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/TextClient.java 2009/06/09 19:22:21 1.7 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/services/TextClient.java 2010/04/23 05:16:45 1.8 @@ -8,13 +8,15 @@ import org.w3c.dom.*; -import javax.xml.transform.stream.*; -import javax.xml.transform.*; import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.*; import java.io.*; import java.net.URL; import java.util.*; +import java.util.logging.*; /** * This class uses XSLT rules to transform MOBY XML data representation @@ -24,20 +26,26 @@ */ public class TextClient{ + public static final String DATA_MAPPING_XSLT_RESOURCE = "ca/ucalgary/seahawk/resources/mobyRules.xsl"; + public static final String RESOURCE_SYSTEM_PROPERTY = "seahawk.textrules"; + public final static String XSLT_NS = "http://www.w3.org/1999/XSL/Transform"; public final static String XSLT_MODE_VAR = "selectedACDTypeTarget"; private Vector moby2textConverters; // XSLT engine private TransformerFactory transFactory; private DocumentBuilder docBuilder; + private URL dataMappingXSLTURL; //private Map id; //todo: unique xslt doc id (e.g. LSID or URL) -> transformer private Map> typeTemplates; //mobytype -> Vector(xsltrule1, xsltrule2,...) private Map> typeNsRestrictions; //mobytype -> Vector(mobynamespace1, ...) private Map templateMode; - private String id; + private Map templateIds; // template name -> URN private Registry registry; + private static Logger logger = Logger.getLogger(TextClient.class.getName()); + public TextClient() throws Exception{ this(SeahawkOptions.getRegistry() == null ? RegistryCache.getDefaultRegistry() : @@ -60,16 +68,95 @@ typeTemplates = new HashMap>(); typeNsRestrictions = new HashMap>(); templateMode = new HashMap(); + templateIds = new HashMap(); + + ClassLoader cl = getClass().getClassLoader(); + if(cl == null){ + cl = ClassLoader.getSystemClassLoader(); + } + String rulesResource = System.getProperty(RESOURCE_SYSTEM_PROPERTY); + if(rulesResource == null){ + dataMappingXSLTURL = cl.getResource(DATA_MAPPING_XSLT_RESOURCE); + } + else if(rulesResource.length() != 0){ + // See if it's a URL + try{ + dataMappingXSLTURL = new URL(rulesResource); + } + catch(Exception e){ + dataMappingXSLTURL = cl.getResource(rulesResource); + } + } + if(dataMappingXSLTURL == null){ + if(rulesResource.length() != 0){ // if not left intentionally blank + logger.log(Level.WARNING, "Could not find MOBY to text mapping resource '"+ + rulesResource+"'"); + } + } + else{ + try{ + addMappingsFromURL(dataMappingXSLTURL); + } + catch(Exception e){ + logger.log(Level.SEVERE, "Error loading default data mapping rules ("+dataMappingXSLTURL+")", e); + e.printStackTrace(); + } + } + } + + public String[] getPossibleTextTypes(MobyPrimaryData dataTemplate, boolean mustHaveURN){ + Vector possibleTypes = new Vector(); + // Search for templates matching the given type or one of its parent types, + // and see if they create the given text type (indicated by the template's mode attribute) + for(MobyDataType type = dataTemplate.getDataType(); + type != null; + type = type.getParent()){ + if(typeTemplates.containsKey(type.getName())){ + // These two vectors should be of the same length! + Vector templateNames = typeTemplates.get(type.getName()); + Vector nsRestrictions = typeNsRestrictions.get(type.getName()); + for(int i = 0; i < templateNames.size(); i++){ + String templateName = templateNames.elementAt(i); + if(mustHaveURN && getTemplateURN(templateName) == null){ + continue; + } + + // the template input moby datatype is the same type as we have an instance of + String textType = templateMode.get(templateName); // mode and text type name are one and the same + // does set-ness match? + if(dataTemplate instanceof MobyPrimaryDataSet){ + if(templateName.startsWith("Collection-")){ + possibleTypes.add(textType); + } + } + else{ + if(!templateName.startsWith("Collection-")){ + possibleTypes.add(textType); + } + } + // Is there a namespace restriction on the transformation rule? + MobyNamespace ns = nsRestrictions.elementAt(i); + if(ns != null){ + for(MobyNamespace n: dataTemplate.getNamespaces()){ + if(ns.equals(n)){ + possibleTypes.add(textType); + } + } + } + } + } + } + return possibleTypes.toArray(new String[possibleTypes.size()]); + } + + public String getTemplateURN(String templateName){ + return templateIds.get(templateName); } /** * @return the data format the xslt creates (the last template mode attribute in the file) */ public synchronized String addMappingsFromURL(URL xsltURL) throws Exception{ - StreamSource stylesheet = new StreamSource(xsltURL.toString()); - // Prepend to list, so later rules can override ones specified earlier - moby2textConverters.insertElementAt(transFactory.newTransformer(stylesheet), 0); - // We actually need to read in the XSLT file and keep track of the template // names, modes, etc.. Currently, this will not follow links that // import other stylesheets into the one being examined. @@ -80,7 +167,6 @@ throw new Exception("Error: Could not get XSLT document as DOM from source URL " + xsltURL + " (empty or malformed document?)"); } - getId(xsltDOMRoot); // retrieve the dublin core metadata String mode = null; // returned in the end @@ -93,6 +179,9 @@ continue; } String templateName = template.getAttribute("name"); + + templateIds.put(templateName, getId(template)); + String m = template.getAttribute("mode"); if(m != null && m.trim().length() > 0){ mode = template.getAttribute("mode"); @@ -150,12 +239,16 @@ typeNsRestrictions.get(templateNameParts[0]).insertElementAt(ns, 0); } + DOMSource stylesheet = new DOMSource(domDoc); + // Prepend to list, so later rules can override ones specified earlier + moby2textConverters.insertElementAt(transFactory.newTransformer(stylesheet), 0); + //System.err.println("Mode returned by " + xsltURL + " is " + mode); return mode; // return the last mode value in the file (useful when mapping XSLT -> data format) } // Looks for Dublin Core metadata - private void getId(Element xsltDOMRoot){ + private String getId(Element xsltDOMRoot){ NodeList idElements = xsltDOMRoot.getElementsByTagNameNS(MobyPrefixResolver.DUBLIN_CORE_NAMESPACE, "identifier"); if(idElements.getLength() == 0){ @@ -163,13 +256,17 @@ "source"); } if(idElements.getLength() == 0){ - return; + return null; } if(idElements.getLength() != 1){ System.err.println("More than one Dublin Core identifier was found, cannot disambiguate."); - return; + return null; } - id = idElements.item(0).getTextContent(); + String id = idElements.item(0).getTextContent(); + // remove child so id doesn't show up in the xslt output! + idElements.item(0).getParentNode().removeChild(idElements.item(0)); + System.err.println("Found and removed "+id); + return id; } /** @@ -374,17 +471,17 @@ e); } - if(client.id == null){ + if(client.templateIds.isEmpty()){ throw new Exception("Internal error: loaded the transformation rule (URI " + ruleURI + ") from " + ruleSource + " but could not retrieve it from TextClient " + "using the URI. Make sure the transformation rule contains a Dublin Core " + "identifier element specifying this URI."); } - else if(!client.id.equals(ruleURI)){ + else if(!client.templateIds.containsValue(ruleURI)){ throw new Exception("Internal error: loaded the transformation rule (URI " + ruleURI + ") from " + ruleSource + " but could not retrieve it from TextClient " + "using the URI. The given Dublin Core info for the rule actually loaded " + - "was " + client.id); + "was " + client.templateIds.values().iterator().next()); } else{ template = new MobyPrimaryDataSimple("templateRuleReturnedObject"); @@ -398,7 +495,7 @@ if(dataTypeNames.size() > 1){ throw new Exception("Multiple TextClient rules were loaded from " + ruleSource + ", please separate them out into separate XSLT files to ensure " + - "they can be referenced inidivudually and unambiguously."); + "they can be referenced indivudually and unambiguously."); } MobyDataType type = MobyDataType.getDataType(dataTypeNames.toArray()[0].toString(), client.getRegistry()); template.setDataType(type); From gordonp at dev.open-bio.org Fri Apr 23 05:17:28 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:17:28 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230517.o3N5HSKc024595@dev.open-bio.org> gordonp Fri Apr 23 01:17:28 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv24559/src/main/ca/ucalgary/seahawk/gui Modified Files: SeahawkTransferable.java Log Message: Better complex object drag and drop export support moby-live/Java/src/main/ca/ucalgary/seahawk/gui SeahawkTransferable.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/SeahawkTransferable.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/seahawk/gui/SeahawkTransferable.java 2009/06/09 19:46:48 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/SeahawkTransferable.java 2010/04/23 05:17:28 1.2 @@ -1,9 +1,15 @@ package ca.ucalgary.seahawk.gui; +import ca.ucalgary.seahawk.util.SeahawkOptions; +import ca.ucalgary.seahawk.services.TextClient; + +import org.biomoby.shared.MobyPrimaryData; import org.biomoby.shared.data.*; import java.awt.datatransfer.*; +import javax.swing.JOptionPane; import java.util.*; +import java.util.logging.*; /** * This class handles the export of data from the Seahawk interface into other applications, @@ -16,9 +22,20 @@ private String lastPastedValue; private String lastTransformRuleURI; + private static TextClient textClient; + private static Logger logger = Logger.getLogger(SeahawkTransferable.class.getName()); + public SeahawkTransferable(MobyContentPane p){ pane = p; } + + private synchronized TextClient getTextClient() throws Exception{ + if(textClient == null){ + textClient = new TextClient(SeahawkOptions.getRegistry()); + //auto populate the rules + } + return textClient; + } public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, java.io.IOException{ @@ -28,7 +45,7 @@ Class clazz = flavor.getRepresentationClass(); // Essentially, we let the user drag Moby objects or submembers rather than substrings of members' text - // so that we can make simple rules for decomposition in programming-by-example. OR an XSLT "DEM" rulew + // so that we can make simple rules for decomposition in programming-by-example. OR an XSLT "DEM" rules // could be applied to provide a particular format e.g. DNASequence -> FastA String fieldString = null; String transformRuleURI = null; @@ -54,12 +71,38 @@ fieldString = ((MobyDataObject) field).getValue().toString(); transformRuleURI = "urn:lsid:bioxml.info:mobyLoweringSchemaMapping:DateTime2String"; } - else if(field instanceof MobyDataObjectVector){ - } - else if(field instanceof MobyDataObjectSet){ + else if(field instanceof MobyDataObjectVector){ + //todo? } else if(field instanceof MobyDataComposite){ - // todo: Is there a DEM rule we can use? + try{ + // Is there a DEM rule we can use? + boolean ONLY_IF_HAS_URN = true; + String[] formatChoices = getTextClient().getPossibleTextTypes((MobyPrimaryData) field, ONLY_IF_HAS_URN); + String targetTextType = null; + if(formatChoices != null && formatChoices.length != 0){ + if(formatChoices.length == 1){ + targetTextType = formatChoices[0]; + } + else{ + // Give the user a choice + targetTextType = formatChoices[0]; + logger.log(Level.INFO, "Chose "+formatChoices[0]+" instead of "+formatChoices[1]); +// targetTextType = (String) JOptionPane.showInputDialog(pane +// "Please select a text format to convert to", +// "Format choices available", +// JOptionPane.QUESTION_MESSAGE, +// null, +// formatChoices, +// formatChoices[0]); + } + } + fieldString = getTextClient().getText(field, targetTextType); + transformRuleURI = getTextClient().getTemplateURN(targetTextType); + } catch(Exception e){ + pane.setStatus("Could not transform Moby object to text: " + e.getMessage()); + logger.log(Level.SEVERE, "Could not transform Moby object to text: ", e); + } } else{ // Must be just a base MobyDataObject From gordonp at dev.open-bio.org Fri Apr 23 05:18:13 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:18:13 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230518.o3N5IDig024639@dev.open-bio.org> gordonp Fri Apr 23 01:18:13 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv24603/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyServicesGUI.java Log Message: Fixed duplication in complex object labels when they have namespaces too moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyServicesGUI.java,1.21,1.22 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.21 retrieving revision 1.22 diff -u -r1.21 -r1.22 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/18 00:31:49 1.21 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/23 05:18:13 1.22 @@ -1315,7 +1315,7 @@ } } if(templateObject instanceof MobyDataObject && id != null && id.length() > 0){ - objectLabel += ""+objectLabel+":" + id; + objectLabel = ""+objectLabel+":" + id; } else if(templateObject instanceof MobyDataObjectSet){ objectLabel = ""+objectLabel+" collection"; From gordonp at dev.open-bio.org Fri Apr 23 05:19:10 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:19:10 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230519.o3N5JAnp024685@dev.open-bio.org> gordonp Fri Apr 23 01:19:10 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv24649/src/main/ca/ucalgary/seahawk/gui Modified Files: MobySaveDialog.java Log Message: Removed redundant popup of single tab export if canceled moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobySaveDialog.java,1.9,1.10 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java 2010/04/18 00:33:05 1.9 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySaveDialog.java 2010/04/23 05:19:10 1.10 @@ -92,11 +92,11 @@ fileChooser.setName(FILE_CHOOSER_SAVE_TITLE); fileChooser.setFileHidingEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); + fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(HTML_EXT, HTML_DESC)); if(document.hasXMLSource()){ - fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(T2FLOW_EXT, T2FLOW_DESC)); fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(XML_EXT, XML_DESC)); + fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(T2FLOW_EXT, T2FLOW_DESC)); } - fileChooser.addChoosableFileFilter(new DescriptiveFileFilter(HTML_EXT, HTML_DESC)); fileChooser.setAcceptAllFileFilterUsed(false); if(lastDirOpened != null){ fileChooser.setCurrentDirectory(lastDirOpened); @@ -277,7 +277,8 @@ // Waits until workflowConfirmed or workflowCanceled is called by the preview dialog dialog.available.acquire(); - return dialog.exportConfirmed; + // Check choice, because if the user cancelled the dialog, don't show it again regardless + return choice == 1 ? true : dialog.exportConfirmed; } catch (Exception ex) { ex.printStackTrace(); JOptionPane.showMessageDialog(null, "Cannot save the Seahawk tab history as a Taverna workflow: "+ex, From gordonp at dev.open-bio.org Fri Apr 23 05:20:00 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:20:00 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230520.o3N5K0NK024729@dev.open-bio.org> gordonp Fri Apr 23 01:20:00 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv24693/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java Log Message: Fixed bug with support of plus sign in URLs to wrap as services moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.29,1.30 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.29 retrieving revision 1.30 diff -u -r1.29 -r1.30 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/16 17:33:25 1.29 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/23 05:20:00 1.30 @@ -273,6 +273,10 @@ } } + public void setStatus(String msg){ + status.setText(msg); + } + // servletPath is either the CGI or SOAP servlet private void createService(String servletPath){ // item name, set by MobyContentGUI's processResults(), is namedXPath#numericXPtr @@ -459,7 +463,7 @@ "Please manually launch a browser and go to the URL " + u); } - desktop.browse(u.toURI()); + desktop.browse(new java.net.URI(u.toURI().toString().replace("+", "%2B"))); } catch (java.net.URISyntaxException urise){ logger.error("Could not create URI from URL ("+u+"): " + urise); } catch (java.io.IOException ioe){ From gordonp at dev.open-bio.org Fri Apr 23 05:21:42 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Fri, 23 Apr 2010 01:21:42 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004230521.o3N5LgTu024871@dev.open-bio.org> gordonp Fri Apr 23 01:21:42 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/resources In directory dev.open-bio.org:/tmp/cvs-serv24839/src/main/ca/ucalgary/seahawk/resources Added Files: mobyRules.xsl Log Message: Sibling of mobyRules.xsl in src/main/ca/ucalgary/services/resources, but with nicer format names and Dublin Core IDs for Daggoo wrapping moby-live/Java/src/main/ca/ucalgary/seahawk/resources mobyRules.xsl,NONE,1.1 From gordonp at dev.open-bio.org Sat Apr 24 17:23:27 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Sat, 24 Apr 2010 13:23:27 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004241723.o3OHNRQZ007370@dev.open-bio.org> gordonp Sat Apr 24 13:23:27 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv7331/src/main/ca/ucalgary/seahawk/gui Modified Files: MobySecondaryInputGUI.java MobyServicesGUI.java Added Files: ServiceChoiceListener.java ServiceSearchDialog.java Log Message: Initial commit of service search dialog moby-live/Java/src/main/ca/ucalgary/seahawk/gui ServiceChoiceListener.java,NONE,1.1 ServiceSearchDialog.java,NONE,1.1 MobySecondaryInputGUI.java,1.7,1.8 MobyServicesGUI.java,1.22,1.23 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySecondaryInputGUI.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySecondaryInputGUI.java 2007/12/06 17:32:32 1.7 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobySecondaryInputGUI.java 2010/04/24 17:23:26 1.8 @@ -1,4 +1,3 @@ - package ca.ucalgary.seahawk.gui; import ca.ucalgary.seahawk.services.MobyClient; =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/23 05:18:13 1.22 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/24 17:23:26 1.23 @@ -27,7 +27,7 @@ * Implementation of the actually popup menu that lists services available, and invokes them. */ -public class MobyServicesGUI implements ActionListener, Comparator, PopupMenuListener{ +public class MobyServicesGUI implements ActionListener, Comparator, PopupMenuListener, ServiceChoiceListener{ public final static int MAX_ID_LEN = 30; public final static String SERVICE_SUBMENU_NAME = "seahawkPopupSubMenuName"; @@ -35,6 +35,10 @@ public final static int MAX_SERVICES_PER_SUBMENU = 12; public final static int MAX_SERVICE_DESC_LEN = 50; public final static String CLIPBOARD_CMD = "clipboard"; + public final static String SERVICESEARCH_CMD = "service_search"; + public final static String SEARCH_LABEL = "Find service by keyword..."; + public final static String CLIPBOARD_LABEL = "Add to clipboard"; + /** Always spring MOBY response in a new window if this modifier is present for a click */ public final static int USE_DEFAULT_HANDLER_MASK = ActionEvent.SHIFT_MASK; public final static int USE_DEFAULT_SECONDARIES_MASK = ActionEvent.CTRL_MASK; @@ -57,6 +61,7 @@ int maxDataDesc = 22; // tracks nested submenus to root submenus of choices popup private Map service2submenu; + private Map search2submenu; private Map submenu2msIndex; private Map submenu2waitItem; // for storing callbacks to other than the default response handler @@ -75,6 +80,7 @@ submenu2msIndex = new HashMap(); submenu2waitItem = new HashMap(); service2submenu = new HashMap(); + search2submenu = new HashMap(); specificHandlers = new HashMap>(); } @@ -124,6 +130,20 @@ } return; } + if(service.equals(SERVICESEARCH_CMD)){ + synchronized(ms){ + if(ms[which_data] == null){ + logger.warn("Ignoring searvice search in " + getClass().getName() + + ", the data to add is currently null (index "+which_data+")"+ + ", from source " + e.getSource()); + removePopupOptions(e.getSource()); + return; + } + setupSearchData(search2submenu.get((JMenuItem) e.getSource()), ms[which_data]); + removePopupOptions(e.getSource()); + } + return; + } // Otherwise call a remote service int which_service = Integer.parseInt(service); @@ -322,7 +342,7 @@ } /** - * If the popup is cancelled, we want to remove any data we've stored, and kill any + * If the popup is canceled, we want to remove any data we've stored, and kill any * requests to MOBYCentral. */ public void popupMenuCanceled(PopupMenuEvent e){ @@ -533,6 +553,7 @@ for(int i = 0; i < submenus.length; i++){ addServicesToSubMenu(submenus[i], serviceAssocObjects[i], handler); + addSearchItem(submenus[i], 1); } } @@ -595,6 +616,7 @@ //}}.start(); } service2submenu.clear(); + search2submenu.clear(); submenu2msIndex.clear(); submenu2waitItem.clear(); ms = new MobyDataServiceAssocInstance[0]; @@ -732,6 +754,7 @@ } addServicesToSubMenu(submenu, serviceAssocObject, handler); + addSearchItem(submenu, 0); } protected synchronized void addServicesToSubMenu(JMenu submenu, MobyDataServiceAssocInstance msadi){ @@ -1333,6 +1356,15 @@ return submenu; } + public void serviceSelected(ServiceSearchDialog dialog, javax.swing.JMenuItem selectedServiceItem){ + actionPerformed(new ActionEvent(selectedServiceItem, 1, selectedServiceItem.getActionCommand())); + removePopupOptions(); + } + + public void selectionCanceled(ServiceSearchDialog dialog){ + removePopupOptions(); //cleanup stored data + } + private synchronized int assignMenuDataIndex(JMenu submenu){ // Make the services array bigger, then copy over existing data, // leaving a blank at the end to be filled in by addServicesToSubMenu @@ -1370,6 +1402,64 @@ } } + /** + * Removes the popup menu and replaces it with a window that has a filter widget + * over the list of services from the original popup. + */ + protected void setupSearchData(JMenu objectMenu, MobyDataInstance mobyData){ + // Setup the chooser dialog + ServiceSearchDialog searchDialog = new ServiceSearchDialog(null, + objectMenu.getText().replaceFirst("Services for", "Run "), + this); + addMenuOptionsToSearch(searchDialog, objectMenu); + + searchDialog.initializeList(); + searchDialog.pack(); + searchDialog.setVisible(true); + } + + private void addMenuOptionsToSearch(ServiceSearchDialog searchDialog, MenuElement menuElement){ + if(menuElement instanceof JPopupMenu || menuElement instanceof JMenu){ + for(MenuElement subMenuElement: menuElement.getSubElements()){ + addMenuOptionsToSearch(searchDialog, subMenuElement); + } + } + else if(menuElement instanceof JMenuItem){ // leaf defining a service + JMenuItem serviceItem = (JMenuItem) menuElement; + String label = serviceItem.getText(); + if(label.equals(SEARCH_LABEL) || label.equals(CLIPBOARD_LABEL)){ + return; // not real services + } + serviceItem.setText(label.replaceFirst("Run ", "")); + searchDialog.addOption(serviceItem, false); + } + else{ + System.err.println("Got dead end with "+menuElement.getClass().getName()); + } + } + + public void addSearchItem(JMenu menu, int location){ + if(menu == null){ + logger.warn("Cannot add service search option, menu reference passed in was null"); + return; + } + + if(!submenu2msIndex.containsKey(menu)){ + logger.warn("Cannot add service search option, cannot find " + + "moby object list index for menu " + + menu.getText()); + return; + } + + + int dataIndex = ((Integer) submenu2msIndex.get(menu)).intValue(); + JMenuItem searchItem = new JMenuItem(SEARCH_LABEL); + searchItem.setActionCommand("MOBY:"+dataIndex+":"+SERVICESEARCH_CMD); + searchItem.addActionListener(this); + menu.add(searchItem, location); + search2submenu.put(searchItem, menu); + } + public void addClipboardItem(JMenu menu, MobyDataInstance mobyData){ if(menu == null){ logger.warn("Cannot add clipboard option, menu reference passed in was null"); @@ -1408,11 +1498,11 @@ } else{ logger.warn("Clipboard option for objects other than MobyDataObject " + - "and MobyDataObjectSet are not yet supported:"+mobyData); + "and MobyDataObjectSet are not yet supported:"+mobyData); return; } - JMenuItem clipItem = new JMenuItem("Add to clipboard"); + JMenuItem clipItem = new JMenuItem(CLIPBOARD_LABEL); clipItem.setActionCommand("MOBY:"+dataIndex+":"+CLIPBOARD_CMD); clipItem.addActionListener(this); menu.add(clipItem); From gordonp at dev.open-bio.org Mon Apr 26 16:25:36 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:25:36 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261625.o3QGPasj025559@dev.open-bio.org> gordonp Mon Apr 26 12:25:36 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util In directory dev.open-bio.org:/tmp/cvs-serv25523/src/main/ca/ucalgary/seahawk/util Modified Files: DataUtils.java Log Message: Ensured that moby namepsace is defined for xpath moby-live/Java/src/main/ca/ucalgary/seahawk/util DataUtils.java,1.6,1.7 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/16 17:33:26 1.6 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataUtils.java 2010/04/26 16:25:36 1.7 @@ -1044,7 +1044,7 @@ // first arg is url#nameBasedXPath peerGroupXPath = userData[0].split("#", 2)[1]; contextNode = XPointerResolver.getNodeFromXPointer(doc, userData[1]); - //System.err.println("Loaded context node " + userData[1] + " as " + contextNode); + System.err.println("Loaded context node " + userData[1] + " as " + contextNode); } else{ // Fallback is to get all nodes with the same name... @@ -1082,13 +1082,16 @@ try{ XPath xpath = xPathFactory.newXPath(); if(contextNode != null){ - xpath.setNamespaceContext(new NamespaceContextImpl(contextNode, "d")); + NamespaceContextImpl nsContext = new NamespaceContextImpl(contextNode, "d"); + nsContext.setPrefix(MobyPrefixResolver.MOBY_XML_NAMESPACE, "d"); + xpath.setNamespaceContext(nsContext); } peerElements = (NodeList) xpath.evaluate(peerGroupXPath, doc, XPathConstants.NODESET); } catch(Exception e){ logger.log(Level.SEVERE, "Could not evaluate UserData XPath "+peerGroupXPath, e); + return null; } //System.err.println("Got " + peerElements.getLength() + " peers for " + peerGroupXPath); From gordonp at dev.open-bio.org Mon Apr 26 16:26:18 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:26:18 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261626.o3QGQIZl025603@dev.open-bio.org> gordonp Mon Apr 26 12:26:18 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv25567/src/main/ca/ucalgary/seahawk/gui Modified Files: ServiceSearchDialog.java Log Message: Case insensitive service name highlighting during search moby-live/Java/src/main/ca/ucalgary/seahawk/gui ServiceSearchDialog.java,1.1,1.2 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/ServiceSearchDialog.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/seahawk/gui/ServiceSearchDialog.java 2010/04/24 17:23:27 1.1 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/ServiceSearchDialog.java 2010/04/26 16:26:18 1.2 @@ -127,6 +127,10 @@ Pattern.DOTALL | Pattern.CASE_INSENSITIVE | Pattern.MULTILINE); activeChoices.clear(); for(JMenuItem serviceChoice: serviceChoices){ + if(serviceChoice.getText() == null){ + continue; + } + String label = serviceChoice.getText().replaceAll("<.*?>", "").replaceAll("see description", ""); // get rid of any coloring @@ -134,12 +138,15 @@ if(searchTerm == null || searchTerm.trim().length() == 0){ serviceChoice.setText(label); activeChoices.addElement(serviceChoice); + continue; } + Matcher matcher = searchPattern.matcher(label); // In the label? - else if(serviceChoice.getText() != null && - searchPattern.matcher(label).find()){ - label = label.replaceAll("("+searchTerm+")", "$1"); - serviceChoice.setText(""+label+""); + if(matcher.find()){ + label = label.substring(0, matcher.start())+"" + + matcher.group(0) + "" + + (matcher.end() >= label.length() ? "" : label.substring(matcher.end())); + serviceChoice.setText("" + label + ""); activeChoices.addElement(serviceChoice); } // In the tooltip? From gordonp at dev.open-bio.org Mon Apr 26 16:27:31 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:27:31 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261627.o3QGRVV6025647@dev.open-bio.org> gordonp Mon Apr 26 12:27:31 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv25611/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyServicesGUI.java Log Message: Better UI refresh moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyServicesGUI.java,1.23,1.24 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.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/MobyServicesGUI.java 2010/04/24 17:23:26 1.23 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyServicesGUI.java 2010/04/26 16:27:31 1.24 @@ -554,6 +554,7 @@ for(int i = 0; i < submenus.length; i++){ addServicesToSubMenu(submenus[i], serviceAssocObjects[i], handler); addSearchItem(submenus[i], 1); + refreshMenu(submenus[i]); } } @@ -755,6 +756,7 @@ addServicesToSubMenu(submenu, serviceAssocObject, handler); addSearchItem(submenu, 0); + refreshMenu(submenu); } protected synchronized void addServicesToSubMenu(JMenu submenu, MobyDataServiceAssocInstance msadi){ @@ -1121,7 +1123,9 @@ } submenu.add(mobyItem); } + } + protected void refreshMenu(JMenu submenu){ // Causes resizing based on new items if(submenu.isPopupMenuVisible()){ submenu.setPopupMenuVisible(false); From gordonp at dev.open-bio.org Mon Apr 26 16:28:11 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:28:11 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261628.o3QGSB9E025691@dev.open-bio.org> gordonp Mon Apr 26 12:28:11 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv25655/src/main/ca/ucalgary/seahawk/gui Modified Files: FilterSearchWidget.java Log Message: Proper update of selected XPath when search restored moby-live/Java/src/main/ca/ucalgary/seahawk/gui FilterSearchWidget.java,1.3,1.4 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.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/seahawk/gui/FilterSearchWidget.java 2010/04/10 00:40:17 1.3 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/26 16:28:11 1.4 @@ -112,6 +112,7 @@ docPartOptions.setEnabled(true); docPartOptions.setModel(new DefaultComboBoxModel(fs.getXPathOptions())); + docPartOptions.setSelectedItem(fs.getSelectedXPath()); currentFilterSearch = fs; // done in this order so no feedback as DocumentEvents while setting fields programmatically } From gordonp at dev.open-bio.org Mon Apr 26 16:29:13 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 12:29:13 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261629.o3QGTD4M025779@dev.open-bio.org> gordonp Mon Apr 26 12:29:13 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv25739/src/main/ca/ucalgary/seahawk/gui Modified Files: MobyContentPane.java MobyPayloadCreator.java Log Message: Account for possibility of null peer elements list moby-live/Java/src/main/ca/ucalgary/seahawk/gui MobyContentPane.java,1.30,1.31 MobyPayloadCreator.java,1.4,1.5 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java,v retrieving revision 1.30 retrieving revision 1.31 diff -u -r1.30 -r1.31 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/23 05:20:00 1.30 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyContentPane.java 2010/04/26 16:29:13 1.31 @@ -1237,7 +1237,7 @@ // note that getPeerElements() will modify the userData to reflect the semantic of the requested peer mode mobyData.setUserData(origUserData); NodeList peerElements = DataUtils.getPeerElements(getCurrentDoc(), mobyData, getFilteredData(), peerMode); - if(peerElements.getLength() <= 1){ + if(peerElements == null || peerElements.getLength() <= 1){ continue; // no 'for each' option if only one to process... } String each = "each (" + peerElements.getLength() + " total)"; =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/18 00:33:56 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/MobyPayloadCreator.java 2010/04/26 16:29:13 1.5 @@ -85,8 +85,12 @@ NodeList peerElements = DataUtils.getPeerElements(doc, mobyDataContext, xptrsToFilter, DataUtils.DATATYPE_PEERS_MODE); - // find the peers of defined by the userData selection constraints and put them into a MobyContentInstance MobyContentInstance payload = new MobyContentInstance(); + if(peerElements == null){ + return payload; + } + + // find the peers of defined by the userData selection constraints and put them into a MobyContentInstance Map jobPrefixes = new LinkedHashMap(); logger.log(Level.FINE, "Loading MobyContentInstance with "+peerElements.getLength()+" elements for xpath "+selectionXPath); From gordonp at dev.open-bio.org Mon Apr 26 17:50:34 2010 From: gordonp at dev.open-bio.org (Paul Gordon) Date: Mon, 26 Apr 2010 13:50:34 -0400 Subject: [MOBY-guts] biomoby commit Message-ID: <201004261750.o3QHoXg0029187@dev.open-bio.org> gordonp Mon Apr 26 13:50:33 EDT 2010 Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui In directory dev.open-bio.org:/tmp/cvs-serv29151/src/main/ca/ucalgary/seahawk/gui Modified Files: FilterSearchWidget.java Log Message: Kung foo with semaphores to let search filter only apply every 600ms or so when typing a longer string moby-live/Java/src/main/ca/ucalgary/seahawk/gui FilterSearchWidget.java,1.4,1.5 =================================================================== RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/26 16:28:11 1.4 +++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/gui/FilterSearchWidget.java 2010/04/26 17:50:33 1.5 @@ -5,6 +5,7 @@ import java.awt.Dimension; import java.awt.event.*; import java.net.URL; +import java.util.concurrent.*; import java.util.logging.*; import javax.swing.*; import javax.swing.event.*; @@ -22,6 +23,8 @@ private JTextField searchField; private JComboBox docPartOptions; private MobyContentPane contentPane; + private Semaphore semaphore; // for search update delays in multikeystroke + public static final String CASE_SENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_sensitive.png"; public static final String CASE_INSENSITIVE_ICON_RESOURCE = "ca/ucalgary/seahawk/resources/images/case_insensitive.png"; private static final String IF_TEXT = "if"; @@ -48,6 +51,8 @@ closeIcon.addMouseListener(new Closer(this)); closeIcon.setToolTipText("Remove filter criteria"); + semaphore = new Semaphore(1); //1 search update for a given timeframe + Dimension buttonSize = new Dimension(24,24); caseButton = new JToggleButton(new ImageIcon(cl.getResource(CASE_SENSITIVE_ICON_RESOURCE))); caseButton.setDisabledIcon(new ImageIcon(cl.getResource(CASE_INSENSITIVE_ICON_RESOURCE))); @@ -162,8 +167,10 @@ return; } StringBuffer sb = currentFilterSearch.getFilterRegex(); - sb.replace(0, sb.length(), searchField.getText()); - contentPane.applyFilter(true); + synchronized(searchField){ + sb.replace(0, sb.length(), searchField.getText()); + } + applyFilterWhenSuitable(); } public void insertUpdate(DocumentEvent e){ @@ -171,8 +178,10 @@ return; } StringBuffer sb = currentFilterSearch.getFilterRegex(); - sb.replace(0, sb.length(), searchField.getText()); - contentPane.applyFilter(true); + synchronized(searchField){ + sb.replace(0, sb.length(), searchField.getText()); + } + applyFilterWhenSuitable(); } public void removeUpdate(DocumentEvent e){ @@ -180,10 +189,53 @@ return; } StringBuffer sb = currentFilterSearch.getFilterRegex(); - sb.replace(0, sb.length(), searchField.getText()); - contentPane.applyFilter(true); + synchronized(searchField){ + sb.replace(0, sb.length(), searchField.getText()); + } + applyFilterWhenSuitable(); } + // Waits 600 milliseconds to see if the user is typing a phrase, rather than + // filtering for each letter added, which can be slow + private void applyFilterWhenSuitable(){ + try{ + final Semaphore sem = semaphore; + final MobyContentPane pane = contentPane; + final JTextField sf = searchField; + if(sem.tryAcquire()){ + new Thread(){ + public void run(){ + try{ + Thread.sleep(500); + } + catch(Exception e){ + logger.log(Level.WARNING, + "Delay less than 400ms on search input due to interrupt", + e); + } + synchronized(sf){ + try{ + // Give 100ms for other threads past sb.replace() in DocumentListener callbacks to + // try to acquire a permit, avoiding redundant applyFiolter call + Thread.sleep(100); + } + catch(Exception e){ + logger.log(Level.WARNING, + "Delay less than 100ms on search input due to interrupt", + e); + } + pane.applyFilter(true); + sem.release(); + } + } + }.start(); + } + }catch(Exception e){ + logger.log(Level.SEVERE, "Search result updater was interrupted while waiting for a semaphore," + + "GUI may not reflect search field", e); + } + // else, it's going to be updated soon anyway with the latest string buffer...just return + } class Closer extends MouseAdapter{ boolean active = false;