[MOBY-guts] biomoby commit

Paul Gordon gordonp at dev.open-bio.org
Thu Feb 3 21:57:23 UTC 2011


gordonp
Thu Feb  3 16:57:23 EST 2011
Update of /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util
In directory dev.open-bio.org:/tmp/cvs-serv20804/src/main/ca/ucalgary/seahawk/util

Modified Files:
	DataFlowRecorder.java 
Log Message:
Numerous improvements to port labelling, input data support, removing cruft code
moby-live/Java/src/main/ca/ucalgary/seahawk/util DataFlowRecorder.java,1.6,1.7
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.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/DataFlowRecorder.java	2010/04/18 00:23:42	1.6
+++ /home/repository/moby/moby-live/Java/src/main/ca/ucalgary/seahawk/util/DataFlowRecorder.java	2011/02/03 21:57:23	1.7
@@ -33,6 +33,8 @@
     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";
+    public static final String T2FLOW_SELECTFILES_BEANSHELL = "ca/ucalgary/seahawk/resources/SelectFilesBeanShell";
+    public static final String T2FLOW_READBINARYFILE_BEANSHELL = "ca/ucalgary/seahawk/resources/BinaryFileLoaderBeanShell";
 
     private Central mobyCentral;
     private Map<String,Integer> namesUsed;  // keep count of workflow element name usage so as not to duplicate an ID
@@ -47,6 +49,8 @@
     private static String xpathFilterScript = null;
     private static String passFilterScript = null;
     private static String listFlattenScript = null;
+    private static String fileSelectionScript = null;
+    private static String readBinaryFileScript = null;
     private static Element dispatchStack = null;
     private static Transformer nullTransformer = null;
     private static Logger logger = Logger.getLogger(DataFlowRecorder.class.getName());
@@ -238,7 +242,7 @@
 	return portEl;
     }
 
