All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.taverna.examples.WorkflowMaker Maven / Gradle / Ivy

The newest version!
package org.apache.taverna.examples;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


import java.io.File;
import java.io.IOException;
import java.net.URI;

import org.apache.taverna.scufl2.api.activity.Activity;
import org.apache.taverna.scufl2.api.common.Scufl2Tools;
import org.apache.taverna.scufl2.api.configurations.Configuration;
import org.apache.taverna.scufl2.api.container.WorkflowBundle;
import org.apache.taverna.scufl2.api.core.DataLink;
import org.apache.taverna.scufl2.api.core.Processor;
import org.apache.taverna.scufl2.api.core.Workflow;
import org.apache.taverna.scufl2.api.io.ReaderException;
import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
import org.apache.taverna.scufl2.api.io.WriterException;
import org.apache.taverna.scufl2.api.iterationstrategy.DotProduct;
import org.apache.taverna.scufl2.api.iterationstrategy.PortNode;
import org.apache.taverna.scufl2.api.port.InputActivityPort;
import org.apache.taverna.scufl2.api.port.InputProcessorPort;
import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
import org.apache.taverna.scufl2.api.port.OutputActivityPort;
import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
import org.apache.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
import org.apache.taverna.scufl2.api.profiles.ProcessorOutputPortBinding;
import org.apache.taverna.scufl2.api.profiles.Profile;

public class WorkflowMaker {
	private static Scufl2Tools scufl2Tools = new Scufl2Tools();
	private static WorkflowBundleIO bundleIO = new WorkflowBundleIO();

	public static void main(String[] args) throws Exception {
		new WorkflowMaker().makeWorkflowBundle();
	}

	protected WorkflowBundle bundle;
	protected Workflow workflow;
	protected Processor p;
	protected InputProcessorPort pIn;
	protected OutputProcessorPort pOut;
	protected Profile profile;
	protected Activity myBeanshell;
	protected File file;

	
	public void makeWorkflowBundle() throws IOException, WriterException,
			ReaderException {

		/** Top-level object is a Workflow Bundle */
		bundle = new WorkflowBundle();

		/** Generate the workflow structure **/
		makeWorkflow();
		
		/** Specify the implementations **/
		makeProfile();

		/**
		 * Before storing the workflow bundle, we'll make sure that everything
		 * we made has a parent included (so that for instance a configuration
		 * is stored together with its parent profile). The
		 * scufl2Tools.setParents method will traverse the WorkflowBundle from
		 * the top and fill in any blank parents.
		 */
		scufl2Tools.setParents(bundle);

		/** Write bundle to StdOut and a new file */
		writeBundleToFile();

	}


