You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/02/23 11:06:02 UTC

[77/79] incubator-taverna-language git commit: validation moved into api

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestAbstractDepthPort.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestAbstractDepthPort.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestAbstractDepthPort.java
new file mode 100644
index 0000000..ecf3252
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestAbstractDepthPort.java
@@ -0,0 +1,143 @@
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.port.InputActivityPort;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NegativeValueProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.junit.Test;
+
+
+
+public class TestAbstractDepthPort {
+	
+	@Test
+	public void testCorrectnessOfDepthSpecifiedIncorrectly() {
+		InputActivityPort iap = new InputActivityPort();
+		iap.setDepth(new Integer(-3));
+		iap.setName("fred");
+		iap.setParent(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(iap, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(1, negativeValueProblems.size());
+		if (!negativeValueProblems.isEmpty()) {
+			NegativeValueProblem problem = negativeValueProblems.iterator().next();
+			assertEquals(problem.getBean(), iap);
+			assertEquals(problem.getFieldName(), "depth");
+			assertEquals(problem.getFieldValue(), Integer.valueOf("-3"));
+		}
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems); // only done when completeness check
+	}
+
+	@Test
+	public void testCompletenessOfDepthSpecifiedIncorrectly() {
+		InputActivityPort iap = new InputActivityPort();
+		iap.setDepth(new Integer(-3));
+		iap.setName("fred");
+		iap.setParent(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(iap, true, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(1, negativeValueProblems.size());
+		if (!negativeValueProblems.isEmpty()) {
+			NegativeValueProblem problem = negativeValueProblems.iterator().next();
+			assertEquals(problem.getBean(), iap);
+			assertEquals(problem.getFieldName(), "depth");
+			assertEquals(problem.getFieldValue(), Integer.valueOf("-3"));
+		}
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty()); // parent
+		boolean depthFieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(iap) && nlp.getFieldName().equals("depth")) {
+				depthFieldProblem = true;
+			}
+		}
+		assertFalse(depthFieldProblem);
+	}
+
+	@Test
+	public void testCorrectnessOfMissingDepth() {
+		InputActivityPort iap = new InputActivityPort();
+		iap.setDepth(null);
+		iap.setName("fred");
+		iap.setParent(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(iap, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(Collections.EMPTY_SET, negativeValueProblems);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems); // only done when completeness check
+	}
+	
+	@Test
+	public void testCompletenessOfMissingDepth() {
+		InputActivityPort iap = new InputActivityPort();
+		iap.setDepth(null);
+		iap.setName("fred");
+		iap.setParent(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(iap, true, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(0, negativeValueProblems.size());
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty()); // depth and parent
+		boolean depthFieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(iap) && nlp.getFieldName().equals("depth")) {
+				depthFieldProblem = true;
+			}
+		}
+		assertTrue(depthFieldProblem);
+
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestAbstractGranularDepthPort.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestAbstractGranularDepthPort.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestAbstractGranularDepthPort.java
new file mode 100644
index 0000000..9586f26
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestAbstractGranularDepthPort.java
@@ -0,0 +1,189 @@
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.port.OutputActivityPort;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.IncompatibleGranularDepthProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.NegativeValueProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.junit.Test;
+
+
+
+public class TestAbstractGranularDepthPort {
+	
+	@Test
+	public void testCorrectnessOfGranularDepthSpecifiedIncorrectly() {
+		OutputActivityPort oap = new OutputActivityPort();
+		oap.setDepth(new Integer(3));
+		oap.setGranularDepth(new Integer(-2));
+		oap.setName("fred");
+		oap.setParent(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(oap, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(1, negativeValueProblems.size());
+		if (!negativeValueProblems.isEmpty()) {
+			NegativeValueProblem problem = negativeValueProblems.iterator().next();
+			assertEquals(problem.getBean(), oap);
+			assertEquals(problem.getFieldName(), "granularDepth");
+			assertEquals(problem.getFieldValue(), Integer.valueOf("-2"));
+		}
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(0, nullFieldProblems.size()); // only done when completeness check
+		
+		assertEquals(0, rcvl.getIncompatibleGranularDepthProblems().size());
+	}
+
+	@Test
+	public void testCompletenessOfGranularDepthSpecifiedIncorrectly() {
+		OutputActivityPort oap = new OutputActivityPort();
+		oap.setDepth(new Integer(3));
+		oap.setGranularDepth(new Integer(-2));
+		oap.setName("fred");
+		oap.setParent(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(oap, true, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(1, negativeValueProblems.size());
+		if (!negativeValueProblems.isEmpty()) {
+			NegativeValueProblem problem = negativeValueProblems.iterator().next();
+			assertEquals(problem.getBean(), oap);
+			assertEquals(problem.getFieldName(), "granularDepth");
+			assertEquals(problem.getFieldValue(), Integer.valueOf("-2"));
+		}
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(1, nullFieldProblems.size()); // parent
+		boolean granularDepthFieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(oap) && nlp.getFieldName().equals("granularDepth")) {
+				granularDepthFieldProblem = true;
+			}
+		}
+		assertFalse(granularDepthFieldProblem);
+		assertEquals(0, rcvl.getIncompatibleGranularDepthProblems().size());
+	}
+
+	@Test
+	public void testCorrectnessOfMissingGranularDepth() {
+		OutputActivityPort oap = new OutputActivityPort();
+		oap.setDepth(new Integer(3));
+		oap.setGranularDepth(null);
+		oap.setName("fred");
+		oap.setParent(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(oap, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(0, negativeValueProblems.size());
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(0, nullFieldProblems.size()); // only done when completeness check
+		assertEquals(0, rcvl.getIncompatibleGranularDepthProblems().size());
+	}
+	
+	@Test
+	public void testCompletenessOfMissingGranularDepth() {
+		OutputActivityPort oap = new OutputActivityPort();
+		oap.setDepth(new Integer(3));
+		oap.setGranularDepth(null);
+		oap.setName("fred");
+		oap.setParent(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(oap, true, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(0, negativeValueProblems.size());
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(2, nullFieldProblems.size()); // granular depth and parent
+		boolean granularDepthFieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(oap) && nlp.getFieldName().equals("granularDepth")) {
+				granularDepthFieldProblem = true;
+			}
+		}
+		assertTrue(granularDepthFieldProblem);
+		assertEquals(0, rcvl.getIncompatibleGranularDepthProblems().size());
+
+	}
+	
+	@Test
+	public void testIncompatibleGranularDepth() {
+		OutputActivityPort oap = new OutputActivityPort();
+		oap.setDepth(new Integer(0));
+		oap.setGranularDepth(new Integer(1));
+		oap.setName("fred");
+		oap.setParent(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(oap, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(0, negativeValueProblems.size());
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(0, nullFieldProblems.size()); // only done when completeness check
+		boolean granularDepthFieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(oap) && nlp.getFieldName().equals("granularDepth")) {
+				granularDepthFieldProblem = true;
+			}
+		}
+		assertFalse(granularDepthFieldProblem);
+		
+		Set<IncompatibleGranularDepthProblem> incompatibleGranularDepthProblems = rcvl.getIncompatibleGranularDepthProblems();
+		assertEquals(1, incompatibleGranularDepthProblems.size());
+		boolean incompatibleGranularDepthProblem = false;
+		for (IncompatibleGranularDepthProblem nlp : incompatibleGranularDepthProblems) {
+			if (nlp.getBean().equals(oap) && nlp.getDepth().equals(Integer.valueOf(0)) && nlp.getGranularDepth().equals(Integer.valueOf(1))) {
+				incompatibleGranularDepthProblem = true;
+			}
+		}
+		assertTrue(incompatibleGranularDepthProblem);
+	}	
+	
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestBlockingControlLink.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestBlockingControlLink.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestBlockingControlLink.java
new file mode 100644
index 0000000..ae1d155
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestBlockingControlLink.java
@@ -0,0 +1,159 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.core.BlockingControlLink;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.OutOfScopeValueProblem;
+import org.junit.Test;
+
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestBlockingControlLink {
+	
+	@Test
+	public void testCorrectnessOfMissingBlock() {
+		BlockingControlLink bcl = new BlockingControlLink();
+		Processor untilFinished = new Processor();
+		bcl.setUntilFinished(untilFinished);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(bcl, false, rcvl);
+		assertEquals(0, rcvl.getNullFieldProblems().size());
+
+	}
+	
+	@Test
+	public void testCompletenessOfMissingBlock() {
+		BlockingControlLink bcl = new BlockingControlLink();
+		Processor untilFinished = new Processor();
+		bcl.setUntilFinished(untilFinished);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(bcl, true, rcvl);
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(2, rcvl.getNullFieldProblems().size()); // parent and block
+		boolean nullFieldProblem = false;
+		for (NullFieldProblem nfp : nullFieldProblems) {
+			if (nfp.getBean().equals(bcl) && nfp.getFieldName().equals("block")) {
+				nullFieldProblem = true;
+			}
+		}
+		assertTrue(nullFieldProblem);
+	}
+	
+	@Test
+	public void testCorrectnessOfMissingUntilFinished() {
+		BlockingControlLink bcl = new BlockingControlLink();
+		Processor block = new Processor();
+		bcl.setBlock(block);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(bcl, false, rcvl);
+		assertEquals(0, rcvl.getNullFieldProblems().size());
+
+	}
+	
+	@Test
+	public void testCompletenessOfMissingUntilFinished() {
+		BlockingControlLink bcl = new BlockingControlLink();
+		Processor block = new Processor();
+		bcl.setBlock(block);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(bcl, true, rcvl);
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(2, rcvl.getNullFieldProblems().size()); // parent and untilFinished
+		boolean nullFieldProblem = false;
+		for (NullFieldProblem nfp : nullFieldProblems) {
+			if (nfp.getBean().equals(bcl) && nfp.getFieldName().equals("untilFinished")) {
+				nullFieldProblem = true;
+			}
+		}
+		assertTrue(nullFieldProblem);
+	}
+	
+	@Test
+	public void testWronglyScopedBlock() {
+		Workflow wf = new Workflow();
+		BlockingControlLink bcl = new BlockingControlLink();
+		bcl.setParent(wf);
+		Processor block = new Processor();
+		Workflow otherWorkflow = new Workflow();
+		block.setParent(otherWorkflow);
+		bcl.setBlock(block);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(bcl, false, rcvl);
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertEquals(1, outOfScopeValueProblems.size());
+		boolean outOfScopeValueProblem = false;
+		for (OutOfScopeValueProblem oosvp : outOfScopeValueProblems) {
+			if (oosvp.getBean().equals(bcl) && oosvp.getFieldName().equals("block") && oosvp.getValue().equals(block)) {
+				outOfScopeValueProblem = true;
+			}
+		}
+		assertTrue(outOfScopeValueProblem);
+	}
+
+	@Test
+	public void testValidlyScopedBlock() {
+		Workflow wf = new Workflow();
+		BlockingControlLink bcl = new BlockingControlLink();
+		bcl.setParent(wf);
+		Processor block = new Processor();
+		block.setParent(wf);
+		bcl.setBlock(block);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(bcl, false, rcvl);
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertEquals(0, outOfScopeValueProblems.size());
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestChild.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestChild.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestChild.java
new file mode 100644
index 0000000..0373f4c
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestChild.java
@@ -0,0 +1,140 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.WrongParentProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestChild {
+
+
+
+	/**
+	 * Test method for {@link org.apache.taverna.scufl2.validation.correctness.CorrectnessVisitor#visitChild(org.apache.taverna.scufl2.api.common.Child)}.
+	 */
+	@Test
+	public void testCorrectnessOfMissingParent() {
+		Workflow w = new Workflow();
+		w.setName("fred");
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(w, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(0, nullFieldProblems.size()); // only done when completeness check
+	}
+	
+	@Test
+	public void testCompletenessOfMissingParent() {
+		Workflow w = new Workflow();
+		w.setName("fred");
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(w, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(1, nullFieldProblems.size()); // parent
+		boolean parentProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(w) && nlp.getFieldName().equals("parent")) {
+				parentProblem = true;
+			}
+		}
+		assertTrue(parentProblem);
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedParent() {
+		Workflow w = new Workflow();
+		w.setName("fred");
+		WorkflowBundle wb = new WorkflowBundle();
+		w.setParent(wb);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(w, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(0, nullFieldProblems.size());
+	}
+	
+	@Test
+	public void testValidParent() {
+		WorkflowBundle parent = new WorkflowBundle();
+		Workflow fw = new Workflow();
+		fw.setParent(parent);
+				
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(parent, false, rcvl);
+		Set<WrongParentProblem> wrongParentProblems = rcvl.getWrongParentProblems();
+		assertEquals(Collections.EMPTY_SET, wrongParentProblems);
+	}
+	
+	@Test
+	public void testInvalidParent() {
+
+		WorkflowBundle parent = new WorkflowBundle();
+		DummyWorkflow fw = new DummyWorkflow(parent);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(parent, false, rcvl);
+		Set<WrongParentProblem> wrongParentProblems = rcvl.getWrongParentProblems();
+		assertEquals(1, wrongParentProblems.size());
+		boolean parentProblem = false;
+		for (WrongParentProblem p : wrongParentProblems) {
+			if (p.getBean().equals(fw)) {
+				parentProblem = true;
+			}
+		}
+		assertTrue(parentProblem);
+	}
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestConfiguration.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestConfiguration.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestConfiguration.java
new file mode 100644
index 0000000..9a20101
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestConfiguration.java
@@ -0,0 +1,172 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.api.configurations.Configuration;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.MismatchConfigurableTypeProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestConfiguration {
+	
+	@Test
+	public void testIdenticalConfigurableTypes() {
+		Configuration configuration = new Configuration();
+		Activity a = new Activity();
+		URI tavernaUri = null;
+		try {
+			tavernaUri = new URI("http://www.taverna.org.uk");
+		} catch (URISyntaxException e) {
+			return;
+		}
+		configuration.setConfigures(a);
+		configuration.setType(tavernaUri);
+		a.setType(tavernaUri);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(configuration, false, rcvl);
+		
+		Set<MismatchConfigurableTypeProblem> mismatchConfigurableTypeProblems = rcvl.getMismatchConfigurableTypeProblems();
+		assertEquals(0, mismatchConfigurableTypeProblems.size());
+	}
+	
+	@Ignore
+	public void testEqualConfigurableTypes() {
+		Configuration configuration = new Configuration();
+		Activity a = new Activity();
+		URI tavernaUri = null;
+		URI tavernaUri2 = null;
+		try {
+			tavernaUri = new URI("http://www.taverna.org.uk");
+			tavernaUri2 = new URI("http://www.taverna.org.uk");
+		} catch (URISyntaxException e) {
+			return;
+		}
+		configuration.setConfigures(a);
+		configuration.setType(tavernaUri);
+		a.setType(tavernaUri2);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(configuration, false, rcvl);
+		
+		Set<MismatchConfigurableTypeProblem> mismatchConfigurableTypeProblems = rcvl.getMismatchConfigurableTypeProblems();
+		assertEquals(0, mismatchConfigurableTypeProblems.size());
+	}
+	
+	@Ignore
+	public void testMismatchingConfigurableTypes() {
+		Configuration configuration = new Configuration();
+		Activity a = new Activity();
+		URI tavernaUri = null;
+		URI myGridUri = null;
+		try {
+			tavernaUri = new URI("http://www.taverna.org.uk");
+			myGridUri = new URI("http://www.mygrid.org.uk");
+		} catch (URISyntaxException e) {
+			return;
+		}
+		configuration.setConfigures(a);
+		configuration.setType(tavernaUri);
+		a.setType(myGridUri);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(configuration, false, rcvl);
+		
+		Set<MismatchConfigurableTypeProblem> mismatchConfigurableTypeProblems = rcvl.getMismatchConfigurableTypeProblems();
+		assertEquals(1, mismatchConfigurableTypeProblems.size());
+		boolean mismatchProblem = false;
+		for (MismatchConfigurableTypeProblem nlp : mismatchConfigurableTypeProblems) {
+			if (nlp.getBean().equals(configuration) && nlp.getConfigurable().equals(a)) {
+				mismatchProblem = true;
+			}
+		}
+		assertTrue(mismatchProblem);
+	}	
+
+	@Test
+	public void testCorrectnessOfMissingConfigures() {
+		Configuration configuration = new Configuration();
+		configuration.setType(URI.create("http://www.example.com/"));
+		configuration.setJson("{ \"hello\": 1337  }");
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(configuration, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(0, nullFieldProblems.size()); // only done when completeness check
+
+	}	
+
+	@Test
+	public void testCompletenessOfMissingConfigures() {
+		Configuration configuration = new Configuration();
+        configuration.setType(URI.create("http://www.example.com/"));
+        configuration.setJson("{ \"hello\": 1337  }");
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(configuration, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty()); // only done when completeness check
+		
+		boolean fieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(configuration) && nlp.getFieldName().equals("configures")) {
+				fieldProblem = true;
+			}
+		}
+		assertTrue(fieldProblem);
+	}
+	
+	// Cannot check propertyResource because of SCUFL2-97
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestDataLink.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestDataLink.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestDataLink.java
new file mode 100644
index 0000000..460379a
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestDataLink.java
@@ -0,0 +1,389 @@
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.core.DataLink;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
+import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NegativeValueProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.OutOfScopeValueProblem;
+import org.junit.Test;
+
+
+
+public class TestDataLink {
+	
+	@Test
+	public void testCorrectnessOfMissingSendsTo() {
+		DataLink dataLink = new DataLink();
+		InputWorkflowPort iwp = new InputWorkflowPort();
+		dataLink.setReceivesFrom(iwp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dataLink, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(0, nullFieldProblems.size()); // only done when completeness check
+
+	}	
+
+	@Test
+	public void testCompletenessOfMissingSendsTo() {
+		DataLink dataLink = new DataLink();
+		InputWorkflowPort iwp = new InputWorkflowPort();
+		dataLink.setReceivesFrom(iwp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty()); // only done when completeness check
+		
+		boolean fieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dataLink) && nlp.getFieldName().equals("sendsTo")) {
+				fieldProblem = true;
+			}
+		}
+		assertTrue(fieldProblem);
+	}
+	
+	@Test
+	public void testCorrectnessOfMissingReceivesFrom() {
+		DataLink dataLink = new DataLink();
+		OutputWorkflowPort owp = new OutputWorkflowPort();
+		dataLink.setSendsTo(owp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dataLink, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(0, nullFieldProblems.size()); // only done when completeness check
+
+	}	
+
+	@Test
+	public void testCompletenessOfMissingReceivesFrom() {
+		DataLink dataLink = new DataLink();
+		OutputWorkflowPort owp = new OutputWorkflowPort();
+		dataLink.setSendsTo(owp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty()); // only done when completeness check
+		
+		boolean fieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dataLink) && nlp.getFieldName().equals("receivesFrom")) {
+				fieldProblem = true;
+			}
+		}
+		assertTrue(fieldProblem);
+	}
+
+	@Test
+	public void testInScopePorts() {
+		Workflow w = new Workflow();
+		DataLink dataLink = new DataLink();
+		dataLink.setParent(w);
+		
+		InputWorkflowPort iwp = new InputWorkflowPort();
+		iwp.setParent(w);
+		
+		OutputWorkflowPort owp = new OutputWorkflowPort();
+		owp.setParent(w);
+		
+		dataLink.setReceivesFrom(iwp);
+		dataLink.setSendsTo(owp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, true, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertEquals(Collections.EMPTY_SET, outOfScopeValueProblems);
+	}
+	
+	@Test
+	public void testOutOfScopeReceivesFrom() {
+		Workflow w = new Workflow();
+		
+		Workflow otherWorkflow = new Workflow();
+		
+		DataLink dataLink = new DataLink();
+		dataLink.setParent(w);
+		
+		InputWorkflowPort iwp = new InputWorkflowPort();
+		iwp.setParent(otherWorkflow);
+		
+		OutputWorkflowPort owp = new OutputWorkflowPort();
+		owp.setParent(w);
+		
+		dataLink.setReceivesFrom(iwp);
+		dataLink.setSendsTo(owp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, true, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(dataLink) && nlp.getFieldName().equals("receivesFrom") && nlp.getValue().equals(iwp)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+	}
+	
+	@Test
+	public void testOutOfScopeSendsTo() {
+		Workflow w = new Workflow();
+		
+		Workflow otherWorkflow = new Workflow();
+		
+		DataLink dataLink = new DataLink();
+		dataLink.setParent(w);
+		
+		InputWorkflowPort iwp = new InputWorkflowPort();
+		iwp.setParent(w);
+		
+		OutputWorkflowPort owp = new OutputWorkflowPort();
+		owp.setParent(otherWorkflow);
+		
+		dataLink.setReceivesFrom(iwp);
+		dataLink.setSendsTo(owp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, true, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(dataLink) && nlp.getFieldName().equals("sendsTo") && nlp.getValue().equals(owp)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+	}
+	
+	@Test
+	public void testInScopeProcessorPorts() {
+		Workflow w = new Workflow();
+		DataLink dataLink = new DataLink();
+		dataLink.setParent(w);
+		
+		Processor p1 = new Processor();
+		p1.setParent(w);
+		
+		InputProcessorPort ipp = new InputProcessorPort();
+		ipp.setParent(p1);
+		
+		Processor p2 = new Processor();
+		p2.setParent(w);
+		
+		OutputProcessorPort opp = new OutputProcessorPort();
+		opp.setParent(p2);
+		
+		dataLink.setReceivesFrom(opp);
+		dataLink.setSendsTo(ipp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, true, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertEquals(Collections.EMPTY_SET, outOfScopeValueProblems);
+	}
+	
+	@Test
+	public void testOutOfScopeReceivesFromProcessorPort() {
+		Workflow w = new Workflow();
+		Workflow otherWorkflow = new Workflow();
+		
+		DataLink dataLink = new DataLink();
+		dataLink.setParent(w);
+		
+		Processor p1 = new Processor();
+		p1.setParent(w);
+		
+		InputProcessorPort ipp = new InputProcessorPort();
+		ipp.setParent(p1);
+		
+		Processor p2 = new Processor();
+		p2.setParent(otherWorkflow);
+		
+		OutputProcessorPort opp = new OutputProcessorPort();
+		opp.setParent(p2);
+		
+		dataLink.setReceivesFrom(opp);
+		dataLink.setSendsTo(ipp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, true, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(dataLink) && nlp.getFieldName().equals("receivesFrom") && nlp.getValue().equals(opp)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+	}
+	
+	@Test
+	public void testOutOfScopeSendsToProcessorPort() {
+		Workflow w = new Workflow();
+		Workflow otherWorkflow = new Workflow();
+		
+		DataLink dataLink = new DataLink();
+		dataLink.setParent(w);
+		
+		Processor p1 = new Processor();
+		p1.setParent(otherWorkflow);
+		
+		InputProcessorPort ipp = new InputProcessorPort();
+		ipp.setParent(p1);
+		
+		Processor p2 = new Processor();
+		p2.setParent(w);
+		
+		OutputProcessorPort opp = new OutputProcessorPort();
+		opp.setParent(p2);
+		
+		dataLink.setReceivesFrom(opp);
+		dataLink.setSendsTo(ipp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, true, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(dataLink) && nlp.getFieldName().equals("sendsTo") && nlp.getValue().equals(ipp)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+	}
+	
+	@Test
+	public void testCorrectnessOfMergePositionSpecifiedIncorrectly() {
+		Workflow w = new Workflow();
+		DataLink dataLink = new DataLink();
+		dataLink.setParent(w);
+		
+		InputWorkflowPort iwp = new InputWorkflowPort();
+		iwp.setParent(w);
+		
+		OutputWorkflowPort owp = new OutputWorkflowPort();
+		owp.setParent(w);
+		
+		dataLink.setReceivesFrom(iwp);
+		dataLink.setSendsTo(owp);
+		
+		Integer mergePosition = Integer.valueOf(-3);
+		dataLink.setMergePosition(mergePosition);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(1, negativeValueProblems.size());
+		if (!negativeValueProblems.isEmpty()) {
+			NegativeValueProblem problem = negativeValueProblems.iterator().next();
+			assertEquals(problem.getBean(), dataLink);
+			assertEquals(problem.getFieldName(), "mergePosition");
+			assertEquals(problem.getFieldValue(), mergePosition);
+		}
+	}
+
+	@Test
+	public void testCorrectnessOfMergePositionSpecifiedCorrectly() {
+		Workflow w = new Workflow();
+		DataLink dataLink = new DataLink();
+		dataLink.setParent(w);
+		
+		InputWorkflowPort iwp = new InputWorkflowPort();
+		iwp.setParent(w);
+		
+		OutputWorkflowPort owp = new OutputWorkflowPort();
+		owp.setParent(w);
+		
+		dataLink.setReceivesFrom(iwp);
+		dataLink.setSendsTo(owp);
+		
+		Integer mergePosition = Integer.valueOf(3);
+		dataLink.setMergePosition(mergePosition);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+				
+		cv.checkCorrectness(dataLink, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(Collections.EMPTY_SET, negativeValueProblems);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestIterationStrategyStack.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestIterationStrategyStack.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestIterationStrategyStack.java
new file mode 100644
index 0000000..1be2a5c
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestIterationStrategyStack.java
@@ -0,0 +1,130 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.iterationstrategy.CrossProduct;
+import org.apache.taverna.scufl2.api.iterationstrategy.DotProduct;
+import org.apache.taverna.scufl2.api.iterationstrategy.IterationStrategyStack;
+import org.apache.taverna.scufl2.api.iterationstrategy.PortNode;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.PortMissingFromIterationStrategyStackProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestIterationStrategyStack {
+	
+	@Test
+	public void testValidIterationStrategyStack() {
+		Processor p = new Processor();
+		IterationStrategyStack iss = new IterationStrategyStack();
+		iss.setParent(p);
+		
+		InputProcessorPort p1 = new InputProcessorPort();
+		p1.setParent(p);
+		InputProcessorPort p2 = new InputProcessorPort();
+		p2.setParent(p);
+		InputProcessorPort p3 = new InputProcessorPort();
+		p3.setParent(p);	
+		
+		CrossProduct cp = new CrossProduct();
+		PortNode pNode1 = new PortNode();
+		pNode1.setInputProcessorPort(p1);
+		cp.add(pNode1);
+		iss.add(cp);
+		
+		DotProduct dp = new DotProduct();
+		PortNode pNode2 = new PortNode();
+		pNode2.setInputProcessorPort(p2);
+		PortNode pNode3 = new PortNode();
+		pNode3.setInputProcessorPort(p3);
+		dp.add(pNode2);
+		dp.add(pNode3);
+		iss.add(dp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(p, true, rcvl);
+		
+		Set<PortMissingFromIterationStrategyStackProblem> problems = rcvl.getPortMissingFromIterationStrategyStackProblems();
+		assertEquals(Collections.EMPTY_SET, problems);
+
+	}
+
+	@Test
+	public void testInvalidIterationStrategyStack() {
+		Processor p = new Processor();
+		IterationStrategyStack iss = new IterationStrategyStack();
+		iss.setParent(p);
+		
+		InputProcessorPort p1 = new InputProcessorPort();
+		p1.setParent(p);
+		InputProcessorPort p2 = new InputProcessorPort();
+		p2.setParent(p);
+		InputProcessorPort p3 = new InputProcessorPort();
+		p3.setParent(p);	
+		
+		CrossProduct cp = new CrossProduct();
+		PortNode pNode1 = new PortNode();
+		pNode1.setInputProcessorPort(p1);
+		cp.add(pNode1);
+		iss.add(cp);
+		
+		DotProduct dp = new DotProduct();
+		PortNode pNode2 = new PortNode();
+		pNode2.setInputProcessorPort(p2);
+		dp.add(pNode2);
+		iss.add(dp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(p, true, rcvl);
+		
+		Set<PortMissingFromIterationStrategyStackProblem> problems = rcvl.getPortMissingFromIterationStrategyStackProblems();
+		assertFalse(problems.isEmpty());
+
+		boolean problem = false;
+		for (PortMissingFromIterationStrategyStackProblem nlp : problems) {
+			if (nlp.getPort().equals(p3) && nlp.getBean().equals(iss)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestIterationStrategyTopNode.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestIterationStrategyTopNode.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestIterationStrategyTopNode.java
new file mode 100644
index 0000000..803a854
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestIterationStrategyTopNode.java
@@ -0,0 +1,187 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.iterationstrategy.CrossProduct;
+import org.apache.taverna.scufl2.api.iterationstrategy.DotProduct;
+import org.apache.taverna.scufl2.api.iterationstrategy.IterationStrategyStack;
+import org.apache.taverna.scufl2.api.iterationstrategy.PortNode;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.PortMentionedTwiceProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestIterationStrategyTopNode {
+	
+	@Test
+	public void testValidIterationStrategyTopNode() {
+		Processor p = new Processor();
+		IterationStrategyStack iss = new IterationStrategyStack();
+		iss.setParent(p);
+		
+		InputProcessorPort p1 = new InputProcessorPort();
+		p1.setParent(p);
+		InputProcessorPort p2 = new InputProcessorPort();
+		p2.setParent(p);
+		InputProcessorPort p3 = new InputProcessorPort();
+		p3.setParent(p);	
+		
+		// Do a crossproduct with a portnode and a dotproduct
+		CrossProduct cp = new CrossProduct();
+		PortNode pNode1 = new PortNode();
+		pNode1.setInputProcessorPort(p1);
+		cp.add(pNode1);
+		iss.add(cp);
+		
+		DotProduct dp = new DotProduct();
+		PortNode pNode2 = new PortNode();
+		pNode2.setInputProcessorPort(p2);
+		PortNode pNode3 = new PortNode();
+		pNode3.setInputProcessorPort(p3);
+		dp.add(pNode2);
+		dp.add(pNode3);
+		cp.add(dp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(p, false, rcvl);
+		
+		Set<PortMentionedTwiceProblem> problems = rcvl.getPortMentionedTwiceProblems();
+		assertEquals(Collections.EMPTY_SET, problems);
+
+	}
+
+	@Test
+	public void testInvalidAtTopIterationStrategyTopNode() {
+		Processor p = new Processor();
+		IterationStrategyStack iss = new IterationStrategyStack();
+		iss.setParent(p);
+		
+		InputProcessorPort p1 = new InputProcessorPort();
+		p1.setParent(p);
+		InputProcessorPort p2 = new InputProcessorPort();
+		p2.setParent(p);
+		InputProcessorPort p3 = new InputProcessorPort();
+		p3.setParent(p);	
+		
+		// Do a crossproduct with a portnode and a dotproduct
+		CrossProduct cp = new CrossProduct();
+		PortNode pNode1 = new PortNode();
+		pNode1.setInputProcessorPort(p1);
+		cp.add(pNode1);
+		PortNode duplicateNode = new PortNode();
+		duplicateNode.setInputProcessorPort(p1);
+		cp.add(duplicateNode);
+		iss.add(cp);
+		
+		DotProduct dp = new DotProduct();
+		PortNode pNode2 = new PortNode();
+		pNode2.setInputProcessorPort(p2);
+		PortNode pNode3 = new PortNode();
+		pNode3.setInputProcessorPort(p3);
+		dp.add(pNode2);
+		dp.add(pNode3);
+		cp.add(dp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(p, false, rcvl);
+		
+		Set<PortMentionedTwiceProblem> problems = rcvl.getPortMentionedTwiceProblems();
+		assertFalse(problems.isEmpty());
+		boolean problemDetected = false;
+		for (PortMentionedTwiceProblem problem : problems) {
+			if (problem.getBean().equals(pNode1) && problem.getDuplicateNode().equals(duplicateNode)) {
+				problemDetected = true;
+			}
+		}
+		assertTrue(problemDetected);
+
+	}
+
+	@Test
+	public void testInvalidDeepInIterationStrategyTopNode() {
+		Processor p = new Processor();
+		IterationStrategyStack iss = new IterationStrategyStack();
+		iss.setParent(p);
+		
+		InputProcessorPort p1 = new InputProcessorPort();
+		p1.setParent(p);
+		InputProcessorPort p2 = new InputProcessorPort();
+		p2.setParent(p);
+		InputProcessorPort p3 = new InputProcessorPort();
+		p3.setParent(p);	
+		
+		// Do a crossproduct with a portnode and a dotproduct
+		CrossProduct cp = new CrossProduct();
+		PortNode pNode1 = new PortNode();
+		pNode1.setInputProcessorPort(p1);
+		cp.add(pNode1);
+		iss.add(cp);
+		
+		DotProduct dp = new DotProduct();
+		PortNode pNode2 = new PortNode();
+		pNode2.setInputProcessorPort(p2);
+		PortNode pNode3 = new PortNode();
+		pNode3.setInputProcessorPort(p3);
+		dp.add(pNode2);
+		dp.add(pNode3);
+		PortNode duplicateNode = new PortNode();
+		duplicateNode.setInputProcessorPort(p1);
+		cp.add(duplicateNode);
+		cp.add(dp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(p, false, rcvl);
+		
+		Set<PortMentionedTwiceProblem> problems = rcvl.getPortMentionedTwiceProblems();
+		assertFalse(problems.isEmpty());
+		boolean problemDetected = false;
+		for (PortMentionedTwiceProblem problem : problems) {
+			if (problem.getBean().equals(pNode1) && problem.getDuplicateNode().equals(duplicateNode)) {
+				problemDetected = true;
+			}
+		}
+		assertTrue(problemDetected);
+
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestNamed.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestNamed.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestNamed.java
new file mode 100644
index 0000000..0082d1e
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestNamed.java
@@ -0,0 +1,136 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestNamed {
+	
+	@Test
+	public void testValidName() {
+		DummyWorkflow w = new DummyWorkflow();
+		w.setName("fred");
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(w, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfInvalidName() {
+		DummyWorkflow w = new DummyWorkflow();
+		w.setName("");
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(w, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfMissingName() {
+		DummyWorkflow w = new DummyWorkflow();
+		w.setName(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(w, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);	
+	}
+	
+	@Test
+	public void testCompletenessOfInvalidName() {
+		DummyWorkflow w = new DummyWorkflow();
+		w.setName("");
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(w, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		
+		Set<NullFieldProblem> problems = rcvl.getNullFieldProblems();
+		assertFalse(problems.isEmpty());
+		boolean problemDetected = false;
+		for (NullFieldProblem problem : problems) {
+			if (problem.getBean().equals(w) && problem.getFieldName().equals("name")) {
+				problemDetected = true;
+			}
+		}
+		assertTrue(problemDetected);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingName() {
+		DummyWorkflow w = new DummyWorkflow();
+		w.setName(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(w, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		
+		Set<NullFieldProblem> problems = rcvl.getNullFieldProblems();
+		assertFalse(problems.isEmpty());
+		boolean problemDetected = false;
+		for (NullFieldProblem problem : problems) {
+			if (problem.getBean().equals(w) && problem.getFieldName().equals("name")) {
+				problemDetected = true;
+			}
+		}
+		assertTrue(problemDetected);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestPortNode.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestPortNode.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestPortNode.java
new file mode 100644
index 0000000..26db7e0
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestPortNode.java
@@ -0,0 +1,252 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.iterationstrategy.CrossProduct;
+import org.apache.taverna.scufl2.api.iterationstrategy.IterationStrategyStack;
+import org.apache.taverna.scufl2.api.iterationstrategy.PortNode;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NegativeValueProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.OutOfScopeValueProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestPortNode {
+	
+	@Test
+	public void testCorrectnessOfDesiredDepthSpecifiedIncorrectly() {
+		PortNode pn = new PortNode();
+		Integer desiredDepth = new Integer(-3);
+		pn.setDesiredDepth(desiredDepth);
+		InputProcessorPort ipp = new InputProcessorPort();
+		pn.setInputProcessorPort(ipp);
+
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pn, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(1, negativeValueProblems.size());
+		if (!negativeValueProblems.isEmpty()) {
+			NegativeValueProblem problem = negativeValueProblems.iterator().next();
+			assertEquals(problem.getBean(), pn);
+			assertEquals(problem.getFieldName(), "desiredDepth");
+			assertEquals(problem.getFieldValue(), desiredDepth);
+		}
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems); // only done when completeness check
+	}
+
+	@Test
+	public void testCompletenessOfDepthSpecifiedIncorrectly() {
+		PortNode pn = new PortNode();
+		Integer desiredDepth = new Integer(-3);
+		pn.setDesiredDepth(desiredDepth);
+		InputProcessorPort ipp = new InputProcessorPort();
+		pn.setInputProcessorPort(ipp);
+
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pn, true, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(1, negativeValueProblems.size());
+		if (!negativeValueProblems.isEmpty()) {
+			NegativeValueProblem problem = negativeValueProblems.iterator().next();
+			assertEquals(problem.getBean(), pn);
+			assertEquals(problem.getFieldName(), "desiredDepth");
+			assertEquals(problem.getFieldValue(), desiredDepth);
+		}
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty()); // parent
+		boolean depthFieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pn) && nlp.getFieldName().equals("desiredDepth")) {
+				depthFieldProblem = true;
+			}
+		}
+		assertFalse(depthFieldProblem);
+	}
+
+	@Test
+	public void testCorrectnessOfMissingDepth() {
+		PortNode pn = new PortNode();
+		InputProcessorPort ipp = new InputProcessorPort();
+		pn.setInputProcessorPort(ipp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pn, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(Collections.EMPTY_SET, negativeValueProblems);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems); // only done when completeness check
+	}
+	
+	@Test
+	public void testCompletenessOfMissingDepth() {
+		PortNode pn = new PortNode();
+		InputProcessorPort ipp = new InputProcessorPort();
+		pn.setInputProcessorPort(ipp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pn, true, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(Collections.EMPTY_SET, negativeValueProblems);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean depthFieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pn) && nlp.getFieldName().equals("desiredDepth")) {
+				depthFieldProblem = true;
+			}
+		}
+		assertTrue(depthFieldProblem);
+
+	}
+
+	@Test
+	public void testCorrectnessOfMissingInputProcessorPort() {
+		PortNode pn = new PortNode();
+		Integer desiredDepth = new Integer(-3);
+		pn.setDesiredDepth(desiredDepth);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pn, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertTrue(nullFieldProblems.isEmpty());
+	}
+	
+	@Test
+	public void testCompletenessOfMissingInputProcessorPort() {
+		PortNode pn = new PortNode();
+		Integer desiredDepth = new Integer(-3);
+		pn.setDesiredDepth(desiredDepth);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pn, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean depthFieldProblem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pn) && nlp.getFieldName().equals("inputProcessorPort")) {
+				depthFieldProblem = true;
+			}
+		}
+		assertTrue(depthFieldProblem);
+
+	}
+	
+	@Test
+	public void testOutOfScopeInputProcessorPort() {
+		Processor p = new Processor();
+		InputProcessorPort ipp = new InputProcessorPort();
+//		ipp.setParent(p);
+		IterationStrategyStack iss = new IterationStrategyStack();
+		p.setIterationStrategyStack(iss);
+		CrossProduct cp = new CrossProduct();
+		iss.add(cp);
+		cp.setParent(iss);
+		PortNode pn = new PortNode();
+		pn.setInputProcessorPort(ipp);
+		cp.add(pn);
+		pn.setParent(cp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pn, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pn) && nlp.getFieldName().equals("inputProcessorPort") && nlp.getValue().equals(ipp)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+
+	@Test
+	public void testInScopeInputProcessorPort() {
+		Processor p = new Processor();
+		InputProcessorPort ipp = new InputProcessorPort();
+		ipp.setParent(p);
+		IterationStrategyStack iss = new IterationStrategyStack();
+		p.setIterationStrategyStack(iss);
+		CrossProduct cp = new CrossProduct();
+		iss.add(cp);
+		cp.setParent(iss);
+		PortNode pn = new PortNode();
+		pn.setInputProcessorPort(ipp);
+		cp.add(pn);
+		pn.setParent(cp);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pn, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertEquals(Collections.EMPTY_SET, outOfScopeValueProblems);
+		
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestPorted.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestPorted.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestPorted.java
new file mode 100644
index 0000000..2daf6c5
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestPorted.java
@@ -0,0 +1,163 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.common.NamedSet;
+import org.apache.taverna.scufl2.api.port.InputWorkflowPort;
+import org.apache.taverna.scufl2.api.port.OutputWorkflowPort;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestPorted {
+	
+	@Test
+	public void testCorrectnessOfMissingInputPorts() {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setOutputPorts(new NamedSet<OutputWorkflowPort>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dw, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems); // only done when completeness check
+	}
+	
+	@Test
+	public void testCompletenessOfMissingInputPorts() {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setOutputPorts(new NamedSet<OutputWorkflowPort>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dw, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dw) && nlp.getFieldName().equals("inputPorts")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedInputPorts() {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setInputPorts(new NamedSet<InputWorkflowPort>());
+		dw.setOutputPorts(new NamedSet<OutputWorkflowPort>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dw, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dw) && nlp.getFieldName().equals("inputPorts")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfMissingOutputPorts() {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setInputPorts(new NamedSet<InputWorkflowPort>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dw, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems); // only done when completeness check
+	}
+	
+	@Test
+	public void testCompletenessOfMissingOutputPorts() {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setInputPorts(new NamedSet<InputWorkflowPort>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dw, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dw) && nlp.getFieldName().equals("outputPorts")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedOutputPorts() {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setInputPorts(new NamedSet<InputWorkflowPort>());
+		dw.setOutputPorts(new NamedSet<OutputWorkflowPort>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dw, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dw) && nlp.getFieldName().equals("outputPorts")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessor.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessor.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessor.java
new file mode 100644
index 0000000..22e61fb
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessor.java
@@ -0,0 +1,121 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.correctness;
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+*/
+
+
+import static org.junit.Assert.*;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestProcessor {
+	
+	@Test
+	public void testCorrectnessOfMissingIterationStrategyStack() {
+		Processor p = new Processor();
+		p.setIterationStrategyStack(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(p, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems); // only done when completeness check
+	}
+	
+	@Test
+	public void testCompletenessOfMissingIterationStrategyStack() {
+		Processor p = new Processor();
+		p.setIterationStrategyStack(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(p, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(p) && nlp.getFieldName().equals("iterationStrategyStack")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedIterationStrategyStack() {
+		Processor p = new Processor();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(p, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(p) && nlp.getFieldName().equals("iterationStrategyStack")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedDispatchStack() {
+		Processor p = new Processor();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(p, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(p) && nlp.getFieldName().equals("dispatchStack")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+}