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:01 UTC

[76/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/TestProcessorBinding.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessorBinding.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessorBinding.java
new file mode 100644
index 0000000..210e292
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessorBinding.java
@@ -0,0 +1,496 @@
+/**
+ * 
+ */
+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.activity.Activity;
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+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 TestProcessorBinding {
+	
+	@Test
+	public void testCorrectnessOfMissingBoundProcessor() {
+		ProcessorBinding pb = new ProcessorBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingBoundProcessor() {
+		ProcessorBinding pb = new ProcessorBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundProcessor")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedBoundProcessor() {
+		ProcessorBinding pb = new ProcessorBinding();
+		pb.setBoundProcessor(new Processor());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundProcessor")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+	@Test
+	public void testCorrectnessOfMissingBoundActivity() {
+		ProcessorBinding pb = new ProcessorBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingBoundActivity() {
+		ProcessorBinding pb = new ProcessorBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundActivity")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedBoundActivity() {
+		ProcessorBinding pb = new ProcessorBinding();
+		pb.setBoundActivity(new Activity());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundActivity")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+	@Test
+	public void testCorrectnessOfMissingInputPortBindings() {
+		ProcessorBinding pb = new ProcessorBinding();
+		pb.setInputPortBindings(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingInputPortBindings() {
+		ProcessorBinding pb = new ProcessorBinding();
+		pb.setInputPortBindings(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("inputPortBindings")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedInputPortBindings() {
+		ProcessorBinding pb = new ProcessorBinding();
+		// No need to specify as default constructor does it
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("inputPortBindings")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+	@Test
+	public void testCorrectnessOfMissingOutputPortBindings() {
+		ProcessorBinding pb = new ProcessorBinding();
+		pb.setOutputPortBindings(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingOutputPortBindings() {
+		ProcessorBinding pb = new ProcessorBinding();
+		pb.setOutputPortBindings(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("outputPortBindings")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedOutputPortBindings() {
+		ProcessorBinding pb = new ProcessorBinding();
+		// No need to specify as default constructor does it
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("outputPortBindings")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingActivityPosition() {
+		// should be OK
+		ProcessorBinding pb = new ProcessorBinding();
+		pb.setActivityPosition(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("activityPosition")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfInvalidActivityPosition() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Integer activityPosition = Integer.valueOf(-3);
+		pb.setActivityPosition(activityPosition);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		boolean problem = false;
+		for (NegativeValueProblem nlp : negativeValueProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("activityPosition") && nlp.getFieldValue().equals(activityPosition)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);	
+	}
+	
+	@Test
+	public void testCorrectnessOfValidActivityPosition() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Integer activityPosition = Integer.valueOf(3);
+		pb.setActivityPosition(activityPosition);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(Collections.EMPTY_SET, negativeValueProblems);
+	}
+	
+	@Test
+	public void testCorrectnessOfOutOfScopeBoundProcessor1() {
+		WorkflowBundle wb = new WorkflowBundle();
+		Profile profile = new Profile();
+		profile.setParent(wb);
+		ProcessorBinding pb = new ProcessorBinding();
+		Processor orphanProcessor = new Processor();
+		pb.setBoundProcessor(orphanProcessor);
+		pb.setParent(profile);
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundProcessor") && nlp.getValue().equals(orphanProcessor)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);	
+	}
+	
+	@Test
+	public void testCorrectnessOfOutOfScopeBoundProcessor2() {
+		WorkflowBundle wb = new WorkflowBundle();
+		Profile profile = new Profile();
+		profile.setParent(wb);
+		ProcessorBinding pb = new ProcessorBinding();
+		
+		Workflow w = new Workflow();
+		Processor processor = new Processor();
+		processor.setParent(w);
+		
+		pb.setBoundProcessor(processor);
+		pb.setParent(profile);
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundProcessor") && nlp.getValue().equals(processor)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);	
+	}
+	
+	@Test
+	public void testCorrectnessOfInScopeBoundProcessor() {
+		WorkflowBundle wb = new WorkflowBundle();
+		Profile profile = new Profile();
+		profile.setParent(wb);
+		ProcessorBinding pb = new ProcessorBinding();
+		
+		Workflow w = new Workflow();
+		Processor processor = new Processor();
+		processor.setParent(w);
+		w.setParent(wb);
+		
+		pb.setBoundProcessor(processor);
+		pb.setParent(profile);
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+//		assertFalse(outOfScopeValueProblems.isEmpty());
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundProcessor") && nlp.getValue().equals(processor)) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);	
+	}
+	
+	@Test
+	public void testCorrectnessOfOutOfScopeBoundActivity() {
+		WorkflowBundle wb = new WorkflowBundle();
+		Profile profile = new Profile();
+		profile.setParent(wb);
+		ProcessorBinding pb = new ProcessorBinding();
+		Activity orphanActivity = new Activity();
+		pb.setBoundActivity(orphanActivity);
+		pb.setParent(profile);
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundActivity") && nlp.getValue().equals(orphanActivity)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);	
+	}
+	
+	@Test
+	public void testCorrectnessOfInScopeBoundActivity1() {
+		// Test when in same profile
+		WorkflowBundle wb = new WorkflowBundle();
+		Profile profile = new Profile();
+		profile.setParent(wb);
+		ProcessorBinding pb = new ProcessorBinding();
+		Activity activity = new Activity();
+		activity.setParent(profile); 
+		pb.setBoundActivity(activity);
+		pb.setParent(profile);
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundActivity") && nlp.getValue().equals(activity)) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);	
+	}
+	
+	@Test
+	public void testCorrectnessOfInScopeBoundActivity2() {
+		// Test when in same profile
+		WorkflowBundle wb = new WorkflowBundle();
+		Profile profile = new Profile();
+		profile.setParent(wb);
+		ProcessorBinding pb = new ProcessorBinding();
+		
+		Profile otherProfile = new Profile();
+		otherProfile.setParent(wb);
+		Activity activity = new Activity();
+		activity.setParent(otherProfile); 
+		pb.setBoundActivity(activity);
+		pb.setParent(profile);
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pb) && nlp.getFieldName().equals("boundActivity") && nlp.getValue().equals(activity)) {
+				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/TestProcessorInputPortBinding.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessorInputPortBinding.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessorInputPortBinding.java
new file mode 100644
index 0000000..4c79970
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessorInputPortBinding.java
@@ -0,0 +1,332 @@
+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.activity.Activity;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.port.InputActivityPort;
+import org.apache.taverna.scufl2.api.port.InputProcessorPort;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+import org.apache.taverna.scufl2.api.profiles.ProcessorInputPortBinding;
+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;
+
+
+public class TestProcessorInputPortBinding {
+	
+	@Test
+	public void testCorrectnessOfMissingBoundProcessorPort() {
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingBoundProcessorPort() {
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedBoundProcessorPort() {
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		pipb.setBoundProcessorPort(new InputProcessorPort());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+	@Test
+	public void testCorrectnessOfMissingBoundActivityPort() {
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingBoundActivityPort() {
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedBoundActivityPort() {
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		pipb.setBoundActivityPort(new InputActivityPort());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfOutOfScopeProcessorPort1() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Processor processor = new Processor();
+		pb.setBoundProcessor(processor);
+		
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		pipb.setParent(pb);
+		
+		InputProcessorPort orphanPort = new InputProcessorPort();
+		pipb.setBoundProcessorPort(orphanPort);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort") && nlp.getValue().equals(orphanPort)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfOutOfScopeProcessorPort2() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Processor processor = new Processor();
+		pb.setBoundProcessor(processor);
+		
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		pipb.setParent(pb);
+		
+		Processor otherProcessor = new Processor();
+		InputProcessorPort elsewherePort = new InputProcessorPort();
+		elsewherePort.setParent(otherProcessor);
+		
+		pipb.setBoundProcessorPort(elsewherePort);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort") && nlp.getValue().equals(elsewherePort)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfInScopeProcessorPort() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Processor processor = new Processor();
+		pb.setBoundProcessor(processor);
+		
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		pipb.setParent(pb);
+		
+		InputProcessorPort port = new InputProcessorPort();
+		port.setParent(processor);
+		
+		pipb.setBoundProcessorPort(port);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort") && nlp.getValue().equals(port)) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+	@Test
+	public void testCorrectnessOfOutOfScopeActivityPort1() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Processor processor = new Processor();
+		pb.setBoundProcessor(processor);
+		
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		pipb.setParent(pb);
+		
+		InputActivityPort orphanPort = new InputActivityPort();
+		pipb.setBoundActivityPort(orphanPort);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort") && nlp.getValue().equals(orphanPort)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfOutOfScopeActivityPort2() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Activity activity = new Activity();
+		pb.setBoundActivity(activity);
+		
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		pipb.setParent(pb);
+		
+		Activity otherActivity = new Activity();
+		InputActivityPort elsewherePort = new InputActivityPort();
+		elsewherePort.setParent(otherActivity);
+		
+		pipb.setBoundActivityPort(elsewherePort);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort") && nlp.getValue().equals(elsewherePort)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfInScopeActivityPort() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Activity activity = new Activity();
+		pb.setBoundActivity(activity);
+		
+		ProcessorInputPortBinding pipb = new ProcessorInputPortBinding();
+		pipb.setParent(pb);
+		
+		InputActivityPort port = new InputActivityPort();
+		port.setParent(activity);
+		
+		pipb.setBoundActivityPort(port);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort") && nlp.getValue().equals(port)) {
+				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/TestProcessorOutputPortBinding.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessorOutputPortBinding.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessorOutputPortBinding.java
new file mode 100644
index 0000000..74b4a2f
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProcessorOutputPortBinding.java
@@ -0,0 +1,332 @@
+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.activity.Activity;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.port.OutputActivityPort;
+import org.apache.taverna.scufl2.api.port.OutputProcessorPort;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+import org.apache.taverna.scufl2.api.profiles.ProcessorOutputPortBinding;
+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;
+
+
+public class TestProcessorOutputPortBinding {
+	
+	@Test
+	public void testCorrectnessOfMissingBoundProcessorPort() {
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingBoundProcessorPort() {
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedBoundProcessorPort() {
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		pipb.setBoundProcessorPort(new OutputProcessorPort());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+	@Test
+	public void testCorrectnessOfMissingBoundActivityPort() {
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingBoundActivityPort() {
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedBoundActivityPort() {
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		pipb.setBoundActivityPort(new OutputActivityPort());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfOutOfScopeProcessorPort1() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Processor processor = new Processor();
+		pb.setBoundProcessor(processor);
+		
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		pipb.setParent(pb);
+		
+		OutputProcessorPort orphanPort = new OutputProcessorPort();
+		pipb.setBoundProcessorPort(orphanPort);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort") && nlp.getValue().equals(orphanPort)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfOutOfScopeProcessorPort2() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Processor processor = new Processor();
+		pb.setBoundProcessor(processor);
+		
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		pipb.setParent(pb);
+		
+		Processor otherProcessor = new Processor();
+		OutputProcessorPort elsewherePort = new OutputProcessorPort();
+		elsewherePort.setParent(otherProcessor);
+		
+		pipb.setBoundProcessorPort(elsewherePort);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort") && nlp.getValue().equals(elsewherePort)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfInScopeProcessorPort() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Processor processor = new Processor();
+		pb.setBoundProcessor(processor);
+		
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		pipb.setParent(pb);
+		
+		OutputProcessorPort port = new OutputProcessorPort();
+		port.setParent(processor);
+		
+		pipb.setBoundProcessorPort(port);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundProcessorPort") && nlp.getValue().equals(port)) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+	@Test
+	public void testCorrectnessOfOutOfScopeActivityPort1() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Processor processor = new Processor();
+		pb.setBoundProcessor(processor);
+		
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		pipb.setParent(pb);
+		
+		OutputActivityPort orphanPort = new OutputActivityPort();
+		pipb.setBoundActivityPort(orphanPort);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort") && nlp.getValue().equals(orphanPort)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfOutOfScopeActivityPort2() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Activity activity = new Activity();
+		pb.setBoundActivity(activity);
+		
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		pipb.setParent(pb);
+		
+		Activity otherActivity = new Activity();
+		OutputActivityPort elsewherePort = new OutputActivityPort();
+		elsewherePort.setParent(otherActivity);
+		
+		pipb.setBoundActivityPort(elsewherePort);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort") && nlp.getValue().equals(elsewherePort)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfInScopeActivityPort() {
+		ProcessorBinding pb = new ProcessorBinding();
+		Activity activity = new Activity();
+		pb.setBoundActivity(activity);
+		
+		ProcessorOutputPortBinding pipb = new ProcessorOutputPortBinding();
+		pipb.setParent(pb);
+		
+		OutputActivityPort port = new OutputActivityPort();
+		port.setParent(activity);
+		
+		pipb.setBoundActivityPort(port);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(pipb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(pipb) && nlp.getFieldName().equals("boundActivityPort") && nlp.getValue().equals(port)) {
+				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/TestProfile.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProfile.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProfile.java
new file mode 100644
index 0000000..cc15708
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestProfile.java
@@ -0,0 +1,226 @@
+/**
+ * 
+ */
+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.activity.Activity;
+import org.apache.taverna.scufl2.api.common.NamedSet;
+import org.apache.taverna.scufl2.api.configurations.Configuration;
+import org.apache.taverna.scufl2.api.profiles.ProcessorBinding;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+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;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestProfile {
+	
+	@Test
+	public void testCompletenessOfMissingProfilePosition() {
+		// should be OK
+		Profile profile = new Profile();
+		profile.setProfilePosition(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(profile, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(profile) && nlp.getFieldName().equals("profilePosition")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+	
+	@Test
+	public void testCorrectnessOfInvalidProfilePosition() {
+		Profile profile = new Profile();
+		Integer profilePosition = Integer.valueOf(-3);
+		profile.setProfilePosition(profilePosition);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(profile, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		boolean problem = false;
+		for (NegativeValueProblem nlp : negativeValueProblems) {
+			if (nlp.getBean().equals(profile) && nlp.getFieldName().equals("profilePosition") && nlp.getFieldValue().equals(profilePosition)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);	
+	}
+	
+	@Test
+	public void testCorrectnessOfValidProfilePosition() {
+		Profile profile = new Profile();
+		Integer profilePosition = Integer.valueOf(3);
+		profile.setProfilePosition(profilePosition);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(profile, false, rcvl);
+		
+		Set<NegativeValueProblem> negativeValueProblems = rcvl.getNegativeValueProblems();
+		assertEquals(Collections.EMPTY_SET, negativeValueProblems);
+	}
+	
+	@Test
+	public void testCorrectnessOfMissingFieldss() {
+		DummyProfile profile = new DummyProfile();
+		// The fields will default to null
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(profile, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingFields() {
+		DummyProfile profile = new DummyProfile();
+		// The fields will default to null
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(profile, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(profile) && nlp.getFieldName().equals("processorBindings")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+		problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(profile) && nlp.getFieldName().equals("configurations")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+		problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(profile) && nlp.getFieldName().equals("activities")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedProcessorBindings() {
+		DummyProfile profile = new DummyProfile();
+		// The fields will default to null
+		profile.setProcessorBindings(new NamedSet<ProcessorBinding>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(profile, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(profile) && nlp.getFieldName().equals("processorBindings")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+	@Test
+	public void testCompletenessOfSpecifiedConfigurations() {
+		DummyProfile profile = new DummyProfile();
+		// The fields will default to null
+		profile.setConfigurations(new NamedSet<Configuration>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(profile, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(profile) && nlp.getFieldName().equals("configurations")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+
+
+	@Test
+	public void testCompletenessOfSpecifiedActivities() {
+		DummyProfile profile = new DummyProfile();
+		// The fields will default to null
+		profile.setActivities(new NamedSet<Activity>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(profile, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(profile) && nlp.getFieldName().equals("activities")) {
+				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/TestRoot.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestRoot.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestRoot.java
new file mode 100644
index 0000000..beea5a7
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestRoot.java
@@ -0,0 +1,147 @@
+/**
+ * 
+ */
+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.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NonAbsoluteURIProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestRoot {
+	
+	@Test
+	public void testCorrectnessOfMissingGlobalBaseURI() {
+		WorkflowBundle wb = new WorkflowBundle();
+		wb.setGlobalBaseURI(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(wb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingGlobalBaseURI() {
+		WorkflowBundle wb = new WorkflowBundle();
+		wb.setGlobalBaseURI(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(wb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(wb) && nlp.getFieldName().equals("globalBaseURI")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfGlobalBaseURI() throws URISyntaxException {
+		WorkflowBundle wb = new WorkflowBundle();
+		wb.setGlobalBaseURI(new URI("http://www.taverna.org.uk"));
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(wb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(wb) && nlp.getFieldName().equals("globalBaseURI")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+	}
+	
+	@Test
+	public void testNonAbsoluteURI() throws URISyntaxException {
+		WorkflowBundle wb = new WorkflowBundle();
+		URI globalBaseURI = new URI("fred/soup");
+		wb.setGlobalBaseURI(globalBaseURI);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(wb, false, rcvl);
+		
+		Set<NonAbsoluteURIProblem> problems = rcvl.getNonAbsoluteURIProblems();
+		boolean problem = false;
+		for (NonAbsoluteURIProblem p : problems) {
+			if (p.getBean().equals(wb) && p.getFieldName().equals("globalBaseURI") && p.getFieldValue().equals(globalBaseURI)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testFileURI() throws URISyntaxException {
+		WorkflowBundle wb = new WorkflowBundle();
+		URI globalBaseURI = new URI("file:///fred/soup");
+		wb.setGlobalBaseURI(globalBaseURI);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(wb, false, rcvl);
+		
+		Set<NonAbsoluteURIProblem> problems = rcvl.getNonAbsoluteURIProblems();
+		boolean problem = false;
+		for (NonAbsoluteURIProblem p : problems) {
+			if (p.getBean().equals(wb) && p.getFieldName().equals("globalBaseURI") && p.getFieldValue().equals(globalBaseURI)) {
+				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/TestTyped.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestTyped.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestTyped.java
new file mode 100644
index 0000000..e35b58c
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestTyped.java
@@ -0,0 +1,145 @@
+/**
+ * 
+ */
+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.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.taverna.scufl2.api.activity.Activity;
+import org.apache.taverna.scufl2.validation.correctness.CorrectnessValidator;
+import org.apache.taverna.scufl2.validation.correctness.ReportCorrectnessValidationListener;
+import org.apache.taverna.scufl2.validation.correctness.report.NonAbsoluteURIProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestTyped {
+	
+	@Test
+	public void testCorrectnessOfMissingConfigurableType() {
+		Activity a = new Activity();
+		a.setType(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(a, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingConfigurableType() {
+		Activity a = new Activity();
+		a.setType(null);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(a, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(a) && nlp.getFieldName().equals("configurableType")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfConfigurableType() throws URISyntaxException {
+		Activity a = new Activity();
+		a.setType(new URI("http://www.taverna.org.uk"));
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(a, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(a) && nlp.getFieldName().equals("configurableType")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+	}
+	
+	@Test
+	public void testNonAbsoluteURI() throws URISyntaxException {
+		Activity a = new Activity();
+		URI type = new URI("fred/soup");
+		a.setType(type);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(a, false, rcvl);
+		
+		Set<NonAbsoluteURIProblem> problems = rcvl.getNonAbsoluteURIProblems();
+		boolean problem = false;
+		for (NonAbsoluteURIProblem p : problems) {
+			if (p.getBean().equals(a) && p.getFieldName().equals("configurableType") && p.getFieldValue().equals(type)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+	}
+	
+	@Test
+	public void testFileURI() throws URISyntaxException {
+		Activity a = new Activity();
+		URI type = new URI("file:///fred/soup");
+		a.setType(type);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(a, false, rcvl);
+		
+		Set<NonAbsoluteURIProblem> problems = rcvl.getNonAbsoluteURIProblems();
+		boolean problem = false;
+		for (NonAbsoluteURIProblem p : problems) {
+			if (p.getBean().equals(a) && p.getFieldName().equals("configurableType") && p.getFieldValue().equals(type)) {
+				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/TestWorkflow.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestWorkflow.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestWorkflow.java
new file mode 100644
index 0000000..33f80f5
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestWorkflow.java
@@ -0,0 +1,242 @@
+/**
+ * 
+ */
+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.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.taverna.scufl2.api.common.NamedSet;
+import org.apache.taverna.scufl2.api.core.ControlLink;
+import org.apache.taverna.scufl2.api.core.DataLink;
+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.NonAbsoluteURIProblem;
+import org.apache.taverna.scufl2.validation.correctness.report.NullFieldProblem;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class TestWorkflow {
+	
+	@Test
+	public void testCorrectnessOfMissingFields() {
+		DummyWorkflow dw = new DummyWorkflow();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dw, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingFields() {
+		DummyWorkflow dw = new DummyWorkflow();
+		
+		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("dataLinks")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+		problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dw) && nlp.getFieldName().equals("controlLinks")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+		problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dw) && nlp.getFieldName().equals("processors")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+		problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dw) && nlp.getFieldName().equals("workflowIdentifier")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedDataLinks() {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setDataLinks(new TreeSet<DataLink>());
+		
+		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("dataLinks")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+
+	}
+
+	
+	@Test
+	public void testCompletenessOfSpecifiedControlLinks() {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setControlLinks(new TreeSet<ControlLink>());
+		
+		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("controlLinks")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+
+	}
+
+	
+	@Test
+	public void testCompletenessOfSpecifiedProcessors() {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setProcessors(new NamedSet<Processor>());
+		
+		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("processors")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+
+	}
+
+	
+	@Test
+	public void testCompletenessOfSpecifiedWorkflowIdentifier() throws URISyntaxException {
+		DummyWorkflow dw = new DummyWorkflow();
+		dw.setIdentifier(new URI("http://www.mygrid.org.uk/fred/"));
+		
+		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("workflowIdentifier")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+
+	}
+
+	@Test
+	public void testNonAbsoluteURI() throws URISyntaxException {
+		DummyWorkflow dw = new DummyWorkflow();
+		URI workflowIdentifier = new URI("fred/soup");
+		dw.setIdentifier(workflowIdentifier);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dw, false, rcvl);
+		
+		Set<NonAbsoluteURIProblem> problems = rcvl.getNonAbsoluteURIProblems();
+		boolean problem = false;
+		for (NonAbsoluteURIProblem p : problems) {
+			if (p.getBean().equals(dw) && p.getFieldName().equals("workflowIdentifier") && p.getFieldValue().equals(workflowIdentifier)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+	}
+	
+	@Test
+	public void testFileURI() throws URISyntaxException {
+		DummyWorkflow dw = new DummyWorkflow();
+		URI workflowIdentifier = new URI("file:///fred/soup");
+		dw.setIdentifier(workflowIdentifier);
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dw, false, rcvl);
+		
+		Set<NonAbsoluteURIProblem> problems = rcvl.getNonAbsoluteURIProblems();
+		boolean problem = false;
+		for (NonAbsoluteURIProblem p : problems) {
+			if (p.getBean().equals(dw) && p.getFieldName().equals("workflowIdentifier") && p.getFieldValue().equals(workflowIdentifier)) {
+				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/TestWorkflowBundle.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestWorkflowBundle.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestWorkflowBundle.java
new file mode 100644
index 0000000..3147fa0
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/correctness/TestWorkflowBundle.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.common.NamedSet;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.profiles.Profile;
+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 TestWorkflowBundle {
+	
+	@Test
+	public void testCorrectnessOfMissingFields() {
+		DummyWorkflowBundle dwb = new DummyWorkflowBundle();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dwb, false, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertEquals(Collections.EMPTY_SET, nullFieldProblems);
+	}
+	
+	@Test
+	public void testCompletenessOfMissingFields() {
+		DummyWorkflowBundle dwb = new DummyWorkflowBundle();
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dwb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		assertFalse(nullFieldProblems.isEmpty());
+		
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("profiles")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+		problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("workflows")) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+		
+		problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("mainProfile")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+		problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("mainWorkflow")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+		
+	}
+	
+	@Test
+	public void testCompletenessOfSpecifiedProfiles() {
+		DummyWorkflowBundle dwb = new DummyWorkflowBundle();
+		dwb.setProfiles(new NamedSet<Profile>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dwb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("profiles")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+
+	}
+
+	@Test
+	public void testCompletenessOfSpecifiedWorkflows() {
+		DummyWorkflowBundle dwb = new DummyWorkflowBundle();
+		dwb.setWorkflows(new NamedSet<Workflow>());
+		
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dwb, true, rcvl);
+		
+		Set<NullFieldProblem> nullFieldProblems = rcvl.getNullFieldProblems();
+		
+		boolean problem = false;
+		for (NullFieldProblem nlp : nullFieldProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("workflows")) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+	}
+
+	@Test
+	public void testOutOfScopeMainProfile() {
+		DummyWorkflowBundle dwb = new DummyWorkflowBundle();
+		Profile orphanProfile = new Profile();
+		dwb.setMainProfile(orphanProfile);
+		dwb.setProfiles(new NamedSet<Profile>());
+
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dwb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("mainProfile") && nlp.getValue().equals(orphanProfile)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+
+	}
+
+	@Test
+	public void testInScopeMainProfile() {
+		DummyWorkflowBundle dwb = new DummyWorkflowBundle();
+		Profile profile = new Profile();
+		dwb.setMainProfile(profile);
+		NamedSet<Profile> profiles = new NamedSet<Profile>();
+		dwb.setProfiles(profiles);
+		profiles.add(profile);
+
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dwb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("mainProfile") && nlp.getValue().equals(profile)) {
+				problem = true;
+			}
+		}
+		assertFalse(problem);
+
+	}
+
+	@Test
+	public void testOutOfScopeMainWorkflow() {
+		DummyWorkflowBundle dwb = new DummyWorkflowBundle();
+		Workflow orphanWorkflow = new Workflow();
+		dwb.setMainWorkflow(orphanWorkflow);
+		dwb.setWorkflows(new NamedSet<Workflow>());
+
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dwb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		assertFalse(outOfScopeValueProblems.isEmpty());
+		
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("mainWorkflow") && nlp.getValue().equals(orphanWorkflow)) {
+				problem = true;
+			}
+		}
+		assertTrue(problem);
+
+	}
+
+	@Test
+	public void testInScopeMainWorkflow() {
+		DummyWorkflowBundle dwb = new DummyWorkflowBundle();
+		Workflow workflow = new Workflow();
+		dwb.setMainWorkflow(workflow);
+		NamedSet<Workflow> workflows = new NamedSet<Workflow>();
+		dwb.setWorkflows(workflows);
+		workflows.add(workflow);
+
+		CorrectnessValidator cv = new CorrectnessValidator();
+		ReportCorrectnessValidationListener rcvl = new ReportCorrectnessValidationListener();
+		
+		cv.checkCorrectness(dwb, false, rcvl);
+		
+		Set<OutOfScopeValueProblem> outOfScopeValueProblems = rcvl.getOutOfScopeValueProblems();
+		
+		boolean problem = false;
+		for (OutOfScopeValueProblem nlp : outOfScopeValueProblems) {
+			if (nlp.getBean().equals(dwb) && nlp.getFieldName().equals("mainWorkflow") && nlp.getValue().equals(workflow)) {
+				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/structural/CrossProductTest.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/structural/CrossProductTest.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/structural/CrossProductTest.java
new file mode 100644
index 0000000..0b3676c
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/structural/CrossProductTest.java
@@ -0,0 +1,138 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.structural;
+/*
+ *
+ * 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 java.util.HashMap;
+import java.util.Map;
+
+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.structural.StructuralValidator;
+import org.junit.Test;
+
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class CrossProductTest {
+	
+	private InputProcessorPort a;
+	private InputProcessorPort b;
+
+	private CrossProduct getCross(int depthA, int depthB) {
+		a = new InputProcessorPort();
+		a.setName("a");
+		a.setDepth(0);
+		CrossProduct cp = new CrossProduct();
+		PortNode nipn1 = new PortNode(cp, a);
+		nipn1.setDesiredDepth(depthA);
+		
+		b = new InputProcessorPort();
+		b.setName("b");
+		b.setDepth(0);
+		PortNode nipn2 = new PortNode(cp, b);
+		nipn2.setDesiredDepth(depthB);
+
+		return cp;
+	}
+	
+	@Test
+	public void testSingletonCrossUnstagedIteration(){
+		CrossProduct cp = getCross(0, 0);
+		
+		StructuralValidator sv = new StructuralValidator();
+		Map<InputProcessorPort, Integer> tempDepths = new HashMap<InputProcessorPort, Integer>();
+		tempDepths.put(a, 1);
+		tempDepths.put(b, 1);
+
+		assertEquals(Integer.valueOf(2), sv.getIterationDepth(cp,
+		tempDepths));
+	}
+	
+	@Test
+	public void testListCrossUnstagedIteration() {
+		CrossProduct cp = getCross(0, 0);
+		StructuralValidator sv = new StructuralValidator();
+		Map<InputProcessorPort, Integer> tempDepths = new HashMap<InputProcessorPort, Integer>();
+		tempDepths.put(a,2);
+		tempDepths.put(b,2);
+		
+		assertEquals(Integer.valueOf(4), sv.getIterationDepth(cp,
+		tempDepths));
+	}
+	
+	@Test
+	public void testListCrossDifferentIterationsUnstagedIteration() {
+		CrossProduct cp = getCross(0, 0);
+		StructuralValidator sv = new StructuralValidator();
+		Map<InputProcessorPort, Integer> tempDepths = new HashMap<InputProcessorPort, Integer>();
+		tempDepths.put(a,1);
+		tempDepths.put(b,2);
+		
+		assertEquals(Integer.valueOf(3), sv.getIterationDepth(cp,
+		tempDepths));
+		
+	}
+	
+	@Test
+	public void testDifferentDepthsCrossUnstagedIteration() {
+		CrossProduct cp = getCross(0, 1);
+		StructuralValidator sv = new StructuralValidator();
+		Map<InputProcessorPort, Integer> tempDepths = new HashMap<InputProcessorPort, Integer>();
+		tempDepths.put(a,3);
+		tempDepths.put(b,4);
+		
+		assertEquals(Integer.valueOf(6), sv.getIterationDepth(cp,
+		tempDepths));
+		
+	}
+	
+	@Test
+	public void testStagedCombinationOfCross() {
+		
+		Processor p = new Processor();
+		IterationStrategyStack iss = new IterationStrategyStack(p);
+
+	iss.add(getCross(1, 1));
+	iss.add(getCross(0, 0));
+	StructuralValidator sv = new StructuralValidator();
+	sv.getValidatorState().setProcessor(p);
+	Map<InputProcessorPort, Integer> tempDepths = new HashMap<InputProcessorPort, Integer>();
+	tempDepths.put(a,2);
+	tempDepths.put(b,2);
+
+	assertEquals(Integer.valueOf(4), sv.calculateResultWrappingDepth(tempDepths));
+
+}
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-language/blob/f8af1400/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/structural/DepthInheritanceTest.java
----------------------------------------------------------------------
diff --git a/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/structural/DepthInheritanceTest.java b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/structural/DepthInheritanceTest.java
new file mode 100644
index 0000000..cbbf223
--- /dev/null
+++ b/taverna-scufl2-api/src/test/java/org/apache/taverna/scufl2/validation/structural/DepthInheritanceTest.java
@@ -0,0 +1,154 @@
+/**
+ * 
+ */
+package org.apache.taverna.scufl2.validation.structural;
+/*
+ *
+ * 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 org.apache.taverna.scufl2.api.container.WorkflowBundle;
+import org.apache.taverna.scufl2.api.core.DataLink;
+import org.apache.taverna.scufl2.api.core.Processor;
+import org.apache.taverna.scufl2.api.core.Workflow;
+import org.apache.taverna.scufl2.api.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.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.structural.ReportStructuralValidationListener;
+import org.apache.taverna.scufl2.validation.structural.StructuralValidator;
+import org.apache.taverna.scufl2.validation.structural.ValidatorState;
+import org.junit.Test;
+
+
+/**
+ * @author alanrw
+ * 
+ */
+public class DepthInheritanceTest {
+
+	@Test
+	public void testDataLinkInheritanceFromInputWorkflowPorts() {
+		WorkflowBundle wb = new WorkflowBundle();
+		Workflow w = new Workflow();
+		wb.setMainWorkflow(w);
+
+		InputWorkflowPort a = new InputWorkflowPort(w, "a");
+		a.setDepth(0);
+
+		InputWorkflowPort b = new InputWorkflowPort(w, "b");
+		b.setDepth(7);
+
+		OutputWorkflowPort outA = new OutputWorkflowPort(w, "outA");
+		OutputWorkflowPort outB = new OutputWorkflowPort(w, "outB");
+
+		DataLink aLink = new DataLink(w, a, outA);
+		DataLink bLink = new DataLink(w, b, outB);
+
+		StructuralValidator sv = new StructuralValidator();
+		ReportStructuralValidationListener l = new ReportStructuralValidationListener();
+		sv.checkStructure(wb, l);
+		ValidatorState vs = sv.getValidatorState();
+		assertEquals(0, l.getIncompleteWorkflows().size());
+		assertEquals(Integer.valueOf(0), vs.getDataLinkResolvedDepth(aLink));
+		assertEquals(Integer.valueOf(7), vs.getDataLinkResolvedDepth(bLink));
+		assertEquals(Integer.valueOf(0), vs.getPortResolvedDepth(outA));
+		assertEquals(Integer.valueOf(7), vs.getPortResolvedDepth(outB));
+	}
+
+	@Test
+	public void testMergingToOutputWorkflowPort() {
+		WorkflowBundle wb = new WorkflowBundle();
+		Workflow w = new Workflow();
+		wb.setMainWorkflow(w);
+
+		InputWorkflowPort a = new InputWorkflowPort(w, "a");
+		a.setDepth(0);
+
+		InputWorkflowPort b = new InputWorkflowPort(w, "b");
+		b.setDepth(7);
+
+		OutputWorkflowPort outA = new OutputWorkflowPort(w, "outA");
+		OutputWorkflowPort outB = new OutputWorkflowPort(w, "outB");
+
+		DataLink aLink = new DataLink(w, a, outA);
+		aLink.setMergePosition(0);
+		DataLink bLink = new DataLink(w, b, outA);
+		bLink.setMergePosition(1);
+
+		DataLink aLink2 = new DataLink(w, a, outB);
+		aLink2.setMergePosition(1);
+		DataLink bLink2 = new DataLink(w, b, outB);
+		bLink2.setMergePosition(0);
+
+		StructuralValidator sv = new StructuralValidator();
+		ReportStructuralValidationListener l = new ReportStructuralValidationListener();
+		sv.checkStructure(wb, l);
+		ValidatorState vs = sv.getValidatorState();
+		assertEquals(0, l.getIncompleteWorkflows().size());
+		assertEquals(Integer.valueOf(0), vs.getDataLinkResolvedDepth(aLink));
+		assertEquals(Integer.valueOf(7), vs.getDataLinkResolvedDepth(bLink));
+		assertEquals(Integer.valueOf(1), vs.getPortResolvedDepth(outA));
+		assertEquals(Integer.valueOf(8), vs.getPortResolvedDepth(outB));
+
+	}
+
+	@Test
+	public void testSimpleIteration() {
+		WorkflowBundle wb = new WorkflowBundle();
+		Workflow w = new Workflow();
+		wb.setMainWorkflow(w);
+
+		InputWorkflowPort a = new InputWorkflowPort(w, "a");
+		a.setDepth(1);
+
+		Processor p = new Processor(w, "p");
+
+		InputProcessorPort ipp = new InputProcessorPort(p, "in");
+		ipp.setDepth(0);
+
+		OutputProcessorPort opp = new OutputProcessorPort(p, "out");
+		opp.setDepth(3);
+
+		DataLink inLink = new DataLink(w, a, ipp);
+
+		IterationStrategyStack iss = new IterationStrategyStack(p);
+		CrossProduct cp = new CrossProduct();
+		iss.add(cp);
+		PortNode portNode = new PortNode(cp, ipp);
+		portNode.setDesiredDepth(0);
+
+		StructuralValidator sv = new StructuralValidator();
+		ReportStructuralValidationListener l = new ReportStructuralValidationListener();
+		sv.checkStructure(wb, l);
+		ValidatorState vs = sv.getValidatorState();
+		assertEquals(0, l.getIncompleteWorkflows().size());
+		assertEquals(Integer.valueOf(1), vs.getPortResolvedDepth(a));
+		assertEquals(Integer.valueOf(1), vs.getDataLinkResolvedDepth(inLink));
+		assertEquals(Integer.valueOf(1), vs.getPortResolvedDepth(ipp));
+		assertEquals(Integer.valueOf(4), vs.getPortResolvedDepth(opp));
+	}
+
+}