You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by re...@apache.org on 2015/03/23 17:37:57 UTC

[13/51] [partial] incubator-taverna-engine git commit:

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/HealthCheck.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/HealthCheck.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/HealthCheck.java
new file mode 100644
index 0000000..4bffc3d
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/HealthCheck.java
@@ -0,0 +1,84 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.health;
+
+import org.apache.taverna.visit.VisitKind;
+import org.apache.taverna.visit.Visitor;
+
+/**
+ * A HealthCheck is a kind of visit that determines if the corresponding object
+ * in a workflow (normally an Activity) will work during a workflow run.
+ * 
+ * @author alanrw
+ * 
+ */
+public class HealthCheck extends VisitKind {
+	/*
+	 * The following values indicate the type of results that can be associated
+	 * with a VisitReport generated by a health-checking visitor.
+	 */
+
+	public static final int NO_PROBLEM = 0;
+	public static final int NOT_IMPLEMENTED = 1;
+	public static final int CONNECTION_PROBLEM = 2;
+	public static final int INVALID_URL = 3;
+	public static final int TIME_OUT = 4;
+	public static final int IO_PROBLEM = 5;
+	public static final int MISSING_CLASS = 6;
+	public static final int MISSING_DEPENDENCY = 7;
+	public static final int INVALID_SCRIPT = 8;
+	public static final int NO_CONFIGURATION = 9;
+	public static final int NULL_VALUE = 10;
+	public static final int DEFAULT_VALUE = 11;
+	public static final int BAD_WSDL = 12;
+	public static final int NOT_HTTP = 13;
+	public static final int UNSUPPORTED_STYLE = 14;
+	public static final int UNKNOWN_OPERATION = 15;
+	public static final int NO_ENDPOINTS = 16;
+	public static final int INVALID_CONFIGURATION = 17;
+	public static final int NULL_DATATYPE = 18;
+	public static final int DISABLED = 19;
+	public static final int DATATYPE_SOURCE = 20;
+	public static final int UNRECOGNIZED = 21;
+    public static final int LOOP_CONNECTION = 22;
+    public static final int UNMANAGED_LOCATION = 23;
+    public static final int INCOMPATIBLE_MIMETYPES = 24;
+    public static final int HIGH_PORT_DEPTH = 25;
+
+    @SuppressWarnings("rawtypes")
+	private static final Class healthCheckerClass = HealthChecker.class;
+
+    /**
+	 * Sub-classes of HealthChecker are used to perform HealthCheck visits.
+	 */
+	@Override
+	@SuppressWarnings("unchecked")
+	public Class<? extends Visitor<?>> getVisitorClass() {
+		return healthCheckerClass;
+	}
+
+	private static class Singleton {
+		private static HealthCheck instance = new HealthCheck();
+	}
+
+	public static HealthCheck getInstance() {
+		return Singleton.instance;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/HealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/HealthChecker.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/HealthChecker.java
new file mode 100644
index 0000000..618c06b
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/HealthChecker.java
@@ -0,0 +1,36 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.health;
+
+import org.apache.taverna.visit.Visitor;
+
+/**
+ * An SPI interface whose implementation performs a health check on an arbitrary
+ * instance.
+ * 
+ * @author Stuart Owen
+ * @author David Withers
+ * 
+ * @param <Type>
+ *            the type of the item being checked
+ */
+public interface HealthChecker<T> extends Visitor<T> {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/RemoteHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/RemoteHealthChecker.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/RemoteHealthChecker.java
new file mode 100644
index 0000000..94504c6
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/RemoteHealthChecker.java
@@ -0,0 +1,236 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.health;
+
+import static java.lang.System.currentTimeMillis;
+import static java.net.HttpURLConnection.HTTP_GONE;
+import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.apache.taverna.visit.VisitReport.Status.SEVERE;
+import static org.apache.taverna.visit.VisitReport.Status.WARNING;
+import static org.apache.taverna.workflowmodel.health.HealthCheck.CONNECTION_PROBLEM;
+import static org.apache.taverna.workflowmodel.health.HealthCheck.INVALID_URL;
+import static org.apache.taverna.workflowmodel.health.HealthCheck.IO_PROBLEM;
+import static org.apache.taverna.workflowmodel.health.HealthCheck.NOT_HTTP;
+import static org.apache.taverna.workflowmodel.health.HealthCheck.NO_PROBLEM;
+import static org.apache.taverna.workflowmodel.health.HealthCheck.TIME_OUT;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.net.ssl.SSLException;
+
+import org.apache.taverna.visit.VisitReport;
+import org.apache.taverna.visit.VisitReport.Status;
+import org.apache.taverna.workflowmodel.processor.activity.Activity;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A RemoteHealthChecker performs a visit to an Activity by trying to contact a
+ * specific endpoint
+ * 
+ * @author alanrw
+ */
+public abstract class RemoteHealthChecker implements HealthChecker<Object> {
+	public static final long ENDPOINT_EXPIRY_MILLIS = 30 * 1000; // 30 seconds
+	private static final Logger logger = Logger.getLogger(RemoteHealthChecker.class);
+	private static int timeout = 10000; // TODO Manage via bean?
+	private static long endpointExpiryMillis = ENDPOINT_EXPIRY_MILLIS;
+
+	public static int getTimeoutInSeconds() {
+		return timeout / 1000;
+	}
+
+	public static void setTimeoutInSeconds(int timeout) {
+		RemoteHealthChecker.timeout = timeout * 1000;
+	}
+
+	public static long getEndpointExpiryInMilliseconds() {
+		return endpointExpiryMillis;
+	}
+
+	public static void setEndpointExpiryInMilliseconds(int endpointExpiry) {
+		endpointExpiryMillis = endpointExpiry;
+	}
+
+	/**
+	 * Clear the cached endpoint statuses. Normally {@link RemoteHealthChecker}
+	 * will only check an endpoint again if it has been more than
+	 * {@link #getEndpointExpiryInMilliseconds()} milliseconds since last check,
+	 * by default 30 seconds.
+	 */
+	public static void clearCachedEndpointStatus() {
+		visitReportsByEndpoint.clear();
+	}
+
+	private static Map<String, WeakReference<VisitReport>> visitReportsByEndpoint = new ConcurrentHashMap<>();
+
+	/**
+	 * Try to contact the specified endpoint as part of the health-checking of
+	 * the Activity.
+	 * 
+	 * @param activity
+	 *            The activity that is being checked
+	 * @param endpoint
+	 *            The String corresponding to the URL of the endpoint
+	 * 
+	 * @return
+	 */
+	public static VisitReport contactEndpoint(Activity<?> activity,
+			String endpoint) {
+		WeakReference<VisitReport> cachedReportRef = visitReportsByEndpoint
+				.get(endpoint);
+		VisitReport cachedReport = null;
+		if (cachedReportRef != null)
+			cachedReport = cachedReportRef.get();
+		if (cachedReport != null) {
+			long now = currentTimeMillis();
+			long age = now - cachedReport.getCheckTime();
+			if (age < getEndpointExpiryInMilliseconds()) {
+				VisitReport newReport;
+				try {
+					// Make a copy
+					newReport = cachedReport.clone();
+					// But changed the subject
+					newReport.setSubject(activity);
+					logger.info("Returning cached report for endpoint "
+							+ endpoint + ": " + newReport);
+					return newReport;
+				} catch (CloneNotSupportedException e) {
+					logger.warn("Could not clone VisitReport " + cachedReport,
+							e);
+				}
+			}
+		}
+		
+		Status status = Status.OK;
+		String message = "Responded OK";
+		int resultId = NO_PROBLEM;
+		URLConnection connection = null;
+		int responseCode = HTTP_OK;
+		Exception ex = null;
+		try {
+			URL url = new URL(endpoint);
+			connection = url.openConnection();
+			connection.setReadTimeout(timeout);
+			connection.setConnectTimeout(timeout);
+			if (connection instanceof HttpURLConnection) {
+				HttpURLConnection httpConnection = (HttpURLConnection) connection;
+				httpConnection.setRequestMethod("HEAD");
+				httpConnection.connect();
+				responseCode = httpConnection.getResponseCode();
+				if (responseCode != HTTP_OK) {
+					try {
+						if ((connection != null)
+								&& (connection.getInputStream() != null))
+							connection.getInputStream().close();
+					} catch (IOException e) {
+						logger.info(
+								"Unable to close connection to " + endpoint, e);
+					}
+					connection = url.openConnection();
+					connection.setReadTimeout(timeout);
+					connection.setConnectTimeout(timeout);
+					httpConnection = (HttpURLConnection) connection;
+					httpConnection.setRequestMethod("GET");
+					httpConnection.connect();
+					responseCode = httpConnection.getResponseCode();
+				}
+				if (responseCode != HTTP_OK) {
+					if ((responseCode > HTTP_INTERNAL_ERROR)) {
+						status = WARNING;
+						message = "Unexpected response";
+						resultId = CONNECTION_PROBLEM;
+					} else if ((responseCode == HTTP_NOT_FOUND)
+							|| (responseCode == HTTP_GONE)) {
+						status = WARNING;
+						message = "Bad response";
+						resultId = CONNECTION_PROBLEM;
+					}
+				}
+			} else {
+			    connection.connect();
+				status = WARNING;
+				message = "Not HTTP";
+				resultId = NOT_HTTP;
+			}
+		} catch (MalformedURLException e) {
+			status = SEVERE;
+			message = "Invalid URL";
+			resultId = INVALID_URL;
+			ex = e;
+		} catch (SocketTimeoutException e) {
+			status = SEVERE;
+			message = "Timed out";
+			resultId = TIME_OUT;
+			ex = e;
+		} catch (SSLException e){
+			// Some kind of error when trying to establish an HTTPS connection to the endpoint
+			status = SEVERE;
+			message = "HTTPS connection problem";
+			resultId = IO_PROBLEM; // SSLException is an IOException
+			ex = e;
+		} catch (IOException e) {
+			status = SEVERE;
+			message = "Read problem";
+			resultId = IO_PROBLEM;
+			ex = e;
+		} finally {
+			try {
+				if ((connection != null)
+						&& (connection.getInputStream() != null))
+					connection.getInputStream().close();
+			} catch (IOException e) {
+				logger.info("Unable to close connection to " + endpoint, e);
+			}
+		}
+		
+		VisitReport vr = new VisitReport(HealthCheck.getInstance(), activity, message,
+				resultId, status);
+		vr.setProperty("endpoint", endpoint);
+		if (ex != null)
+		    vr.setProperty("exception", ex);
+		if (responseCode != HTTP_OK)
+			vr.setProperty("responseCode", Integer.toString(responseCode));
+		if (resultId == TIME_OUT)
+			vr.setProperty("timeOut", Integer.toString(timeout));
+		visitReportsByEndpoint.put(endpoint, new WeakReference<>(vr));
+		return vr;
+	}
+
+	/**
+	 * A remote health-check is time consuming as it tries to contact an
+	 * external resource.
+	 */
+	@Override
+	public boolean isTimeConsuming() {
+		return true;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/UnrecognizedActivityHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/UnrecognizedActivityHealthChecker.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/UnrecognizedActivityHealthChecker.java
new file mode 100644
index 0000000..3232eb6
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/UnrecognizedActivityHealthChecker.java
@@ -0,0 +1,64 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.health;
+
+import static org.apache.taverna.visit.VisitReport.Status.SEVERE;
+import static org.apache.taverna.workflowmodel.health.HealthCheck.UNRECOGNIZED;
+
+import java.util.List;
+
+import org.apache.taverna.visit.VisitReport;
+import org.apache.taverna.workflowmodel.processor.activity.UnrecognizedActivity;
+
+/**
+ * Check on the health of a UnrecognizedActivity
+ * 
+ * @author alanrw
+ * 
+ */
+public class UnrecognizedActivityHealthChecker implements
+		HealthChecker<UnrecognizedActivity> {
+
+	/**
+	 * The visitor can visit {@link UnrecognizedActivity}s.
+	 */
+	@Override
+	public boolean canVisit(Object o) {
+		return ((o != null) && (o instanceof UnrecognizedActivity));
+	}
+
+	/**
+	 * The check is not time consuming as it simply constructs a VisitReport
+	 */
+	@Override
+	public boolean isTimeConsuming() {
+		return false;
+	}
+
+	/**
+	 * The result of the visit is simply a VisitReport to state that the service
+	 * is not available.
+	 */
+	@Override
+	public VisitReport visit(UnrecognizedActivity o, List<Object> ancestry) {
+		return new VisitReport(HealthCheck.getInstance(), o,
+				"Service is unrecognized", UNRECOGNIZED, SEVERE);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/package.html
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/package.html b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/package.html
new file mode 100644
index 0000000..6cbc3b5
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/health/package.html
@@ -0,0 +1,6 @@
+<body>
+
+A package that contains a set of classes to be used in testing a Dataflow prior to invocation.<br>
+These can carry our various tests such as a service endpoint being accessible. HealthChecker provides an
+SPI extension point to allow 3rd party developers to implement their own Activity checkers.
+</body>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/package.html
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/package.html b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/package.html
new file mode 100644
index 0000000..abaa693
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/package.html
@@ -0,0 +1,3 @@
+<body>
+Defines classes and interfaces for workflow level entities and events.
+</body>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AbstractActivity.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AbstractActivity.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AbstractActivity.java
new file mode 100644
index 0000000..a3fc2d7
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AbstractActivity.java
@@ -0,0 +1,263 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.taverna.annotation.AbstractAnnotatedThing;
+import org.apache.taverna.annotation.annotationbeans.MimeType;
+import org.apache.taverna.reference.ExternalReferenceSPI;
+import org.apache.taverna.workflowmodel.EditException;
+import org.apache.taverna.workflowmodel.Edits;
+import org.apache.taverna.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean;
+import org.apache.taverna.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean;
+import org.apache.taverna.workflowmodel.processor.activity.config.ActivityPortsDefinitionBean;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Convenience abstract superclass for generic Activity instances. Parameterised
+ * on the configuration type used by the Activity implementation - when this
+ * object is serialised the getConfiguration method is used to store specific
+ * details of the activity, this is then used immediately after a call to the
+ * default constructor when deserialising from XML on a workflow load.
+ * <p>
+ * This class holds port sets and mappings, and returns references directly to
+ * them rather than copies thereof.
+ * <p>
+ * If you're writing an abstract activity (one that cannot be directly invoked)
+ * you should extend this class for convenience. This can be useful when you
+ * wish to specify some kind of abstract definition of a process which will be
+ * bound at workflow invocation time to a particular concrete activity through
+ * the action of a custom dispatch stack layer (which you will also provide)
+ *
+ * @author Tom Oinn
+ * @author Stuart Owen
+ *
+ * @param <ConfigType>
+ *            type of configuration object to be used to hold configuration
+ *            information
+ */
+public abstract class AbstractActivity<ConfigType> extends
+		AbstractAnnotatedThing<Activity<?>> implements Activity<ConfigType> {
+	private static Logger logger = Logger.getLogger(AbstractActivity.class);
+
+	private Edits edits;
+
+	protected Map<String, String> inputPortMapping = new HashMap<>();
+	protected Map<String, String> outputPortMapping = new HashMap<>();
+	protected Set<ActivityOutputPort> outputPorts = new HashSet<>();
+	protected Set<ActivityInputPort> inputPorts = new HashSet<>();
+
+	@Override
+	public void setEdits(Edits edits) {
+		if (edits == null)
+			throw new IllegalArgumentException("Edits can not be null.");
+		this.edits = edits;
+	}
+
+	/**
+	 * @return the edits
+	 */
+	public Edits getEdits() {
+		if (edits == null)
+			throw new IllegalStateException(
+					"Unable to run this meathod until setEdits has been called");
+		return edits;
+	}
+
+	/**
+	 * @see org.apache.taverna.workflowmodel.processor.activity.Activity#configure(java.lang.Object)
+	 */
+	@Override
+	public abstract void configure(ConfigType conf)
+			throws ActivityConfigurationException;
+
+	/**
+	 * @see org.apache.taverna.workflowmodel.processor.activity.Activity#getConfiguration()
+	 */
+	@Override
+	public abstract ConfigType getConfiguration();
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.apache.taverna.workflowmodel.processor.activity.Activity#getInputPortMapping()
+	 */
+	@Override
+	public final Map<String, String> getInputPortMapping() {
+		return this.inputPortMapping;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.apache.taverna.workflowmodel.processor.activity.Activity#getInputPorts()
+	 */
+	@Override
+	public final Set<ActivityInputPort> getInputPorts() {
+		return inputPorts;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.apache.taverna.workflowmodel.processor.activity.Activity#getOutputPortMapping()
+	 */
+	@Override
+	public final Map<String, String> getOutputPortMapping() {
+		return this.outputPortMapping;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.apache.taverna.workflowmodel.processor.activity.Activity#getOutputPorts()
+	 */
+	@Override
+	public final Set<ActivityOutputPort> getOutputPorts() {
+		return outputPorts;
+	}
+
+	/**
+	 * Creates and adds a new input port with the provided properties.
+	 *
+	 * @see #removeInputs()
+	 * @param portName -
+	 *            the name of the port to be created.
+	 * @param portDepth -
+	 *            the depth of the port to be created.
+	 */
+	protected void addInput(
+			String portName,
+			int portDepth,
+			boolean allowsLiteralValues,
+			List<Class<? extends ExternalReferenceSPI>> handledReferenceSchemes,
+			Class<?> translatedElementClass) {
+		if (handledReferenceSchemes == null)
+			handledReferenceSchemes = Collections.emptyList();
+		inputPorts.add(getEdits().createActivityInputPort(portName, portDepth,
+				allowsLiteralValues, handledReferenceSchemes,
+				translatedElementClass));
+	}
+
+	/**
+	 * Creates and adds a new output port with the provided properties.
+	 *
+	 * @see #removeOutputs()
+	 * @param portName -
+	 *            the name of the port to be created.
+	 * @param portDepth -
+	 *            the depth of the port to be created
+	 * @param granularDepth -
+	 *            the granular depth of the port to be created
+	 * @param mimeTypes -
+	 *            a List of String representations of the MIME type this port
+	 *            will emit as outputs.
+	 */
+	protected void addOutput(String portName, int portDepth, int granularDepth) {
+		outputPorts.add(getEdits().createActivityOutputPort(
+				portName, portDepth, granularDepth));
+	}
+
+	/**
+	 * Convenience method, creates a new output port with depth and granular
+	 * depth both set to the value for depth, i.e. no streaming behaviour.
+	 * <p>
+	 *
+	 * @see #removeOutputs()
+	 * @param portName
+	 * @param portDepth
+	 */
+	protected void addOutput(String portName, int portDepth) {
+		addOutput(portName, portDepth, portDepth);
+	}
+
+	/**
+	 * <p>
+	 * Simplifies configuring the Activity input and output ports if its
+	 * ConfigType is an implementation of {@link ActivityPortsDefinitionBean}
+	 * </p>
+	 * <p>
+	 * For an Activity that has ports that are defined dynamically it is natural
+	 * that is ConfigType will not implement this interface.
+	 * </p>
+	 *
+	 * @param configBean
+	 */
+	protected void configurePorts(ActivityPortsDefinitionBean configBean) {
+		removeInputs();
+		for (ActivityInputPortDefinitionBean inputDef : configBean
+				.getInputPortDefinitions()) {
+			addInput(inputDef.getName(), inputDef.getDepth(), inputDef
+					.getAllowsLiteralValues(), inputDef
+					.getHandledReferenceSchemes(), inputDef
+					.getTranslatedElementType());
+			// TODO - use the mime types from the config bean if required,
+			// probably best handled elsewhere though
+		}
+		removeOutputs();
+
+		for (ActivityOutputPortDefinitionBean outputDef : configBean
+				.getOutputPortDefinitions()) {
+			ActivityOutputPort createActivityOutputPort = getEdits()
+					.createActivityOutputPort(outputDef.getName(),
+							outputDef.getDepth(), outputDef.getGranularDepth());
+//			addOutput(outputDef.getName(), outputDef.getDepth(), outputDef
+//					.getGranularDepth());
+			outputPorts.add(createActivityOutputPort);
+			// add the mime types as annotations
+			for (String mimeType : outputDef.getMimeTypes())
+				setMimeType(createActivityOutputPort, mimeType);
+		}
+	}
+
+	private void setMimeType(ActivityOutputPort outputPort, String mimeType) {
+		MimeType mimeTypeAnnotation = new MimeType();
+		mimeTypeAnnotation.setText(mimeType);
+		try {
+			getEdits()
+					.getAddAnnotationChainEdit(outputPort, mimeTypeAnnotation)
+					.doEdit();
+		} catch (EditException e) {
+			logger.error(e);
+		}
+	}
+
+	/**
+	 * Remove existing output ports.
+	 */
+	protected void removeOutputs() {
+		outputPorts.clear();
+	}
+
+	/**
+	 * Remove existing input ports
+	 *
+	 */
+	protected void removeInputs() {
+		inputPorts.clear();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AbstractAsynchronousActivity.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AbstractAsynchronousActivity.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AbstractAsynchronousActivity.java
new file mode 100644
index 0000000..762b5e9
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AbstractAsynchronousActivity.java
@@ -0,0 +1,80 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.util.Map;
+
+import org.apache.taverna.reference.T2Reference;
+
+/**
+ * Abstract superclass for asynchronous activities. Activity providers should only
+ * have to implement the configuration and invocation methods to have a fully
+ * functional activity - serialisation and deserialisation are handled
+ * automatically.
+ * 
+ * @author Tom Oinn
+ * 
+ * @param <ConfigType>
+ *            the configuration type used for this activity
+ */
+public abstract class AbstractAsynchronousActivity<ConfigType> extends
+		AbstractActivity<ConfigType> implements AsynchronousActivity<ConfigType> {
+
+	/**
+	 * Called immediately after object construction by the deserialisation
+	 * framework with a configuration bean built from the auto-generated XML.
+	 * <p>
+	 * This method is responsible for the creation of input and output ports,
+	 * something that is currently done in the constructor of the Taverna 1
+	 * Processor class.
+	 */
+	@Override
+	public abstract void configure(ConfigType conf)
+			throws ActivityConfigurationException;
+
+	/**
+	 * Get a configuration bean representing the definition of the activity. This
+	 * bean should contain enough information to rebuild the input and output
+	 * port sets, mappings are explicitly handled by the serialisation framework
+	 * but the ports are assumed to be generated during the configuration stage
+	 * rather than explicitly stored.
+	 */
+	@Override
+	public abstract ConfigType getConfiguration();
+
+	/**
+	 * Request an asynchronous invocation of the activity on the specified data.
+	 * The data items are named relative to the input port names of the activity
+	 * (as opposed to the parent processor), the invocation layer is responsible
+	 * for translating these appropriately before this method is called. The
+	 * callback object provides access to a DataManager instance that can be
+	 * used to resolve the entity identifiers in the data map, push results up
+	 * and signal failure conditions.
+	 * <p>
+	 * This method must not block! However it happens this method must return
+	 * immediately after creating the new activity invocation. Do not do any
+	 * heavy lifting in the body of this method without creating a new thread
+	 * specifically for it.
+	 */
+	@Override
+	public abstract void executeAsynch(Map<String, T2Reference> data,
+			AsynchronousActivityCallback callback);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/Activity.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/Activity.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/Activity.java
new file mode 100644
index 0000000..9438009
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/Activity.java
@@ -0,0 +1,92 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import static org.apache.taverna.annotation.HierarchyRole.CHILD;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.taverna.annotation.Annotated;
+import org.apache.taverna.annotation.HierarchyTraversal;
+import org.apache.taverna.workflowmodel.Configurable;
+import org.apache.taverna.workflowmodel.Edits;
+
+/**
+ * Defines a single abstract or concrete invokable activity. Each Processor
+ * contains at least one of these and may contain many, similarly the dispatch
+ * stack may create new Activity instances from e.g. dynamic lookup or
+ * resolution of an abstract activity to a concrete activity or set of
+ * activities.
+ * 
+ * @param <ConfigurationType>
+ *            the ConfigurationType associated with the Activity. This is an
+ *            arbitrary java class that provides details on how the Activity is
+ *            configured..
+ * @author Tom Oinn
+ * @author David Withers
+ */
+public interface Activity<ConfigurationType> extends Annotated<Activity<?>>,
+		Configurable<ConfigurationType> {
+	/**
+	 * An Activity contains a set of named input ports. Names must be unique
+	 * within this set.
+	 *
+	 * @return the set of input ports for this activity
+	 */
+	@HierarchyTraversal(hierarchies = { "workflowStructure" }, role = { CHILD })
+	Set<ActivityInputPort> getInputPorts();
+
+	/**
+	 * A processor may have different input port names to the activity or
+	 * activities it contains. This map is keyed on the processor input port
+	 * names with the corresponding value being the activity port name.
+	 * 
+	 * @return mapping from processor input port names to activity input port
+	 *         names
+	 */
+	Map<String, String> getInputPortMapping();
+
+	/**
+	 * An Activity contains a set of named output ports. As with input ports
+	 * names must be unique within the set.
+	 * 
+	 * @return
+	 */
+	@HierarchyTraversal(hierarchies = { "workflowStructure" }, role = { CHILD })
+	Set<ActivityOutputPort> getOutputPorts();
+
+	/**
+	 * Outputs of the activity may be named differently to those of the
+	 * processor. This map is keyed on an activity output port name with each
+	 * corresponding value being the processor output port name to which the
+	 * activity output is bound.
+	 * 
+	 * @return mapping from activity output port name to processor output port
+	 *         name
+	 */
+	Map<String, String> getOutputPortMapping();
+
+	@Override
+	abstract void configure(ConfigurationType conf)
+			throws ActivityConfigurationException;
+
+	void setEdits(Edits edits);
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityAndBeanWrapper.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityAndBeanWrapper.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityAndBeanWrapper.java
new file mode 100644
index 0000000..c2e771b
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityAndBeanWrapper.java
@@ -0,0 +1,61 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.awt.datatransfer.Transferable;
+
+/**
+ * Used when dragging activities from the palette onto "something". Place it
+ * inside a {@link Transferable} when doing a drag operation. Contains an
+ * {@link Activity} and its configuration bean.
+ * 
+ * @author Ian Dunlop
+ */
+public class ActivityAndBeanWrapper {
+	/** The Activity being dragged */
+	private Activity<?> activity;
+	/** The bean used to configure the activity */
+	private Object bean;
+	private String name;
+
+	public Activity<?> getActivity() {
+		return activity;
+	}
+
+	public void setActivity(Activity<?> activity) {
+		this.activity = activity;
+	}
+
+	public Object getBean() {
+		return bean;
+	}
+
+	public void setBean(Object bean) {
+		this.bean = bean;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityConfigurationException.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityConfigurationException.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityConfigurationException.java
new file mode 100644
index 0000000..c3ee06c
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityConfigurationException.java
@@ -0,0 +1,61 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import org.apache.taverna.workflowmodel.ConfigurationException;
+
+/**
+ * Thrown when attempting to configure an Activity instance with an invalid
+ * configuration. Causes may include actual configuration errors, unavailable
+ * activities etc.
+ * 
+ * @author Tom Oinn
+ */
+public class ActivityConfigurationException extends ConfigurationException {
+	private static final long serialVersionUID = 6940385954331153900L;
+
+	/**
+	 * @param msg
+	 *            a message describing the reason for the exception.
+	 */
+	public ActivityConfigurationException(String msg) {
+		super(msg);
+	}
+
+	/**
+	 * @param cause
+	 *            a previous exception that caused this
+	 *            ActivityConfigurationException to be thrown.
+	 */
+	public ActivityConfigurationException(Throwable cause) {
+		super(cause);
+	}
+
+	/**
+	 * @param msg
+	 *            a message describing the reason for the exception.
+	 * @param cause
+	 *            a previous exception that caused this
+	 *            ActivityConfigurationException to be thrown.
+	 */
+	public ActivityConfigurationException(String msg, Throwable cause) {
+		super(msg, cause);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityFactory.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityFactory.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityFactory.java
new file mode 100644
index 0000000..bbee4ef
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityFactory.java
@@ -0,0 +1,88 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.net.URI;
+import java.util.Set;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Factory for creating {@link Activity} instances.
+ * 
+ * @author David Withers
+ */
+public interface ActivityFactory {
+	/**
+	 * Creates a new <code>Activity</code> instance.
+	 * 
+	 * @return the new <code>Activity</code> instance
+	 */
+	Activity<?> createActivity();
+
+	/**
+	 * What type of <code>Activity</code>s can this factory create?
+	 * 
+	 * @return the type of the <code>Activity</code>s that this factory can
+	 *         create
+	 */
+	URI getActivityType();
+
+	/**
+	 * Returns the JSON Schema for the configuration required by the
+	 * <code>Activity</code>.
+	 * 
+	 * @return the JSON Schema for the configuration required by the
+	 *         <code>Activity</code>
+	 */
+	JsonNode getActivityConfigurationSchema();
+
+	/**
+	 * Returns the <code>ActivityInputPort</code>s that the
+	 * <code>Activity</code> requires to be present in order to execute with the
+	 * specified configuration.
+	 * <p>
+	 * If the <code>Activity</code> does not require any input port for the
+	 * configuration then an empty set is returned.
+	 * 
+	 * @param configuration
+	 *            the configuration
+	 * @return the <code>ActivityInputPort</code>s that the
+	 *         <code>Activity</code> requires to be present in order to execute
+	 */
+	Set<ActivityInputPort> getInputPorts(JsonNode configuration)
+			throws ActivityConfigurationException;
+
+	/**
+	 * Returns the <code>ActivityOutputPort</code>s that the
+	 * <code>Activity</code> requires to be present in order to execute with the
+	 * specified configuration.
+	 * <p>
+	 * If the <code>Activity</code> does not require any output ports for the
+	 * configuration then an empty set is returned.
+	 * 
+	 * @param configuration
+	 *            the configuration
+	 * @return the <code>ActivityOutputPort</code>s that the
+	 *         <code>Activity</code> requires to be present in order to execute
+	 */
+	Set<ActivityOutputPort> getOutputPorts(JsonNode configuration)
+			throws ActivityConfigurationException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityInputPort.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityInputPort.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityInputPort.java
new file mode 100644
index 0000000..a748b75
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityInputPort.java
@@ -0,0 +1,77 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.util.List;
+
+import org.apache.taverna.reference.ExternalReferenceSPI;
+import org.apache.taverna.workflowmodel.InputPort;
+
+/**
+ * Specialisation of InputPort to capture the extra information required by
+ * Activity instances.
+ * 
+ * @author Tom Oinn
+ */
+public interface ActivityInputPort extends InputPort, ActivityPort {
+	/**
+	 * Declares that the DataDocument instances fed as input data (either
+	 * directly or as elements of a collection) to this input port must contain
+	 * at least one of the specified ReferenceScheme types. This is used to
+	 * specify that e.g. an activity can only accept URLs, values or similar.
+	 * 
+	 * @return Class objects representing the reference scheme types which this
+	 *         input can handle
+	 */
+	List<Class<? extends ExternalReferenceSPI>> getHandledReferenceSchemes();
+
+	/**
+	 * Literal values are a special case as they are not represented by
+	 * reference schemes - in rare cases activities may choose to deny literal
+	 * values, forcing *all* their inputs to be in a particular reference
+	 * scheme. If this is the case then this method should return false, if the
+	 * activity is capable of handling literal types without any upconversion to
+	 * references (please do implement this!) then it returns false
+	 * 
+	 * @return true if the activity can cope with literal values, false if it
+	 *         requires them to be converted to an instance of a reference
+	 *         scheme class (as defined by getHandledReferenceSchemes)
+	 */
+	boolean allowsLiteralValues();
+
+	/**
+	 * The Java object type desired when the input data reference is converted
+	 * to an object. This is only used by the parent Activity when invoking the
+	 * data facade. Where the input data is a list this returns the type of leaf
+	 * nodes within the collection structure - the instances of this type will
+	 * always be wrapped up in a Java collection rather than an array type
+	 * <p>
+	 * Note that this is not intended to allow activities to consume arbitrary
+	 * java classes, activities such as the API consumer should handle this
+	 * through the reference scheme mechanism backed by an appropriate store
+	 * (most likely an in-memory hash of active objects)
+	 * 
+	 * @return the desired class of the object returned by the data facade when
+	 *         converting the input data reference into a java object. This will
+	 *         almost always be String.class or byte[].class but other cases may
+	 *         exist.
+	 */
+	Class<?> getTranslatedElementClass();
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityOutputPort.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityOutputPort.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityOutputPort.java
new file mode 100644
index 0000000..b79f7a8
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityOutputPort.java
@@ -0,0 +1,31 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import org.apache.taverna.workflowmodel.OutputPort;
+
+/**
+ * The output port of an {@link Activity}.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public interface ActivityOutputPort extends OutputPort, ActivityPort {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityPort.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityPort.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityPort.java
new file mode 100644
index 0000000..20793d0
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/ActivityPort.java
@@ -0,0 +1,33 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import org.apache.taverna.workflowmodel.Port;
+
+/**
+ * The input or output port of an {@link Activity}.
+ * 
+ * @see ActivityInputPort
+ * @see ActivityOutputPort
+ * @author Stian Soiland-Reyes
+ */
+public interface ActivityPort extends Port {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AsynchronousActivity.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AsynchronousActivity.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AsynchronousActivity.java
new file mode 100644
index 0000000..d34316a
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AsynchronousActivity.java
@@ -0,0 +1,49 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.util.Map;
+
+import org.apache.taverna.reference.T2Reference;
+
+/**
+ * A concrete invokable activity with an asynchronous invocation API and no
+ * knowledge of invocation context. This is the most common concrete activity
+ * type in Taverna 2, it has no knowledge of any enclosing iteration or other
+ * handling process. The activity may stream results in the sense that it can
+ * use the AsynchronousActivityCallback object to push multiple results followed
+ * by a completion event. If a completion event is received by the callback
+ * before any data events the callback will insert a data event containing empty
+ * collections of the appropriate depth.
+ * 
+ * @param <ConfigurationType>
+ *            the ConfigurationType associated with the Activity.
+ * @author Tom Oinn
+ */
+public interface AsynchronousActivity<ConfigurationType> extends
+		Activity<ConfigurationType> {
+	/**
+	 * Invoke the activity in an asynchronous manner. The activity uses the
+	 * specified ActivityCallback object to push results, errors and completion
+	 * events back to the dispatch stack.
+	 */
+	void executeAsynch(Map<String, T2Reference> data,
+			AsynchronousActivityCallback callback);
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AsynchronousActivityCallback.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AsynchronousActivityCallback.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AsynchronousActivityCallback.java
new file mode 100644
index 0000000..78be314
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/AsynchronousActivityCallback.java
@@ -0,0 +1,136 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.util.Map;
+
+import org.apache.taverna.invocation.InvocationContext;
+import org.apache.taverna.reference.T2Reference;
+import org.apache.taverna.workflowmodel.processor.dispatch.events.DispatchErrorType;
+
+/**
+ * The callback interface used by instances of AsynchronousActivity to push
+ * results and failure messages back to the invocation layer.
+ * 
+ * @author Tom Oinn
+ */
+public interface AsynchronousActivityCallback {
+	/**
+	 * The invocation context contains resources such as data managers, security
+	 * agents and provenance consumers to be used by the Activity as it runs.
+	 * This replaces the getLocalDataManager and getLocalSecurityManager calls.
+	 */
+	InvocationContext getContext();
+
+	/**
+	 * If an activity proxy wants to create a new thread of activity it should
+	 * use this method unless there is a very good reason not to. This allows
+	 * the workflow framework to control its own thread usage, possibly
+	 * implementing per user, per workflow or per processor thread limit
+	 * policies. Exceptions to this principle might include cases where the
+	 * activity proxy is capable of managing thread usage across all instances
+	 * of that activity type and therefore more efficiently (fewer threads) than
+	 * if it let the workflow manager perform this function.
+	 * 
+	 * @param runMe
+	 *            a Runnable to implement the activity proxy logic.
+	 */
+	void requestRun(Runnable runMe);
+
+	/**
+	 * Push a map of named identifiers out to the invocation layer which is then
+	 * responsible for wrapping them up into an appropriate Job object and
+	 * sending it up the dispatch stack. The keys of the map are names local to
+	 * the activity, the callback object is responsible for rewriting them
+	 * according to the activity mapping rules (i.e. Activity.getXXXPortMapping)
+	 * 
+	 * @param data
+	 *            a single result data packet
+	 * @param index
+	 *            the index of the result in the context of this single process
+	 *            invocation. If there's no streaming involved this should be a
+	 *            zero length int[].
+	 */
+	void receiveResult(Map<String, T2Reference> data, int[] index);
+
+	/**
+	 * If (and only if) the activity is streaming data then this method can be
+	 * called to signal a (possibly partial) completion of the stream. If this
+	 * is a total completion event, i.e. one with a zero length index array and
+	 * there have been no result data sent the callback object will create a
+	 * single job containing empty lists and send that instead otherwise it will
+	 * be passed straight through. The index array is relative to this
+	 * particular activity invocation as the invocation has no contextual
+	 * awareness.
+	 * 
+	 * @param completionIndex
+	 */
+	void receiveCompletion(int[] completionIndex);
+
+	/**
+	 * If the job fails (as opposed to succeeding and sending an error for which
+	 * the receiveResult method is used) this method will cause an error to be
+	 * sent up the dispatch stack, triggering any appropriate handling methods
+	 * such as retry, failover etc. This particular method accepts both a free
+	 * text message and an instance of Throwable for additional information, in
+	 * addition to which it sends an error type which allows upstream layers to
+	 * determine whether they can handle the error or whether it should be
+	 * passed directly upwards.
+	 * 
+	 * @param message
+	 * @param t
+	 */
+	void fail(String message, Throwable t, DispatchErrorType errorType);
+
+	/**
+	 * If the job fails (as opposed to succeeding and sending an error for which
+	 * the receiveResult method is used) this method will cause an error to be
+	 * sent up the dispatch stack, triggering any appropriate handling methods
+	 * such as retry, failover etc. This particular method accepts both a free
+	 * text message and an instance of Throwable for additional information.
+	 * 
+	 * @param message
+	 * @param t
+	 */
+	void fail(String message, Throwable t);
+
+	/**
+	 * If the job fails (as opposed to succeeding and sending an error for which
+	 * the receiveResult method is used) this method will cause an error to be
+	 * sent up the dispatch stack, triggering any appropriate handling methods
+	 * such as retry, failover etc. This method just takes a free text message
+	 * for cases where a failure is properly described by an instance of
+	 * Throwable
+	 * 
+	 * @param message
+	 */
+	void fail(String message);
+
+	/**
+	 * For activities which are going to establish state below the invoke node
+	 * in the monitor tree this method returns the owning process identifier
+	 * allocated to the invoke node. This is particularly necessary for nested
+	 * workflow activities.
+	 * <p>
+	 * Any calls to Monitor.register... must establish a state tree rooted at
+	 * this node, they may assume that this node already exists.
+	 */
+	String getParentProcessIdentifier();
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/DisabledActivity.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/DisabledActivity.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/DisabledActivity.java
new file mode 100644
index 0000000..19123aa
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/DisabledActivity.java
@@ -0,0 +1,190 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.util.HashSet;
+import java.util.Map;
+
+import org.apache.taverna.workflowmodel.OutputPort;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A disabled activity is a wrapper for an Activity that is offline or similarly
+ * disabled. This cannot be done just by setting a flag on the corresponding
+ * activity as special code needs to be used to create the ports of the disabled
+ * activity that, obviously, cannot be done by confighuring the offline
+ * activity.
+ *
+ * @author alanrw
+ */
+public final class DisabledActivity extends
+		NonExecutableActivity<ActivityAndBeanWrapper> {
+	public static final String URI = "http://ns.taverna.org.uk/2010/activity/disabled";
+	private static final Logger logger = Logger
+			.getLogger(DisabledActivity.class);
+
+	/**
+	 * Conf holds the offline Activity and its configuration.
+	 */
+	private ActivityAndBeanWrapper conf;
+	private Object lastWorkingConfiguration;
+
+	/**
+	 * It is not possible to create a "naked" DisabledActivity.
+	 */
+	private DisabledActivity() {
+		super();
+		lastWorkingConfiguration = null;
+	}
+
+	/**
+	 * Create a DisabledActivity that represents an offline activity of the
+	 * specified class with the specified configuration. This constructor is
+	 * commonly used when reading in an Activity which cannot be initially
+	 * configured because it is offline.
+	 *
+	 * @param activityClass
+	 *            The class of Activity that is offline.
+	 * @param config
+	 *            The configuration of the offline Activity.
+	 * @throws InstantiationException
+	 * @throws IllegalAccessException
+	 * @throws ActivityConfigurationException
+	 */
+	public DisabledActivity(Class<? extends Activity<?>> activityClass,
+			Object config) throws InstantiationException,
+			IllegalAccessException, ActivityConfigurationException {
+		this(activityClass.newInstance(), config);
+	}
+
+	/**
+	 * Create a DisabledActivity that represents a specific Activity with its
+	 * configuration.
+	 *
+	 * @param activity
+	 *            The Activity that is offline
+	 * @param config
+	 *            The configuration of the activity.
+	 */
+	public DisabledActivity(Activity<?> activity, Object config) {
+		this();
+		ActivityAndBeanWrapper disabledConfig = new ActivityAndBeanWrapper();
+		disabledConfig.setActivity(activity);
+		disabledConfig.setBean(config);
+		try {
+			configure(disabledConfig);
+		} catch (ActivityConfigurationException e) {
+			logger.error(e);
+		}
+	}
+
+	/**
+	 * Create a DisabledActivity that represents a specific Activity that is now
+	 * disabled e.g. by its remote endpoint going offline. Note that in this
+	 * case, the ports of the DisabledActivity and their mapping to the
+	 * containing Processor's ports can be inherited from the Activity that is
+	 * now disabled.
+	 * 
+	 * @param activity
+	 *            The Activity that is now disabled.
+	 */
+	public DisabledActivity(Activity<?> activity) {
+		this(activity, activity.getConfiguration());
+		for (ActivityInputPort aip : activity.getInputPorts())
+			addInput(aip.getName(), aip.getDepth(), aip.allowsLiteralValues(),
+					aip.getHandledReferenceSchemes(),
+					aip.getTranslatedElementClass());
+		for (OutputPort op : activity.getOutputPorts())
+			addOutput(op.getName(), op.getDepth(), op.getGranularDepth());
+		getInputPortMapping().clear();
+		getInputPortMapping().putAll(activity.getInputPortMapping());
+		getOutputPortMapping().clear();
+		getOutputPortMapping().putAll(activity.getOutputPortMapping());
+	}
+
+	@Override
+	public void configure(ActivityAndBeanWrapper conf)
+			throws ActivityConfigurationException {
+		this.conf = conf;
+	}
+
+	@Override
+	public ActivityAndBeanWrapper getConfiguration() {
+		return conf;
+	}
+
+	/**
+	 * @return The Activity that has been disabled
+	 */
+	public Activity<?> getActivity() {
+		return getConfiguration().getActivity();
+	}
+
+	/**
+	 * @return The configuration of the Activity that has been disabled
+	 */
+	public Object getActivityConfiguration() {
+		return getConfiguration().getBean();
+	}
+
+	public boolean configurationWouldWork() {
+		return configurationWouldWork(conf.getBean());
+	}
+
+	public boolean configurationWouldWork(Object newConfig) {
+		boolean result = true;
+		lastWorkingConfiguration = null;
+		try {
+			@SuppressWarnings("unchecked")
+			Activity<Object> aa = conf.getActivity().getClass().newInstance();
+			aa.configure(newConfig);
+			boolean unknownPort = false;
+			Map<String, String> currentInputPortMap = getInputPortMapping();
+			HashSet<String> currentInputNames = new HashSet<>();
+			currentInputNames.addAll(currentInputPortMap.values()) ;
+			for (ActivityInputPort aip : aa.getInputPorts())
+				currentInputNames.remove(aip.getName());
+			unknownPort = !currentInputNames.isEmpty();
+
+			if (!unknownPort) {
+				Map<String, String> currentOutputPortMap = getOutputPortMapping();
+				HashSet<String> currentOutputNames = new HashSet<>();
+				currentOutputNames.addAll(currentOutputPortMap.values());
+				for (OutputPort aop : aa.getOutputPorts())
+					currentOutputNames.remove(aop.getName());
+				unknownPort = !currentOutputNames.isEmpty();
+			}
+			if (unknownPort)
+				result = false;
+		} catch (ActivityConfigurationException ex) {
+			result = false;
+		} catch (InstantiationException|IllegalAccessException e) {
+			return false;
+		}
+		if (result)
+		    lastWorkingConfiguration = newConfig;
+		return result;
+	}
+
+	public Object getLastWorkingConfiguration() {
+	    return lastWorkingConfiguration;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/Job.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/Job.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/Job.java
new file mode 100644
index 0000000..66b61ac
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/Job.java
@@ -0,0 +1,129 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.util.Map;
+
+import org.apache.taverna.invocation.InvocationContext;
+import org.apache.taverna.invocation.IterationInternalEvent;
+import org.apache.taverna.invocation.ProcessIdentifierException;
+import org.apache.taverna.reference.T2Reference;
+
+/**
+ * Contains a (possibly partial) job description. A job is the smallest entity
+ * that can be enacted by the invocation layer of the dispatch stack within a
+ * processor. Jobs are partial jobs if the set of keys in the data map is not
+ * identical to the set of named input ports on the processor within which the
+ * job is used. These objects are used internally within the processor to stage
+ * data during iteration and within the dispatch stack, they do not appear
+ * within the workflow itself.
+ * 
+ * @author Tom Oinn
+ */
+public class Job extends IterationInternalEvent<Job> {
+	private Map<String, T2Reference> dataMap;
+
+	/**
+	 * Push the index array onto the owning process name and return the new Job
+	 * object. Does not modify this object, the method creates a new Job with
+	 * the modified index array and owning process
+	 * 
+	 * @return
+	 */
+	@Override
+	public Job pushIndex() {
+		return new Job(getPushedOwningProcess(), new int[] {}, dataMap, context);
+	}
+
+	/**
+	 * Pull the index array previous pushed to the owning process name and
+	 * prepend it to the current index array
+	 */
+	@Override
+	public Job popIndex() {
+		return new Job(owner.substring(0, owner.lastIndexOf(':')),
+				getPoppedIndex(), dataMap, context);
+	}
+
+	/**
+	 * The actual data carried by this (partial) Job object is in the form of a
+	 * map, where the keys of the map are Strings identifying the named input
+	 * and the values are Strings containing valid data identifiers within the
+	 * context of a visible DataManager object (see CloudOne specification for
+	 * further information on the DataManager system)
+	 * 
+	 * @return Map of name to data reference for this Job
+	 */
+	public Map<String, T2Reference> getData() {
+		return this.dataMap;
+	}
+
+	/**
+	 * Create a new Job object with the specified owning process (colon
+	 * separated 'list' of process identifiers), index array and data map
+	 * 
+	 * @param owner
+	 * @param index
+	 * @param data
+	 */
+	public Job(String owner, int[] index, Map<String, T2Reference> data,
+			InvocationContext context) {
+		super(owner, index, context);
+		this.dataMap = data;
+	}
+
+	/**
+	 * Show the owner, index array and data map in textual form for debugging
+	 * and any other purpose. Jobs appear in the form :
+	 * 
+	 * <pre>
+	 * Job(Process1)[2,0]{Input2=dataID4,Input1=dataID3}
+	 * </pre>
+	 */
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("Job(").append(owner).append(")[");
+		String sep = "";
+		for (int i : index) {
+			sb.append(sep).append(i);
+			sep = ",";
+		}
+		sb.append("]{");
+		sep = "";
+		for (String key : dataMap.keySet()) {
+			sb.append(sep).append(key).append("=").append(dataMap.get(key));
+			sep = ",";
+		}
+		sb.append("}");
+		return sb.toString();
+	}
+
+	@Override
+	public Job popOwningProcess() throws ProcessIdentifierException {
+		return new Job(popOwner(), index, dataMap, context);
+	}
+
+	@Override
+	public Job pushOwningProcess(String localProcessName)
+			throws ProcessIdentifierException {
+		return new Job(pushOwner(localProcessName), index, dataMap, context);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/LockedNestedDataflow.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/LockedNestedDataflow.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/LockedNestedDataflow.java
new file mode 100644
index 0000000..f93d062
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/LockedNestedDataflow.java
@@ -0,0 +1,30 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+/**
+ * A LockedNestedDataflow is intended to be unchangeable. It is normally defined
+ * elsewhere to the workflow.
+ * 
+ * @author alanrw
+ */
+public interface LockedNestedDataflow extends NestedDataflow {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/MonitorableAsynchronousActivity.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/MonitorableAsynchronousActivity.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/MonitorableAsynchronousActivity.java
new file mode 100644
index 0000000..a6e3a2d
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/MonitorableAsynchronousActivity.java
@@ -0,0 +1,55 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.taverna.monitor.MonitorableProperty;
+import org.apache.taverna.reference.T2Reference;
+
+/**
+ * An extension of AsynchronousActivity with the additional stipulation that
+ * implementing classes must return a set of monitorable properties for the
+ * activity invocation instance when invoked. This allows for deep state
+ * management, where the monitor state extends out from the workflow engine into
+ * the remote resources themselves and is dependant on the resource proxied by
+ * the activity implementation providing this information.
+ * 
+ * @author Tom Oinn
+ */
+public interface MonitorableAsynchronousActivity<ConfigType> extends
+		AsynchronousActivity<ConfigType> {
+	/**
+	 * This has the same invocation semantics as
+	 * {@link AsynchronousActivity}<code>.executeAsynch</code> and all
+	 * implementations should also implement that method, with the difference
+	 * that this one returns immediately with a set of monitorable properties
+	 * which represent monitorable or steerable state within the invocation
+	 * itself.
+	 * 
+	 * @param data
+	 * @param callback
+	 * @return a set of monitorable properties representing internal state of
+	 *         the invoked resource
+	 */
+	Set<MonitorableProperty<?>> executeAsynchWithMonitoring(
+			Map<String, T2Reference> data, AsynchronousActivityCallback callback);
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NestedDataflow.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NestedDataflow.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NestedDataflow.java
new file mode 100644
index 0000000..e70f8b1
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NestedDataflow.java
@@ -0,0 +1,35 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import org.apache.taverna.workflowmodel.Dataflow;
+
+/**
+ * Nested workflows/dataflows can come in many shapes and sizes - in-line, url
+ * etc. However, they are all {@link Dataflow}s. Implement this in any
+ * implementation of a Nested dataflow
+ * 
+ * @author Ian Dunlop
+ */
+public interface NestedDataflow {
+	Dataflow getNestedDataflow();
+
+	void setNestedDataflow(Dataflow dataflow);
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NestedDataflowSource.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NestedDataflowSource.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NestedDataflowSource.java
new file mode 100644
index 0000000..21446d9
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NestedDataflowSource.java
@@ -0,0 +1,34 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import org.apache.taverna.workflowmodel.Dataflow;
+
+/**
+ * @author alanrw
+ */
+public interface NestedDataflowSource<T extends NestedDataflow> {
+	T getNestedDataflow();
+
+	Dataflow getParentDataflow();
+
+	@Override
+	String toString();
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NonExecutableActivity.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NonExecutableActivity.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NonExecutableActivity.java
new file mode 100644
index 0000000..9b94d74
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/NonExecutableActivity.java
@@ -0,0 +1,96 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+import java.util.Map;
+
+import org.apache.taverna.reference.T2Reference;
+
+/**
+ * A non-executable activity is a wrapper for an Activity that cannot be
+ * executed, for example because it is offline or unrecognized.
+ * 
+ * @author alanrw
+ */
+public abstract class NonExecutableActivity<T> extends
+		AbstractAsynchronousActivity<T> {
+	public static final String URI = "http://ns.taverna.org.uk/2010/activity/nonExecutable";
+
+	/**
+	 * It is not possible to create a "naked" NonExecutableActivity.
+	 */
+	protected NonExecutableActivity() {
+		super();
+	}
+
+	/**
+	 * Add an input to the NonExecutableActivity with the specified name.
+	 * 
+	 * @param portName
+	 */
+	public void addProxyInput(String portName) {
+		super.addInput(portName, 0, true, null, null);
+	}
+
+	/**
+	 * Add an input to the NonExecutableActivity with the specified name and
+	 * depth.
+	 * 
+	 * @param portName
+	 * @param depth
+	 */
+	public void addProxyInput(String portName, int depth) {
+		super.addInput(portName, depth, true, null, null);
+	}
+
+	/**
+	 * Add an output to the NonExecutableActivity with the specified name
+	 * 
+	 * @param portName
+	 */
+	public void addProxyOutput(String portName) {
+		super.addOutput(portName, 0);
+	}
+
+	/**
+	 * Add an output to the NonExecutableActivity with the specified name and
+	 * depth
+	 * 
+	 * @param portName
+	 * @param depth
+	 */
+	public void addProxyOutput(String portName, int depth) {
+		super.addOutput(portName, depth);
+	}
+
+	/**
+	 * Attempting to run a NonExecutableActivity will always fail.
+	 */
+	@Override
+	public void executeAsynch(Map<String, T2Reference> data,
+			final AsynchronousActivityCallback callback) {
+		callback.requestRun(new Runnable() {
+			@Override
+			public void run() {
+				callback.fail("The service is not executable");
+			}
+		});
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/SupersededActivity.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/SupersededActivity.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/SupersededActivity.java
new file mode 100644
index 0000000..cb01d6f
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/processor/activity/SupersededActivity.java
@@ -0,0 +1,32 @@
+/*
+* 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.
+*/
+
+package org.apache.taverna.workflowmodel.processor.activity;
+
+/**
+ * 
+ * A superseded activity is one which has been replaced be another activity type
+ * of similar functionality but different configuration and name
+ * 
+ * @author alanrw
+ */
+public interface SupersededActivity<ConfigurationType> extends
+		Activity<ConfigurationType> {
+	Activity<?> getReplacementActivity() throws ActivityConfigurationException;
+}