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;
+}