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:54 UTC
[10/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/utils/Tools.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/utils/Tools.java b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/utils/Tools.java
new file mode 100644
index 0000000..cb4b3f2
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/java/org/apache/taverna/workflowmodel/utils/Tools.java
@@ -0,0 +1,794 @@
+/*
+* 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.utils;
+
+import static java.lang.Character.isLetterOrDigit;
+import static org.apache.taverna.workflowmodel.utils.AnnotationTools.addAnnotation;
+import static org.apache.taverna.workflowmodel.utils.AnnotationTools.getAnnotation;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.apache.taverna.annotation.annotationbeans.IdentificationAssertion;
+import org.apache.taverna.workflowmodel.CompoundEdit;
+import org.apache.taverna.workflowmodel.Dataflow;
+import org.apache.taverna.workflowmodel.DataflowInputPort;
+import org.apache.taverna.workflowmodel.DataflowOutputPort;
+import org.apache.taverna.workflowmodel.Datalink;
+import org.apache.taverna.workflowmodel.Edit;
+import org.apache.taverna.workflowmodel.EditException;
+import org.apache.taverna.workflowmodel.Edits;
+import org.apache.taverna.workflowmodel.EventForwardingOutputPort;
+import org.apache.taverna.workflowmodel.EventHandlingInputPort;
+import org.apache.taverna.workflowmodel.InputPort;
+import org.apache.taverna.workflowmodel.Merge;
+import org.apache.taverna.workflowmodel.MergeInputPort;
+import org.apache.taverna.workflowmodel.MergeOutputPort;
+import org.apache.taverna.workflowmodel.NamedWorkflowEntity;
+import org.apache.taverna.workflowmodel.OutputPort;
+import org.apache.taverna.workflowmodel.Port;
+import org.apache.taverna.workflowmodel.Processor;
+import org.apache.taverna.workflowmodel.ProcessorInputPort;
+import org.apache.taverna.workflowmodel.ProcessorOutputPort;
+import org.apache.taverna.workflowmodel.TokenProcessingEntity;
+import org.apache.taverna.workflowmodel.processor.activity.Activity;
+import org.apache.taverna.workflowmodel.processor.activity.ActivityConfigurationException;
+import org.apache.taverna.workflowmodel.processor.activity.ActivityInputPort;
+import org.apache.taverna.workflowmodel.processor.activity.ActivityOutputPort;
+import org.apache.taverna.workflowmodel.processor.activity.DisabledActivity;
+import org.apache.taverna.workflowmodel.processor.activity.NestedDataflow;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Various workflow model tools that can be helpful when constructing a
+ * dataflow.
+ * <p>
+ * Not to be confused with the @deprecated
+ * {@link org.apache.taverna.workflowmodel.impl.Tools}
+ *
+ * @author David Withers
+ * @author Stian Soiland-Reyes
+ */
+public class Tools {
+ private static Logger logger = Logger.getLogger(Tools.class);
+
+ // private static Edits edits = new EditsImpl();
+
+ /**
+ * Find (and possibly create) an EventHandlingInputPort.
+ * <p>
+ * If the given inputPort is an instance of {@link EventHandlingInputPort},
+ * it is returned directly. If it is an ActivityInputPort - the owning
+ * processors (found by searching the dataflow) will be searced for a mapped
+ * input port. If this cannot be found, one will be created and mapped. The
+ * edits for this will be added to the editList and needs to be executed by
+ * the caller.
+ *
+ * @see #findEventHandlingOutputPort(List, Dataflow, OutputPort)
+ * @param editList
+ * List of {@link Edit}s to append any required edits (yet to be
+ * performed) to
+ * @param dataflow
+ * Dataflow containing the processors
+ * @param inputPort
+ * An EventHandlingInputPort or ActivityInputPort
+ * @return The found or created EventHandlingInputPort
+ */
+ protected static EventHandlingInputPort findEventHandlingInputPort(
+ List<Edit<?>> editList, Dataflow dataflow, InputPort inputPort,
+ Edits edits) {
+ if (inputPort instanceof EventHandlingInputPort)
+ return (EventHandlingInputPort) inputPort;
+ else if (!(inputPort instanceof ActivityInputPort))
+ throw new IllegalArgumentException("Unknown input port type for "
+ + inputPort);
+
+ ActivityInputPort activityInput = (ActivityInputPort) inputPort;
+ Collection<Processor> processors = getProcessorsWithActivityInputPort(
+ dataflow, activityInput);
+ if (processors.isEmpty())
+ throw new IllegalArgumentException("Can't find ActivityInputPort "
+ + activityInput.getName() + " in workflow " + dataflow);
+
+ // FIXME: Assumes only one matching processor
+ Processor processor = processors.iterator().next();
+ Activity<?> activity = null;
+ for (Activity<?> checkActivity : processor.getActivityList())
+ if (checkActivity.getInputPorts().contains(activityInput)) {
+ activity = checkActivity;
+ break;
+ }
+ if (activity == null)
+ throw new IllegalArgumentException("Can't find activity for port "
+ + activityInput.getName() + "within processor " + processor);
+
+ ProcessorInputPort input = getProcessorInputPort(processor, activity,
+ activityInput);
+ if (input != null)
+ return input;
+ // port doesn't exist so create a processor port and map it
+ String processorPortName = uniquePortName(activityInput.getName(),
+ processor.getInputPorts());
+ ProcessorInputPort processorInputPort = edits.createProcessorInputPort(
+ processor, processorPortName, activityInput.getDepth());
+ editList.add(edits.getAddProcessorInputPortEdit(processor,
+ processorInputPort));
+ editList.add(edits.getAddActivityInputPortMappingEdit(activity,
+ processorPortName, activityInput.getName()));
+ return processorInputPort;
+ }
+
+ /**
+ * Find (and possibly create) an EventForwardingOutputPort.
+ * <p>
+ * If the given outputPort is an instance of
+ * {@link EventForwardingOutputPort}, it is returned directly. If it is an
+ * ActivityOutputPort - the owning processors (found by searching the
+ * dataflow) will be searced for a mapped output port. If this cannot be
+ * found, one will be created and mapped. The edits for this will be added
+ * to the editList and needs to be executed by the caller.
+ *
+ * @see #findEventHandlingInputPort(List, Dataflow, InputPort)
+ * @param editList
+ * List of {@link Edit}s to append any required edits (yet to be
+ * performed) to
+ * @param dataflow
+ * Dataflow containing the processors
+ * @param outputPort
+ * An EventForwardingOutputPort or ActivityOutputPort
+ * @return The found or created EventForwardingOutputPort
+ */
+ protected static EventForwardingOutputPort findEventHandlingOutputPort(
+ List<Edit<?>> editList, Dataflow dataflow, OutputPort outputPort,
+ Edits edits) {
+ if (outputPort instanceof EventForwardingOutputPort)
+ return (EventForwardingOutputPort) outputPort;
+ else if (!(outputPort instanceof ActivityOutputPort))
+ throw new IllegalArgumentException("Unknown output port type for "
+ + outputPort);
+
+ ActivityOutputPort activityOutput = (ActivityOutputPort) outputPort;
+ Collection<Processor> processors = getProcessorsWithActivityOutputPort(
+ dataflow, activityOutput);
+ if (processors.isEmpty())
+ throw new IllegalArgumentException("Can't find ActivityOutputPort "
+ + activityOutput.getName() + " in workflow " + dataflow);
+
+ // FIXME: Assumes only one matching processor
+ Processor processor = processors.iterator().next();
+ Activity<?> activity = null;
+ for (Activity<?> checkActivity : processor.getActivityList())
+ if (checkActivity.getOutputPorts().contains(activityOutput)) {
+ activity = checkActivity;
+ break;
+ }
+ if (activity == null)
+ throw new IllegalArgumentException("Can't find activity for port "
+ + activityOutput.getName() + "within processor "
+ + processor);
+
+ ProcessorOutputPort processorOutputPort = Tools.getProcessorOutputPort(
+ processor, activity, activityOutput);
+ if (processorOutputPort != null)
+ return processorOutputPort;
+
+ // port doesn't exist so create a processor port and map it
+ String processorPortName = uniquePortName(activityOutput.getName(),
+ processor.getOutputPorts());
+ processorOutputPort = edits.createProcessorOutputPort(processor,
+ processorPortName, activityOutput.getDepth(),
+ activityOutput.getGranularDepth());
+ editList.add(edits.getAddProcessorOutputPortEdit(processor,
+ processorOutputPort));
+ editList.add(edits.getAddActivityOutputPortMappingEdit(activity,
+ processorPortName, activityOutput.getName()));
+
+ return processorOutputPort;
+ }
+
+ /**
+ * Creates an Edit that creates a Datalink between a source and sink port
+ * and connects the Datalink.
+ *
+ * If the sink port already has a Datalink connected this method checks if a
+ * new Merge is required and creates and connects the required Datalinks.
+ *
+ * @param dataflow
+ * the Dataflow to add the Datalink to
+ * @param source
+ * the source of the Datalink
+ * @param sink
+ * the source of the Datalink
+ * @return an Edit that creates a Datalink between a source and sink port
+ * and connects the Datalink
+ */
+ public static Edit<?> getCreateAndConnectDatalinkEdit(Dataflow dataflow,
+ EventForwardingOutputPort source, EventHandlingInputPort sink,
+ Edits edits) {
+ Edit<?> edit = null;
+
+ Datalink incomingLink = sink.getIncomingLink();
+ if (incomingLink == null) {
+ Datalink datalink = edits.createDatalink(source, sink);
+ edit = edits.getConnectDatalinkEdit(datalink);
+ } else {
+ List<Edit<?>> editList = new ArrayList<>();
+
+ Merge merge = null;
+ int counter = 0; // counter for merge input port names
+ if (incomingLink.getSource() instanceof MergeOutputPort)
+ merge = ((MergeOutputPort) incomingLink.getSource()).getMerge();
+ else {
+ merge = edits.createMerge(dataflow);
+ editList.add(edits.getAddMergeEdit(dataflow, merge));
+ editList.add(edits.getDisconnectDatalinkEdit(incomingLink));
+ MergeInputPort mergeInputPort = edits.createMergeInputPort(
+ merge,
+ getUniqueMergeInputPortName(merge,
+ incomingLink.getSource().getName() + "To"
+ + merge.getLocalName() + "_input",
+ counter++), incomingLink.getSink().getDepth());
+ editList.add(edits.getAddMergeInputPortEdit(merge,
+ mergeInputPort));
+ Datalink datalink = edits.createDatalink(
+ incomingLink.getSource(), mergeInputPort);
+ editList.add(edits.getConnectDatalinkEdit(datalink));
+ datalink = edits.createDatalink(merge.getOutputPort(),
+ incomingLink.getSink());
+ editList.add(edits.getConnectDatalinkEdit(datalink));
+ }
+ MergeInputPort mergeInputPort = edits.createMergeInputPort(
+ merge,
+ getUniqueMergeInputPortName(merge, source.getName() + "To"
+ + merge.getLocalName() + "_input", counter),
+ sink.getDepth());
+ editList.add(edits.getAddMergeInputPortEdit(merge, mergeInputPort));
+ Datalink datalink = edits.createDatalink(source, mergeInputPort);
+ editList.add(edits.getConnectDatalinkEdit(datalink));
+
+ edit = new CompoundEdit(editList);
+ }
+
+ return edit;
+ }
+
+ /**
+ * Get an {@link Edit} that will link the given output port to the given
+ * input port.
+ * <p>
+ * The output port can be an {@link EventForwardingOutputPort} (such as an
+ * {@link ProcessorOutputPort}, or an {@link ActivityOutputPort}. The input
+ * port can be an {@link EventHandlingInputPort} (such as an
+ * {@link ProcessorInputPort}, or an {@link ActivityInputPort}.
+ * <p>
+ * If an input and/or output port is an activity port, processors in the
+ * given dataflow will be searched for matching mappings, create the
+ * processor port and mapping if needed, before constructing the edits for
+ * adding the datalink.
+ *
+ * @param dataflow
+ * Dataflow (indirectly) containing ports
+ * @param outputPort
+ * An {@link EventForwardingOutputPort} or an
+ * {@link ActivityOutputPort}
+ * @param inputPort
+ * An {@link EventHandlingInputPort} or an
+ * {@link ActivityInputPort}
+ * @return A compound edit for creating and connecting the datalink and any
+ * neccessary processor ports and mappings
+ */
+ public static Edit<?> getCreateAndConnectDatalinkEdit(Dataflow dataflow,
+ OutputPort outputPort, InputPort inputPort, Edits edits) {
+ List<Edit<?>> editList = new ArrayList<>();
+ EventHandlingInputPort sink = findEventHandlingInputPort(editList,
+ dataflow, inputPort, edits);
+ EventForwardingOutputPort source = findEventHandlingOutputPort(
+ editList, dataflow, outputPort, edits);
+ editList.add(getCreateAndConnectDatalinkEdit(dataflow, source, sink,
+ edits));
+ return new CompoundEdit(editList);
+ }
+
+ /**
+ * Find a unique port name given a list of existing ports.
+ * <p>
+ * If needed, the returned port name will be prefixed with an underscore and
+ * a number, starting from 2. (The original being 'number 1')
+ * <p>
+ * Although not strictly needed by Taverna, for added user friendliness the
+ * case of the existing port names are ignored when checking for uniqueness.
+ *
+ * @see #uniqueProcessorName(String, Dataflow)
+ *
+ * @param suggestedPortName
+ * Port name suggested for new port
+ * @param existingPorts
+ * Collection of existing {@link Port}s
+ * @return A port name unique for the given collection of port
+ */
+ public static String uniquePortName(String suggestedPortName,
+ Collection<? extends Port> existingPorts) {
+ // Make sure we have a unique port name
+ Set<String> existingNames = new HashSet<>();
+ for (Port existingPort : existingPorts)
+ existingNames.add(existingPort.getName().toLowerCase());
+ String candidateName = suggestedPortName;
+ long counter = 2;
+ while (existingNames.contains(candidateName.toLowerCase()))
+ candidateName = suggestedPortName + "_" + counter++;
+ return candidateName;
+ }
+
+ public static Edit<?> getMoveDatalinkSinkEdit(Dataflow dataflow,
+ Datalink datalink, EventHandlingInputPort sink, Edits edits) {
+ List<Edit<?>> editList = new ArrayList<>();
+ editList.add(edits.getDisconnectDatalinkEdit(datalink));
+ if (datalink.getSink() instanceof ProcessorInputPort)
+ editList.add(getRemoveProcessorInputPortEdit(
+ (ProcessorInputPort) datalink.getSink(), edits));
+ editList.add(getCreateAndConnectDatalinkEdit(dataflow,
+ datalink.getSource(), sink, edits));
+ return new CompoundEdit(editList);
+ }
+
+ public static Edit<?> getDisconnectDatalinkAndRemovePortsEdit(
+ Datalink datalink, Edits edits) {
+ List<Edit<?>> editList = new ArrayList<>();
+ editList.add(edits.getDisconnectDatalinkEdit(datalink));
+ if (datalink.getSource() instanceof ProcessorOutputPort) {
+ ProcessorOutputPort processorOutputPort = (ProcessorOutputPort) datalink
+ .getSource();
+ if (processorOutputPort.getOutgoingLinks().size() == 1)
+ editList.add(getRemoveProcessorOutputPortEdit(
+ processorOutputPort, edits));
+ }
+ if (datalink.getSink() instanceof ProcessorInputPort)
+ editList.add(getRemoveProcessorInputPortEdit(
+ (ProcessorInputPort) datalink.getSink(), edits));
+ return new CompoundEdit(editList);
+ }
+
+ public static Edit<?> getRemoveProcessorOutputPortEdit(
+ ProcessorOutputPort port, Edits edits) {
+ List<Edit<?>> editList = new ArrayList<>();
+ Processor processor = port.getProcessor();
+ editList.add(edits.getRemoveProcessorOutputPortEdit(
+ port.getProcessor(), port));
+ for (Activity<?> activity : processor.getActivityList())
+ editList.add(edits.getRemoveActivityOutputPortMappingEdit(activity,
+ port.getName()));
+ return new CompoundEdit(editList);
+ }
+
+ public static Edit<?> getRemoveProcessorInputPortEdit(
+ ProcessorInputPort port, Edits edits) {
+ List<Edit<?>> editList = new ArrayList<>();
+ Processor processor = port.getProcessor();
+ editList.add(edits.getRemoveProcessorInputPortEdit(port.getProcessor(),
+ port));
+ for (Activity<?> activity : processor.getActivityList())
+ editList.add(edits.getRemoveActivityInputPortMappingEdit(activity,
+ port.getName()));
+ return new CompoundEdit(editList);
+ }
+
+ public static Edit<?> getEnableDisabledActivityEdit(Processor processor,
+ DisabledActivity disabledActivity, Edits edits) {
+ List<Edit<?>> editList = new ArrayList<>();
+ Activity<?> brokenActivity = disabledActivity.getActivity();
+ try {
+ @SuppressWarnings("unchecked")
+ Activity<Object> ra = brokenActivity.getClass().newInstance();
+ Object lastConfig = disabledActivity.getLastWorkingConfiguration();
+ if (lastConfig == null)
+ lastConfig = disabledActivity.getActivityConfiguration();
+ ra.configure(lastConfig);
+
+ Map<String, String> portMapping = ra.getInputPortMapping();
+ Set<String> portNames = new HashSet<>();
+ portNames.addAll(portMapping.keySet());
+ for (String portName : portNames)
+ editList.add(edits.getRemoveActivityInputPortMappingEdit(ra,
+ portName));
+ portMapping = ra.getOutputPortMapping();
+ portNames.clear();
+ portNames.addAll(portMapping.keySet());
+ for (String portName : portNames)
+ editList.add(edits.getRemoveActivityOutputPortMappingEdit(ra,
+ portName));
+
+ portMapping = disabledActivity.getInputPortMapping();
+ for (String portName : portMapping.keySet())
+ editList.add(edits.getAddActivityInputPortMappingEdit(ra,
+ portName, portMapping.get(portName)));
+ portMapping = disabledActivity.getOutputPortMapping();
+ for (String portName : portMapping.keySet())
+ editList.add(edits.getAddActivityOutputPortMappingEdit(ra,
+ portName, portMapping.get(portName)));
+
+ editList.add(edits.getRemoveActivityEdit(processor,
+ disabledActivity));
+ editList.add(edits.getAddActivityEdit(processor, ra));
+ } catch (ActivityConfigurationException ex) {
+ logger.error("Configuration exception ", ex);
+ return null;
+ } catch (InstantiationException | IllegalAccessException e) {
+ return null;
+ }
+ return new CompoundEdit(editList);
+ }
+
+ public static ProcessorInputPort getProcessorInputPort(Processor processor,
+ Activity<?> activity, InputPort activityInputPort) {
+ ProcessorInputPort result = null;
+ for (Entry<String, String> mapEntry : activity.getInputPortMapping()
+ .entrySet())
+ if (mapEntry.getValue().equals(activityInputPort.getName())) {
+ for (ProcessorInputPort processorInputPort : processor
+ .getInputPorts())
+ if (processorInputPort.getName().equals(mapEntry.getKey())) {
+ result = processorInputPort;
+ break;
+ }
+ break;
+ }
+ return result;
+ }
+
+ public static ProcessorOutputPort getProcessorOutputPort(
+ Processor processor, Activity<?> activity,
+ OutputPort activityOutputPort) {
+ ProcessorOutputPort result = null;
+ for (Entry<String, String> mapEntry : activity.getOutputPortMapping()
+ .entrySet())
+ if (mapEntry.getValue().equals(activityOutputPort.getName())) {
+ for (ProcessorOutputPort processorOutputPort : processor
+ .getOutputPorts())
+ if (processorOutputPort.getName().equals(mapEntry.getKey())) {
+ result = processorOutputPort;
+ break;
+ }
+ break;
+ }
+ return result;
+ }
+
+ public static ActivityInputPort getActivityInputPort(Activity<?> activity,
+ String portName) {
+ ActivityInputPort activityInputPort = null;
+ for (ActivityInputPort inputPort : activity.getInputPorts())
+ if (inputPort.getName().equals(portName)) {
+ activityInputPort = inputPort;
+ break;
+ }
+ return activityInputPort;
+ }
+
+ public static OutputPort getActivityOutputPort(Activity<?> activity,
+ String portName) {
+ OutputPort activityOutputPort = null;
+ for (OutputPort outputPort : activity.getOutputPorts())
+ if (outputPort.getName().equals(portName)) {
+ activityOutputPort = outputPort;
+ break;
+ }
+ return activityOutputPort;
+ }
+
+ public static String getUniqueMergeInputPortName(Merge merge, String name,
+ int count) {
+ String uniqueName = name + count;
+ for (MergeInputPort mergeInputPort : merge.getInputPorts())
+ if (mergeInputPort.getName().equals(uniqueName))
+ return getUniqueMergeInputPortName(merge, name, ++count);
+ return uniqueName;
+ }
+
+ public static Collection<Processor> getProcessorsWithActivity(
+ Dataflow dataflow, Activity<?> activity) {
+ Set<Processor> processors = new HashSet<>();
+ for (Processor processor : dataflow.getProcessors())
+ if (processor.getActivityList().contains(activity))
+ processors.add(processor);
+ return processors;
+ }
+
+ public static Collection<Processor> getProcessorsWithActivityInputPort(
+ Dataflow dataflow, ActivityInputPort inputPort) {
+ Set<Processor> processors = new HashSet<>();
+ for (Processor processor : dataflow.getProcessors()) {
+ // Does it contain a nested workflow?
+ if (containsNestedWorkflow(processor))
+ // Get the nested workflow and check all its nested processors
+ processors.addAll(getProcessorsWithActivityInputPort(
+ getNestedWorkflow(processor), inputPort));
+
+ /*
+ * Check all processor's activities (even if the processor contained
+ * a nested workflow, as its dataflow activity still contains input
+ * and output ports)
+ */
+ for (Activity<?> activity : processor.getActivityList())
+ if (activity.getInputPorts().contains(inputPort))
+ processors.add(processor);
+ }
+ return processors;
+ }
+
+ public static Collection<Processor> getProcessorsWithActivityOutputPort(
+ Dataflow dataflow, OutputPort outputPort) {
+ Set<Processor> processors = new HashSet<>();
+ for (Processor processor : dataflow.getProcessors()) {
+ // Does it contain a nested workflow?
+ if (containsNestedWorkflow(processor))
+ // Get the nested workflow and check all its nested processors
+ processors.addAll(getProcessorsWithActivityOutputPort(
+ getNestedWorkflow(processor), outputPort));
+
+ /*
+ * Check all processor's activities (even if the processor contained
+ * a nested workflow, as its dataflow activity still contains input
+ * and output ports)
+ */
+ for (Activity<?> activity : processor.getActivityList())
+ if (activity.getOutputPorts().contains(outputPort))
+ processors.add(processor);
+ }
+ return processors;
+ }
+
+ /**
+ * Get the TokenProcessingEntity (Processor, Merge or Dataflow) from the
+ * workflow that contains the given EventForwardingOutputPort. This can be
+ * an output port of a Processor or a Merge or an input port of a Dataflow
+ * that has an internal EventForwardingOutputPort attached to it.
+ *
+ * @param port
+ * @param workflow
+ * @return
+ */
+ public static TokenProcessingEntity getTokenProcessingEntityWithEventForwardingOutputPort(
+ EventForwardingOutputPort port, Dataflow workflow) {
+ // First check the workflow's inputs
+ for (DataflowInputPort input : workflow.getInputPorts())
+ if (input.getInternalOutputPort().equals(port))
+ return workflow;
+
+ // Check workflow's merges
+ for (Merge merge : workflow.getMerges())
+ if (merge.getOutputPort().equals(port))
+ return merge;
+
+ // Check workflow's processors
+ for (Processor processor : workflow.getProcessors()) {
+ for (OutputPort output : processor.getOutputPorts())
+ if (output.equals(port))
+ return processor;
+
+ // If processor contains a nested workflow - descend into it
+ if (containsNestedWorkflow(processor)) {
+ TokenProcessingEntity entity = getTokenProcessingEntityWithEventForwardingOutputPort(
+ port, getNestedWorkflow(processor));
+ if (entity != null)
+ return entity;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the TokenProcessingEntity (Processor, Merge or Dataflow) from the
+ * workflow that contains the given target EventHandlingInputPort. This can
+ * be an input port of a Processor or a Merge or an output port of a
+ * Dataflow that has an internal EventHandlingInputPort attached to it.
+ *
+ * @param port
+ * @param workflow
+ * @return
+ */
+ public static TokenProcessingEntity getTokenProcessingEntityWithEventHandlingInputPort(
+ EventHandlingInputPort port, Dataflow workflow) {
+ // First check the workflow's outputs
+ for (DataflowOutputPort output : workflow.getOutputPorts())
+ if (output.getInternalInputPort().equals(port))
+ return workflow;
+
+ // Check workflow's merges
+ for (Merge merge : workflow.getMerges())
+ for (EventHandlingInputPort input : merge.getInputPorts())
+ if (input.equals(port))
+ return merge;
+
+ // Check workflow's processors
+ for (Processor processor : workflow.getProcessors()) {
+ for (EventHandlingInputPort output : processor.getInputPorts())
+ if (output.equals(port))
+ return processor;
+
+ // If processor contains a nested workflow - descend into it
+ if (containsNestedWorkflow(processor)) {
+ TokenProcessingEntity entity = getTokenProcessingEntityWithEventHandlingInputPort(
+ port, getNestedWorkflow(processor));
+ if (entity != null)
+ return entity;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns true if processor contains a nested workflow.
+ */
+ public static boolean containsNestedWorkflow(Processor processor) {
+ List<?> activities = processor.getActivityList();
+ return !activities.isEmpty()
+ && activities.get(0) instanceof NestedDataflow;
+ }
+
+ /**
+ * Get the workflow that is nested inside. Only call this if
+ * {@link #containsNestedWorkflow()} returns true.
+ */
+ private static Dataflow getNestedWorkflow(Processor processor) {
+ return ((NestedDataflow) processor.getActivityList().get(0))
+ .getNestedDataflow();
+ }
+
+ /**
+ * Find the first processor that contains an activity that has the given
+ * activity input port. See #get
+ *
+ * @param dataflow
+ * @param targetPort
+ * @return
+ */
+ public static Processor getFirstProcessorWithActivityInputPort(
+ Dataflow dataflow, ActivityInputPort targetPort) {
+ for (Processor processor : getProcessorsWithActivityInputPort(
+ dataflow, targetPort))
+ return processor;
+ return null;
+ }
+
+ public static Processor getFirstProcessorWithActivityOutputPort(
+ Dataflow dataflow, ActivityOutputPort targetPort) {
+ for (Processor processor : getProcessorsWithActivityOutputPort(
+ dataflow, targetPort))
+ return processor;
+ return null;
+ }
+
+ /**
+ * Find a unique processor name for the supplied Dataflow, based upon the
+ * preferred name. If needed, an underscore and a numeric suffix is added to
+ * the preferred name, and incremented until it is unique, starting from 2.
+ * (The original being 'number 1')
+ * <p>
+ * Note that this method checks the uniqueness against the names of all
+ * {@link NamedWorkflowEntity}s, including {@link Merge}s.
+ * <p>
+ * Although not strictly needed by Taverna, for added user friendliness the
+ * case of the existing port names are ignored when checking for uniqueness.
+ *
+ * @param preferredName
+ * the preferred name for the Processor
+ * @param dataflow
+ * the dataflow for which the Processor name needs to be unique
+ * @return A unique processor name
+ */
+ public static String uniqueProcessorName(String preferredName,
+ Dataflow dataflow) {
+ Set<String> existingNames = new HashSet<>();
+ for (NamedWorkflowEntity entity : dataflow
+ .getEntities(NamedWorkflowEntity.class))
+ existingNames.add(entity.getLocalName().toLowerCase());
+ return uniqueObjectName(preferredName, existingNames);
+ }
+
+ /**
+ * Checks that the name does not have any characters that are invalid for a
+ * Taverna name.
+ *
+ * The name must contain only the chars[A-Za-z_0-9].
+ *
+ * @param name
+ * the original name
+ * @return the sanitised name
+ */
+ public static String sanitiseName(String name) {
+ if (Pattern.matches("\\w++", name) == false) {
+ StringBuilder result = new StringBuilder(name.length());
+ for (char c : name.toCharArray())
+ result.append(isLetterOrDigit(c) || c == '_' ? c : "_");
+ return result.toString();
+ }
+ return name;
+ }
+
+ public static String uniqueObjectName(String preferredName,
+ Set<String> existingNames) {
+ String uniqueName = preferredName;
+ long suffix = 2;
+ while (existingNames.contains(uniqueName.toLowerCase()))
+ uniqueName = preferredName + "_" + suffix++;
+ return uniqueName;
+
+ }
+
+ /**
+ * Add the identification of a Dataflow into its identification annotation
+ * chain (if necessary)
+ *
+ * @return Whether an identification needed to be added
+ */
+ public static boolean addDataflowIdentification(Dataflow dataflow,
+ String internalId, Edits edits) {
+ IdentificationAssertion ia = (IdentificationAssertion) getAnnotation(
+ dataflow, IdentificationAssertion.class);
+ if (ia != null && ia.getIdentification().equals(internalId))
+ return false;
+ IdentificationAssertion newIa = new IdentificationAssertion();
+ newIa.setIdentification(internalId);
+ try {
+ addAnnotation(dataflow, newIa, edits).doEdit();
+ return true;
+ } catch (EditException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Return a path of processors where the last element is this processor and
+ * previous ones are nested processors that contain this one all the way to
+ * the top but excluding the top level workflow as this is only a list of
+ * processors.
+ */
+ public static List<Processor> getNestedPathForProcessor(
+ Processor processor, Dataflow dataflow) {
+ for (Processor proc : dataflow.getProcessors())
+ if (proc == processor) { // found it
+ List<Processor> list = new ArrayList<>();
+ list.add(processor);
+ return list;
+ } else if (containsNestedWorkflow(proc)) {
+ /*
+ * check inside this nested processor
+ */
+ List<Processor> nestedList = getNestedPathForProcessor(
+ processor, getNestedWorkflow(proc));
+ if (nestedList == null)
+ // processor not found in this nested workflow
+ continue;
+ // add this nested processor to the list
+ nestedList.add(0, proc);
+ return nestedList;
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/resources/META-INF/services/net.sf.taverna.t2.visit.VisitKind
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/resources/META-INF/services/net.sf.taverna.t2.visit.VisitKind b/taverna-workflowmodel-api/src/main/resources/META-INF/services/net.sf.taverna.t2.visit.VisitKind
deleted file mode 100644
index 4ef9d66..0000000
--- a/taverna-workflowmodel-api/src/main/resources/META-INF/services/net.sf.taverna.t2.visit.VisitKind
+++ /dev/null
@@ -1 +0,0 @@
-net.sf.taverna.t2.workflowmodel.health.HealthCheck
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker b/taverna-workflowmodel-api/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker
deleted file mode 100644
index e2708bc..0000000
--- a/taverna-workflowmodel-api/src/main/resources/META-INF/services/net.sf.taverna.t2.workflowmodel.health.HealthChecker
+++ /dev/null
@@ -1,2 +0,0 @@
-net.sf.taverna.t2.workflowmodel.health.DisabledActivityHealthChecker
-net.sf.taverna.t2.workflowmodel.health.UnrecognizedActivityHealthChecker
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/resources/META-INF/services/org.apache.taverna.visit.VisitKind
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/resources/META-INF/services/org.apache.taverna.visit.VisitKind b/taverna-workflowmodel-api/src/main/resources/META-INF/services/org.apache.taverna.visit.VisitKind
new file mode 100644
index 0000000..6568472
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/resources/META-INF/services/org.apache.taverna.visit.VisitKind
@@ -0,0 +1 @@
+org.apache.taverna.workflowmodel.health.HealthCheck
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/resources/META-INF/services/org.apache.taverna.workflowmodel.health.HealthChecker
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/resources/META-INF/services/org.apache.taverna.workflowmodel.health.HealthChecker b/taverna-workflowmodel-api/src/main/resources/META-INF/services/org.apache.taverna.workflowmodel.health.HealthChecker
new file mode 100644
index 0000000..46e84d8
--- /dev/null
+++ b/taverna-workflowmodel-api/src/main/resources/META-INF/services/org.apache.taverna.workflowmodel.health.HealthChecker
@@ -0,0 +1,2 @@
+org.apache.taverna.workflowmodel.health.DisabledActivityHealthChecker
+org.apache.taverna.workflowmodel.health.UnrecognizedActivityHealthChecker
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context-osgi.xml
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context-osgi.xml b/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context-osgi.xml
index 8fdabdf..9dea97c 100644
--- a/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context-osgi.xml
+++ b/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context-osgi.xml
@@ -6,20 +6,20 @@
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd">
- <service ref="author" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />
- <service ref="descriptiveTitle" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />
- <service ref="freeTextDescription" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />
- <service ref="hostInstitution" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />
- <!--<service ref="mimeType" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />-->
- <service ref="documentationUrl" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />
- <service ref="optional" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />
- <service ref="exampleValue" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />
- <service ref="semanticAnnotation" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />
- <service ref="identificationAssertion" interface="net.sf.taverna.t2.annotation.AnnotationBeanSPI" />
+ <service ref="author" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />
+ <service ref="descriptiveTitle" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />
+ <service ref="freeTextDescription" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />
+ <service ref="hostInstitution" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />
+ <!--<service ref="mimeType" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />-->
+ <service ref="documentationUrl" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />
+ <service ref="optional" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />
+ <service ref="exampleValue" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />
+ <service ref="semanticAnnotation" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />
+ <service ref="identificationAssertion" interface="org.apache.taverna.annotation.AnnotationBeanSPI" />
- <service ref="healthCheck" interface="net.sf.taverna.t2.visit.VisitKind" />
+ <service ref="healthCheck" interface="org.apache.taverna.visit.VisitKind" />
- <service ref="disabledActivityHealthChecker" interface="net.sf.taverna.t2.workflowmodel.health.HealthChecker" />
- <service ref="unrecognizedActivityHealthChecker" interface="net.sf.taverna.t2.workflowmodel.health.HealthChecker" />
+ <service ref="disabledActivityHealthChecker" interface="org.apache.taverna.workflowmodel.health.HealthChecker" />
+ <service ref="unrecognizedActivityHealthChecker" interface="org.apache.taverna.workflowmodel.health.HealthChecker" />
</beans:beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context.xml
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context.xml b/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context.xml
index ea52514..f0c0b77 100644
--- a/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context.xml
+++ b/taverna-workflowmodel-api/src/main/resources/META-INF/spring/workflowmodel-api-context.xml
@@ -4,20 +4,20 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
- <bean id="author" class="net.sf.taverna.t2.annotation.annotationbeans.Author" />
- <bean id="descriptiveTitle" class="net.sf.taverna.t2.annotation.annotationbeans.DescriptiveTitle" />
- <bean id="freeTextDescription" class="net.sf.taverna.t2.annotation.annotationbeans.FreeTextDescription" />
- <bean id="hostInstitution" class="net.sf.taverna.t2.annotation.annotationbeans.HostInstitution" />
- <!--<bean id="mimeType" class="net.sf.taverna.t2.annotation.annotationbeans.MimeType" />-->
- <bean id="documentationUrl" class="net.sf.taverna.t2.annotation.annotationbeans.DocumentationUrl" />
- <bean id="optional" class="net.sf.taverna.t2.annotation.annotationbeans.Optional" />
- <bean id="exampleValue" class="net.sf.taverna.t2.annotation.annotationbeans.ExampleValue" />
- <bean id="semanticAnnotation" class="net.sf.taverna.t2.annotation.annotationbeans.SemanticAnnotation" />
- <bean id="identificationAssertion" class="net.sf.taverna.t2.annotation.annotationbeans.IdentificationAssertion" />
+ <bean id="author" class="org.apache.taverna.annotation.annotationbeans.Author" />
+ <bean id="descriptiveTitle" class="org.apache.taverna.annotation.annotationbeans.DescriptiveTitle" />
+ <bean id="freeTextDescription" class="org.apache.taverna.annotation.annotationbeans.FreeTextDescription" />
+ <bean id="hostInstitution" class="org.apache.taverna.annotation.annotationbeans.HostInstitution" />
+ <!--<bean id="mimeType" class="org.apache.taverna.annotation.annotationbeans.MimeType" />-->
+ <bean id="documentationUrl" class="org.apache.taverna.annotation.annotationbeans.DocumentationUrl" />
+ <bean id="optional" class="org.apache.taverna.annotation.annotationbeans.Optional" />
+ <bean id="exampleValue" class="org.apache.taverna.annotation.annotationbeans.ExampleValue" />
+ <bean id="semanticAnnotation" class="org.apache.taverna.annotation.annotationbeans.SemanticAnnotation" />
+ <bean id="identificationAssertion" class="org.apache.taverna.annotation.annotationbeans.IdentificationAssertion" />
- <bean id="healthCheck" class="net.sf.taverna.t2.workflowmodel.health.HealthCheck" />
+ <bean id="healthCheck" class="org.apache.taverna.workflowmodel.health.HealthCheck" />
- <bean id="disabledActivityHealthChecker" class="net.sf.taverna.t2.workflowmodel.health.DisabledActivityHealthChecker" />
- <bean id="unrecognizedActivityHealthChecker" class="net.sf.taverna.t2.workflowmodel.health.UnrecognizedActivityHealthChecker" />
+ <bean id="disabledActivityHealthChecker" class="org.apache.taverna.workflowmodel.health.DisabledActivityHealthChecker" />
+ <bean id="unrecognizedActivityHealthChecker" class="org.apache.taverna.workflowmodel.health.UnrecognizedActivityHealthChecker" />
</beans>
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/monitor/TestMonitorManager.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/monitor/TestMonitorManager.java b/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/monitor/TestMonitorManager.java
deleted file mode 100644
index 8ce2b6e..0000000
--- a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/monitor/TestMonitorManager.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007 The University of Manchester
- *
- * Modifications to the initial code base are copyright of their
- * respective authors, or their employers as appropriate.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- ******************************************************************************/
-package net.sf.taverna.t2.monitor;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
-
-import net.sf.taverna.t2.lang.observer.Observable;
-import net.sf.taverna.t2.lang.observer.Observer;
-import net.sf.taverna.t2.monitor.MonitorManager.AddPropertiesMessage;
-import net.sf.taverna.t2.monitor.MonitorManager.DeregisterNodeMessage;
-import net.sf.taverna.t2.monitor.MonitorManager.MonitorMessage;
-import net.sf.taverna.t2.monitor.MonitorManager.RegisterNodeMessage;
-
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Test {@link MonitorManager}.
- *
- * @author Stian Soiland-Reyes
- *
- */
-public class TestMonitorManager {
- private MonitorManager monitorManager;
-
- @Test
- public void addMonitor() {
- TestMonitor testMonitor = new TestMonitor();
- monitorManager.addObserver(testMonitor);
- assertEquals(0, testMonitor.getCounts());
- // Make a fake registration
- Object workflowObject = "The workflow object as a string";
- String[] owningProcess = { "dataflow0", "process4", "42424" };
- Set<MonitorableProperty<?>> properties = new HashSet<>();
- properties.add(new ExampleProperty());
- monitorManager.registerNode(workflowObject, owningProcess, properties);
-
- assertEquals(1, testMonitor.getCounts());
- assertEquals(monitorManager, testMonitor.lastSender);
- MonitorMessage lastMessage = testMonitor.lastMessage;
- assertTrue("Owning process did not match", Arrays.equals(owningProcess,
- lastMessage.getOwningProcess()));
-
- assertTrue("Message was not a RegisterNodeMessage",
- lastMessage instanceof RegisterNodeMessage);
- RegisterNodeMessage registerNodeMessage = (RegisterNodeMessage) lastMessage;
- assertSame("Workflow object was not same", workflowObject,
- registerNodeMessage.getWorkflowObject());
- assertEquals(properties, registerNodeMessage.getProperties());
-
- assertEquals("Another event was received", 1, testMonitor.getCounts());
- }
-
- @Test
- public void addProperties() {
- TestMonitor testMonitor = new TestMonitor();
- monitorManager.addObserver(testMonitor);
- assertEquals(0, testMonitor.getCounts());
- // Make a fake add properties
- String[] owningProcess = { "dataflow0", "process4", "42424" };
- Set<MonitorableProperty<?>> newProperties = new HashSet<>();
- newProperties.add(new ExampleProperty());
- monitorManager.addPropertiesToNode(owningProcess, newProperties);
-
- assertEquals(1, testMonitor.getCounts());
- assertEquals(monitorManager, testMonitor.lastSender);
- MonitorMessage lastMessage = testMonitor.lastMessage;
- assertTrue("Owning process did not match", Arrays.equals(owningProcess,
- lastMessage.getOwningProcess()));
-
- assertTrue("Message was not a AddPropertiesMessage",
- lastMessage instanceof AddPropertiesMessage);
- AddPropertiesMessage registerNodeMessage = (AddPropertiesMessage) lastMessage;
- assertEquals(newProperties, registerNodeMessage.getNewProperties());
-
- assertEquals("Another event was received", 1, testMonitor.getCounts());
- }
-
- @Before
- public void findMonitorManager() {
- monitorManager = MonitorManager.getInstance();
- }
-
- @Test
- public void removeMonitor() {
- TestMonitor testMonitor = new TestMonitor();
- monitorManager.addObserver(testMonitor);
- assertEquals(0, testMonitor.getCounts());
-
- // Make a fake deregistration
- String[] owningProcess = { "dataflow0", "process4", "1337" };
- monitorManager.deregisterNode(owningProcess);
-
- assertEquals(1, testMonitor.getCounts());
- assertEquals(monitorManager, testMonitor.lastSender);
- MonitorMessage lastMessage = testMonitor.lastMessage;
- assertTrue("Owning process did not match", Arrays.equals(owningProcess,
- lastMessage.getOwningProcess()));
- assertTrue("Message was not a DeregisterNodeMessage",
- lastMessage instanceof DeregisterNodeMessage);
- assertEquals("Another event was received", 1, testMonitor.getCounts());
- }
-
- public class TestMonitor implements Observer<MonitorManager.MonitorMessage> {
-
- private int counts = 0;
- private MonitorMessage lastMessage;
- private Observable<MonitorMessage> lastSender;
-
- public int getCounts() {
- return counts;
- }
-
- public MonitorMessage getMessage() {
- return lastMessage;
- }
-
- public Observable<MonitorMessage> getSender() {
- return lastSender;
- }
-
- @Override
- public synchronized void notify(Observable<MonitorMessage> sender,
- MonitorMessage message) throws Exception {
- this.lastSender = sender;
- this.lastMessage = message;
- this.counts++;
- }
- }
-
- private final class ExampleProperty implements MonitorableProperty<String> {
- @Override
- public Date getLastModified() {
- return new Date();
- }
-
- @Override
- public String[] getName() {
- return new String[] { "monitor", "test", "example" };
- }
-
- @Override
- public String getValue() throws NoSuchPropertyException {
- return "Example property value";
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/DummyVisitKind.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/DummyVisitKind.java b/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/DummyVisitKind.java
deleted file mode 100644
index 7f8767f..0000000
--- a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/DummyVisitKind.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- *
- */
-package net.sf.taverna.t2.workflowmodel.health;
-
-import net.sf.taverna.t2.visit.VisitKind;
-import net.sf.taverna.t2.visit.Visitor;
-
-/**
- * @author alanrw
- *
- */
-public class DummyVisitKind extends VisitKind {
- @Override
- public Class<? extends Visitor<?>> getVisitorClass() {
- return null;
- }
-
- private static class Singleton {
- private static DummyVisitKind instance = new DummyVisitKind();
- }
-
- public static DummyVisitKind getInstance() {
- return Singleton.instance;
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/FloatHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/FloatHealthChecker.java b/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/FloatHealthChecker.java
deleted file mode 100644
index 228ed5d..0000000
--- a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/FloatHealthChecker.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007 The University of Manchester
- *
- * Modifications to the initial code base are copyright of their
- * respective authors, or their employers as appropriate.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- ******************************************************************************/
-package net.sf.taverna.t2.workflowmodel.health;
-
-import java.util.List;
-
-import net.sf.taverna.t2.visit.VisitReport;
-import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
-
-public class FloatHealthChecker implements HealthChecker<Float> {
-
- @Override
- public boolean canVisit(Object subject) {
- return subject!=null && subject instanceof Float;
- }
-
- @Override
- public VisitReport visit(Float o, List<Object> ancestry) {
- return null;
- }
-
- @Override
- public boolean isTimeConsuming() {
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/FloatHealthChecker2.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/FloatHealthChecker2.java b/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/FloatHealthChecker2.java
deleted file mode 100644
index 80acac8..0000000
--- a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/FloatHealthChecker2.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007 The University of Manchester
- *
- * Modifications to the initial code base are copyright of their
- * respective authors, or their employers as appropriate.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- ******************************************************************************/
-package net.sf.taverna.t2.workflowmodel.health;
-
-import java.util.List;
-
-import net.sf.taverna.t2.visit.VisitReport;
-
-public class FloatHealthChecker2 implements HealthChecker<Float> {
-
- @Override
- public boolean canVisit(Object subject) {
- return subject!=null && subject instanceof Float;
- }
-
- @Override
- public VisitReport visit(Float o, List<Object> ancestry) {
- return null;
- }
-
- @Override
- public boolean isTimeConsuming() {
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/HealthReportTest.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/HealthReportTest.java b/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/HealthReportTest.java
deleted file mode 100644
index 9ee1fd9..0000000
--- a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/HealthReportTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007 The University of Manchester
- *
- * Modifications to the initial code base are copyright of their
- * respective authors, or their employers as appropriate.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- ******************************************************************************/
-package net.sf.taverna.t2.workflowmodel.health;
-
-
-import static org.junit.Assert.assertEquals;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import net.sf.taverna.t2.visit.VisitReport;
-import net.sf.taverna.t2.visit.VisitReport.Status;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class HealthReportTest {
-
- VisitReport report;
-
- @Before
- public void setUp() throws Exception {
- List<VisitReport> subreports = new ArrayList<>();
- subreports.add(new VisitReport(DummyVisitKind.getInstance(), "sub subject","this is a subreport",0,Status.OK));
- report = new VisitReport(DummyVisitKind.getInstance(), "a subject","a message",0, Status.WARNING,subreports);
- }
-
- @Test
- public void testActivityVisitReportStringStatus() {
- report = new VisitReport(DummyVisitKind.getInstance(), "the subject","a string",0, Status.SEVERE);
- assertEquals("a string",report.getMessage());
- assertEquals(Status.SEVERE,report.getStatus());
- assertEquals("the subject",report.getSubject());
- assertEquals("the subreports should be an empty list",0,report.getSubReports().size());
- }
-
- @Test
- public void testGetMessage() {
- assertEquals("a message",report.getMessage());
- }
-
- @Test
- public void testGetStatus() {
- assertEquals(Status.WARNING,report.getStatus());
- }
-
- @Test
- public void testGetSubject() {
- assertEquals("a subject",report.getSubject());
- }
-
- @Test
- public void testGetSubreports() {
- Collection<VisitReport> subreports = report.getSubReports();
- assertEquals("There should be 1 report",1,subreports.size());
- assertEquals("Wrong subject","sub subject",subreports.iterator().next().getSubject());
- }
-
- @Test
- public void testStatusHighestIncludingSubReports() {
- report = new VisitReport(DummyVisitKind.getInstance(), "parent","set to ok",0, Status.OK);
- assertEquals("should be OK",Status.OK,report.getStatus());
- report.getSubReports().add(new VisitReport(DummyVisitKind.getInstance(), "child1","set to warning",0, Status.WARNING));
- assertEquals("should be WARNING",Status.WARNING,report.getStatus());
- report.getSubReports().add(new VisitReport(DummyVisitKind.getInstance(), "child1","set to severe",0, Status.SEVERE));
- assertEquals("should be SEVERE",Status.SEVERE,report.getStatus());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/StringHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/StringHealthChecker.java b/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/StringHealthChecker.java
deleted file mode 100644
index d550a40..0000000
--- a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/health/StringHealthChecker.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007 The University of Manchester
- *
- * Modifications to the initial code base are copyright of their
- * respective authors, or their employers as appropriate.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- ******************************************************************************/
-package net.sf.taverna.t2.workflowmodel.health;
-
-import java.util.List;
-
-import net.sf.taverna.t2.visit.VisitReport;
-import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
-
-public class StringHealthChecker implements HealthChecker<String> {
-
- @Override
- public boolean canVisit(Object subject) {
- return subject!=null && subject instanceof String;
- }
-
- @Override
- public VisitReport visit(String o, List<Object> ancestry) {
- return null;
- }
-
- @Override
- public boolean isTimeConsuming() {
- return false;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/processor/iteration/TestIterationStrategyNodes.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/processor/iteration/TestIterationStrategyNodes.java b/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/processor/iteration/TestIterationStrategyNodes.java
deleted file mode 100644
index 8cf8141..0000000
--- a/taverna-workflowmodel-api/src/test/java/net/sf/taverna/t2/workflowmodel/processor/iteration/TestIterationStrategyNodes.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*******************************************************************************
- * Copyright (C) 2007 The University of Manchester
- *
- * Modifications to the initial code base are copyright of their
- * respective authors, or their employers as appropriate.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- ******************************************************************************/
-package net.sf.taverna.t2.workflowmodel.processor.iteration;
-
-import static org.junit.Assert.*;
-
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.Map;
-
-import javax.swing.tree.TreeNode;
-
-import net.sf.taverna.t2.invocation.Completion;
-import net.sf.taverna.t2.workflowmodel.processor.activity.Job;
-
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Test {@link AbstractIterationStrategyNode} implementations for
- * {@link TreeNode} behaviour.
- *
- * @author Stian Soiland-Reyes
- *
- */
-public class TestIterationStrategyNodes {
-
- TerminalNode root;
- private NamedInputPortNode input1;
- private NamedInputPortNode input2;
- private CrossProduct crossProduct1;
- private CrossProduct crossProduct2;
- private DotProduct dotProduct1;
- private DotProduct dotProduct2;
-
- @Test
- public void addSingleChildToTerminal() throws Exception {
- assertNull(input1.getParent());
- assertEquals(0, root.getChildCount());
- root.insert(input1);
- assertEquals(root, input1.getParent());
- assertEquals(1, root.getChildCount());
- assertEquals(input1, root.getChildAt(0));
- assertEquals(Arrays.asList(input1), root.getChildren());
-
- root.insert(input1);
- assertEquals(1, root.getChildCount());
-
- root.insert(input1, 0);
- assertEquals(1, root.getChildCount());
- }
-
- @Test(expected = IllegalStateException.class)
- public void cantAddSeveralChildrenToTerminal() throws Exception {
- root.insert(input1);
- root.insert(input2);
- }
-
- @Test
- public void addCrossProduct() throws Exception {
- assertNull(crossProduct1.getParent());
- crossProduct1.setParent(root);
- assertEquals(root, crossProduct1.getParent());
- assertEquals(1, root.getChildCount());
- assertEquals(crossProduct1, root.getChildAt(0));
- assertEquals(Arrays.asList(crossProduct1), root.getChildren());
- assertEquals(0, crossProduct1.getChildCount());
-
- crossProduct1.insert(input1);
- assertEquals(input1, crossProduct1.getChildAt(0));
- crossProduct1.insert(input2, 0);
- assertEquals(input2, crossProduct1.getChildAt(0));
- assertEquals(input1, crossProduct1.getChildAt(1));
- assertEquals(2, crossProduct1.getChildCount());
- assertEquals(Arrays.asList(input2, input1), crossProduct1.getChildren());
-
- // A re-insert should move it
- crossProduct1.insert(input2, 2);
- assertEquals(2, crossProduct1.getChildCount());
- assertEquals(Arrays.asList(input1, input2), crossProduct1.getChildren());
-
- crossProduct1.insert(input2, 0);
- assertEquals(Arrays.asList(input2, input1), crossProduct1.getChildren());
-
- crossProduct1.insert(input1, 1);
- assertEquals(Arrays.asList(input2, input1), crossProduct1.getChildren());
- }
-
- @Test
- public void addCrossProductMany() {
- crossProduct1.insert(dotProduct1);
- crossProduct1.insert(dotProduct2);
- crossProduct1.insert(input1);
- crossProduct1.insert(input2);
- crossProduct1.insert(crossProduct2);
- assertEquals(5, crossProduct1.getChildCount());
- assertEquals(Arrays.asList(dotProduct1, dotProduct2, input1, input2,
- crossProduct2), crossProduct1.getChildren());
- Enumeration<IterationStrategyNode> enumeration = crossProduct1
- .children();
- assertTrue(enumeration.hasMoreElements());
- assertEquals(dotProduct1, enumeration.nextElement());
- assertEquals(dotProduct2, enumeration.nextElement());
- assertEquals(input1, enumeration.nextElement());
- assertEquals(input2, enumeration.nextElement());
- assertEquals(crossProduct2, enumeration.nextElement());
- assertFalse(enumeration.hasMoreElements());
- }
-
- @Test
- public void moveNodeToDifferentParent() {
- crossProduct1.setParent(root);
- crossProduct1.insert(input1);
- crossProduct1.insert(dotProduct1);
- dotProduct1.insert(input2);
- dotProduct1.insert(crossProduct2);
-
- // Check tree
- assertEquals(crossProduct2, root.getChildAt(0).getChildAt(1)
- .getChildAt(1));
- assertEquals(Arrays.asList(input2, crossProduct2), dotProduct1
- .getChildren());
-
- crossProduct1.insert(crossProduct2, 1);
- assertEquals(Arrays.asList(input1, crossProduct2, dotProduct1),
- crossProduct1.getChildren());
- assertEquals(crossProduct1, crossProduct2.getParent());
- // Should no longer be in dotProduct1
- assertEquals(Arrays.asList(input2), dotProduct1.getChildren());
- }
-
- @Test(expected = IllegalStateException.class)
- public void cantAddToNamedInput() throws Exception {
- input1.insert(dotProduct1);
- }
-
- @Test
- public void cantAddSelf() throws Exception {
- dotProduct1.setParent(crossProduct1);
- try {
- dotProduct1.insert(dotProduct1);
- fail("Didn't throw IllegalArgumentException");
- } catch (IllegalArgumentException ex) {
- // Make sure we didn't loose our old parent and
- // ended up in a funny state
- assertEquals(crossProduct1, dotProduct1.getParent());
- assertEquals(dotProduct1, crossProduct1.getChildAt(0));
- }
- }
-
- @Test
- public void cantSetSelfParent() throws Exception {
- crossProduct1.insert(dotProduct1);
- try {
- dotProduct1.setParent(dotProduct1);
- fail("Didn't throw IllegalArgumentException");
- } catch (IllegalArgumentException ex) {
- // Make sure we didn't loose our old parent and
- // ended up in a funny state
- assertEquals(crossProduct1, dotProduct1.getParent());
- assertEquals(dotProduct1, crossProduct1.getChildAt(0));
- }
- }
-
- @Before
- public void makeNodes() throws Exception {
- root = new DummyTerminalNode();
- input1 = new NamedInputPortNode("input1", 1);
- input2 = new NamedInputPortNode("input2", 2);
- crossProduct1 = new CrossProduct();
- crossProduct2 = new CrossProduct();
- dotProduct1 = new DotProduct();
- dotProduct2 = new DotProduct();
- }
-
- @SuppressWarnings("serial")
- protected final class DummyTerminalNode extends TerminalNode {
-
- @Override
- public int getIterationDepth(Map<String, Integer> inputDepths)
- throws IterationTypeMismatchException {
- return 0;
- }
-
- @Override
- public void receiveCompletion(int inputIndex, Completion completion) {
- }
-
- @Override
- public void receiveJob(int inputIndex, Job newJob) {
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/org/apache/taverna/monitor/TestMonitorManager.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/org/apache/taverna/monitor/TestMonitorManager.java b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/monitor/TestMonitorManager.java
new file mode 100644
index 0000000..93f7496
--- /dev/null
+++ b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/monitor/TestMonitorManager.java
@@ -0,0 +1,172 @@
+/*
+* 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.monitor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.monitor.MonitorManager.AddPropertiesMessage;
+import org.apache.taverna.monitor.MonitorManager.DeregisterNodeMessage;
+import org.apache.taverna.monitor.MonitorManager.MonitorMessage;
+import org.apache.taverna.monitor.MonitorManager.RegisterNodeMessage;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test {@link MonitorManager}.
+ *
+ * @author Stian Soiland-Reyes
+ *
+ */
+public class TestMonitorManager {
+ private MonitorManager monitorManager;
+
+ @Test
+ public void addMonitor() {
+ TestMonitor testMonitor = new TestMonitor();
+ monitorManager.addObserver(testMonitor);
+ assertEquals(0, testMonitor.getCounts());
+ // Make a fake registration
+ Object workflowObject = "The workflow object as a string";
+ String[] owningProcess = { "dataflow0", "process4", "42424" };
+ Set<MonitorableProperty<?>> properties = new HashSet<>();
+ properties.add(new ExampleProperty());
+ monitorManager.registerNode(workflowObject, owningProcess, properties);
+
+ assertEquals(1, testMonitor.getCounts());
+ assertEquals(monitorManager, testMonitor.lastSender);
+ MonitorMessage lastMessage = testMonitor.lastMessage;
+ assertTrue("Owning process did not match", Arrays.equals(owningProcess,
+ lastMessage.getOwningProcess()));
+
+ assertTrue("Message was not a RegisterNodeMessage",
+ lastMessage instanceof RegisterNodeMessage);
+ RegisterNodeMessage registerNodeMessage = (RegisterNodeMessage) lastMessage;
+ assertSame("Workflow object was not same", workflowObject,
+ registerNodeMessage.getWorkflowObject());
+ assertEquals(properties, registerNodeMessage.getProperties());
+
+ assertEquals("Another event was received", 1, testMonitor.getCounts());
+ }
+
+ @Test
+ public void addProperties() {
+ TestMonitor testMonitor = new TestMonitor();
+ monitorManager.addObserver(testMonitor);
+ assertEquals(0, testMonitor.getCounts());
+ // Make a fake add properties
+ String[] owningProcess = { "dataflow0", "process4", "42424" };
+ Set<MonitorableProperty<?>> newProperties = new HashSet<>();
+ newProperties.add(new ExampleProperty());
+ monitorManager.addPropertiesToNode(owningProcess, newProperties);
+
+ assertEquals(1, testMonitor.getCounts());
+ assertEquals(monitorManager, testMonitor.lastSender);
+ MonitorMessage lastMessage = testMonitor.lastMessage;
+ assertTrue("Owning process did not match", Arrays.equals(owningProcess,
+ lastMessage.getOwningProcess()));
+
+ assertTrue("Message was not a AddPropertiesMessage",
+ lastMessage instanceof AddPropertiesMessage);
+ AddPropertiesMessage registerNodeMessage = (AddPropertiesMessage) lastMessage;
+ assertEquals(newProperties, registerNodeMessage.getNewProperties());
+
+ assertEquals("Another event was received", 1, testMonitor.getCounts());
+ }
+
+ @Before
+ public void findMonitorManager() {
+ monitorManager = MonitorManager.getInstance();
+ }
+
+ @Test
+ public void removeMonitor() {
+ TestMonitor testMonitor = new TestMonitor();
+ monitorManager.addObserver(testMonitor);
+ assertEquals(0, testMonitor.getCounts());
+
+ // Make a fake deregistration
+ String[] owningProcess = { "dataflow0", "process4", "1337" };
+ monitorManager.deregisterNode(owningProcess);
+
+ assertEquals(1, testMonitor.getCounts());
+ assertEquals(monitorManager, testMonitor.lastSender);
+ MonitorMessage lastMessage = testMonitor.lastMessage;
+ assertTrue("Owning process did not match", Arrays.equals(owningProcess,
+ lastMessage.getOwningProcess()));
+ assertTrue("Message was not a DeregisterNodeMessage",
+ lastMessage instanceof DeregisterNodeMessage);
+ assertEquals("Another event was received", 1, testMonitor.getCounts());
+ }
+
+ public class TestMonitor implements Observer<MonitorManager.MonitorMessage> {
+
+ private int counts = 0;
+ private MonitorMessage lastMessage;
+ private Observable<MonitorMessage> lastSender;
+
+ public int getCounts() {
+ return counts;
+ }
+
+ public MonitorMessage getMessage() {
+ return lastMessage;
+ }
+
+ public Observable<MonitorMessage> getSender() {
+ return lastSender;
+ }
+
+ @Override
+ public synchronized void notify(Observable<MonitorMessage> sender,
+ MonitorMessage message) throws Exception {
+ this.lastSender = sender;
+ this.lastMessage = message;
+ this.counts++;
+ }
+ }
+
+ private final class ExampleProperty implements MonitorableProperty<String> {
+ @Override
+ public Date getLastModified() {
+ return new Date();
+ }
+
+ @Override
+ public String[] getName() {
+ return new String[] { "monitor", "test", "example" };
+ }
+
+ @Override
+ public String getValue() throws NoSuchPropertyException {
+ return "Example property value";
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/DummyVisitKind.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/DummyVisitKind.java b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/DummyVisitKind.java
new file mode 100644
index 0000000..4c7ef30
--- /dev/null
+++ b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/DummyVisitKind.java
@@ -0,0 +1,42 @@
+/*
+* 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;
+
+/**
+ * @author alanrw
+ *
+ */
+public class DummyVisitKind extends VisitKind {
+ @Override
+ public Class<? extends Visitor<?>> getVisitorClass() {
+ return null;
+ }
+
+ private static class Singleton {
+ private static DummyVisitKind instance = new DummyVisitKind();
+ }
+
+ public static DummyVisitKind getInstance() {
+ return Singleton.instance;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/FloatHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/FloatHealthChecker.java b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/FloatHealthChecker.java
new file mode 100644
index 0000000..d88aaac
--- /dev/null
+++ b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/FloatHealthChecker.java
@@ -0,0 +1,43 @@
+/*
+* 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 java.util.List;
+
+import org.apache.taverna.visit.VisitReport;
+
+public class FloatHealthChecker implements HealthChecker<Float> {
+
+ @Override
+ public boolean canVisit(Object subject) {
+ return subject!=null && subject instanceof Float;
+ }
+
+ @Override
+ public VisitReport visit(Float o, List<Object> ancestry) {
+ return null;
+ }
+
+ @Override
+ public boolean isTimeConsuming() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/FloatHealthChecker2.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/FloatHealthChecker2.java b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/FloatHealthChecker2.java
new file mode 100644
index 0000000..9a05080
--- /dev/null
+++ b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/FloatHealthChecker2.java
@@ -0,0 +1,43 @@
+/*
+* 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 java.util.List;
+
+import org.apache.taverna.visit.VisitReport;
+
+public class FloatHealthChecker2 implements HealthChecker<Float> {
+
+ @Override
+ public boolean canVisit(Object subject) {
+ return subject!=null && subject instanceof Float;
+ }
+
+ @Override
+ public VisitReport visit(Float o, List<Object> ancestry) {
+ return null;
+ }
+
+ @Override
+ public boolean isTimeConsuming() {
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/HealthReportTest.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/HealthReportTest.java b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/HealthReportTest.java
new file mode 100644
index 0000000..acd14a3
--- /dev/null
+++ b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/HealthReportTest.java
@@ -0,0 +1,87 @@
+/*
+* 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.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.taverna.visit.VisitReport;
+import org.apache.taverna.visit.VisitReport.Status;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class HealthReportTest {
+
+ VisitReport report;
+
+ @Before
+ public void setUp() throws Exception {
+ List<VisitReport> subreports = new ArrayList<>();
+ subreports.add(new VisitReport(DummyVisitKind.getInstance(), "sub subject","this is a subreport",0,Status.OK));
+ report = new VisitReport(DummyVisitKind.getInstance(), "a subject","a message",0, Status.WARNING,subreports);
+ }
+
+ @Test
+ public void testActivityVisitReportStringStatus() {
+ report = new VisitReport(DummyVisitKind.getInstance(), "the subject","a string",0, Status.SEVERE);
+ assertEquals("a string",report.getMessage());
+ assertEquals(Status.SEVERE,report.getStatus());
+ assertEquals("the subject",report.getSubject());
+ assertEquals("the subreports should be an empty list",0,report.getSubReports().size());
+ }
+
+ @Test
+ public void testGetMessage() {
+ assertEquals("a message",report.getMessage());
+ }
+
+ @Test
+ public void testGetStatus() {
+ assertEquals(Status.WARNING,report.getStatus());
+ }
+
+ @Test
+ public void testGetSubject() {
+ assertEquals("a subject",report.getSubject());
+ }
+
+ @Test
+ public void testGetSubreports() {
+ Collection<VisitReport> subreports = report.getSubReports();
+ assertEquals("There should be 1 report",1,subreports.size());
+ assertEquals("Wrong subject","sub subject",subreports.iterator().next().getSubject());
+ }
+
+ @Test
+ public void testStatusHighestIncludingSubReports() {
+ report = new VisitReport(DummyVisitKind.getInstance(), "parent","set to ok",0, Status.OK);
+ assertEquals("should be OK",Status.OK,report.getStatus());
+ report.getSubReports().add(new VisitReport(DummyVisitKind.getInstance(), "child1","set to warning",0, Status.WARNING));
+ assertEquals("should be WARNING",Status.WARNING,report.getStatus());
+ report.getSubReports().add(new VisitReport(DummyVisitKind.getInstance(), "child1","set to severe",0, Status.SEVERE));
+ assertEquals("should be SEVERE",Status.SEVERE,report.getStatus());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-engine/blob/5f1ddb71/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/StringHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/StringHealthChecker.java b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/StringHealthChecker.java
new file mode 100644
index 0000000..7bf6960
--- /dev/null
+++ b/taverna-workflowmodel-api/src/test/java/org/apache/taverna/workflowmodel/health/StringHealthChecker.java
@@ -0,0 +1,43 @@
+/*
+* 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 java.util.List;
+
+import org.apache.taverna.visit.VisitReport;
+
+public class StringHealthChecker implements HealthChecker<String> {
+
+ @Override
+ public boolean canVisit(Object subject) {
+ return subject!=null && subject instanceof String;
+ }
+
+ @Override
+ public VisitReport visit(String o, List<Object> ancestry) {
+ return null;
+ }
+
+ @Override
+ public boolean isTimeConsuming() {
+ return false;
+ }
+
+}