-    private Element createWorkflowInputElement(String name, MobyPrimaryData sampleData, Document doc){
+    private Element createWorkflowInputElement(String name, MobyNamespace ns, String id, MobyPrimaryData[] sampleData, Document doc){
 	Element portEl = doc.createElementNS(T2FLOW_NS, "port");
 
 	Element nameEl = doc.createElementNS(T2FLOW_NS, "name");
@@ -253,15 +257,29 @@
 	granularDepthEl.appendChild(doc.createTextNode("0"));
 	portEl.appendChild(granularDepthEl);
 
-	MobyNamespace ns = null;
-	if(sampleData.getNamespaces() != null &&
-	   sampleData.getNamespaces().length > 0){
-	    ns = sampleData.getNamespaces()[0];
+	String descText = "File/Spreadsheet of one or more lines, " +
+	    (sampleData.length == 1 ? 
+	     "each line containing one ":
+	     "with the following "+sampleData.length+" fields in order:");
+	for(MobyPrimaryData sampleDatum: sampleData){
+	    descText += sampleDatum.getName()+" ("+sampleDatum.getDataType().getName()+"),";
+	}
+	if(ns != null && !ns.getName().equals("unknown")){
+	    descText += ns.getName()+" (ID)";
+	}
+	else{
+	    descText = descText.substring(0, descText.length()-1);
+	}
+	String exampleText = "";
+	for(MobyPrimaryData sampleDatum: sampleData){
+	    exampleText += ((MobyDataObject) sampleDatum).getObject().toString()+",";
+	}
+	if(ns != null && !ns.getName().equals("unknown")){
+	    exampleText += id;
+	}
+	else{
+	    exampleText = exampleText.substring(0, exampleText.length()-1);
 	}
-
-	String descText = "File of one or more"+(ns == null ? "" : " "+
-						 ns.getName())+" IDs, one per line";
-	String exampleText = sampleData.getId();
 	Element annotations = doc.createElementNS(T2FLOW_NS, "annotations");
 	portEl.appendChild(annotations);
 	annotations.appendChild(createAnnotationChain("net.sf.taverna.t2.annotation.annotationbeans.FreeTextDescription", descText, doc));
@@ -475,14 +493,9 @@
 	    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?
-	    }
+	    mobifyingProcessorNameAndPorts = addDataMobifyingProcessor(processors, datalinks, inputPorts,
+								       sampleData, doc);
+	    input2Processor.put(inputKey, mobifyingProcessorNameAndPorts);
 	}
 	// link the created data to the workflow service
 	datalinks.appendChild(createDataLinkElement(mobifyingProcessorNameAndPorts[0], 
@@ -503,22 +516,86 @@
 	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.
-    // Returns [spreadsheetReadingProcName, outputPort]
-    private String[] addIdMobifyingProcessor(Element processors, Element datalinks, Element dataFlowInputPorts,
-					     MobyPrimaryData sampleData, Document doc) throws Exception{
-	String processorName = "Create-" + sampleData.getDataType().getName();
+    private String[] addDataMobifyingProcessor(Element processors, Element datalinks, Element dataFlowInputPorts,
+					       MobyPrimaryData sampleData, Document doc) throws Exception{
+	MobyDataType sampleDataType = sampleData.getDataType();
+	
+	boolean hasBinaryBase = false;
+	List<String[]> sampleCompositeProcessors = new ArrayList<String[]>();
+	List<MobyDataComposite> sampleComposites = new ArrayList<MobyDataComposite>();
+	List<MobyPrimaryData> samplePrimitives = new ArrayList<MobyPrimaryData>();
+        String[] binaryFileReaderProcNameAndPorts = null;
+	if(sampleData instanceof MobyDataComposite){
+	    if(sampleData instanceof MobyDataBytes){ // binary data needs special handling
+		binaryFileReaderProcNameAndPorts = addBinaryFileReaderBeanShell(processors, doc);
+		
+		// connect the article name constant to the binary file reader
+		String[] fileSelectionProcNameAndPorts = addFileSelectionBeanShell(processors, doc);
+		String constantTitle = createUniqueName("File_dialog_title");
+		processors.appendChild(createConstantProcessor(constantTitle, "Load multiple " + MobyDataBytes.ENCODED_MEMBER_NAME + " files", doc));
+		datalinks.appendChild(createDataLinkElement(constantTitle, 
+							    "value",
+							    fileSelectionProcNameAndPorts[0],
+							    fileSelectionProcNameAndPorts[1],
+							    doc));
+
+		// connect the dialog title constant to the binary file reader
+		String constantName = createUniqueName(MobyDataBytes.ENCODED_MEMBER_NAME+"-article_name");
+		processors.appendChild(createConstantProcessor(constantName, MobyDataBytes.ENCODED_MEMBER_NAME, doc));
+		datalinks.appendChild(createDataLinkElement(constantName, 
+							    "value",
+							    binaryFileReaderProcNameAndPorts[0],
+							    binaryFileReaderProcNameAndPorts[1],
+							    doc));
+		// link the file selection dialog results to the binary file reader
+		datalinks.appendChild(createDataLinkElement(fileSelectionProcNameAndPorts[0],
+							    fileSelectionProcNameAndPorts[fileSelectionProcNameAndPorts.length-1],
+							    binaryFileReaderProcNameAndPorts[0],
+							    binaryFileReaderProcNameAndPorts[2],
+							    doc));
+		hasBinaryBase = true;
+	    }
+	    // recurse to fill in other fields
+	    for(MobyPrimaryData child: ((MobyDataComposite) sampleData).values()){
+		if(hasBinaryBase && child.getName().equals(MobyDataBytes.ENCODED_MEMBER_NAME)){
+		    continue; // handled this member in an if condition earlier
+		}
+		if(child instanceof MobyDataComposite){
+		    // must recurse because the complex object contains another complex object
+		    sampleCompositeProcessors.add(addDataMobifyingProcessor(processors, 
+									    datalinks, 
+									    dataFlowInputPorts, 
+									    child, 
+									    doc));
+		    sampleComposites.add((MobyDataComposite) child);
+		}
+		else{
+		    samplePrimitives.add(child);		    
+		}
+	    }
+	}
+	// a Moby primitive
+	else if(!sampleDataType.getName().equals(MobyTags.MOBYOBJECT)){
+	    samplePrimitives.add(sampleData);
+	}
+
+	String processorName = "Create-" + sampleDataType.getName();
 	MobyNamespace ns = null;
 	MobyNamespace[] nss = ((MobyPrimaryData) sampleData).getNamespaces();
-	if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT) &&
-	   nss != null && nss.length > 0){
-	    ns = nss[0];  //we will use only the primary namespace
-	    processorName = "Create-" + ns.getName() + "-ID";
+	if(nss != null && nss.length > 0){
+	    ns = nss[0];  // we will use only the primary namespace for now
+	    if(sampleData.getDataType().getName().equals(MobyTags.MOBYOBJECT)){
+		processorName = "Create-" + ns.getName() + "-ID";
+	    }
+	    else{  //datatype + ns in proc name
+		processorName += "-"+ns.getName() + "-ID";
+	    }
 	}
 	processorName = createUniqueName(processorName);
 
+	// now we need to merge the primitive object fields with the processors creating binary and other complex objects
+
+	// Create the Mobifying processor
 	Element processor = doc.createElementNS(T2FLOW_NS, "processor");
 	processors.appendChild(processor);
 	Element name = doc.createElementNS(T2FLOW_NS, "name");
@@ -596,10 +673,41 @@
 	iteration.appendChild(strategy);
 	Element cross = doc.createElementNS(T2FLOW_NS, "cross");
 	strategy.appendChild(cross);
+	Element dot = doc.createElementNS(T2FLOW_NS, "dot");
+	cross.appendChild(dot);
+
+	// object members + 3 standard input ports, and one output
+	String[] portNames = new String[4+sampleCompositeProcessors.size()+samplePrimitives.size()+(binaryFileReaderProcNameAndPorts != null ? 1 :0)];
+	portNames[portNames.length-4] = "id";
+	portNames[portNames.length-3] = "namespace";
+	portNames[portNames.length-2] = "article name";
+	portNames[portNames.length-1] = "mobyData";
+
+        if(binaryFileReaderProcNameAndPorts != null){
+            portNames[0] = getPortName(((MobyDataBytes) sampleData).get(MobyDataBytes.ENCODED_MEMBER_NAME), false);
+            datalinks.appendChild(createDataLinkElement(binaryFileReaderProcNameAndPorts[0],
+							binaryFileReaderProcNameAndPorts[binaryFileReaderProcNameAndPorts.length-1],
+							processorName,
+                                                        portNames[0],
+							doc));
+        }
+	// fill the new processor's input port list with the composites' output ports 
+	for(int i = (binaryFileReaderProcNameAndPorts != null ? 1 :0); i < sampleCompositeProcessors.size(); i++){
+	    String[] compositeProcNameAndPorts = sampleCompositeProcessors.get(i);
+	    portNames[i] = getPortName(sampleComposites.get(i), false);		
+	    datalinks.appendChild(createDataLinkElement(compositeProcNameAndPorts[0],
+							compositeProcNameAndPorts[compositeProcNameAndPorts.length-1],
+							processorName,
+							portNames[i],
+							doc));
+	}
+	// then the primitives' output ports...
+	for(int i = (binaryFileReaderProcNameAndPorts != null ? 1 :0); i < samplePrimitives.size(); i++){
+	    portNames[sampleCompositeProcessors.size()+i] = getPortName(samplePrimitives.get(i), false);
+	}
 
-	// 3 input ports, one output
-	String[] portNames = new String[]{"namespace", "article name", "id", "mobyData"};
-	for(String portNameString: portNames){
+	for(int i = 0; i < portNames.length; i++){
+	    String portNameString = portNames[i];
 	    // Map them
 	    Element map = createMapFromTo(portNameString, portNameString, doc); //identity map
 	    if(portNameString.equals("mobyData")){
@@ -607,25 +715,38 @@
 		outputMap.appendChild(map);
 	    }
 	    else{
-		inputPorts.appendChild(createParamPort(portNameString, "0", doc));
-		
+		inputPorts.appendChild(createParamPort(portNameString, "0", doc));		
 		inputMap.appendChild(map);
 	    
 		// Add the iteration strategy
 		Element portRef = doc.createElementNS(T2FLOW_NS, "port");
 		portRef.setAttribute("name", portNameString);
 		portRef.setAttribute("depth", "0");
-		cross.appendChild(portRef);
+		// last few standard attributes are constants, so cross them instead of dot
+		if(i >= portNames.length - (ns==null || ns.getName().equals("unknown") ? 4 : 3)){
+		    cross.appendChild(portRef);
+		}
+		else{
+		    dot.appendChild(portRef);
+		}
 	    }
 	}
 
-	// Create the constant value processors for the articlename 
-	// NOTE: WE REPURPOSE THE VARIABLES ABOVE FOR NEW ELEMENTS!!!
+	// Create the constant value processors for the object
 	Map<String,String> constants = new HashMap<String,String>();
 	Map<String,String> feeds = new HashMap<String,String>();  //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", "unimportant");
+	if(ns != null && !ns.getName().equals("unknown")){
+	    constants.put(ns.getName()+"-namespace-constant", ns.getName());
+	    feeds.put(ns.getName()+"-namespace-constant", "namespace");	    
+	    // id is fed from spreadsheet importer if ns is defined, no need to populate here
+	}
+	else{
+	    constants.put("blank-namespace", "");
+	    feeds.put("blank-namespace", "namespace");	    
+	    constants.put("blank-id", "");
+	    feeds.put("blank-id", "id");	    	    
+	}
+	constants.put("article_name-constant", sampleData.getName());
 	feeds.put("article_name-constant", "article name");
 
 	for(Map.Entry<String,String> constant: constants.entrySet()){
@@ -638,54 +759,115 @@
 							doc));
 	}
 
+	if(samplePrimitives.isEmpty() && hasBinaryBase && 
+	   sampleCompositeProcessors.isEmpty()){  // just a plain binary object to return, no need for spreadsheet importer
+
+	    // return the name of the data creator and output port so it can be hooked up
+	    // to input ports for Moby services
+	    return new String[]{processorName, portNames[portNames.length-1]};
+	}
+
+	String[] spreadsheetProcessorNameAndPorts = 
+	    addPrimitiveSpreadsheetProcessor(processors, datalinks, dataFlowInputPorts,
+					     sampleDataType, ns, sampleData.getId(),
+					     samplePrimitives.toArray(new MobyPrimaryData[samplePrimitives.size()]), 
+					     doc);
+	
+	
+	// link the spreadsheet reader to the Moby data creator 
+	for(int i = 1; i < spreadsheetProcessorNameAndPorts.length; i++){
+	    datalinks.appendChild(createDataLinkElement(spreadsheetProcessorNameAndPorts[0], 
+							spreadsheetProcessorNameAndPorts[i],
+							processorName,
+							portNames[(binaryFileReaderProcNameAndPorts != null ? 1 :0)+sampleCompositeProcessors.size()+i-1],
+							doc));
+	}
+
+	// return the name of the data creator processor and output port so it can be hooked up
+	// to input ports for Moby services
+	return new String[]{processorName, portNames[portNames.length-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.
+    // Returns [spreadsheetReadingProcName, outputPort1, outputPort2, etc.]
+    private String[] addPrimitiveSpreadsheetProcessor(Element processors, Element datalinks, Element dataFlowInputPorts,
+						      MobyDataType dataType, MobyNamespace ns, String id,
+						      MobyPrimaryData[] sampleData, Document doc) throws Exception{
+
 	// feed the id input of the Moby data creator with a spreadsheet importer,
 	// so users can easily give a file list of IDs to run.
-	String importerName = createUniqueName("SpreadsheetImporter-"+ns.getName()+"-IDs");
+	String dataTypeName = dataType.getName();
+	if(dataTypeName.equals(MobyTags.MOBYOBJECT)){
+	    dataTypeName = ns.getName()+"-ID";
+	}
+	else{
+	    dataTypeName += "-fields";
+	}
+	String importerName = createUniqueName("SpreadsheetImporter-"+dataTypeName);
 	Element importProcessor = doc.createElementNS(T2FLOW_NS, "processor");
 	processors.appendChild(importProcessor);
-	name = doc.createElementNS(T2FLOW_NS, "name");
+	Element name = doc.createElementNS(T2FLOW_NS, "name");
 	name.appendChild(doc.createTextNode(importerName));
 	importProcessor.appendChild(name);
-	inputPorts = doc.createElementNS(T2FLOW_NS, "inputPorts");
+	Element inputPorts = doc.createElementNS(T2FLOW_NS, "inputPorts");
 	importProcessor.appendChild(inputPorts);	
 	inputPorts.appendChild(createParamPort("fileurl", "0", doc));
 
-	outputPorts = doc.createElementNS(T2FLOW_NS, "outputPorts");
+	Element outputPorts = doc.createElementNS(T2FLOW_NS, "outputPorts");
 	importProcessor.appendChild(outputPorts);
-	String outputUniqueName = createUniqueName(ns.getName());// output name
-	outputPorts.appendChild(createParamPort(outputUniqueName, "1", "1", doc));
+	String[] outputUniqueNames = new String[sampleData.length+(ns!=null && !ns.getName().equals("unknown")?1:0)];
+	for(int i = 0; i < sampleData.length; i++){
+	    String outputName = sampleData[i].getName();
+	    if(sampleData[i].getDataType().getName().equals(MobyTags.MOBYOBJECT)){		
+		outputName += "-"+sampleData[i].getNamespaces()[0].getName()+"-ID";  
+	    }
+	    else{
+		outputName += "-"+sampleData[i].getDataType().getName();
+	    }
+	    outputUniqueNames[i] = createUniqueName(outputName);// output name
+	    outputPorts.appendChild(createParamPort(outputUniqueNames[i], "1", "1", doc));
+	}
+	// special port name case for id field of object, if present
+	if(ns != null && !ns.getName().equals("unknown")){
+	    outputUniqueNames[outputUniqueNames.length-1] = "id";
+	    outputPorts.appendChild(createParamPort("id", "1", "1", doc));
+	}
 	
 	importProcessor.appendChild(doc.createElementNS(T2FLOW_NS, "annotations"));
-	activities = doc.createElementNS(T2FLOW_NS, "activities");
+	Element activities = doc.createElementNS(T2FLOW_NS, "activities");
 	importProcessor.appendChild(activities);
-	activity = doc.createElementNS(T2FLOW_NS, "activity");
+	Element activity = doc.createElementNS(T2FLOW_NS, "activity");
 	activities.appendChild(activity);
-	raven = doc.createElementNS(T2FLOW_NS, "raven");
-	group = doc.createElementNS(T2FLOW_NS, "group");
+	Element raven = doc.createElementNS(T2FLOW_NS, "raven");
+	Element group = doc.createElementNS(T2FLOW_NS, "group");
 	group.appendChild(doc.createTextNode("net.sf.taverna.t2.activities"));
 	raven.appendChild(group);
-	artifact = doc.createElementNS(T2FLOW_NS, "artifact");
+	Element artifact = doc.createElementNS(T2FLOW_NS, "artifact");
 	artifact.appendChild(doc.createTextNode("spreadsheet-import-activity"));
 	raven.appendChild(artifact);
-	version = doc.createElementNS(T2FLOW_NS, "version");
+	Element version = doc.createElementNS(T2FLOW_NS, "version");
 	version.appendChild(doc.createTextNode("1.0"));
 	raven.appendChild(version);
 	activity.appendChild(raven);
 
-	clas = doc.createElementNS(T2FLOW_NS, "class");
+	Element clas = doc.createElementNS(T2FLOW_NS, "class");
 	activity.appendChild(clas);
 	clas.appendChild(doc.createTextNode("net.sf.taverna.t2.activities.spreadsheet.SpreadsheetImportActivity"));	
 
 	    
-	inputMap = doc.createElementNS(T2FLOW_NS, "inputMap");
+	Element inputMap = doc.createElementNS(T2FLOW_NS, "inputMap");
 	activity.appendChild(inputMap);
 	inputMap.appendChild(createMapFromTo("fileurl", "fileurl", doc)); //identity map
 
-	outputMap = doc.createElementNS(T2FLOW_NS, "outputMap");
+	Element outputMap = doc.createElementNS(T2FLOW_NS, "outputMap");
 	activity.appendChild(outputMap);
-	outputMap.appendChild(createMapFromTo(outputUniqueName, outputUniqueName, doc));
+	for(int i = 0; i < outputUniqueNames.length; i++){
+	    outputMap.appendChild(createMapFromTo(outputUniqueNames[i], outputUniqueNames[i], doc));
+	}
 
-	configBean = doc.createElementNS(T2FLOW_NS, "configBean");
+	Element configBean = doc.createElementNS(T2FLOW_NS, "configBean");
 	configBean.setAttribute("encoding", "xstream");
 	activity.appendChild(configBean);
 	Element SpreadsheetImportConfiguration = 
@@ -697,7 +879,7 @@
 	Element columnRange = doc.createElementNS("", "columnRange");
 	SpreadsheetImportConfiguration.appendChild(columnRange);
 	columnRange.appendChild(createElWithText(doc,"","start","0"));
-	columnRange.appendChild(createElWithText(doc,"","end","0"));
+	columnRange.appendChild(createElWithText(doc,"","end", ""+(sampleData.length-1+(ns!=null && !ns.getName().equals("unknown")?1:0))));
 	columnRange.appendChild(doc.createElementNS("", "excludes"));
 
 	Element rowRange = doc.createElementNS("", "rowRange");
@@ -710,10 +892,18 @@
 	
 	Element columnNames = doc.createElementNS("", "columnNames");
 	SpreadsheetImportConfiguration.appendChild(columnNames);
-	Element entry = doc.createElementNS("", "entry");
-	columnNames.appendChild(entry);
-	entry.appendChild(createElWithText(doc,"","string","A"));
-	entry.appendChild(createElWithText(doc,"","string",outputUniqueName));
+	// NOTE: Use 26 column names, if more, name as in Excel, AA, AB, etc
+	String[] columnLetters = new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",
+	                                      "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "X", "Y", "Z"};
+	for(int i = 0; i < outputUniqueNames.length; i++){
+	    Element entry = doc.createElementNS("", "entry");
+	    columnNames.appendChild(entry);
+	    entry.appendChild(createElWithText(doc,"","string", 
+					       (i >= columnLetters.length ? 
+						columnLetters[i/columnLetters.length-1]: "")+
+					       columnLetters[i%columnLetters.length]));
+	    entry.appendChild(createElWithText(doc,"","string", outputUniqueNames[i]));
+	}
 
 	SpreadsheetImportConfiguration.appendChild(createElWithText(doc,"","allRows","true"));
 	SpreadsheetImportConfiguration.appendChild(createElWithText(doc,"","excludeFirstRow","false"));
@@ -726,36 +916,35 @@
 
 	importProcessor.appendChild(getDispatchStack(doc));
 
-	iterationStrategyStack = doc.createElementNS(T2FLOW_NS, "iterationStrategyStack");
+	Element iterationStrategyStack = doc.createElementNS(T2FLOW_NS, "iterationStrategyStack");
 	importProcessor.appendChild(iterationStrategyStack);
-	iteration = doc.createElementNS(T2FLOW_NS, "iteration");
+	Element iteration = doc.createElementNS(T2FLOW_NS, "iteration");
 	iterationStrategyStack.appendChild(iteration);
-	strategy = doc.createElementNS(T2FLOW_NS, "strategy");
+	Element strategy = doc.createElementNS(T2FLOW_NS, "strategy");
 	iteration.appendChild(strategy);
-	cross = doc.createElementNS(T2FLOW_NS, "cross");
+	Element cross = doc.createElementNS(T2FLOW_NS, "cross");
 	strategy.appendChild(cross);
 	Element port = doc.createElementNS(T2FLOW_NS, "port");
 	cross.appendChild(port);
 	port.setAttribute("name", "fileurl");
 	port.setAttribute("depth", "0");
 
-	String uniqueInputName = createUniqueName(getInputName(sampleData));
+	String uniqueInputName = createUniqueName(getInputName(dataType, ns));
 	// todo: sample data may be of more specific type than service requires
-	dataFlowInputPorts.appendChild(createWorkflowInputElement(uniqueInputName, sampleData, doc));
+	dataFlowInputPorts.appendChild(createWorkflowInputElement(uniqueInputName, ns, id, 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));
-
-	// 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]};
+	// processor name, output ports (same number as sampleData length) 
+	String[] procAndPortNames = new String[outputUniqueNames.length+1];
+	procAndPortNames[0] = importerName;
+	System.arraycopy(outputUniqueNames, 0, procAndPortNames, 1, outputUniqueNames.length);
+
+	// return the name of the spreadsheet reading processor and output ports so it can be hooked up
+	// to input ports for Moby data creator 
+	return procAndPortNames;
     }
 
     private Element createConstantProcessor(String constantName, String constantValue, Document doc)
@@ -1287,142 +1476,8 @@
 	}
 	return endpoint;
     }
-
-    // Returns the name of the moby object building processor and its ports, so we can create the data links in the caller
-    private String[] addMobyDataCreatorProcessor(MobyPrimaryData mobyData, Element processors, Document doc) 
-	throws Exception{
-	String dataType = null;
-	boolean primitiveDataType = false;
-	if(mobyData instanceof MobyPrimaryDataSet){
-	    dataType = "Collections - unimplemented";
-	}
-	else if(mobyData instanceof MobyPrimaryDataSimple){
-	    if(mobyData instanceof MobyDataComposite){
-		dataType = "Composite datatype - unimplemented";
-	    }
-	    // a Moby primitive
-	    else if(mobyData instanceof MobyDataString){
-		dataType = MobyTags.MOBYSTRING;
-		primitiveDataType = true;
-	    }
-	    else if(mobyData instanceof MobyDataBoolean){
-		dataType = MobyTags.MOBYBOOLEAN;
-		primitiveDataType = true;
-	    }
-	    else if(mobyData instanceof MobyDataDateTime){
-		dataType = MobyTags.MOBYDATETIME;
-		primitiveDataType = true;
-	    }
-	    else if(mobyData instanceof MobyDataFloat){
-		dataType = MobyTags.MOBYFLOAT;
-		primitiveDataType = true;
-	    }
-	    else if(mobyData instanceof MobyDataInt){
-		dataType = MobyTags.MOBYINTEGER;
-		primitiveDataType = true;
-	    }
-	    // base object or xref
-	    else{
-		MobyNamespace[] nss = ((MobyPrimaryDataSimple) mobyData).getNamespaces();
-		if(nss.length != 0){
-		    dataType = nss[0].getName()+"_ID";
-		}
-		else{
-		    dataType = "Object";
-		}
-	    }
-	}
-
-	String builderProcName = createUniqueName("Create_"+dataType+"s");
-	Element builderProcessor = doc.createElementNS(T2FLOW_NS, "processor");
-	processors.appendChild(builderProcessor);
-	builderProcessor.appendChild(createElWithText(doc, T2FLOW_NS, "name", builderProcName));
-
-	Element inputPorts = doc.createElementNS(T2FLOW_NS, "inputPorts");
-	builderProcessor.appendChild(inputPorts);
-	inputPorts.appendChild(createParamPort("id", "0", doc));
-	inputPorts.appendChild(createParamPort("namespace", "0", doc));
-	if(primitiveDataType){
-	    inputPorts.appendChild(createParamPort("value", "0", doc));
-	}
-
-	Element outputPorts = doc.createElementNS(T2FLOW_NS, "outputPorts");
-	builderProcessor.appendChild(outputPorts);
-	outputPorts.appendChild(createParamPort("mobyData", "0", "0", doc));
-
-	builderProcessor.appendChild(doc.createElementNS(T2FLOW_NS, "annotations"));
-
-	Element activities = doc.createElementNS(T2FLOW_NS, "activities");
-	builderProcessor.appendChild(activities);
-	Element activity = doc.createElementNS(T2FLOW_NS, "activity");
-	activities.appendChild(activity);
-	Element raven = doc.createElementNS(T2FLOW_NS, "raven");
-	raven.appendChild(createElWithText(doc, T2FLOW_NS, "group", "net.sf.taverna.t2.activities"));
-	raven.appendChild(createElWithText(doc, T2FLOW_NS, "artifact", "biomoby-activity"));
-	raven.appendChild(createElWithText(doc, T2FLOW_NS, "version", "1.0"));
-	activity.appendChild(raven);
-
-	activity.appendChild(createElWithText(doc, T2FLOW_NS, "class", 
-					      "net.sf.taverna.t2.activities.biomoby.BiomobyObjectActivity"));
-
-	Element inputMap = doc.createElementNS(T2FLOW_NS, "inputMap");
-	activity.appendChild(inputMap);
-	inputMap.appendChild(createMapFromTo("id", "id", doc));
-	inputMap.appendChild(createMapFromTo("namespace", "namespace", doc));	
-	if(primitiveDataType){
-	    inputMap.appendChild(createMapFromTo("value", "value", doc));
-	}
-	Element outputMap = doc.createElementNS(T2FLOW_NS, "outputMap");
-	activity.appendChild(outputMap);
-	outputMap.appendChild(createMapFromTo("mobyData", "mobyData", doc));
-	
-	Element configBean = doc.createElementNS(T2FLOW_NS, "configBean");
-	configBean.setAttribute("encoding", "xstream");
-	activity.appendChild(configBean);
-	Element BuildActivityConfigurationBean = 
-	    doc.createElementNS("", 
-				"net.sf.taverna.t2.activities.biomoby.BiomobyObjectActivityConfigurationBean");
-	configBean.appendChild(BuildActivityConfigurationBean);
-	BuildActivityConfigurationBean.appendChild(createElWithText(doc, "", "mobyEndpoint", 
-								    getCentralEndpointFromMobyData(mobyData)));
-	BuildActivityConfigurationBean.appendChild(createElWithText(doc, "", "serviceName", 
-								    mobyData.getDataType().getName()));
-	BuildActivityConfigurationBean.appendChild(doc.createElementNS("", "authorityName"));
-	
-	activity.appendChild(doc.createElementNS(T2FLOW_NS, "annotations"));
-
-	builderProcessor.appendChild(getDispatchStack(doc));
-
-	Element iterationStrategyStack = doc.createElementNS(T2FLOW_NS, "iterationStrategyStack");
-	builderProcessor.appendChild(iterationStrategyStack);
-	Element iteration = doc.createElementNS(T2FLOW_NS, "iteration");
-	iterationStrategyStack.appendChild(iteration);
-	Element strategy = doc.createElementNS(T2FLOW_NS, "strategy");
-	iteration.appendChild(strategy);
-	Element dot = doc.createElementNS(T2FLOW_NS, "dot");
-	strategy.appendChild(dot);
-
-	Element port = doc.createElementNS(T2FLOW_NS, "port");
-	dot.appendChild(port);
-	port.setAttribute("depth", "0");
-	port.setAttribute("name", "id");
-	port = doc.createElementNS(T2FLOW_NS, "port");
-	dot.appendChild(port);
-	port.setAttribute("depth", "0");
-	port.setAttribute("name", "namespace");
-	if(primitiveDataType){
-	    port = doc.createElementNS(T2FLOW_NS, "port");
-	    dot.appendChild(port);
-	    port.setAttribute("depth", "0");
-	    port.setAttribute("name", "value");
-	    return new String[]{builderProcName, "id", "namespace", "value", "mobyData"};
-	}
-	else{
-	    return new String[]{builderProcName, "id", "namespace", "mobyData"};
-	}
-    }
-
-   private String[] addListFlattenBeanShell(Element processors, Document doc) 
+    
+    private String[] addListFlattenBeanShell(Element processors, Document doc) 
 	throws Exception{
 	String beanShellProcName = createUniqueName("Create_Pass_Fail_List");
 	
@@ -1434,13 +1489,52 @@
 	inputTypes.put("inputlist", "text/plain");
 	Map<String,String> outputsMap = new LinkedHashMap<String,String>();
 	outputsMap.put("outputlist", "1");
-
+	
 	return addBeanShell(beanShellProcName, "dot",
 			    inputsMap, inputTypes, outputsMap, 
 			    getListFlattenScript(), new String[]{}, 
 			    processors, doc);	
     }    
+    
+    private String[] addFileSelectionBeanShell(Element processors, Document doc) 
+	throws Exception{
+	String beanShellProcName = createUniqueName("Select_Files");
+	
+	// Now do all the param-specific stuff below (inserts into various parts of the elements defined above)
+	Map<String,String> inputsMap = new LinkedHashMap<String,String>();  
+	// linked because order is important to line up port connections
+	Map<String,String> inputTypes = new LinkedHashMap<String,String>();
+	inputsMap.put("title", "0");
+	inputTypes.put("title", "text/plain");
+	Map<String,String> outputsMap = new LinkedHashMap<String,String>();
+	outputsMap.put("selectedFiles", "1");
+
+	return addBeanShell(beanShellProcName, "cross",
+			    inputsMap, inputTypes, outputsMap, 
+			    getFileSelectionScript(), new String[]{}, 
+			    processors, doc);	
+    }    
 
+   private String[] addBinaryFileReaderBeanShell(Element processors, Document doc) 
+	throws Exception{
+	String beanShellProcName = createUniqueName("Load_Binary_File");
+	
+	// Now do all the param-specific stuff below (inserts into various parts of the elements defined above)
+	Map<String,String> inputsMap = new LinkedHashMap<String,String>();  
+	// linked because order is important to line up port connections
+	Map<String,String> inputTypes = new LinkedHashMap<String,String>();
+	inputsMap.put("articleName", "0");
+	inputTypes.put("articleName", "text/plain");
+	inputsMap.put("absoluteFilePath", "0");
+	inputTypes.put("absoluteFilePath", "text/plain");
+	Map<String,String> outputsMap = new LinkedHashMap<String,String>();
+	outputsMap.put("encodedString", "0");
+
+	return addBeanShell(beanShellProcName, "cross",
+			    inputsMap, inputTypes, outputsMap, 
+			    getBinaryFileReaderScript(), new String[]{}, 
+			    processors, doc);	
+    }    
     private String[] addPassFilterBeanShell(Element processors, Document doc) 
 	throws Exception{
 	String beanShellProcName = createUniqueName("IfPassesContentFilter");
@@ -1667,7 +1761,7 @@
 
     private Element createWorkflowInputLinkElement(String inputName, String processorName,
 						   String processorParamPortName, 
-						   MobyPrimaryData sampleData, Document doc){
+						   Document doc){
 	Element datalink = doc.createElementNS(T2FLOW_NS, "datalink");
 
 	Element sink = doc.createElementNS(T2FLOW_NS, "sink");
@@ -1770,6 +1864,25 @@
 	return preferredName;
     }
 
+    // same as next function, but takes service data type into account (e.g. if data is DNASequence, but
+    // equivalent service param is GenericSequence, use GenericSequence)
+    private String getPortName(MobyPrimaryData data, MobyService service, boolean asCollection){
+        String dataName = data.getName();
+        for(MobyPrimaryData param: service.getPrimaryInputs()){
+            if(param.getName().equals(dataName)){
+                if(!param.getDataType().getName().equals(data.getDataType().getName())){
+                    MobyPrimaryData superTypedData = ((data instanceof MobyPrimaryDataSet) ? (new MobyPrimaryDataSet(dataName)) : (new MobyPrimaryDataSimple(dataName)));
+                    superTypedData.setDataType(param.getDataType());
+                    return getPortName(superTypedData, asCollection);
+                }
+                else{
+                    break;
+                }
+            }
+        }
+        return getPortName(data, asCollection);
+    }
+
     // dataType(articleName) as required by the Taverna Moby plugin
     private String getPortName(MobyPrimaryData data, boolean asCollection){
 	if(data instanceof MobyPrimaryDataSet){
@@ -1786,22 +1899,20 @@
     }
 
     // A useful human-legible name for a workflow input
-    private String getInputName(MobyPrimaryData data){
-	String dataType = data.getDataType().getName();
-	if(dataType.equals(MobyTags.MOBYOBJECT)){	    
-	    MobyNamespace[] namespaces = data.getNamespaces();
-	    if(namespaces.length == 0){
-		return "FileOf"+dataType+"-"+data.getName()+"-IDs";
+    private String getInputName(MobyDataType dataType, MobyNamespace ns){
+	if(dataType.getName().equals(MobyTags.MOBYOBJECT)){
+	    if(ns == null){
+		return "FileOfObjects"; //????
 	    }
 	    else{
 		// Note: we could concatenate all allowed namespaces, but the service wouldn't 
 		// necessarily return the same results for all input namespaces, so we'll be
 		// safe and stick to the primary one.
-		return "FileOf"+namespaces[0].getName()+"-"+data.getName()+"IDs";
+		return "FileOf"+ns.getName()+"-IDs";
 	    }
 	}
 	else{
-	    return dataType+"-"+data.getName();
+	    return "FileOf"+dataType.getName()+"-fields";
 	}
     }
 
@@ -1993,6 +2104,28 @@
 	return listFlattenScript;
     }
 
+    private synchronized String getBinaryFileReaderScript() throws Exception{
+	if(readBinaryFileScript == null){
+	    URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_READBINARYFILE_BEANSHELL);
+	    if(scriptURL == null){
+		throw new Exception("Cannot find resource " + T2FLOW_READBINARYFILE_BEANSHELL);
+	    }
+	    readBinaryFileScript = HTMLUtils.getURLContents(scriptURL);
+	}
+	return readBinaryFileScript;
+    }
+
+    private synchronized String getFileSelectionScript() throws Exception{
+	if(fileSelectionScript == null){
+	    URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_SELECTFILES_BEANSHELL);
+	    if(scriptURL == null){
+		throw new Exception("Cannot find resource " + T2FLOW_SELECTFILES_BEANSHELL);
+	    }
+	    fileSelectionScript = HTMLUtils.getURLContents(scriptURL);
+	}
+	return fileSelectionScript;
+    }
+
     private synchronized String getPassFilterScript() throws Exception{
 	if(passFilterScript == null){
 	    URL scriptURL = getClass().getClassLoader().getResource(T2FLOW_PASSFILTER_BEANSHELL);




More information about the MOBY-guts mailing list