Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/utils/DebuggingHelper.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/utils/DebuggingHelper.java	(revision 1852)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/utils/DebuggingHelper.java	(revision 1852)
@@ -0,0 +1,85 @@
+//   Copyright 2012 Georg-August-Universität Göttingen, Germany
+//
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+
+package de.ugoe.cs.autoquest.tasktrees.temporalrelation.utils;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class DebuggingHelper {
+
+    /**
+     *
+     */
+    public static String toPlainStr(ITask task) {
+        StringBuffer result = new StringBuffer();
+        toPlainStr(task, result);
+        return result.toString();
+    }
+
+    /**
+     *
+     */
+    public static void toPlainStr(ITask task, StringBuffer result) {
+        if (task instanceof IEventTask) {
+            IEventTaskInstance eventTaskInstance =
+                (IEventTaskInstance) task.getInstances().iterator().next();
+            result.append(eventTaskInstance.getEvent().getType().getName());
+            result.append(" on ");
+            result.append(eventTaskInstance.getEvent().getTarget());
+        }
+        else if (task instanceof ISequence) {
+            result.append("sequence (");
+
+            for (ITask child : ((ISequence) task).getChildren()) {
+                toPlainStr(child, result);
+                result.append(", ");
+            }
+
+            result.append(")");
+        }
+        else if (task instanceof ISelection) {
+            result.append("selection (");
+
+            for (ITask child : ((ISelection) task).getChildren()) {
+                toPlainStr(child, result);
+                result.append(", ");
+            }
+
+            result.append(")");
+        }
+        else if (task instanceof IIteration) {
+            result.append("iteration (");
+            toPlainStr(((IIteration) task).getMarkedTask(), result);
+            result.append(")");
+        }
+        else if (task instanceof IOptional) {
+            result.append("optional (");
+            toPlainStr(((IOptional) task).getMarkedTask(), result);
+            result.append(")");
+        }
+    }
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/utils/TaskTreeEncoder.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/utils/TaskTreeEncoder.java	(revision 1852)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/utils/TaskTreeEncoder.java	(revision 1852)
@@ -0,0 +1,419 @@
+//   Copyright 2012 Georg-August-Universität Göttingen, Germany
+//
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+
+package de.ugoe.cs.autoquest.tasktrees.temporalrelation.utils;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import de.ugoe.cs.autoquest.eventcore.Event;
+import de.ugoe.cs.autoquest.eventcore.gui.TextInput;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITemporalRelationship;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskPath;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 01.04.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class TaskTreeEncoder {
+    
+    /**
+     *
+     */
+    public void encode(List<IUserSession> userSessions)
+        throws FileNotFoundException
+    {
+        PrintStream out = null;
+        try {
+            out = new PrintStream(new FileOutputStream("userSessions.txt"));
+            for (IUserSession session : userSessions) {
+                encode(session, out);
+            }
+        }
+        finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+    
+    /**
+     *
+     */
+    public void encode(ITaskInstanceList taskInstanceList)
+        throws FileNotFoundException
+    {
+        PrintStream out = null;
+        try {
+            out = new PrintStream(new FileOutputStream("taskInstanceList.txt"));
+            encode(taskInstanceList, out);
+        }
+        finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+    
+    /**
+     *
+     */
+    public void encode(ITask task)
+        throws FileNotFoundException
+    {
+        PrintStream out = null;
+        try {
+            out = new PrintStream(new FileOutputStream("task.txt"));
+            encode(task, out);
+        }
+        finally {
+            if (out != null) {
+                out.close();
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    public void encode(ITaskInstanceList taskInstanceList, PrintStream out) {
+        encode(taskInstanceList, out, null);
+    }
+
+    /**
+     *
+     */
+    public void encode(ITaskInstanceList taskInstanceList,
+                       PrintStream       out,
+                       List<TaskPath>    excludes)
+    {
+        TaskPath path = new TaskPath();
+        if (taskInstanceList instanceof IUserSession) {
+            out.println("UserSession {");
+        }
+        else {
+            out.println("TaskInstances {");
+        }
+        
+        if (taskInstanceList instanceof ITaskInstance) {
+            path.add(((ITaskInstance) taskInstanceList).getTask(), 0);
+        }
+        
+        int i = 0;
+        for (ITaskInstance taskInstance : taskInstanceList) {
+            encode(taskInstance, out, "  ", i++, path, excludes);
+        }
+        
+        out.println('}');
+    }
+
+    /**
+     *
+     */
+    public void encode(ITaskInstance taskInstance, PrintStream out) {
+        encode(taskInstance, out, null);
+    }
+
+    /**
+     *
+     */
+    public void encode(ITaskInstance taskInstance, PrintStream out, List<TaskPath> excludes) {
+        TaskPath path = new TaskPath();
+        encode(taskInstance, out, "", 0, path, excludes);
+    }
+
+    /**
+     *
+     */
+    public void encode(ITask task, PrintStream out) {
+        encode(task, out, "", 0);
+    }
+    
+    /**
+     *
+     */
+    private void encode(ITaskInstance  taskInstance,
+                        PrintStream    out,
+                        String         indent,
+                        int            index,
+                        TaskPath       parentPath,
+                        List<TaskPath> excludes)
+    {
+        ITask task = taskInstance.getTask();
+        TaskPath path = parentPath;
+        path.add(task, index);
+        
+        if (task instanceof ITemporalRelationship) {
+            if (index > 0) {
+                out.println();
+            }
+            out.print(indent);
+
+            if (task instanceof ISequence) {
+                out.print("Sequence ");
+            }
+            else if (task instanceof ISelection) {
+                out.print("Selection ");
+            }            
+            else if (task instanceof IIteration) {
+                out.print("Iteration ");
+            }            
+            else if (task instanceof IOptional) {
+                out.print("Optional ");
+            }
+            
+            out.print(task.getId());
+            
+            if (task.getDescription() != null) {
+                out.print('(');
+                out.print(task.getDescription());
+                out.print(") ");
+            }
+            
+            out.print('{');
+            
+            if ((excludes == null) || (!excludes.contains(path))) {
+                out.println();
+            }
+        }
+        else if (task instanceof IEventTask) {
+            out.print(indent);
+            out.print(task);
+        }
+        else {
+            throw new RuntimeException
+                ("unknown type of task referred by task instance " + taskInstance);
+        }
+
+        if ((excludes == null) || (!excludes.contains(path))) {
+            int i = 0;
+        
+            if (taskInstance instanceof ITaskInstanceList) {
+                for (ITaskInstance child : (ITaskInstanceList) taskInstance) {
+                    encode(child, out, indent + "  ", i++, path, excludes);
+                }
+            }
+            else if (taskInstance instanceof ISelectionInstance) {
+                encode(((ISelectionInstance) taskInstance).getChild(), out, indent + "  ", i++,
+                       path, excludes);
+            }
+            else if (taskInstance instanceof IOptionalInstance) {
+                if (((IOptionalInstance) taskInstance).getChild() != null) {
+                    encode(((IOptionalInstance) taskInstance).getChild(), out, indent + "  ", i++,
+                           path, excludes);
+                }
+            }
+
+            if (task instanceof ITemporalRelationship) {
+                out.print(indent);
+                out.print("}");
+            }
+        }
+        else {
+            if (task instanceof ITemporalRelationship) {
+                out.print(" ... }");
+            }
+        }
+
+        out.println();
+        
+        parentPath.removeLast();
+    }
+    
+    /**
+     *
+     */
+    private void encode(ITask         task,
+                        PrintStream   out,
+                        String        indent,
+                        int           index)
+    {
+        if (task instanceof ITemporalRelationship) {
+            if (index > 0) {
+                out.println();
+            }
+            out.print(indent);
+
+            if (task instanceof ISequence) {
+                out.print("Sequence ");
+            }
+            else if (task instanceof ISelection) {
+                out.print("Selection ");
+            }            
+            else if (task instanceof IIteration) {
+                out.print("Iteration ");
+            }            
+            else if (task instanceof IOptional) {
+                out.print("Optional ");
+            }
+            
+            out.print(task.getId());
+            out.println(" {");
+        }
+        else if (task instanceof IEventTask) {
+            out.print(indent);
+            out.print(task);
+        }
+        else {
+            throw new RuntimeException("unknown type of task " + task);
+        }
+
+        int i = 0;
+        
+        if (task instanceof IStructuringTemporalRelationship) {
+            for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) {
+                encode(child, out, indent + "  ", i++);
+            }
+        }
+        else if (task instanceof IMarkingTemporalRelationship) {
+            encode(((IMarkingTemporalRelationship) task).getMarkedTask(), out, indent + "  ", i++);
+        }
+
+        if (task instanceof ITemporalRelationship) {
+            out.print(indent);
+            out.print("}");
+        }
+
+        out.println();
+    }
+    
+    /**
+     *
+     */
+    public void dumpAsCheckString(IUserSession userSession) {
+        int[] typeCounters = new int[4];
+        Map<ITask, String> taskIds = new HashMap<ITask, String>();
+        
+        for (ITaskInstance taskInstance : userSession) {
+            dumpTaskInstanceAsCheckString(taskInstance, typeCounters, taskIds, "");
+        }
+    }
+
+    /**
+     *
+     */
+    private void dumpTaskInstanceAsCheckString(ITaskInstance      taskInstance,
+                                               int[]              typeCounters,
+                                               Map<ITask, String> taskIds,
+                                               String             indent)
+    {
+        ITask task = taskInstance.getTask();
+        
+        System.out.print("       \"");
+        System.out.print(indent);
+
+        String id = taskIds.get(task);
+        
+        if (task instanceof ISequence) {
+            if (id == null) {
+                id = "sequence" + typeCounters[0]++;
+            }
+            
+            System.out.print("Sequence ");
+            System.out.print(id);
+            System.out.println(" {\" +");
+        }
+        else if (task instanceof IIteration) {
+            if (id == null) {
+                id = "iteration" + typeCounters[1]++;
+            }
+            
+            System.out.print("Iteration ");
+            System.out.print(id);
+            System.out.println(" {\" +");
+        }
+        else if (task instanceof ISelection) {
+            if (id == null) {
+                id = "selection" + typeCounters[2]++;
+            }
+            
+            System.out.print("Selection ");
+            System.out.print(id);
+            System.out.println(" {\" +");
+        }
+        else if (task instanceof IEventTask) {
+            Event event = ((IEventTaskInstance) taskInstance).getEvent();
+            if (event.getType() instanceof TextInput) {
+                if (id == null) {
+                    id = "textInput" + typeCounters[3]++;
+                }
+                
+                System.out.print("TextInputEvent ");
+                System.out.print(id);
+                System.out.print(" \"");
+                System.out.print(((TextInput) event.getType()).getEnteredText());
+                System.out.print("\"");
+            }
+            else {
+                if (id == null) {
+                    id = "event" + typeCounters[3]++;
+                }
+                
+                System.out.print("Event ");
+                System.out.print(id);
+                System.out.print(' ');
+                System.out.print(event.getType().getName());
+            }
+            System.out.print(" {}\" +");
+        }
+        else {
+            throw new RuntimeException("unknown type of task referred by task instance " + taskInstance);
+        }
+
+        taskIds.put(task, id);
+        
+        if (taskInstance instanceof ITaskInstanceList) {
+            for (ITaskInstance child : (ITaskInstanceList) taskInstance) {
+                dumpTaskInstanceAsCheckString(child, typeCounters, taskIds, indent + "  ");
+            }
+        }
+        else if (taskInstance instanceof ISelectionInstance) {
+            dumpTaskInstanceAsCheckString
+                (((ISelectionInstance) taskInstance).getChild(), typeCounters, taskIds, indent + "  ");
+        }
+        else if (taskInstance instanceof IOptionalInstance) {
+            dumpTaskInstanceAsCheckString
+                (((IOptionalInstance) taskInstance).getChild(), typeCounters, taskIds, indent + "  ");
+        }
+
+        if (!(task instanceof IEventTask)) {
+            System.out.print("       \"");
+            System.out.print(indent);
+            System.out.print("}\" +");
+        }
+
+        System.out.println();
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/utils/TaskTreeValidator.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/utils/TaskTreeValidator.java	(revision 1852)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/utils/TaskTreeValidator.java	(revision 1852)
@@ -0,0 +1,406 @@
+//   Copyright 2012 Georg-August-Universität Göttingen, Germany
+//
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+
+package de.ugoe.cs.autoquest.tasktrees.temporalrelation.utils;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+
+/**
+ * <p>
+ * TODO comment
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class TaskTreeValidator {
+
+    /**
+     * 
+     */
+    public void validate(List<IUserSession> userSessions, boolean checkInstances) {
+        validate(userSessions);
+        
+        if (!checkInstances) {
+            return;
+        }
+        
+        Map<ITask, List<ITaskInstance>> allTasks = new HashMap<ITask, List<ITaskInstance>>();
+        
+        for (IUserSession userSession : userSessions) {
+            getAllTasksAndInstances(userSession, allTasks);
+        }
+        
+        for (Map.Entry<ITask, List<ITaskInstance>> entry : allTasks.entrySet()) {
+            assertEquals(entry.getKey(), "number of task instances of task " + entry.getKey() +
+                         " in the sessions is not equal to those referenced by the model",
+                         entry.getValue().size(), entry.getKey().getInstances().size());
+            
+            for (ITaskInstance candidate : entry.getValue()) {
+                boolean found = false;
+                for (ITaskInstance instance : entry.getKey().getInstances()) {
+                    if (candidate.equals(instance)) {
+                        if (!found) {
+                            found = true;
+                        }
+                        else {
+                            fail(entry.getKey(), "the same instance is referred twice by the task");
+                        }
+                    }
+                }
+                
+                assertTrue(candidate.getTask(), "instance " + candidate +
+                           " is not referred by task", found);
+            }
+        }
+    }
+
+    /**
+     * 
+     */
+    public void validate(List<IUserSession> userSessions) {
+        for (IUserSession userSession : userSessions) {
+            validate(userSession);
+        }
+    }
+
+    /**
+     * 
+     */
+    public void validate(ITaskInstanceList taskInstances) {
+        for (ITaskInstance taskInstance : taskInstances) {
+            validate(taskInstance);
+        }
+    }
+
+    /**
+     * 
+     */
+    public void validate(ITask task) {
+        assertTrue(task, "task has no instances", task.getInstances().size() > 0);
+        assertTrue(task, "task has no instances", task.getInstances().iterator().hasNext());
+        assertNotNull(task, "task has no instances", task.getInstances().iterator().next());
+        
+        for (ITaskInstance taskInstance : task.getInstances()) {
+            assertSame(task, "task of instance does not match task", task, taskInstance.getTask());
+            validate(taskInstance);
+        }
+    }
+
+    /**
+     * 
+     */
+    public void validate(ITaskInstance taskInstance) {
+        ITask task = taskInstance.getTask();
+        assertNotNull(task, "task model of task instance must not be null", task);
+        
+        if (task instanceof ISequence) {
+            ISequence seq = (ISequence) taskInstance.getTask();
+            
+            assertEquals(seq, "number of children of sequence instance must match sequence model",
+                         ((ISequenceInstance) taskInstance).size(), seq.getChildren().size());
+            
+            for (int i = 0; i < ((ISequenceInstance) taskInstance).size(); i++) {
+                assertNotNull(seq, "sequence instance child " + i + " was null",
+                              ((ISequenceInstance) taskInstance).get(i));
+                ITask childTask = ((ISequenceInstance) taskInstance).get(i).getTask();
+                assertSame(seq, "task of sequence instance child " + i + "(" +
+                           ((ISequenceInstance) taskInstance).get(i) + ") does not match " +
+                           "sequence model (" + seq.getChildren().get(i) + ")",
+                           childTask, seq.getChildren().get(i));
+            }
+        }
+        else if (task instanceof ISelection) {
+            ISelection sel = (ISelection) task;
+            
+            assertNotNull(sel, "number of children of selection instance must be 1",
+                          ((ISelectionInstance) taskInstance).getChild());
+            
+            assertTrue(sel, "number of children of selection must be larger 0",
+                       sel.getChildren().size() > 0);
+            
+            boolean found = false;
+            for (ITask childTask : sel.getChildren()) {
+                assertNotNull(sel, "child of selection model must not be null", childTask);
+                assertFalse(sel, "child of selection model must not be a selection",
+                            childTask instanceof ISelection);
+                /*assertFalse("child of selection model must not be an optional",
+                            childTask instanceof IOptional);*/
+                if (childTask.equals(((ISelectionInstance) taskInstance).getChild().getTask())) {
+                    found = true;
+                    break;
+                }
+            }
+            
+            assertTrue(sel, "no child of the selection model matches the model of child of the " +
+                       "selection instance", found);
+        }
+        else if (task instanceof IIteration) {
+            ITask childTask = ((IIteration) task).getMarkedTask();
+            assertNotNull(task, "child task of iteration model must not be null", childTask);
+            assertFalse(task, "child of iteration model must not be an iteration",
+                        childTask instanceof IIteration);
+            assertFalse(task, "child of iteration model must not be an optional",
+                        childTask instanceof IOptional);
+            
+            for (int i = 0; i < ((IIterationInstance) taskInstance).size(); i++) {
+                assertNotNull(task, "iteration instance child " + i + " was null",
+                              ((IIterationInstance) taskInstance).get(i));
+                assertSame(task, "task of iteration child " + i + " does not match iteration model",
+                           childTask, ((IIterationInstance) taskInstance).get(i).getTask());
+            }
+        }
+        else if (task instanceof IOptional) {
+            ITask childTask = ((IOptional) task).getMarkedTask();
+            assertNotNull(task, "child task of optional model must not be null", childTask);
+            assertFalse(task, "child of optional model must not be an optional",
+                        childTask instanceof IOptional);
+            
+            if (((IOptionalInstance) taskInstance).getChild() != null) {
+                assertSame(task, "task of optional child does not match optional model", childTask,
+                           ((IOptionalInstance) taskInstance).getChild().getTask());
+            }
+        }
+        else if (task instanceof IEventTask) {
+            IEventTask eventTask = (IEventTask) task;
+            assertNotNull(task, "event task model must not be null", eventTask);
+            assertNotNull(task, "event of event task instance must not be null",
+                          ((IEventTaskInstance) taskInstance).getEvent());
+        }
+        else {
+            fail(task, "unknown task model: " + task);
+        }
+        
+        if (taskInstance instanceof ITaskInstanceList) {
+            for (ITaskInstance child : (ITaskInstanceList) taskInstance) {
+                validate(child);
+            }
+        }
+        else if (taskInstance instanceof ISelectionInstance) {
+            validate(((ISelectionInstance) taskInstance).getChild());
+        }
+        else if (taskInstance instanceof IOptionalInstance) {
+            if (((IOptionalInstance) taskInstance).getChild() != null) {
+                validate(((IOptionalInstance) taskInstance).getChild());
+            }
+        }
+    }
+
+    /**
+     * 
+     */
+    private void getAllTasksAndInstances(ITaskInstanceList                     taskInstances,
+                                         final Map<ITask, List<ITaskInstance>> allTasks)
+    {
+        for (ITaskInstance taskInstance : taskInstances) {
+            
+            taskInstance.accept(new DefaultTaskInstanceTraversingVisitor() {
+
+                /* (non-Javadoc)
+                 * @see DefaultTaskInstanceTraversingVisitor#visit(IOptionalInstance)
+                 */
+                @Override
+                public void visit(IOptionalInstance optionalInstance) {
+                    addToInstanceList(optionalInstance);
+                    super.visit(optionalInstance);
+                }
+
+                /* (non-Javadoc)
+                 * @see DefaultTaskInstanceTraversingVisitor#visit(ISelectionInstance)
+                 */
+                @Override
+                public void visit(ISelectionInstance selectionInstance) {
+                    addToInstanceList(selectionInstance);
+                    super.visit(selectionInstance);
+                }
+
+                /* (non-Javadoc)
+                 * @see DefaultTaskInstanceTraversingVisitor#visit(IEventTaskInstance)
+                 */
+                @Override
+                public void visit(IEventTaskInstance eventTaskInstance) {
+                    addToInstanceList(eventTaskInstance);
+                    super.visit(eventTaskInstance);
+                }
+
+                /* (non-Javadoc)
+                 * @see DefaultTaskInstanceTraversingVisitor#visit(IIterationInstance)
+                 */
+                @Override
+                public void visit(IIterationInstance iterationInstance) {
+                    addToInstanceList(iterationInstance);
+                    super.visit(iterationInstance);
+                }
+
+                /* (non-Javadoc)
+                 * @see DefaultTaskInstanceTraversingVisitor#visit(ISequenceInstance)
+                 */
+                @Override
+                public void visit(ISequenceInstance sequenceInstance) {
+                    addToInstanceList(sequenceInstance);
+                    super.visit(sequenceInstance);
+                }
+
+                private void addToInstanceList(ITaskInstance taskInstance) {
+                    List<ITaskInstance> instances = allTasks.get(taskInstance.getTask());
+                    
+                    if (instances == null) {
+                        instances = new LinkedList<ITaskInstance>();
+                        allTasks.put(taskInstance.getTask(), instances);
+                    }
+                    
+                    boolean found = false;
+                    
+                    for (ITaskInstance candidate : instances) {
+                        if (candidate.equals(taskInstance)) {
+                            found = true;
+                            break;
+                        }
+                    }
+                    
+                    assertFalse(taskInstance.getTask(), "instance " + taskInstance +
+                                " occurred twice", found);
+                    
+                    instances.add(taskInstance);
+                }
+                
+            });
+        }
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param string
+     */
+    private void fail(ITask task, String message) {
+        System.err.println("failing validation for task " + task);
+        System.err.println("message: " + message);
+        new TaskTreeEncoder().encode(task, System.err);
+
+        throw new RuntimeException(message);
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param string
+     * @param task
+     */
+    private void assertNotNull(ITask task, String message, Object object) {
+        if (object == null) {
+            System.err.println("failing validation for task " + task);
+            System.err.println("message: " + message);
+            new TaskTreeEncoder().encode(task, System.err);
+
+            throw new RuntimeException(message);
+        }
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param string
+     * @param found
+     */
+    private void assertTrue(ITask task, String message, boolean value) {
+        if (!value) {
+            System.err.println("failing validation for task " + task);
+            System.err.println("message: " + message);
+            new TaskTreeEncoder().encode(task, System.err);
+
+            throw new RuntimeException(message);
+        }
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param string
+     * @param found
+     */
+    private void assertFalse(ITask task, String message, boolean value) {
+        if (value) {
+            System.err.println("failing validation for task " + task);
+            System.err.println("message: " + message);
+            new TaskTreeEncoder().encode(task, System.err);
+
+            throw new RuntimeException(message);
+        }
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param string
+     * @param childTask
+     * @param task
+     */
+    private void assertEquals(ITask task, String message, Object object1, Object object2) {
+        if (!object1.equals(object2)) {
+            System.err.println("failing validation for task " + task);
+            System.err.println("message: " + message);
+            new TaskTreeEncoder().encode(task, System.err);
+
+            throw new RuntimeException(message);
+        }
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param string
+     * @param childTask
+     * @param task
+     */
+    private void assertSame(ITask task, String message, Object object1, Object object2) {
+        if (object1 != object2) {
+            System.err.println("failing validation for task " + task);
+            System.err.println("message: " + message);
+            new TaskTreeEncoder().encode(task, System.err);
+
+            throw new RuntimeException(message);
+        }
+    }
+}