	private void makeWorkflow() {
		workflow = new Workflow();
		/** Workflow names must be unique within the WorkflowBundle */
		workflow.setName("Echotest");
	
		bundle.setMainWorkflow(workflow);
		/**
		 * Additional (typically nested) workflows can be added:
		 * 
		 * 
		 * bundle.getWorkflows().add(workflow2)
		 * 
* * but the above is implied by setMainWorkflow() */ /** Creating and adding a workflow port */ InputWorkflowPort in1 = new InputWorkflowPort(); in1.setName("in1"); in1.setDepth(0); /** where does this input port belong? */ in1.setParent(workflow); /** * implies: * *
		 * workflow.getInputPorts().add(in1);
		 * 
*/ /** * If input should be a list instead of single value: * *
		 * in1.setDepth(1);
		 * 
*/ /** Output, this time using the shorthand constructors */ OutputWorkflowPort out1 = new OutputWorkflowPort(workflow, "out1"); /** * A processor is a unit which performs some work in a workflow. The * name must be unique within the parent workflow. * */ p = new Processor(workflow, "p"); /** * Same as: * *
		 * Processor p = new Processor();
		 * p.setName("p");
		 * p.setParent(workflow);
		 * workflow.getProcessors().add(p);
		 * 
*/ /** * Processors typically have inputs and outputs which are connected * within the workflow */ pIn = new InputProcessorPort(p, "pIn"); pIn.setDepth(0); pOut = new OutputProcessorPort(p, "pOut"); pOut.setDepth(0); pOut.setGranularDepth(0); /** * .. any additional ports must have a unique name within the input or * output ports of that processor. */ /** * Defining a data link from the workflow input port 'in1' to the * processor input port 'pIn' - this means that data will flow from * 'in1' to 'pIn'. */ DataLink link = new DataLink(); link.setReceivesFrom(in1); link.setSendsTo(pIn); /** * The ports must be either processor or workflow ports, and both of the * same workflow as the datalink is added to: */ workflow.getDataLinks().add(link); /** * Or more compact style: pOut -> out1 .. connecting processor output * port 'pOut' to the workflow output port 'out1' */ new DataLink(workflow, pOut, out1); /** * the constructor will perform for us: * *
		 * setParent(workflow)
		 * 		workflow.getDataLinks().add(workflow)
		 * 
*/ /** * Note: As datalinks are unique based on the connection, they don't * have names */ /** * Not covered by this example: * * Dispatch stack: * *
		 * DispatchStackLayer dispatchStackLayer = new DispatchStackLayer();
		 * dispatchStackLayer
		 * 		.setConfigurableType(URI
		 * 				.create("http://ns.taverna.org.uk/2010/scufl2/taverna/dispatchlayer/Retry"));
		 * p.getDispatchStack().add(dispatchStackLayer);
		 * Configuration retryConfig = new Configuration();
		 * retryConfig.setConfigures(dispatchStackLayer);
		 * // ..
		 * 
*/ /* * Iteration strategies: */ DotProduct dot = new DotProduct(); PortNode e = new PortNode(dot, pIn); e.setDesiredDepth(0); p.getIterationStrategyStack().add(dot); } private void makeProfile() { profile = new Profile("default"); /** * One profile can be suggest as the 'main' profile - but alternative * execution profiles can also be added, for instance to provide * Grid-based activities rather than Web Service activities - each of * them must have a unique name within the profiles of the workflow * bundle. */ bundle.setMainProfile(profile); /** * Additional profiles can be added with: * *
		 * bundle.getProfiles().add(profile2);
		 * 
*/ myBeanshell = new Activity("myBeanshell"); /** * Activities are of different types, identified by an URI. A workflow * engine will typically expose which activity types it supports. *

* The default types of Taverna have the prefix * http://ns.taverna.org.uk/2010/activity/, but other plugins will have * different URI bases. */ URI BEANSHELL = URI .create("http://ns.taverna.org.uk/2010/activity/beanshell"); myBeanshell.setType(BEANSHELL); /** * Activities are activated within a particular profile (Therefore * execution of a profile requires the engine to support all types of * all activities of the profile) */ profile.getActivities().add(myBeanshell); makeConfiguration(); /** * A Processor Binding connects a Processor ('p') with an Activity * 'myBeanshell'. This means that execution of p will use the activity. */ ProcessorBinding binding = new ProcessorBinding(); binding.setBoundProcessor(p); binding.setBoundActivity(myBeanshell); /** * It is possible, but not common, for multiple processor bindings to * reuse the same activity. On execution, the workflow engine might or * might not instantiate this as the same activity implementation. */ /** And add binding to the profile */ binding.setParent(profile); /** * alternatively: * *

		 * profile.getProcessorBindings().add(binding)
		 * 
*/ /** * It is possible to bind more than one activity for the same processor, * in which case they will be used as alternate services on failure. (As * the default Dispatch Stack contains the Failover layer). In this * case, the processor bindings should specify the 'activity position', * which determines the ordering of activities within a processor: * *
		 * binding.setActivityPosition(15);
		 * 
*/ /** * Activities have input and output ports as well, normally these match * one-to-one with the bound processor's port names and depth. */ InputActivityPort aIn1 = new InputActivityPort(myBeanshell, "in1"); aIn1.setDepth(0); myBeanshell.getInputPorts().add(aIn1); OutputActivityPort aOut1 = new OutputActivityPort(myBeanshell, "out1"); aOut1.setDepth(0); aOut1.setGranularDepth(0); myBeanshell.getOutputPorts().add(aOut1); /** * But in case the activities don't match up (such as when multiple * activities are bound to the same processor, or as in this example * where the port matches the script), a port mapping must be specified * in the processor binding: */ binding.getInputPortBindings().add( new ProcessorInputPortBinding(binding, pIn, aIn1)); new ProcessorOutputPortBinding(binding, aOut1, pOut); /** * It is not required to bind any processor input port, but many * activities expect some or all their inputs bound. It is not required * to bind all activity output ports, but all processor output ports * must be bound for each processor binding. */ /** If the port names match up, the above can all be done in one go with */ //scufl2Tools.bindActivityToProcessorByMatchingPorts(myBeanshell, p); } private void makeConfiguration() { URI BEANSHELL = URI .create("http://ns.taverna.org.uk/2010/activity/beanshell"); /** * Most activities also require a configuration in order to run. The * name of the configuration is not important, but must be unique within * the configurations of a profile. The default constructor * Configuration() generates a UUID-based name as a fallback. */ Configuration beanshellConfig = new Configuration("beanshellConf"); /** * The activity we configure. (DispatchStackLayer can also be * configured) */ beanshellConfig.setConfigures(myBeanshell); /** * A configuration is of a specified type (specified as an URI), which * is typically related to (but different from) the activity type - but * might in some cases be shared amongst several activity types. */ beanshellConfig.setType(BEANSHELL.resolve("#Config")); /** * Configurations are normally shared in the same profile as the * activity they configure (the parent) - but in some cases might also * be added by other profiles in order to reuse a configuration across * profiles. (Note: A profile is *stored* within its parent profile). */ beanshellConfig.setParent(profile); profile.getConfigurations().add(beanshellConfig); /** * Depending on the configuration type specified above, certain * *properties* should be specified, and other properties might be * optional. In this case, only "script" is * specified, as a string value. (more complex properties can be * specified using Jackson JSON methods of the ObjectNode) */ beanshellConfig.getJsonAsObjectNode().put("script", "out1 = in1"); /** * Note that property names are specified as URIs, which are often * related to the URI of the configuration type - but might be reused * across several configuration types. */ } private void writeBundleToFile() throws IOException, WriterException, ReaderException { file = File.createTempFile("test", ".wfbundle"); /** * Bundle IO */ bundleIO.writeBundle(bundle, file, "application/vnd.taverna.scufl2.workflow-bundle"); System.out.println("Written to " + file + "\n"); // Read it back in WorkflowBundle secondBundle = bundleIO.readBundle(file, "application/vnd.taverna.scufl2.workflow-bundle"); // Write in a debug text format bundleIO.writeBundle(secondBundle, System.out, "text/vnd.taverna.scufl2.structure"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy