Index: /branches/ralph/.classpath
===================================================================
--- /branches/ralph/.classpath	(revision 1551)
+++ /branches/ralph/.classpath	(revision 1551)
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
Index: /branches/ralph/.project
===================================================================
--- /branches/ralph/.project	(revision 1551)
+++ /branches/ralph/.project	(revision 1551)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>autoquest-core-tasktrees</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
Index: /branches/ralph/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /branches/ralph/.settings/org.eclipse.jdt.core.prefs	(revision 1551)
+++ /branches/ralph/.settings/org.eclipse.jdt.core.prefs	(revision 1551)
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7
Index: /branches/ralph/.settings/org.eclipse.m2e.core.prefs
===================================================================
--- /branches/ralph/.settings/org.eclipse.m2e.core.prefs	(revision 1551)
+++ /branches/ralph/.settings/org.eclipse.m2e.core.prefs	(revision 1551)
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
Index: /branches/ralph/pom.xml
===================================================================
--- /branches/ralph/pom.xml	(revision 1551)
+++ /branches/ralph/pom.xml	(revision 1551)
@@ -0,0 +1,38 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>de.ugoe.cs.autoquest</groupId>
+    <artifactId>autoquest</artifactId>
+    <version>0.1.1-SNAPSHOT</version>
+    <relativePath>../autoquest/pom.xml</relativePath>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>autoquest-core-tasktrees</artifactId>
+  <name>autoquest-core-tasktrees</name>
+  <licenses>
+    <license>
+      <name>The Apache Software License, Version 2.0</name>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+    </license>
+  </licenses>
+  <scm>
+    <url>${autoquest-scm-trunk-dir}/${project.artifactId}</url>
+    <connection>scm:svn:${autoquest-scm-trunk-dir}/${project.artifactId}</connection>
+  </scm>
+  <dependencies>
+    <dependency>
+      <groupId>de.ugoe.cs.autoquest</groupId>
+      <artifactId>autoquest-core-events</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>de.ugoe.cs.autoquest</groupId>
+      <artifactId>autoquest-core-usageprofiles</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.googlecode.java-diff-utils</groupId>
+      <artifactId>diffutils</artifactId>
+      <version>1.2.1</version>
+    </dependency>
+  </dependencies>
+</project>
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/manager/ComponentManager.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/manager/ComponentManager.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/manager/ComponentManager.java	(revision 1551)
@@ -0,0 +1,137 @@
+//   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.manager;
+
+import de.ugoe.cs.autoquest.tasktrees.temporalrelation.TemporalRelationshipRuleManager;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
+import de.ugoe.cs.autoquest.tasktrees.treeimpl.TaskBuilder;
+import de.ugoe.cs.autoquest.tasktrees.treeimpl.TaskFactory;
+
+/**
+ * <p>
+ * The component manager is the central reference for the distinct submodules required for
+ * task tree generation. Such include the temporal relationship rule manager, the task equality
+ * rule manager, the default task builder, as well as the default task factory.
+ * </p>
+ * 
+ * @version 1.0
+ * @author pharms
+ */
+public class ComponentManager {
+    
+    /**
+     * <p>
+     * singleton instance of this class
+     * </p>
+     */
+    private static ComponentManager instance;
+
+    /**
+     * <p>
+     * the default temporal relationship rule manager
+     * </p>
+     */
+    private TemporalRelationshipRuleManager temporalRelationshipRuleManager;
+
+    /**
+     * <p>
+     * the default task builder
+     * </p>
+     */
+    private ITaskBuilder taskBuilder;
+
+    /**
+     * <p>
+     * the default task factory
+     * </p>
+     */
+    private ITaskFactory taskFactory;
+
+    /**
+     * <p>
+     * returns the default temporal relationship rule manager
+     * </p>
+     * 
+     * @return as described
+     */
+    public static TemporalRelationshipRuleManager getTemporalRelationshipRuleManager() {
+        return getInstance().temporalRelationshipRuleManager;
+    }
+
+    /**
+     * <p>
+     * returns the default task builder
+     * </p>
+     * 
+     * @return as described
+     */
+    public static ITaskBuilder getDefaultTaskBuilder() {
+        return getInstance().taskBuilder;
+    }
+
+    /**
+     * <p>
+     * returns the default task factory
+     * </p>
+     * 
+     * @return as described
+     */
+    public static ITaskFactory getDefaultTaskFactory() {
+        return getInstance().taskFactory;
+    }
+
+    /**
+     * <p>
+     * clears the singleton instance. Needed for test purposes to ensure statelessness between
+     * tests.
+     * </p>
+     */
+    public static synchronized void clearInstance() {
+        instance = null;
+    }
+
+    /**
+     * <p>
+     * returns the singleton instance of this class
+     * </p>
+     * 
+     * @return as described
+     */
+    private static synchronized ComponentManager getInstance() {
+        if (instance == null) {
+            instance = new ComponentManager();
+            instance.init();
+        }
+        return instance;
+    }
+
+    /**
+     * <p>
+     * initialized the component manager with all it default components which are the temporal
+     * relationship rule manager, the task equality rule manager, the default task builder, as
+     * well as the default task factory. 
+     * </p>
+     */
+    private void init() {
+        taskBuilder = new TaskBuilder();
+        taskFactory = new TaskFactory();
+
+        temporalRelationshipRuleManager =
+            new TemporalRelationshipRuleManager(taskFactory, taskBuilder);
+        temporalRelationshipRuleManager.init();
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/manager/TaskTreeManager.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/manager/TaskTreeManager.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/manager/TaskTreeManager.java	(revision 1551)
@@ -0,0 +1,174 @@
+//   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.manager;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Level;
+
+import de.ugoe.cs.autoquest.eventcore.Event;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * The task tree manager is responsible for transforming one or more user sessions into a task
+ * model. It can be called by providing a collection of user sessions where the result
+ * will be a task model. Furthermore, it can be used by providing single events in their respective
+ * order including notifications about where a user session ends. The result is a task model,
+ * as well. 
+ * </p>
+ * 
+ * @version 1.0
+ * @author pharms
+ */
+public class TaskTreeManager {
+    
+    /**
+     * <p>
+     * the internally used task builder
+     * </p>
+     */
+    private ITaskBuilder taskBuilder = ComponentManager.getDefaultTaskBuilder();
+
+    /**
+     * <p>
+     * the internally used task factory
+     * </p>
+     */
+    private ITaskFactory taskFactory = ComponentManager.getDefaultTaskFactory();
+
+    /**
+     * <p>
+     * if single events are provided, the user sessions collected so far
+     * </p>
+     */
+    private List<IUserSession> sessions = null;
+
+    /**
+     * <p>
+     * if single events are provided, the currently collected user session
+     * </p>
+     */
+    private IUserSession currentSession = null;
+
+    /**
+     * <p>
+     * initializes the task tree manager
+     * </p>
+     */
+    public TaskTreeManager() {
+        sessions = new LinkedList<IUserSession>();
+    }
+
+    /**
+     * <p>
+     * creates a task model based on the provided user sessions. Yet, the user sessions are
+     * list of events. Such will be transformed in into task instances of event tasks assigned
+     * to {@link IUserSession}s. The {@link IUserSession}s will then be restructured using
+     * the temporal relationship rule manager to detect tasks and respective instances. The
+     * results of this transformation is stored in a task model which is the return value of
+     * this method.
+     * </p>
+     * 
+     * @param newSessions the user sessions of which the task model shall be created
+     * 
+     * @return the task model created from the user sessions
+     * 
+     * @throws IllegalStateException if the task manager is already used by providing it with
+     *                               single events
+     */
+    public synchronized ITaskModel createTaskModel(Collection<List<Event>> newSessions) {
+        if ((currentSession != null) || (sessions.size() > 0)) {
+            throw new IllegalStateException("do not mix calls to this method with calls to the " +
+                                            "other methods for handling tasks. Use only one " +
+                                            "variant instead.");
+        }
+        
+        for (List<Event> newSession : newSessions) {
+            if (newSession.size() > 0) {
+                for (Event event : newSession) {
+                    handleNewEvent(event);
+                }
+                finishSession();
+            }
+        }
+        
+        return getTaskModel();
+    }
+
+    /**
+     * <p>
+     * handles a single event that occurred in a user session.
+     * </p>
+     * 
+     * @param event the event to handle
+     */
+    public void handleNewEvent(Event event) {
+        assertSessionSequence();
+        String description = event.getType().getName() + " \u21D2 " + event.getTarget();
+        IEventTask eventTask = taskFactory.createNewEventTask(description);
+        taskBuilder.addExecutedTask
+            (currentSession, taskFactory.createNewTaskInstance(eventTask, event));
+    }
+
+    /**
+     * <p>
+     * used to denote, that all previously added events using {@link #handleNewEvent(Event)}
+     * belong to the same session and that this session is now complete. All further events
+     * will be added to a new session which may be ended using this method, as well.
+     * </p>
+     */
+    public void finishSession() {
+        if ((currentSession != null) && (currentSession.size() > 0)) {
+            sessions.add(currentSession);
+            currentSession = null;
+        }
+    }
+
+    /**
+     * <p>
+     * returns the task model, that belongs to the events in the user sessions collected so far.
+     * </p>
+     * 
+     * @return the task model
+     */
+    public synchronized ITaskModel getTaskModel() {
+        finishSession();
+        
+        Console.traceln(Level.INFO, "applying temporal relationship generation rules");
+        
+        ComponentManager.getTemporalRelationshipRuleManager().applyRules(sessions);
+
+        return taskFactory.createTaskModel(sessions);
+    }
+
+    /**
+     * <p>
+     * internally asserts that there is a current session to add new events to
+     * </p>
+     */
+    private void assertSessionSequence() {
+        if (currentSession == null) {
+            currentSession = taskFactory.createUserSession();
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/EventTaskComparisonRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/EventTaskComparisonRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/EventTaskComparisonRule.java	(revision 1551)
@@ -0,0 +1,148 @@
+//   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.taskequality;
+
+import java.util.Collection;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * This rule identifies two tasks as lexically equal, if they are both event tasks and
+ * if their respective event types and targets equal. 
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class EventTaskComparisonRule implements TaskComparisonRule {
+    
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITask, ITask)
+     */
+    @Override
+    public boolean isApplicable(ITask task1, ITask task2) {
+        return (task1 instanceof IEventTask) && (task2 instanceof IEventTask);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        Collection<ITaskInstance> taskInstances1 = task1.getInstances();
+        Collection<ITaskInstance> taskInstances2 = task2.getInstances();
+        
+        for (ITaskInstance instance1 : taskInstances1) {
+            boolean found = false;
+            
+            for (ITaskInstance instance2 : taskInstances2) {
+                if (areLexicallyEqual(instance1, instance2)) {
+                    found = true;
+                    break;
+                }
+            }
+            
+            if (!found) {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
+        return areLexicallyEqual(task1, task2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
+        return areLexicallyEqual(task1, task2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITask, ITask)
+     */
+    @Override
+    public TaskEquality compare(ITask task1, ITask task2) {
+        if (areLexicallyEqual(task1, task2)) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+
+    
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
+        return
+            (instance1 instanceof IEventTaskInstance) && (instance2 instanceof IEventTaskInstance);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        IEventTaskInstance eventTask1 = (IEventTaskInstance) instance1;
+        IEventTaskInstance eventTask2 = (IEventTaskInstance) instance2;
+        
+        return (eventTask1.getEvent().getType().equals(eventTask2.getEvent().getType()) &&
+                eventTask1.getEvent().getTarget().equals(eventTask2.getEvent().getTarget()));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        return areLexicallyEqual(instance1, instance2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        return areLexicallyEqual(instance1, instance2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
+        if (areLexicallyEqual(instance1, instance2)) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/GUIEventTaskComparisonRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/GUIEventTaskComparisonRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/GUIEventTaskComparisonRule.java	(revision 1551)
@@ -0,0 +1,621 @@
+//   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.taskequality;
+
+import java.util.Collection;
+
+import de.ugoe.cs.autoquest.eventcore.IEventTarget;
+import de.ugoe.cs.autoquest.eventcore.gui.IInteraction;
+import de.ugoe.cs.autoquest.eventcore.gui.KeyInteraction;
+import de.ugoe.cs.autoquest.eventcore.gui.KeyPressed;
+import de.ugoe.cs.autoquest.eventcore.gui.KeyReleased;
+import de.ugoe.cs.autoquest.eventcore.gui.KeyTyped;
+import de.ugoe.cs.autoquest.eventcore.gui.MouseButtonDown;
+import de.ugoe.cs.autoquest.eventcore.gui.MouseButtonInteraction;
+import de.ugoe.cs.autoquest.eventcore.gui.MouseButtonUp;
+import de.ugoe.cs.autoquest.eventcore.gui.MouseClick;
+import de.ugoe.cs.autoquest.eventcore.gui.MouseDoubleClick;
+import de.ugoe.cs.autoquest.eventcore.gui.MouseDragAndDrop;
+import de.ugoe.cs.autoquest.eventcore.gui.Scroll;
+import de.ugoe.cs.autoquest.eventcore.gui.TextInput;
+import de.ugoe.cs.autoquest.eventcore.gui.ValueSelection;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IButton;
+import de.ugoe.cs.autoquest.eventcore.guimodel.ICheckBox;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IComboBox;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IImage;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IListBox;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IMenu;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IMenuButton;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IRadioButton;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IShape;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IText;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IToolTip;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * This rule compares GUI event tasks (i.e. it is more concrete, than the
+ * {@link EventTaskComparisonRule}). Two GUI event tasks are only equal if their event type and
+ * target are equal. The returned equality is even more fine-grained for events whose type is
+ * {@link TextInput} and {@link ValueSelection}. For text inputs, lexical equality is returned if
+ * the same text is entered using the same key interactions. Syntactical equality is returned if
+ * the same text is entered using different key interactions. Semantical equality is returned if
+ * different text is entered, but into the same event target. Value selections are syntactically
+ * equal, if the same value is selected. Otherwise they are semantically equal.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class GUIEventTaskComparisonRule implements TaskComparisonRule {
+    
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITask, ITask)
+     */
+    @Override
+    public boolean isApplicable(ITask task1, ITask task2) {
+        for (ITaskInstance instance : task1.getInstances()) {
+            if ((!(instance instanceof IEventTaskInstance)) ||
+                (!(((IEventTaskInstance) instance).getEvent().getType() instanceof IInteraction)))
+            {
+                return false;
+            }
+        }
+        
+        for (ITaskInstance instance : task2.getInstances()) {
+            if ((!(instance instanceof IEventTaskInstance)) ||
+                (!(((IEventTaskInstance) instance).getEvent().getType() instanceof IInteraction)))
+            {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITask, ITask)
+     */
+    @Override
+    public TaskEquality compare(ITask task1, ITask task2) {
+        return getEquality(task1, task2, null);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#isApplicable(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
+     */
+    @Override
+    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
+        return
+            (instance1 instanceof IEventTaskInstance) &&
+            (instance2 instanceof IEventTaskInstance) &&
+            (((IEventTaskInstance) instance1).getEvent().getType() instanceof IInteraction) &&
+            (((IEventTaskInstance) instance1).getEvent().getType() instanceof IInteraction);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#areLexicallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#areSyntacticallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#areSemanticallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#compare(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
+     */
+    @Override
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
+        return getEquality(instance1, instance2, null);
+    }
+
+    /**
+     * 
+     */
+    private TaskEquality getEquality(ITask         task1,
+                                     ITask         task2,
+                                     TaskEquality  requiredEqualityLevel)
+    {
+        Collection<ITaskInstance> taskInstances1 = task1.getInstances();
+        Collection<ITaskInstance> taskInstances2 = task2.getInstances();
+        
+        TaskEquality checkedEquality =
+            requiredEqualityLevel != null ? requiredEqualityLevel : TaskEquality.SEMANTICALLY_EQUAL;
+        
+        TaskEquality commonDenominator = TaskEquality.LEXICALLY_EQUAL;
+        
+        for (ITaskInstance instance1 : taskInstances1) {
+            TaskEquality mostConcreteEquality = null;
+            
+            for (ITaskInstance instance2 : taskInstances2) {
+                TaskEquality equality = getEquality(instance1, instance2, requiredEqualityLevel);
+                
+                if ((equality != null) && ((mostConcreteEquality == null) ||
+                                           (equality.isAtLeast(mostConcreteEquality))))
+                {
+                    mostConcreteEquality = equality;
+                    
+                    if (((requiredEqualityLevel != null) &&
+                         (mostConcreteEquality.isAtLeast(requiredEqualityLevel))) ||
+                        (mostConcreteEquality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)))
+                    {
+                        break;
+                    }
+                }
+            }
+            
+            commonDenominator = commonDenominator.getCommonDenominator(mostConcreteEquality);
+            
+            if (!commonDenominator.isAtLeast(checkedEquality)) {
+                return TaskEquality.UNEQUAL;
+            }
+        }
+        
+        return commonDenominator;
+    }
+
+    /**
+     * 
+     */
+    private TaskEquality getEquality(ITaskInstance instance1,
+                                     ITaskInstance instance2,
+                                     TaskEquality  requiredEqualityLevel)
+    {
+        IEventTaskInstance eventTask1 = (IEventTaskInstance) instance1;
+        IEventTaskInstance eventTask2 = (IEventTaskInstance) instance2;
+        
+        if (!eventTask1.getEvent().getTarget().equals(eventTask2.getEvent().getTarget())) {
+            return TaskEquality.UNEQUAL;
+        }
+        
+        IInteraction interaction1 = (IInteraction) eventTask1.getEvent().getType();
+        IInteraction interaction2 = (IInteraction) eventTask2.getEvent().getType();
+        
+        return compareInteractions
+            (interaction1, interaction2, eventTask1.getEvent().getTarget(), requiredEqualityLevel);
+    }
+
+    /**
+     * <p>
+     * compares two interactions. The method delegates to other, more specific compare method, e.g.,
+     * {@link #compareTextInputs(TextInput, TextInput)} and
+     * {@link #compareValueSelections(ValueSelection, ValueSelection)}, if any exist for the
+     * concrete interaction types. Otherwise it uses the equals method of the interactions for
+     * comparison. In this case, if the interactions equals method returns true, this method
+     * returns lexical equality.
+     * </p>
+     * <p>
+     * The provided equality level can be used to restrict the quality check to the given level.
+     * This is done for optimization purposes. The returned equality level can be at most as
+     * concrete as the provided one. If the provided one is null, it is expected to be lexical
+     * equality.
+     * </p>
+     *
+     * @param interaction1  the first interaction to compare
+     * @param interaction2  the second interaction to compare
+     * @param eventTarget   the event target on which the interactions happened (used within
+     *                      special comparisons like mouse clicks on buttons, where the coordinates
+     *                      can be ignored)
+     * @param equalityLevel the equality level to be checked for
+     * 
+     * @return as described
+     */
+    private TaskEquality compareInteractions(IInteraction interaction1,
+                                             IInteraction interaction2,
+                                             IEventTarget eventTarget,
+                                             TaskEquality equalityLevel)
+    {
+        TaskEquality level = equalityLevel;
+        
+        if (level == null) {
+            level = TaskEquality.LEXICALLY_EQUAL;
+        }
+        
+        if (interaction1 == interaction2) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else if ((interaction1 instanceof KeyInteraction) &&
+                 (interaction2 instanceof KeyInteraction))
+        {
+            return compareKeyInteractions
+                ((KeyInteraction) interaction1, (KeyInteraction) interaction2, level);
+        }
+        else if ((interaction1 instanceof MouseButtonInteraction) &&
+                 (interaction2 instanceof MouseButtonInteraction))
+        {
+            return compareMouseButtonInteractions
+                ((MouseButtonInteraction) interaction1, (MouseButtonInteraction) interaction2,
+                 eventTarget, level);
+        }
+        else if ((interaction1 instanceof Scroll) && (interaction2 instanceof Scroll)) {
+            return compareScrolls((Scroll) interaction1, (Scroll) interaction2, level);
+        }
+        else if ((interaction1 instanceof TextInput) && (interaction2 instanceof TextInput)) {
+            return compareTextInputs
+                ((TextInput) interaction1, (TextInput) interaction2, level);
+        }
+        else if ((interaction1 instanceof ValueSelection) &&
+                 (interaction2 instanceof ValueSelection))
+        {
+            return compareValueSelections
+                ((ValueSelection<?>) interaction1, (ValueSelection<?>) interaction2, level);
+        }
+        else if (interaction1.equals(interaction2)) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+
+    /**
+     * <p>
+     * compares two key interactions. If both are of the same type and if both have the
+     * same key, they are lexically equal. If both are only of the same type, they are
+     * semantically equal. Otherwise, they are unequal.
+     * </p>
+     * <p>
+     * The provided equality level can be used to restrict the quality check to the given level.
+     * This is done for optimization purposes. The returned equality level is as concrete as
+     * the provided one. It may be more concrete if there is no difference regarding the
+     * comparison on the levels.
+     * </p>
+     *
+     * @param interaction1  the first key interaction
+     * @param interaction2  the second key interaction
+     * @param equalityLevel the equality level to be checked for
+     * 
+     * @return as described
+     */
+    private TaskEquality compareKeyInteractions(KeyInteraction interaction1,
+                                                KeyInteraction interaction2,
+                                                TaskEquality   equalityLevel)
+    {
+        if (((interaction1 instanceof KeyPressed) && (interaction2 instanceof KeyPressed)) ||
+            ((interaction1 instanceof KeyReleased) && (interaction2 instanceof KeyReleased)) ||
+            ((interaction1 instanceof KeyTyped) && (interaction2 instanceof KeyTyped)))
+        {
+            if ((equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) &&
+                (interaction1.getKey() == interaction2.getKey()))
+            {
+                return TaskEquality.LEXICALLY_EQUAL;
+            }
+            else {
+                return TaskEquality.SEMANTICALLY_EQUAL;
+            }
+        }
+        
+        return TaskEquality.UNEQUAL;
+    }
+    
+    /**
+     * <p>
+     * compares two mouse drag and drops. If both drag and drops have the same start and end
+     * coordinates, they are lexically equal. Otherwise, they are semantically equal.
+     * </p>
+     * <p>
+     * The provided equality level can be used to restrict the quality check to the given level.
+     * This is done for optimization purposes. The returned equality level is as concrete as
+     * the provided one. It may be more concrete if there is no difference regarding the
+     * comparison on the levels.
+     * </p>
+     *
+     * @param interaction1  the first mouse drag and drop to compare
+     * @param interaction2  the second mouse drag and drop to compare
+     * @param equalityLevel the equality level to be checked for
+     * 
+     * @return as described
+     */
+    private TaskEquality compareMouseDragAndDrops(MouseDragAndDrop interaction1,
+                                                  MouseDragAndDrop interaction2,
+                                                  TaskEquality     equalityLevel)
+    {
+        if (interaction1.getButton() != interaction2.getButton()) {
+            return TaskEquality.UNEQUAL;
+        }
+        
+        if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) {
+            int x1 = interaction1.getX();
+            int x1Start = interaction1.getXStart();
+            int x2 = interaction2.getX();
+            int x2Start = interaction2.getXStart();
+            int y1 = interaction1.getY();
+            int y1Start = interaction1.getYStart();
+            int y2 = interaction2.getY();
+            int y2Start = interaction2.getYStart();
+        
+            if ((x1Start == x2Start) && (x1 == x2) && (y1Start == y2Start) && (y1 == y2)) {
+                return TaskEquality.LEXICALLY_EQUAL;
+            }
+        }
+        
+        return TaskEquality.SEMANTICALLY_EQUAL;
+    }
+
+    /**
+     * <p>
+     * compares two mouse button interactions such as clicks, mouse button down, or double clicks.
+     * If both interactions have the same coordinates, they are lexically equal. Otherwise, they
+     * are semantically equal. Mouse clicks for which the coordinates make no lexical difference
+     * (see {@link #clickCoordinatesMakeLexicalDifference(IEventTarget)}) are treated as
+     * lexically equal.
+     * </p>
+     * <p>
+     * The provided equality level can be used to restrict the quality check to the given level.
+     * This is done for optimization purposes. The returned equality level is as concrete as
+     * the provided one. It may be more concrete if there is no difference regarding the
+     * comparison on the levels.
+     * </p>
+     *
+     * @param interaction1  the first mouse button interaction to compare
+     * @param interaction2  the second mouse button interaction to compare
+     * @param eventTarget   the event target on which the interactions happened (used within
+     *                      special comparisons like mouse clicks on buttons, where the coordinates
+     *                      can be ignored)
+     * @param equalityLevel the equality level to be checked for
+     * 
+     * @return as described
+     */
+    private TaskEquality compareMouseButtonInteractions(MouseButtonInteraction interaction1,
+                                                        MouseButtonInteraction interaction2,
+                                                        IEventTarget           eventTarget,
+                                                        TaskEquality           equalityLevel)
+    {
+        boolean coordinatesMatch = true;
+        
+        if ((interaction1 instanceof MouseDragAndDrop) &&
+            (interaction2 instanceof MouseDragAndDrop))
+        {
+            return compareMouseDragAndDrops
+                ((MouseDragAndDrop) interaction1, (MouseDragAndDrop) interaction2, equalityLevel);
+        }
+        else if (interaction1.getButton() != interaction2.getButton()) {
+            return TaskEquality.UNEQUAL;
+        }
+        else if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL) &&
+                 clickCoordinatesMakeLexicalDifference(eventTarget))
+        {
+            int x1 = interaction1.getX();
+            int x2 = interaction2.getX();
+            int y1 = interaction1.getY();
+            int y2 = interaction2.getY();
+
+            if ((x1 != x2) || (y1 != y2)) {
+                coordinatesMatch = false;
+            }
+        }
+        
+        // up to now, they can be equal. Now check the types. Do it as last action as these
+        // checks take the most time and should, therefore, only be done latest
+        if (((interaction1 instanceof MouseClick) && (interaction2 instanceof MouseClick)) ||
+            ((interaction1 instanceof MouseDoubleClick) &&
+             (interaction2 instanceof MouseDoubleClick)) ||
+            ((interaction1 instanceof MouseButtonDown) &&
+             (interaction2 instanceof MouseButtonDown)) ||
+            ((interaction1 instanceof MouseButtonUp) &&
+             (interaction2 instanceof MouseButtonUp)))
+        {
+            if (coordinatesMatch) {
+                return TaskEquality.LEXICALLY_EQUAL;
+            }
+            else {
+                return TaskEquality.SEMANTICALLY_EQUAL;
+            }
+        }
+        
+        return TaskEquality.UNEQUAL;
+    }
+
+    /**
+     * <p>
+     * compares two mouse button interactions such as clicks, mouse button down, or double clicks.
+     * If both interactions have the same coordinates, they are lexically equal. Otherwise, they
+     * are semantically equal. Mouse clicks for which the coordinates make no lexical difference
+     * (see {@link #clickCoordinatesMakeLexicalDifference(IEventTarget)}) are treated as
+     * lexically equal.
+     * </p>
+     * <p>
+     * The provided equality level can be used to restrict the quality check to the given level.
+     * This is done for optimization purposes. The returned equality level is as concrete as
+     * the provided one. It may be more concrete if there is no difference regarding the
+     * comparison on the levels.
+     * </p>
+     *
+     * @param interaction1  the first mouse button interaction to compare
+     * @param interaction2  the second mouse button interaction to compare
+     * @param eventTarget   the event target on which the interactions happened (used within
+     *                      special comparisons like mouse clicks on buttons, where the coordinates
+     *                      can be ignored)
+     * @param equalityLevel the equality level to be checked for
+     * 
+     * @return as described
+     */
+    private TaskEquality compareScrolls(Scroll       interaction1,
+                                        Scroll       interaction2,
+                                        TaskEquality equalityLevel)
+    {
+        if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) {
+            int x1 = interaction1.getXPosition();
+            int x2 = interaction2.getXPosition();
+            int y1 = interaction1.getYPosition();
+            int y2 = interaction2.getYPosition();
+        
+            if ((x1 == x2) && (y1 == y2)) {
+                return TaskEquality.LEXICALLY_EQUAL;
+            }
+        }
+        
+        return TaskEquality.SEMANTICALLY_EQUAL;
+    }
+
+    /**
+     * <p>
+     * compares two text inputs. If both text inputs have the same entered text and text input
+     * events, they are lexically equal. If they only have the same entered text, they are
+     * syntactically equal. If they are only both text inputs, they are semantically equal.
+     * (the equality of the event targets is checked beforehand).
+     * </p>
+     * <p>
+     * The provided equality level can be used to restrict the quality check to the given level.
+     * This is done for optimization purposes. The returned equality level is as concrete as
+     * the provided one. It may be more concrete if there is no difference regarding the
+     * comparison on the levels.
+     * </p>
+     *
+     * @param interaction1  the first text input to compare
+     * @param interaction2  the second text input to compare
+     * @param equalityLevel the equality level to be checked for
+     * 
+     * @return as described
+     */
+    private TaskEquality compareTextInputs(TextInput    interaction1,
+                                           TextInput    interaction2,
+                                           TaskEquality equalityLevel)
+    {
+        switch (equalityLevel) {
+            case LEXICALLY_EQUAL:
+                if (interaction1.getTextInputEvents().equals(interaction2.getTextInputEvents())) {
+                    return TaskEquality.LEXICALLY_EQUAL;
+                }
+                // fall through
+            case SYNTACTICALLY_EQUAL:
+                if (interaction1.getEnteredText().equals(interaction2.getEnteredText())) {
+                    return TaskEquality.SYNTACTICALLY_EQUAL;
+                }
+                // fall through
+            case SEMANTICALLY_EQUAL:
+                return TaskEquality.SEMANTICALLY_EQUAL;
+            default:
+                return TaskEquality.UNEQUAL;
+        }
+    }
+
+    /**
+     * <p>
+     * compares two value selections. If both value selections have the same selected value, they
+     * are syntactically equal, otherwise they are semantically equal.
+     * (the equality of the event targets is checked beforehand).
+     * </p>
+     * <p>
+     * The provided equality level can be used to restrict the quality check to the given level.
+     * This is done for optimization purposes. The returned equality level is as concrete as
+     * the provided one. It may be more concrete if there is no difference regarding the
+     * comparison on the levels.
+     * </p>
+     *
+     * @param interaction1  the first value selection to compare
+     * @param interaction2  the second value selection to compare
+     * @param equalityLevel the equality level to be checked for
+     * 
+     * @return as described
+     */
+    private TaskEquality compareValueSelections(ValueSelection<?> interaction1,
+                                                ValueSelection<?> interaction2,
+                                                TaskEquality      equalityLevel)
+    {
+        if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) {
+            Object value1 = interaction1.getSelectedValue();
+            Object value2 = interaction2.getSelectedValue();
+        
+            if ((value1 == value2) || ((value1 != null) && (value1.equals(value2)))) {
+                return TaskEquality.LEXICALLY_EQUAL;
+            }
+        }
+        
+        return TaskEquality.SEMANTICALLY_EQUAL;
+    }
+
+    /**
+     * <p>
+     * Checks, if the coordinates of a click or double click on the provided event target makes
+     * a lexical difference. Mouse clicks and double clicks on buttons, check boxes,
+     * combo boxes, images, list boxes, menu buttons, radio buttons, shapes, uneditable text,
+     * and tool tips have no lexical difference as long as they happen on the same event target.
+     * The concrete coordinates are not relevant.
+     * </p>
+     *
+     * @param eventTarget the event target on which the interaction occurred
+     * 
+     * @return if the coordinates are important to be considered for clicks and double clicks,
+     *         false else
+     */
+    private boolean clickCoordinatesMakeLexicalDifference(IEventTarget eventTarget) {
+        if ((eventTarget instanceof IButton) ||
+            (eventTarget instanceof ICheckBox) ||
+            (eventTarget instanceof IComboBox) ||
+            (eventTarget instanceof IImage) ||
+            (eventTarget instanceof IListBox) ||
+            (eventTarget instanceof IMenu) ||
+            (eventTarget instanceof IMenuButton) ||
+            (eventTarget instanceof IRadioButton) ||
+            (eventTarget instanceof IShape) ||
+            (eventTarget instanceof IText) ||
+            (eventTarget instanceof IToolTip))
+        {
+            return false;
+        }
+        else {
+            return true;
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/IterationComparisonRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/IterationComparisonRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/IterationComparisonRule.java	(revision 1551)
@@ -0,0 +1,386 @@
+//   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.taskequality;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * This class is capable of comparing Iterations. Iterations equal at distinct levels
+ * in distinct situations. The following table shows the results of the comparison for the
+ * specific situations (the parameters are commutative). In any other situation, the comparison
+ * returns <code>NodeEquality.UNEQUAL</code>:
+ * </p>
+ * 
+ * <table border="1">
+ *   <tr>
+ *     <th>iteration 1</th>
+ *     <th>iteration 2</th>
+ *     <th>comparison result</th>
+ *   </tr>
+ *   <tr>
+ *     <td>any iteration</td>
+ *     <td>any iteration with a child that is lexically equal to the child of iteration 1</td>
+ *     <td><code>NodeEquality.LEXICALLY_EQUAL</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td>any iteration</td>
+ *     <td>any iteration with a child that is syntactically equal to the child of iteration 1</td>
+ *     <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td>any iteration</td>
+ *     <td>any iteration with a child that is semantically equal to the child of iteration 1</td>
+ *     <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td>an iteration with a selection of syntactically equal children</td>
+ *     <td>an iteration with a child that is syntactically equal to the children of the child
+ *     selection of iteration 1</td>
+ *     <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td>an iteration with a selection of syntactically equal children</td>
+ *     <td>an iteration with a selection of syntactically equal children that are all syntactically
+ *     equal to the selection of children of iteration 1</td>
+ *     <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td>an iteration with a selection of semantically equal children</td>
+ *     <td>an iteration with a child that is semantically equal to the children of the child
+ *     selection of iteration 1</td>
+ *     <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td>
+ *   </tr>
+ *   <tr>
+ *     <td>an iteration with a selection of semantically equal children</td>
+ *     <td>an iteration with a selection of semantically equal children that are all semantically
+ *     equal to the selection of children of iteration 1</td>
+ *     <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td>
+ *   </tr>
+ * </table>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class IterationComparisonRule implements TaskComparisonRule {
+    
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITask, ITask)
+     */
+    @Override
+    public boolean isApplicable(ITask task1, ITask task2) {
+        return (task1 instanceof IIteration) && (task2 instanceof IIteration);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        ITask child1 = ((IIteration) task1).getMarkedTask();
+        ITask child2 = ((IIteration) task2).getMarkedTask();
+        
+        if (child1 != null) {
+            if (child2 == null) {
+                return false;
+            }
+            else {
+                // iterations may have 3 different structures.
+                // 1. they have one child, which is the iterated one
+                // 2. they have a sequence of children, which is iterated
+                // 3. they have a selection of different iterated variants (usually the variants
+                //    are semantically equal)
+                // ignore the type of the children but check them for equality.
+                
+                return getNodeEquality(child1, child2).isAtLeast(TaskEquality.LEXICALLY_EQUAL);
+            }
+        }
+        else if (child2 == null) {
+            return true;
+        }
+        
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
+        return areLexicallyEqual(task1, task2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
+        return compare(task1, task2).isAtLeast(TaskEquality.SEMANTICALLY_EQUAL);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITask, ITask)
+     */
+    @Override
+    public TaskEquality compare(ITask task1, ITask task2) {
+        ITask child1 = ((IIteration) task1).getMarkedTask();
+        ITask child2 = ((IIteration) task2).getMarkedTask();
+
+        // if both iterations do not have children, they are equal although this doesn't make sense
+        if ((child1 == null) && (child2 == null)) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else if ((child1 == null) || (child2 == null)) {
+            return TaskEquality.UNEQUAL;
+        }
+
+        // iterations may have 3 different structures.
+        // 1. they have one child, which is the iterated one
+        // 2. they have a sequence of children, which is iterated
+        // 3. they have a selection of different iterated variants (usually the variants are
+        // semantically equal)
+        //
+        // the permutations of the three variants in combination must be checked
+
+        // check if both tasks are the same variants of iterations and if their children are equal.
+        // This condition matches, if both iterations are the same variants of iteration. I.e. three
+        // combinations of the permutation are handled herewith.
+        TaskEquality taskEquality = getNodeEquality(child1, child2);
+        
+        if (taskEquality != null) {
+            return taskEquality;
+        }
+
+        // compare one iteration with a single task as a child and another one with a selection of
+        // semantically equal tasks
+        return selectionChildrenSemanticallyEqualNode(child1, child2);
+        
+        // all other combinations (i.e. sequence with single child and sequence with selection)
+        // can not match
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
+        return isApplicable(instance1.getTask(), instance2.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        IIterationInstance iteration1 = (IIterationInstance) instance1;
+        IIterationInstance iteration2 = (IIterationInstance) instance2;
+
+        // if both sequences do not have children, they are equal although this doesn't make sense
+        if ((iteration1.size() == 0) && (iteration2.size() == 0)) {
+            return true;
+        }
+
+        if (iteration1.size() != iteration2.size()) {
+            return false;
+        }
+
+        for (int i = 0; i < iteration1.size(); i++) {
+            ITaskInstance child1 = iteration1.get(i);
+            ITaskInstance child2 = iteration2.get(i);
+
+            TaskEquality taskEquality =
+                callRuleManager(child1, child2, TaskEquality.LEXICALLY_EQUAL);
+
+            if ((taskEquality == null) || (taskEquality == TaskEquality.UNEQUAL)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        return areLexicallyEqual(instance1, instance2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        return areLexicallyEqual(instance1, instance2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
+        if (areLexicallyEqual(instance1, instance2)) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+
+    /**
+     * <p>
+     * compares two tasks with each other by calling the rule manager. If the rule manager returns
+     * identity, then the returned equality is set to lexically equal. The reason is, that
+     * the children of the iterations are compared and that therefore the distinct iterations
+     * can be at most lexically equal.
+     * </p>
+     * 
+     * @param child1 the first task to be compared
+     * @param child2 the second task to be compared
+     * 
+     * @return the determined equality being at most lexical equality.
+     */
+    private TaskEquality getNodeEquality(ITask child1, ITask child2) {
+        TaskEquality taskEquality = callRuleManager(child1, child2, null);
+
+        if (taskEquality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)) {
+            // prevent, that identical is returned, because the iterations itself are not identical
+            // although the iterated tasks are
+            if (taskEquality == TaskEquality.IDENTICAL) {
+                return TaskEquality.LEXICALLY_EQUAL;
+            }
+            else {
+                return taskEquality;
+            }
+        }
+        
+        return TaskEquality.UNEQUAL;
+    }
+
+    /**
+     * <p>
+     * compares two tasks. One of them must be a selection, the other one can be any task.
+     * The method returns a task equality that is not <code>NodeEquality.UNEQUAL</code>
+     * if the other task is at least semantically equal to the children of the selection. It
+     * returns more concrete equalities, if the equality between the other task and the children
+     * of the selection is more concrete.
+     * </p> 
+     * 
+     * @param task1 the first task to compare
+     * @param task2 the second task to compare
+     * 
+     * @return as described
+     */
+    private TaskEquality selectionChildrenSemanticallyEqualNode(ITask task1, ITask task2) {
+        ISelection selection = null;
+        ITask task = null;
+        if (task1 instanceof ISelection) {
+            selection = (ISelection) task1;
+            task = task2;
+        }
+        else if (task2 instanceof ISelection) {
+            selection = (ISelection) task2;
+            task = task1;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+
+        // Iterations, where one has a selection and the other one not can at most be syntactically
+        // equal but not identical
+        TaskEquality commonDenominatorForAllComparisons = TaskEquality.SYNTACTICALLY_EQUAL;
+
+        for (ITask child : selection.getChildren()) {
+            TaskEquality taskEquality =
+                  callRuleManager(task, child, commonDenominatorForAllComparisons);
+
+            if ((taskEquality == null) || (taskEquality == TaskEquality.UNEQUAL)) {
+                return TaskEquality.UNEQUAL;
+            }
+            
+            commonDenominatorForAllComparisons =
+                commonDenominatorForAllComparisons.getCommonDenominator(taskEquality);
+        }
+
+        return commonDenominatorForAllComparisons;
+    }
+
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param child1                the first task to be compared
+     * @param child2                the second task to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITask        child1,
+                                         ITask        child2,
+                                         TaskEquality requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(child1, child2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                    (child1, child2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+    
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param taskInstance1         the first task instance to be compared
+     * @param taskInstance2         the second task instance to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITaskInstance taskInstance1,
+                                         ITaskInstance taskInstance2,
+                                         TaskEquality  requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                     (taskInstance1, taskInstance2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/SelectionComparisonRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/SelectionComparisonRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/SelectionComparisonRule.java	(revision 1551)
@@ -0,0 +1,347 @@
+//   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.taskequality;
+
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * this task comparison rule is capable of comparing selections. If both selections do not have
+ * children, they are treated as lexically equal. If they have children, each child of both
+ * selections is compared to each child of the respective other selection. The resulting equality
+ * is the most concrete one of all these comparisons. I.e. if all children are at least lexically
+ * equal, then the selections are lexically equal. If all children are at least syntactically
+ * equal, then the selections are syntactically equal. If all children are at least semantically
+ * equal, then the selections are semantically equal. If only one of the selections has children,
+ * then the selections are unequal. The comparison is broken up, if only a specific equality is
+ * checked for and this equality is ensured.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class SelectionComparisonRule implements TaskComparisonRule {
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITask, ITask)
+     */
+    @Override
+    public boolean isApplicable(ITask task1, ITask task2) {
+        return (task1 instanceof ISelection) && (task2 instanceof ISelection);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITask, ITask)
+     */
+    @Override
+    public TaskEquality compare(ITask task1, ITask task2) {
+        return getEquality(task1, task2, null);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
+        return isApplicable(instance1.getTask(), instance2.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
+        return getEquality(instance1, instance2, null);
+    }
+
+    /**
+     * <p>
+     * compares two selections with each other checking for the provided required level of
+     * equality. If this level is ensured, the method immediately returns. The more concrete
+     * the required equality level, the more checks this method performs.
+     * </p>
+     * 
+     * @param task1                 the first task to be compared
+     * @param task2                 the second task to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality.
+     */
+    private TaskEquality getEquality(ITask task1, ITask task2, TaskEquality requiredEqualityLevel) {
+        List<ITask> children1 = ((ISelection) task1).getChildren();
+        List<ITask> children2 = ((ISelection) task2).getChildren();
+
+        // if both selections do not have children, they are lexically equal. If only one of them
+        // has children, they are unequal.
+        if ((children1.size() == 0) && (children2.size() == 0)) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else if ((children1.size() == 0) || (children2.size() == 0)) {
+            return TaskEquality.UNEQUAL;
+        }
+
+        if (requiredEqualityLevel == null) {
+            // calculate the common equality level for all children of both selections.
+            // do it in both directions to ensure commutative comparison
+            return getMostConcreteEqualityLevel(children1, children2);
+        }
+        else {
+            // we are searching for a specific equality
+            if (checkEqualityLevel(children1, children2, requiredEqualityLevel)) {
+                return requiredEqualityLevel;
+            }
+            else {
+                return TaskEquality.UNEQUAL;
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * determines the most concrete equality level for all tasks in the first list compared to all
+     * tasks in the second list. It is sufficient, if there is one task in one list for which there
+     * exist an equal task in the other list.
+     * </p>
+     *
+     * @param children1 the first list to be compared
+     * @param children2 the second list to be compared
+     * 
+     * @return the most concrete task equality identified for all tasks in the first list with
+     *         respect to the second list
+     */
+    private TaskEquality getMostConcreteEqualityLevel(List<ITask> children1, List<ITask> children2)
+    {
+        TaskEquality childEquality;
+        TaskEquality currentEquality;
+        for (ITask child1 : children1) {
+            childEquality = null;
+            for (ITask child2 : children2) {
+                currentEquality = callRuleManager(child1, child2, null);
+                if ((currentEquality != null) && (currentEquality != TaskEquality.UNEQUAL)) {
+                    if (childEquality == null) {
+                        childEquality = currentEquality;
+                    }
+                    else {
+                        childEquality = childEquality.getCommonDenominator(currentEquality);
+                    }
+                    
+                    if (childEquality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)) {
+                        // as we calculate the most concrete equality, we can break up here
+                        return TaskEquality.LEXICALLY_EQUAL;
+                    }
+                }
+            }
+        }
+
+        // as the comparison should be commutative, we do not need to check, if in list 2 there is
+        // a child equal to one in list 1
+        return TaskEquality.UNEQUAL;
+    }
+
+    /**
+     * <p>
+     * ensures for the two given lists, that for at least one task in the first list there is a task
+     * in the second list being on the given level equal to the task in the first list.
+     * </p> 
+     * 
+     * @param children1             the first list to be compared
+     * @param children2             the second list to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return true if there is a task in the first list that has an equal task in the second list
+     *         when considering the given equality level, false else.
+     */
+    private boolean checkEqualityLevel(List<ITask>  children1,
+                                       List<ITask>  children2,
+                                       TaskEquality requiredEqualityLevel)
+    {
+        TaskEquality currentEquality;
+        for (ITask child1 : children1) {
+            for (ITask child2 : children2) {
+                currentEquality = callRuleManager(child1, child2, requiredEqualityLevel);
+                if ((currentEquality != null) && (currentEquality.isAtLeast(requiredEqualityLevel)))
+                {
+                    // we found at least one equal child with sufficient equality in the
+                    // second list. So be can break up for this child.
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param child1                the first task to be compared
+     * @param child2                the second task to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITask        child1,
+                                         ITask        child2,
+                                         TaskEquality requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(child1, child2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                     (child1, child2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+
+    /**
+     * <p>
+     * compares two selection instances with each other checking for the provided required level of
+     * equality. If this level is ensured, the method immediately returns. The more concrete
+     * the required equality level, the more checks this method performs.
+     * </p>
+     * 
+     * @param taskInstance1         the first task instance to be compared
+     * @param taskInstance2         the second task instance to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality.
+     */
+    private TaskEquality getEquality(ITaskInstance taskInstance1,
+                                     ITaskInstance taskInstance2,
+                                     TaskEquality  requiredEqualityLevel)
+    {
+        ITaskInstance child1 = ((ISelectionInstance) taskInstance1).getChild();
+        ITaskInstance child2 = ((ISelectionInstance) taskInstance2).getChild();
+
+        // if both selections do not have children, they are lexically equal. If only one of them
+        // has children, they are unequal.
+        if ((child1 == null) && (child2 == null)) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else if ((child1 == null) || (child2 == null)) {
+            return TaskEquality.UNEQUAL;
+        }
+
+        TaskEquality equality = callRuleManager(child1, child2, requiredEqualityLevel);
+        
+        if (equality == TaskEquality.IDENTICAL) {
+            // two different selection instances can be at most lexically equal even if their
+            // children are identical
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return equality;
+        }
+    }
+
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param taskInstance1         the first task instance to be compared
+     * @param taskInstance2         the second task instance to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITaskInstance taskInstance1,
+                                         ITaskInstance taskInstance2,
+                                         TaskEquality  requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                     (taskInstance1, taskInstance2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/SequenceComparisonRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/SequenceComparisonRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/SequenceComparisonRule.java	(revision 1551)
@@ -0,0 +1,273 @@
+//   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.taskequality;
+
+import java.util.List;
+
+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;
+
+/**
+ * <p>
+ * This rule is capable of comparing sequences. If both sequences do not have children, they are
+ * treated as lexically equal. Sequences are lexically equal, if they have the same number and
+ * order of lexically equal children. The rule can not decide, if two sequences are syntactically
+ * or semantically equal.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class SequenceComparisonRule implements TaskComparisonRule {
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITask, ITask)
+     */
+    @Override
+    public boolean isApplicable(ITask task1, ITask task2) {
+        return (task1 instanceof ISequence) && (task2 instanceof ISequence);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITask, ITask)
+     */
+    @Override
+    public TaskEquality compare(ITask task1, ITask task2) {
+        return getEquality(task1, task2, null);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
+        return isApplicable(instance1.getTask(), instance2.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
+        return getEquality(instance1, instance2, null);
+    }
+
+    /**
+     * <p>
+     * compares two sequences with each other checking for the provided required level of
+     * equality. If this level is ensured, the method immediately returns. The more concrete
+     * the required equality level, the more checks this method performs.
+     * </p>
+     * 
+     * @param task1                 the first task to be compared
+     * @param task2                 the second task to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality.
+     */
+    private TaskEquality getEquality(ITask task1, ITask task2, TaskEquality requiredEqualityLevel) {
+        List<ITask> children1 = ((ISequence) task1).getChildren();
+        List<ITask> children2 = ((ISequence) task2).getChildren();
+
+        // if both sequences do not have children, they are equal although this doesn't make sense
+        if ((children1.size() == 0) && (children2.size() == 0)) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+
+        if (children1.size() != children2.size()) {
+            return TaskEquality.UNEQUAL;
+        }
+
+        TaskEquality resultingEquality = TaskEquality.LEXICALLY_EQUAL;
+        for (int i = 0; i < children1.size(); i++) {
+            ITask child1 = children1.get(i);
+            ITask child2 = children2.get(i);
+
+            TaskEquality taskEquality = callRuleManager(child1, child2, requiredEqualityLevel);
+
+            if ((taskEquality == null) || (taskEquality == TaskEquality.UNEQUAL)) {
+                return TaskEquality.UNEQUAL;
+            }
+            
+            resultingEquality = resultingEquality.getCommonDenominator(taskEquality);
+        }
+
+        return resultingEquality;
+    }
+
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param child1                the first task to be compared
+     * @param child2                the second task to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITask        child1,
+                                         ITask        child2,
+                                         TaskEquality requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(child1, child2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                    (child1, child2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+
+    /**
+     * <p>
+     * compares two sequence instances with each other checking for the provided required level of
+     * equality. If this level is ensured, the method immediately returns. The more concrete
+     * the required equality level, the more checks this method performs.
+     * </p>
+     * 
+     * @param taskInstance1         the first task instance to be compared
+     * @param taskInstance2         the second task instance to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality.
+     */
+    private TaskEquality getEquality(ITaskInstance taskInstance1,
+                                     ITaskInstance taskInstance2,
+                                     TaskEquality  requiredEqualityLevel)
+    {
+        ISequenceInstance sequence1 = (ISequenceInstance) taskInstance1;
+        ISequenceInstance sequence2 = (ISequenceInstance) taskInstance2;
+
+        // if both sequences do not have children, they are equal although this doesn't make sense
+        if ((sequence1.size() == 0) && (sequence2.size() == 0)) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+
+        if (sequence1.size() != sequence2.size()) {
+            return TaskEquality.UNEQUAL;
+        }
+
+        TaskEquality resultingEquality = TaskEquality.LEXICALLY_EQUAL;
+        for (int i = 0; i < sequence1.size(); i++) {
+            ITaskInstance child1 = sequence1.get(i);
+            ITaskInstance child2 = sequence2.get(i);
+
+            TaskEquality taskEquality = callRuleManager(child1, child2, requiredEqualityLevel);
+
+            if ((taskEquality == null) || (taskEquality == TaskEquality.UNEQUAL)) {
+                return TaskEquality.UNEQUAL;
+            }
+            
+            resultingEquality = resultingEquality.getCommonDenominator(taskEquality);
+        }
+
+        return resultingEquality;
+    }
+    
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param taskInstance1         the first task instance to be compared
+     * @param taskInstance2         the second task instance to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITaskInstance taskInstance1,
+                                         ITaskInstance taskInstance2,
+                                         TaskEquality  requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                     (taskInstance1, taskInstance2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskAndIterationComparisonRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskAndIterationComparisonRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskAndIterationComparisonRule.java	(revision 1551)
@@ -0,0 +1,331 @@
+//   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.taskequality;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * This class is capable of comparing any task which is not an iteration with an
+ * iteration. This is needed, because iterations may iterate exactly that task. In this
+ * case, the iteration would be equal to that task if it was executed exactly once. The rule
+ * returns lexically equal, it the child of the iteration is lexically equal to the task
+ * or if the child of the iteration is a selection and this selections contains a lexically equal
+ * task. The same applies for syntactical and semantical equality.
+ * </p>
+
+ * @author Patrick Harms
+ */
+public class TaskAndIterationComparisonRule implements TaskComparisonRule {
+    
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITask, ITask)
+     */
+    @Override
+    public boolean isApplicable(ITask task1, ITask task2) {
+        return ((task1 instanceof IIteration) && (!(task2 instanceof IIteration))) ||
+               ((task2 instanceof IIteration) && (!(task1 instanceof IIteration)));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITask, ITask)
+     */
+    @Override
+    public TaskEquality compare(ITask task1, ITask task2) {
+        return getEquality(task1, task2, null);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
+        return isApplicable(instance1.getTask(), instance2.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
+        return getEquality(instance1, instance2, null);
+    }
+
+    /**
+     * <p>
+     * compares two tasks with each other checking for the provided required level of
+     * equality. One of the tasks must be an iteration, the other one not. If this is not the
+     * case, the method returns null. The returned equality level is at most lexical equality
+     * as the iteration can not be identical to something not being an iteration.
+     * </p>
+     * 
+     * @param task1                 the first task to be compared
+     * @param task2                 the second task to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality.
+     */
+    private TaskEquality getEquality(ITask task1, ITask task2, TaskEquality requiredEqualityLevel) {
+        IIteration iteration = null;
+        ITask task = null;
+        
+        if (task1 instanceof IIteration) {
+            if (task2 instanceof IIteration) {
+                // the rule is not responsible for two iterations
+                return null;
+            }
+            
+            iteration = (IIteration) task1;
+            task = task2;
+        }
+        else if (task2 instanceof IIteration) {
+            if (task1 instanceof IIteration) {
+                // the rule is not responsible for two iterations
+                return null;
+            }
+            
+            iteration = (IIteration) task2;
+            task = task1;
+        }
+        else {
+            return null;
+        }
+
+        ITask child = iteration.getMarkedTask();
+        
+        // now, that we found the iteration and the task, lets compare the child of the iteration
+        // with the task.
+        if (child == null) {
+            return null;
+        }
+
+        TaskEquality taskEquality = callRuleManager(child, task, requiredEqualityLevel);
+
+        // although the subtask may be identical to the task, we can not return identical, as
+        // the iteration is not identical to the task, but at most lexically equal
+        if (taskEquality == TaskEquality.IDENTICAL) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return taskEquality;
+        }
+
+    }
+    
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param child1                the first task to be compared
+     * @param child2                the second task to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITask        child1,
+                                         ITask        child2,
+                                         TaskEquality requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(child1, child2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                     (child1, child2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+
+    /**
+     * <p>
+     * compares two task instances with each other checking for the provided required level of
+     * equality. One of the task instances must be a iteration, the other one not. If this is not
+     * the case, the method returns null. The returned equality level is at most lexical equality
+     * as the iteration can not be identical to something not being a iteration.
+     * </p>
+     * 
+     * @param taskInstance1         the first task instance to be compared
+     * @param taskInstance2         the second task instance to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality.
+     */
+    private TaskEquality getEquality(ITaskInstance taskInstance1,
+                                     ITaskInstance taskInstance2,
+                                     TaskEquality  requiredEqualityLevel)
+    {
+        IIterationInstance iteration = null;
+        ITaskInstance task = null;
+        
+        if (taskInstance1 instanceof IIterationInstance) {
+            if (taskInstance2 instanceof IIterationInstance) {
+                // the rule is not responsible for two iterations
+                return null;
+            }
+            
+            iteration = (IIterationInstance) taskInstance1;
+            task = taskInstance2;
+        }
+        else if (taskInstance2 instanceof IIterationInstance) {
+            if (taskInstance1 instanceof IIterationInstance) {
+                // the rule is not responsible for two iterations
+                return null;
+            }
+            
+            iteration = (IIterationInstance) taskInstance2;
+            task = taskInstance1;
+        }
+        else {
+            return null;
+        }
+
+        // now, that we found the iteration and the task, lets compare the children of the iteration
+        // with the task.
+        
+        if (iteration.size() < 1) {
+            return null;
+        }
+
+        TaskEquality mostConcreteNodeEquality = null;
+        
+        for (ITaskInstance child : iteration) {
+            TaskEquality taskEquality = callRuleManager(child, task, requiredEqualityLevel);
+            
+            if (taskEquality != TaskEquality.UNEQUAL) {
+                if (mostConcreteNodeEquality == null) {
+                    mostConcreteNodeEquality = taskEquality;
+                }
+                else if (mostConcreteNodeEquality.isAtLeast(taskEquality)) {
+                    mostConcreteNodeEquality = taskEquality;
+                    
+                }
+                
+                if ((requiredEqualityLevel != null) &&
+                    (mostConcreteNodeEquality.isAtLeast(requiredEqualityLevel)))
+                {
+                    // if we found one child of the selection that is as equal as required, then
+                    // we can consider the selection to be sufficiently equal to the other task.
+                    // So we break up checking further children.
+                    break;
+                }
+            }
+        }
+        
+        // although the subtask may be identical to the task, we can not return identical, as
+        // the selection is not identical to the task, but at most lexically equal
+        if (mostConcreteNodeEquality == TaskEquality.IDENTICAL) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return mostConcreteNodeEquality;
+        }
+
+    }
+    
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param taskInstance1         the first task instance to be compared
+     * @param taskInstance2         the second task instance to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITaskInstance taskInstance1,
+                                         ITaskInstance taskInstance2,
+                                         TaskEquality  requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                     (taskInstance1, taskInstance2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskAndSelectionComparisonRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskAndSelectionComparisonRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskAndSelectionComparisonRule.java	(revision 1551)
@@ -0,0 +1,333 @@
+//   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.taskequality;
+
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * This class is capable of comparing any task which is not a selection with a
+ * selection. This is needed, because selections may contain exactly that task. Therefore, if
+ * this task is selected out of a selection the selection is equal to the task itself. 
+ * The rule returns lexically equal, if the selection contains a lexically equal task. The same
+ * applies for syntactical and semantical equality.
+ * </p>
+
+ * @author Patrick Harms
+ */
+public class TaskAndSelectionComparisonRule implements TaskComparisonRule {
+    
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITask, ITask)
+     */
+    @Override
+    public boolean isApplicable(ITask task1, ITask task2) {
+        return ((task1 instanceof ISelection) && (!(task2 instanceof ISelection))) ||
+               ((task2 instanceof ISelection) && (!(task1 instanceof ISelection)));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
+        TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITask, ITask)
+     */
+    @Override
+    public TaskEquality compare(ITask task1, ITask task2) {
+        return getEquality(task1, task2, null);
+    }
+    
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
+        return isApplicable(instance1.getTask(), instance2.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL);
+        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
+        return getEquality(instance1, instance2, null);
+    }
+
+    /**
+     * <p>
+     * compares two tasks with each other checking for the provided required level of
+     * equality. One of the tasks must be a selection, the other one not. If this is not the
+     * case, the method returns null. The returned equality level is at most lexical equality
+     * as the selection can not be identical to something not being a selection.
+     * </p>
+     * 
+     * @param task1                 the first task to be compared
+     * @param task2                 the second task to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality.
+     */
+    private TaskEquality getEquality(ITask task1, ITask task2, TaskEquality requiredEqualityLevel) {
+        ISelection selection = null;
+        ITask task = null;
+        
+        if (task1 instanceof ISelection) {
+            if (task2 instanceof ISelection) {
+                // the rule is not responsible for two selections
+                return null;
+            }
+            
+            selection = (ISelection) task1;
+            task = task2;
+        }
+        else if (task2 instanceof ISelection) {
+            if (task1 instanceof ISelection) {
+                // the rule is not responsible for two selections
+                return null;
+            }
+            
+            selection = (ISelection) task2;
+            task = task1;
+        }
+        else {
+            return null;
+        }
+
+        // now, that we found the selection and the task, lets compare the children of the selection
+        // with the task.
+        List<ITask> children = selection.getChildren();
+        
+        if (children.size() < 1) {
+            return null;
+        }
+
+        TaskEquality mostConcreteNodeEquality = null;
+        
+        for (ITask child : children) {
+            TaskEquality taskEquality = callRuleManager(child, task, requiredEqualityLevel);
+            
+            if (taskEquality != TaskEquality.UNEQUAL) {
+                if (mostConcreteNodeEquality == null) {
+                    mostConcreteNodeEquality = taskEquality;
+                }
+                else if (mostConcreteNodeEquality.isAtLeast(taskEquality)) {
+                    mostConcreteNodeEquality = taskEquality;
+                    
+                }
+                
+                if ((requiredEqualityLevel != null) &&
+                    (mostConcreteNodeEquality.isAtLeast(requiredEqualityLevel)))
+                {
+                    // if we found one child of the selection that is as equal as required, then
+                    // we can consider the selection to be sufficiently equal to the other task.
+                    // So we break up checking further children.
+                    break;
+                }
+            }
+        }
+        
+        // although the subtask may be identical to the task, we can not return identical, as
+        // the selection is not identical to the task, but at most lexically equal
+        if (mostConcreteNodeEquality == TaskEquality.IDENTICAL) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return mostConcreteNodeEquality;
+        }
+
+    }
+    
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param child1                the first task to be compared
+     * @param child2                the second task to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITask        child1,
+                                         ITask        child2,
+                                         TaskEquality requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(child1, child2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                     (child1, child2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+
+    /**
+     * <p>
+     * compares two task instances with each other checking for the provided required level of
+     * equality. One of the task instances must be a selection, the other one not. If this is not
+     * the case, the method returns null. The returned equality level is at most lexical equality
+     * as the selection can not be identical to something not being a selection.
+     * </p>
+     * 
+     * @param taskInstance1         the first task instance to be compared
+     * @param taskInstance2         the second task instance to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality.
+     */
+    private TaskEquality getEquality(ITaskInstance taskInstance1,
+                                     ITaskInstance taskInstance2,
+                                     TaskEquality  requiredEqualityLevel)
+    {
+        ISelectionInstance selection = null;
+        ITaskInstance task = null;
+        
+        if (taskInstance1 instanceof ISelectionInstance) {
+            if (taskInstance2 instanceof ISelectionInstance) {
+                // the rule is not responsible for two selections
+                return null;
+            }
+            
+            selection = (ISelectionInstance) taskInstance1;
+            task = taskInstance2;
+        }
+        else if (taskInstance2 instanceof ISelectionInstance) {
+            if (taskInstance1 instanceof ISelectionInstance) {
+                // the rule is not responsible for two selections
+                return null;
+            }
+            
+            selection = (ISelectionInstance) taskInstance2;
+            task = taskInstance1;
+        }
+        else {
+            return null;
+        }
+
+        // now, that we found the selection and the task, lets compare the child of the selection
+        // with the task.
+        ITaskInstance child = selection.getChild();
+        
+        if (child == null) {
+            return null;
+        }
+
+        TaskEquality taskEquality = callRuleManager(child, task, requiredEqualityLevel);
+
+        // although the subtask may be identical to the task, we can not return identical, as
+        // the selection is not identical to the task, but at most lexically equal
+        if (taskEquality == TaskEquality.IDENTICAL) {
+            return TaskEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return taskEquality;
+        }
+
+    }
+    
+    /**
+     * <p>
+     * used to to call the task equality rule manager for the comparison of the two provided
+     * children. If no required equality level is provided, than the most concrete equality is
+     * returned. Otherwise, the required equality is returned as long as the children are equal
+     * on that level.
+     * </p> 
+     * 
+     * @param taskInstance1         the first task instance to be compared
+     * @param taskInstance2         the second task instance to be compared
+     * @param requiredEqualityLevel the equality level to be checked for
+     * 
+     * @return the determined equality
+     */
+    private TaskEquality callRuleManager(ITaskInstance taskInstance1,
+                                         ITaskInstance taskInstance2,
+                                         TaskEquality  requiredEqualityLevel)
+    {
+        if (requiredEqualityLevel == null) {
+            return TaskEqualityRuleManager.getInstance().compare(taskInstance1, taskInstance2);
+        }
+        else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                     (taskInstance1, taskInstance2, requiredEqualityLevel))
+        {
+            return requiredEqualityLevel;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskComparisonRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskComparisonRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskComparisonRule.java	(revision 1551)
@@ -0,0 +1,155 @@
+//   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.taskequality;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * A task comparison rule is used by the {@link TaskEqualityRuleManager} to compare tasks and
+ * task instances with each other. It provides several methods to be called for a comparison.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface TaskComparisonRule {
+
+    /**
+     * <p>
+     * checks if the rule is applicable for comparing the two provided tasks
+     * </p>
+     * 
+     * @param task1 the first task to compare
+     * @param task2 the second task to compare
+     * 
+     * @return true, if the rule is applicable, false else
+     */
+    public boolean isApplicable(ITask task1, ITask task2);
+
+    /**
+     * <p>
+     * checks, if the provided tasks are lexically equal
+     * </p>
+     * 
+     * @param task1 the first task to compare
+     * @param task2 the second task to compare
+     * 
+     * @return true, if the tasks are equal, false else
+     */
+    public boolean areLexicallyEqual(ITask task1, ITask task2);
+
+    /**
+     * <p>
+     * checks, if the provided tasks are syntactically equal
+     * </p>
+     * 
+     * @param task1 the first task to compare
+     * @param task2 the second task to compare
+     * 
+     * @return true, if the tasks are equal, false else
+     */
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2);
+
+    /**
+     * <p>
+     * checks, if the provided tasks are semantically equal
+     * </p>
+     * 
+     * @param task1 the first task to compare
+     * @param task2 the second task to compare
+     * 
+     * @return true, if the tasks are equal, false else
+     */
+    public boolean areSemanticallyEqual(ITask task1, ITask task2);
+
+    /**
+     * <p>
+     * compares two tasks with each other. The result of the method is either a task equality or
+     * null. If it is null, it means, that the rule is not able to correctly compare the two given
+     * tasks
+     * </p>
+     * 
+     * @param task1 the first task to compare
+     * @param task2 the second task to compare
+     * 
+     * @return as described
+     */
+    public TaskEquality compare(ITask task1, ITask task2);
+
+    /**
+     * <p>
+     * checks if the rule is applicable for comparing the two provided task instances
+     * </p>
+     * 
+     * @param instance1 the first task instance to compare
+     * @param instance2 the second task instance to compare
+     * 
+     * @return true, if the rule is applicable, false else
+     */
+    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2);
+
+    /**
+     * <p>
+     * checks, if the provided task instances are lexically equal
+     * </p>
+     * 
+     * @param instance1 the first task instance to compare
+     * @param instance2 the second task instance to compare
+     * 
+     * @return true, if the tasks are equal, false else
+     */
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2);
+
+    /**
+     * <p>
+     * checks, if the provided task instances are syntactically equal
+     * </p>
+     * 
+     * @param instance1 the first task instance to compare
+     * @param instance2 the second task instance to compare
+     * 
+     * @return true, if the tasks are equal, false else
+     */
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2);
+
+    /**
+     * <p>
+     * checks, if the provided task instances are semantically equal
+     * </p>
+     * 
+     * @param instance1 the first task instance to compare
+     * @param instance2 the second task instance to compare
+     * 
+     * @return true, if the tasks are equal, false else
+     */
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2);
+
+    /**
+     * <p>
+     * compares two task instances with each other. The result of the method is either a task
+     * instance equality or null. If it is null, it means, that the rule is not able to correctly
+     * compare the two given task instances
+     * </p>
+     * 
+     * @param instance1 the first task instance to compare
+     * @param instance2 the second task instance to compare
+     * 
+     * @return as described
+     */
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2);
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskEquality.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskEquality.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskEquality.java	(revision 1551)
@@ -0,0 +1,128 @@
+//   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.taskequality;
+
+/**
+ * <p>
+ * A task equality denotes, how equal two tasks are. There are different equality levels
+ * which are similar to the usual design levels of GUI design. These levels are
+ * <ul>
+ *   <li>conceptual design: defines the concepts to be edited using a GUI</li>
+ *   <li>semantical design: defines the possible functions for editing the concepts</li>
+ *   <li>syntactical design: defines, which steps are needed to execute the functions</li>
+ *   <li>lexical design: defines on the key stroke level, how the steps for executing a function
+ *       can be performed</li>
+ * </ul>
+ * It is not possible to compare two tasks conceptually. But the other design levels can be
+ * identified and compared.
+ * </p>
+ * <p>
+ * Tasks can be identical. This is the case if in the java virtual machine, their comparison
+ * using the <code>==</code> operator or the equals method return true.
+ * </p>
+ * <p>
+ * Tasks are lexically equal, if they represent the same events on a key stroke level to be
+ * carried out to execute the task. Identical tasks are also syntactically equal.
+ * </p>
+ * <p>
+ * Nodes are syntactically equal, if they differ in their events on key stroke level, but the
+ * syntactical result is the same. For example, entering the text "hello" into a text field can
+ * be done by entering the letters in their correct order, but also by copying the text into the
+ * text field. The syntactical result is the same: The text "hello" was entered. But the tasks
+ * lexically differ because the events on key stroke level are different. On the other hand,
+ * lexically equal tasks are also syntactically equal.  
+ * </p>
+ * <p>
+ * Tasks are semantically equal, if they execute the same function for editing the concepts. An
+ * example are a click on a button and a short cut, both executing the same function. These tasks
+ * are syntactically and, therefore, also lexically different, but semantically equal.
+ * Syntactically equal tasks are always also semantically equal.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public enum TaskEquality {
+    IDENTICAL,
+    LEXICALLY_EQUAL,
+    SYNTACTICALLY_EQUAL,
+    SEMANTICALLY_EQUAL,
+    UNEQUAL;
+
+    /**
+     * <p>
+     * Checks for the current task equality, if it is at least identical to the
+     * provided one or even more concrete. As an example, the task equality identical also
+     * indicates, that the tasks are e.g. lexically, syntactically and semantically equal.
+     * Therefore, the method called on <code>IDENTICAL</code> with <code>SEMANTICALLY_EQUAL</code>
+     * as parameter will return true. If this method is called on <code>SYNTACTICALLY_EQUAL</code>
+     * with the parameter <code>IDENTICAL</code> instead, it returns false;
+     * </p>
+     *
+     * @param taskEquality the task equality to compare with.
+     * 
+     * @return as described
+     */
+    public boolean isAtLeast(TaskEquality taskEquality)
+    {
+        switch (taskEquality) {
+            case IDENTICAL:
+                return
+                    (this == IDENTICAL);
+            case LEXICALLY_EQUAL:
+                return
+                    (this == IDENTICAL) ||
+                    (this == LEXICALLY_EQUAL);
+            case SYNTACTICALLY_EQUAL:
+                return
+                    (this == IDENTICAL) ||
+                    (this == LEXICALLY_EQUAL) ||
+                    (this == SYNTACTICALLY_EQUAL);
+            case SEMANTICALLY_EQUAL:
+                return
+                    (this == IDENTICAL) ||
+                    (this == LEXICALLY_EQUAL) ||
+                    (this == SYNTACTICALLY_EQUAL) ||
+                    (this == SEMANTICALLY_EQUAL);
+            case UNEQUAL:
+                return
+                    (this == UNEQUAL);
+            default :
+                return false;
+        }
+    }
+
+    /**
+     * <p>
+     * returns the common denominator of this task equality and the provided one. I.e. if one
+     * equality is e.g. syntactical and the other one only semantical, then semantical is returned.
+     * </p>
+     *
+     * @param otherEquality the equality, to compare this with
+     * 
+     * @return as described
+     */
+    public TaskEquality getCommonDenominator(TaskEquality otherEquality) {
+        if (this.isAtLeast(otherEquality)) {
+            return otherEquality;
+        }
+        else if (otherEquality.isAtLeast(this)) {
+            return this;
+        }
+        else {
+            return TaskEquality.UNEQUAL;
+        }
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskEqualityRuleManager.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskEqualityRuleManager.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskEqualityRuleManager.java	(revision 1551)
@@ -0,0 +1,475 @@
+//   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.taskequality;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * The task equality rule manager is capable of comparing tasks and task instances based on its
+ * internal list of comparison rules. These rules are asked for comparing the two provided tasks or
+ * task instance. If a rule returns a task equality other than null, this equality is returned.
+ * Otherwise the next rule is asked.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class TaskEqualityRuleManager {
+    
+    /**
+     * <p>
+     * the singleton instance of this class
+     * </p>
+     */
+    private static final TaskEqualityRuleManager instance = new TaskEqualityRuleManager();
+
+    /**
+     * <p>
+     * the rules that can be used for comparing tasks
+     * </p>
+     */
+    private List<TaskComparisonRule> mRuleIndex = null;
+
+    /**
+     * <p>
+     * initializes the task equality rule manager by filling the internal list of comparison rules.
+     * </p>
+     */
+    private TaskEqualityRuleManager() {
+        mRuleIndex = new ArrayList<TaskComparisonRule>();
+        mRuleIndex.add(new TaskIdentityRule());
+        mRuleIndex.add(new GUIEventTaskComparisonRule());
+        mRuleIndex.add(new EventTaskComparisonRule());
+        mRuleIndex.add(new IterationComparisonRule());
+        mRuleIndex.add(new SequenceComparisonRule());
+        mRuleIndex.add(new SelectionComparisonRule());
+        mRuleIndex.add(new TaskAndIterationComparisonRule());
+        mRuleIndex.add(new TaskAndSelectionComparisonRule());
+    }
+
+
+    /**
+     * <p>
+     * returns the singleton instance of this class
+     * </p>
+     * 
+     * @return as described
+     */
+    public static TaskEqualityRuleManager getInstance() {
+        return instance;
+    }
+
+    /**
+     * <p>
+     * this method performs a comparison of the two provided tasks. It iterates its internal
+     * comparison rules. If the first rule returns a task equality other than null,
+     * this equality is returned. Otherwise the next rule is tried. If no rule returns an equality
+     * <code>NodeEquality.UNEQUAL</code> is returned.
+     * </p>
+     * 
+     * @param task1 the first task to be compared
+     * @param task2 the second task to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public TaskEquality compare(ITask task1, ITask task2)
+        throws IllegalStateException
+    {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        // LOG.info("checking for equality of " + task1 + " and " + task2);
+        TaskEquality taskEquality = null;
+
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(task1, task2)) {
+                taskEquality = rule.compare(task1, task2);
+                if (taskEquality != null) {
+                    // LOG.warning("used rule " + rule + " for equality check");
+                    return taskEquality;
+                }
+            }
+        }
+
+        // LOG.warning("no rule could be applied --> handling tasks as unequal");
+
+        return TaskEquality.UNEQUAL;
+    }
+
+    /**
+     * <p>
+     * this method two tasks with respect to the fiven equality level and returns true, if this
+     * level is given.
+     * </p>
+     * 
+     * @param task1         the first task to be compared
+     * @param task2         the second task to be compared
+     * @param equalityLevel the level of equality to be checked for
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areAtLeastEqual(ITask task1, ITask task2, TaskEquality equalityLevel) {
+        if (equalityLevel == null) {
+            throw new IllegalArgumentException("required equality level must not be null");
+        }
+        
+        switch (equalityLevel) {
+            case IDENTICAL:
+                return areIdentical(task1, task2);
+            case LEXICALLY_EQUAL:
+                return areLexicallyEqual(task1, task2);
+            case SYNTACTICALLY_EQUAL:
+                return areSyntacticallyEqual(task1, task2);
+            case SEMANTICALLY_EQUAL:
+                return areSemanticallyEqual(task1, task2);
+            case UNEQUAL:
+                return !areSemanticallyEqual(task1, task2);
+            default:
+                throw new IllegalArgumentException("unknown required equality: " + equalityLevel);
+        }
+    }
+
+    /**
+     * <p>
+     * this method checks if the two given tasks are identical. For this, it iterates its internal
+     * comparison rules. If the first rule returns true, than this method returns true as well.
+     * If no rule returns true, this method returns false.
+     * </p>
+     * 
+     * @param task1 the first task to be compared
+     * @param task2 the second task to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areIdentical(ITask task1, ITask task2) {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(task1, task2) && rule.areLexicallyEqual(task1, task2)) {
+                 return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * <p>
+     * this method checks if the two given tasks are lexically equal. For this, it iterates its
+     * internal comparison rules. If the first rule returns true, than this method returns true
+     * as well. If no rule returns true, this method returns false.
+     * </p>
+     * 
+     * @param task1 the first task to be compared
+     * @param task2 the second task to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(task1, task2) && rule.areLexicallyEqual(task1, task2)) {
+                 return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * <p>
+     * this method checks if the two given tasks are syntactically equal. For this, it iterates its
+     * internal comparison rules. If the first rule returns true, than this method returns true
+     * as well. If no rule returns true, this method returns false.
+     * </p>
+     * 
+     * @param task1 the first task to be compared
+     * @param task2 the second task to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(task1, task2) && rule.areSyntacticallyEqual(task1, task2)) {
+                 return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * <p>
+     * this method checks if the two given tasks are semantically equal. For this, it iterates its
+     * internal comparison rules. If the first rule returns true, than this method returns true
+     * as well. If no rule returns true, this method returns false.
+     * </p>
+     * 
+     * @param task1 the first task to be compared
+     * @param task2 the second task to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(task1, task2) && rule.areSemanticallyEqual(task1, task2)) {
+                 return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * <p>
+     * this method performs a comparison of the two provided task instances. It iterates its
+     * internal comparison rules. If the first rule returns a task instance equality other than
+     * null, this equality is returned. Otherwise the next rule is tried. If no rule returns an
+     * equality <code>TaskEquality.UNEQUAL</code> is returned.
+     * </p>
+     * 
+     * @param instance1 the first task instance to be compared
+     * @param instance2 the second task instance to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2)
+        throws IllegalStateException
+    {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        // LOG.info("checking for equality of " + instance1 + " and " + instance2);
+        TaskEquality instanceEquality = null;
+
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(instance1, instance2)) {
+                instanceEquality = rule.compare(instance1, instance2);
+                if (instanceEquality != null) {
+                    // LOG.warning("used rule " + rule + " for equality check");
+                    return instanceEquality;
+                }
+            }
+        }
+
+        // LOG.warning("no rule could be applied --> handling tasks as unequal");
+
+        return TaskEquality.UNEQUAL;
+    }
+
+    /**
+     * <p>
+     * this method compares two task instances with respect to the given equality level and returns
+     * true, if this level is given.
+     * </p>
+     * 
+     * @param instance1     the first task instance to be compared
+     * @param instance2     the second task instance to be compared
+     * @param equalityLevel the level of equality to be checked for
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areAtLeastEqual(ITaskInstance        instance1,
+                                   ITaskInstance        instance2,
+                                   TaskEquality equalityLevel)
+    {
+        if (equalityLevel == null) {
+            throw new IllegalArgumentException("required equality level must not be null");
+        }
+        
+        switch (equalityLevel) {
+            case IDENTICAL:
+                return areIdentical(instance1, instance2);
+            case LEXICALLY_EQUAL:
+                return areLexicallyEqual(instance1, instance2);
+            case SYNTACTICALLY_EQUAL:
+                return areSyntacticallyEqual(instance1, instance2);
+            case SEMANTICALLY_EQUAL:
+                return areSemanticallyEqual(instance1, instance2);
+            case UNEQUAL:
+                return !areSemanticallyEqual(instance1, instance2);
+            default:
+                throw new IllegalArgumentException("unknown required equality: " + equalityLevel);
+        }
+    }
+
+    /**
+     * <p>
+     * this method checks if the two given task instances are identical. For this, it iterates its
+     * internal comparison rules. If the first rule returns true, than this method returns true
+     * as well. If no rule returns true, this method returns false.
+     * </p>
+     * 
+     * @param instance1 the first task instance to be compared
+     * @param instance2 the second task instance to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areIdentical(ITaskInstance instance1, ITaskInstance instance2) {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(instance1, instance2) &&
+                rule.areLexicallyEqual(instance1, instance2))
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * <p>
+     * this method checks if the two given task instances are lexically equal. For this, it
+     * iterates its internal comparison rules. If the first rule returns true, than this method
+     * returns true, as well. If no rule returns true, this method returns false.
+     * </p>
+     * 
+     * @param instance1 the first task instance to be compared
+     * @param instance2 the second task instance to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(instance1, instance2) &&
+                rule.areLexicallyEqual(instance1, instance2))
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * <p>
+     * this method checks if the two given task instances are syntactically equal. For this, it
+     * iterates its internal comparison rules. If the first rule returns true, than this method
+     * returns true, as well. If no rule returns true, this method returns false.
+     * </p>
+     * 
+     * @param instance1 the first task instance to be compared
+     * @param instance2 the second task instance to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(instance1, instance2) &&
+                rule.areSyntacticallyEqual(instance1, instance2))
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * <p>
+     * this method checks if the two given task instances are semantically equal. For this, it
+     * iterates its internal comparison rules. If the first rule returns true, than this method
+     * returns true, as well. If no rule returns true, this method returns false.
+     * </p>
+     * 
+     * @param instance1 the first task instance to be compared
+     * @param instance2 the second task instance to be compared
+     * 
+     * @return as described
+     * 
+     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
+     *                               manager before a call to this method.
+     */
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        for (TaskComparisonRule rule : mRuleIndex) {
+            if (rule.isApplicable(instance1, instance2) &&
+                rule.areSemanticallyEqual(instance1, instance2))
+            {
+                 return true;
+            }
+        }
+
+        return false;
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskIdentityRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskIdentityRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/TaskIdentityRule.java	(revision 1551)
@@ -0,0 +1,122 @@
+//   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.taskequality;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * This comparison rule returns <code>TaskEquality.IDENTICAL</code> if the comparison of the two
+ * tasks using the <code>==</code> operator returns true. Else it returns null to denote, that
+ * it can not compare the tasks.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class TaskIdentityRule implements TaskComparisonRule {
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITask, ITask)
+     */
+    @Override
+    public boolean isApplicable(ITask task1, ITask task2) {
+        return (task1 == task2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        return (task1 == task2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
+        return (task1 == task2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
+        return (task1 == task2);
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITask, ITask)
+     */
+    @Override
+    public TaskEquality compare(ITask task1, ITask task2) {
+        if (isApplicable(task1, task2)) {
+            return TaskEquality.IDENTICAL;
+        }
+        else {
+            return null;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
+        return (instance1.getTask() == instance2.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        return (instance1.getTask() == instance2.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        return (instance1.getTask() == instance2.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
+        return (instance1.getTask() == instance2.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance)
+     */
+    @Override
+    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
+        if (isApplicable(instance1, instance2)) {
+            return TaskEquality.IDENTICAL;
+        }
+        else {
+            return null;
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ISessionScopeRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ISessionScopeRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ISessionScopeRule.java	(revision 1551)
@@ -0,0 +1,48 @@
+//   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;
+
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+
+/**
+ * <p>
+ * A session scope rule is able to detected temporal relationships between task instances of the
+ * sessions provided to the {@link #apply(List<IUserSession>)} method. The rule creates temporal
+ * relationships between the tasks of the task instances, i.e. substructures in the task tree, if
+ * it detects a temporal relationship and instantiates the temporal relationships according to
+ * their occurrences.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+interface ISessionScopeRule extends ITemporalRelationshipRule {
+
+    /**
+     * <p>
+     * Applies the rule to the given sessions. The returned rule application result is null, if the
+     * rule can not be applied, i.e. it does not detect a temporal relationship. It returns a rule
+     * application result with a status {@link RuleApplicationStatus#RULE_APPLICATION_FINISHED} if
+     * the rule was applied. The result contains all newly created tasks and task instances.
+     * </p>
+     * 
+     * @param sessions the session on which the rule shall be applied
+     *                    
+     * @return the rule application result as described.
+     */
+    RuleApplicationResult apply(List<IUserSession> sessions);
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ITaskInstanceScopeRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ITaskInstanceScopeRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ITaskInstanceScopeRule.java	(revision 1551)
@@ -0,0 +1,45 @@
+//   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;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * a task instance scope rule is able to detected temporal relationships between the children of
+ * a task instance provided to the {@link #apply(ITaskInstance)} method. A rule creates temporal
+ * relationships between the task instances, i.e. substructures in the task tree, if
+ * it detects a temporal relationship and instantiates the temporal relationships accordingly.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+interface ITaskInstanceScopeRule extends ITemporalRelationshipRule {
+
+  /**
+   * <p>
+   * applies the rule to the given task instance. The returned rule application result is null,
+   * if the rule can not be applied, i.e. it does not detect a temporal relationship. It returns a
+   * rule application result with a status {@link RuleApplicationStatus#RULE_APPLICATION_FINISHED}
+   * if the rule was applied. The result contains all newly created parent tasks and task instances.
+   * </p>
+   * 
+   * @param taskInstance the task instances to apply the rule on
+   *                    
+   * @return the rule application result as described.
+   */
+  RuleApplicationResult apply(ITaskInstance taskInstance);
+  
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ITemporalRelationshipRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ITemporalRelationshipRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/ITemporalRelationshipRule.java	(revision 1551)
@@ -0,0 +1,28 @@
+//   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;
+
+/**
+ * <p>
+ * a temporal relationship rule is the main interface for all rules applied for generating
+ * temporal relationships in a task tree. It is just a marker interface. More important are the
+ * sub interfaces {@link ISessionScopeRule} and {@link ITaskInstanceScopeRule}.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+interface ITemporalRelationshipRule {
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationResult.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationResult.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationResult.java	(revision 1551)
@@ -0,0 +1,107 @@
+//   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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * The rule application result describes the result of applying a {@link ITemporalRelationshipRule}.
+ * It contains a {@link RuleApplicationStatus} and a list of all parent task instances and tasks
+ * that were created during a rule application. See the description of
+ * {@link ITemporalRelationshipRule} for more details.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class RuleApplicationResult {
+
+    /** */
+    private RuleApplicationStatus status = RuleApplicationStatus.NOT_APPLIED;
+
+    /** */
+    private List<ITask> newParentTasks = new ArrayList<ITask>();
+
+    /** */
+    private List<ITaskInstance> newParentInstances = new ArrayList<ITaskInstance>();
+
+    /**
+     * <p>
+     * create a rule application result with a status {@link RuleApplicationStatus#RULE_NOT_APPLIED}
+     * </p>
+     */
+    RuleApplicationResult() {
+        // this is the default indicating nothing so far
+    }
+
+    /**
+     * <p>
+     * set the rule application status
+     * </p>
+     */
+    void setRuleApplicationStatus(RuleApplicationStatus status) {
+        this.status = status;
+    }
+
+    /**
+     * <p>
+     * return the rule application status
+     * </p>
+     */
+    RuleApplicationStatus getRuleApplicationStatus() {
+        return status;
+    }
+
+    /**
+     * <p>
+     * add a further parent task created during the rule application
+     * </p>
+     */
+    void addNewlyCreatedTask(ITask newParent) {
+        newParentTasks.add(newParent);
+    }
+
+    /**
+     * <p>
+     * return all parent tasks created during the rule application
+     * </p>
+     */
+    List<ITask> getNewlyCreatedTasks() {
+        return newParentTasks;
+    }
+
+    /**
+     * <p>
+     * add a further parent task instance created during the rule application
+     * </p>
+     */
+    void addNewlyCreatedTaskInstance(ITaskInstance newParent) {
+        newParentInstances.add(newParent);
+    }
+
+    /**
+     * <p>
+     * return all parent task instances created during the rule application
+     * </p>
+     */
+    List<ITaskInstance> getNewlyCreatedTaskInstances() {
+        return newParentInstances;
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationStatus.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationStatus.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleApplicationStatus.java	(revision 1551)
@@ -0,0 +1,28 @@
+//   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;
+
+/**
+ * <p>
+ * The rule application status describes the result of applying a {@link ITemporalRelationshipRule}.
+ * See the description of {@link ITemporalRelationshipRule} for more details.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+enum RuleApplicationStatus {
+    FINISHED,
+    NOT_APPLIED;
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleUtils.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleUtils.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/RuleUtils.java	(revision 1551)
@@ -0,0 +1,125 @@
+//   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;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
+
+/**
+ * <p>
+ * provides some convenience methods for rule application
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class RuleUtils {
+    
+    /**
+     * <p>
+     * counter for generating unique ids. Starts at 0 for each new program start
+     * </p>
+     */
+    private static int idCounter = 0;
+
+    /**
+     * <p>
+     * generates a sub sequence for a specified range of elements in the provided task instances
+     * list.
+     * </p>
+     *
+     * @param parent      the list of which the range shall be extracted
+     * @param startIndex  the start index of the range
+     * @param endIndex    the end index of the range (inclusive)
+     * @param model       the task model (required for instantiating the sub sequence)
+     * @param taskFactory the task factory used for instantiating the sub sequence
+     * @param taskBuilder the task builder to perform changes in the task structure
+     * 
+     * @return a task instance representing the requested sub sequence
+     */
+    static ITaskInstance getSubSequenceInRange(ITaskInstanceList parent,
+                                               int               startIndex,
+                                               int               endIndex,
+                                               ISequence         model,
+                                               ITaskFactory      taskFactory,
+                                               ITaskBuilder      taskBuilder)
+    {
+        ISequenceInstance subsequence = taskFactory.createNewTaskInstance(model);
+
+        for (int i = startIndex; i <= endIndex; i++) {
+            taskBuilder.addChild(subsequence, parent.get(i));
+        }
+
+        return subsequence;
+    }
+
+    /**
+     * <p>
+     * replaces a sub sequence for a specified range of elements in the provided task instances
+     * list by a sub task instance
+     * </p>
+     *
+     * @param parent      the list of which the range shall be replaced
+     * @param startIndex  the start index of the range
+     * @param endIndex    the end index of the range (inclusive)
+     * @param model       the task model (required for instantiating the sub sequence)
+     * @param taskFactory the task factory used for instantiating the sub sequence
+     * @param taskBuilder the task builder to perform changes in the task structure
+     * 
+     * @return the replacement for the range
+     */
+    static ISequenceInstance createNewSubSequenceInRange(ITaskInstanceList parent,
+                                                         int               startIndex,
+                                                         int               endIndex,
+                                                         ISequence         model,
+                                                         ITaskFactory      taskFactory,
+                                                         ITaskBuilder      taskBuilder)
+    {
+        ISequenceInstance subsequence = taskFactory.createNewTaskInstance(model);
+
+        for (int i = startIndex; i <= endIndex; i++) {
+            taskBuilder.addChild(subsequence, parent.get(startIndex));
+            taskBuilder.removeTaskInstance(parent, startIndex);
+        }
+
+        taskBuilder.addTaskInstance(parent, startIndex, subsequence);
+
+        return subsequence;
+    }
+
+    /**
+     * <p>
+     * returns the next available id (uses the id counter)
+     * </p>
+     * 
+     * @return the next available id
+     */
+    static synchronized String getNewId() {
+        return Integer.toString(idCounter++);
+    }
+
+    /**
+     * <p>
+     * prevent instantiation
+     * </p>
+     */
+    private RuleUtils() {
+        // prevent instantiation
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRule.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRule.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceForTaskDetectionRule.java	(revision 1551)
@@ -0,0 +1,1139 @@
+//   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;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+
+import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+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.ITaskBuilder;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+import de.ugoe.cs.autoquest.usageprofiles.SymbolMap;
+import de.ugoe.cs.autoquest.usageprofiles.Trie;
+import de.ugoe.cs.autoquest.usageprofiles.TrieProcessor;
+import de.ugoe.cs.util.StopWatch;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <p>
+ * This class implements the major rule for creating task trees based on a set of recorded
+ * user sessions. For this, it first harmonizes all tasks. This eases later comparison. Then it
+ * searches the sessions for iterations and replaces them accordingly. Then it searches for sub
+ * sequences being the longest and occurring most often. For each found sub sequence, it replaces
+ * the occurrences by creating appropriate {@link ISequence}s. Afterwards, again searches for
+ * iterations and then again for sub sequences until no more replacements are done.
+ * </p>
+ * <p>
+ * For determining the longest sequence occurring most often, the implementation uses a 
+ * {@link Trie}. The depth of the tree is initially 3. If the algorithm has a longest sequence
+ * occurring most often whose length is equal to the depth of the trie, it recalculates the trie
+ * with an increased depth. 
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class SequenceForTaskDetectionRule implements ISessionScopeRule {
+    
+    /**
+     * <p>
+     * the task factory to be used for creating substructures for the temporal
+     * relationships identified during rul application
+     * </p>
+     */
+    private ITaskFactory taskFactory;
+    /**
+     * <p>
+     * the task builder to be used for creating substructures for the temporal relationships
+     * identified during rule application
+     * </p>
+     */
+    private ITaskBuilder taskBuilder;
+
+    /**
+     * <p>
+     * the task handling strategy to be used for comparing tasks for preparation, i.e., before
+     * the tasks are harmonized
+     * </p>
+     */
+    private TaskHandlingStrategy preparationTaskHandlingStrategy;
+    
+    /**
+     * <p>
+     * the task handling strategy to be used for comparing tasks during iteration detection an trie
+     * generation, i.e., after the tasks are harmonized 
+     * </p>
+     */
+    private TaskHandlingStrategy identityTaskHandlingStrategy;;
+    
+    /**
+     * <p>
+     * instantiates the rule and initializes it with a task equality to be considered when
+     * comparing tasks as well as a task factory and builder to be used for creating task
+     * structures.
+     * </p>
+     * 
+     * @param minimalTaskEquality the task equality to be considered when comparing tasks
+     * @param taskFactory         the task factory to be used for creating substructures
+     * @param taskBuilder         the task builder to be used for creating substructures
+     */
+    SequenceForTaskDetectionRule(TaskEquality minimalTaskEquality,
+                                 ITaskFactory taskFactory,
+                                 ITaskBuilder taskBuilder)
+    {
+        this.taskFactory = taskFactory;
+        this.taskBuilder = taskBuilder;
+        
+        this.preparationTaskHandlingStrategy = new TaskHandlingStrategy(minimalTaskEquality);
+        this.identityTaskHandlingStrategy = new TaskHandlingStrategy(TaskEquality.IDENTICAL);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "SequenceForTaskDetectionRule";
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.ISessionScopeRule#apply(java.util.List)
+     */
+    @Override
+    public RuleApplicationResult apply(List<IUserSession> sessions) {
+        RuleApplicationData appData = new RuleApplicationData(sessions);
+        
+        // this is the real rule application. Loop while something is replaced.
+        harmonizeEventTaskInstancesModel(appData);
+        do {
+            System.out.println();
+            
+            appData.getStopWatch().start("whole loop");
+            detectAndReplaceIterations(appData);
+
+            appData.getStopWatch().start("task replacement");
+            detectAndReplaceTasks(appData);
+            appData.getStopWatch().stop("task replacement");
+            appData.getStopWatch().stop("whole loop");
+            
+            //((TaskTreeNodeComparator) taskComparator).getStopWatch().dumpStatistics(System.out);
+            //((TaskTreeNodeComparator) taskComparator).getStopWatch().reset();
+            
+            appData.getStopWatch().dumpStatistics(System.out);
+            appData.getStopWatch().reset();
+            
+        }
+        while (appData.detectedAndReplacedTasks());
+        
+        Console.println
+            ("created " + appData.getResult().getNewlyCreatedTasks().size() +
+             " new tasks and " + appData.getResult().getNewlyCreatedTaskInstances().size() +
+             " appropriate instances\n");
+        
+        if ((appData.getResult().getNewlyCreatedTasks().size() > 0) ||
+            (appData.getResult().getNewlyCreatedTaskInstances().size() > 0))
+        {
+            appData.getResult().setRuleApplicationStatus(RuleApplicationStatus.FINISHED);
+        }
+        
+        return appData.getResult();
+    }
+
+    /**
+     * <p>
+     * harmonizes the event task instances by unifying tasks. This is done, as initially the
+     * event tasks being equal with respect to the considered task equality are distinct objects.
+     * The comparison of these distinct objects is more time consuming than comparing the object
+     * references.
+     * </p>
+     *
+     * @param appData the rule application data combining all data used for applying this rule
+     */
+    private void harmonizeEventTaskInstancesModel(RuleApplicationData appData) {
+        Console.traceln(Level.INFO, "harmonizing task model of event task instances");
+        appData.getStopWatch().start("harmonizing event tasks");
+
+        SymbolMap<ITaskInstance, ITask> uniqueTasks =
+            preparationTaskHandlingStrategy.createSymbolMap();
+        TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator();
+        
+        int unifiedTasks = 0;
+        ITask task;
+        List<IUserSession> sessions = appData.getSessions();
+        int sessionNo = 0;
+        for (IUserSession session : sessions) {
+            Console.traceln(Level.FINE, "handling " + (++sessionNo) + ". " + session);
+            for (ITaskInstance taskInstance : session) {
+                task = uniqueTasks.getValue(taskInstance);
+                
+                if (task == null) {
+                    uniqueTasks.addSymbol(taskInstance, taskInstance.getTask());
+                }
+                else {
+                    taskBuilder.setTask(taskInstance, task);
+                    unifiedTasks++;
+                }
+            }
+            
+            comparator.clearBuffers();
+        }
+        
+        appData.getStopWatch().stop("harmonizing event tasks");
+        Console.traceln(Level.INFO, "harmonized " + unifiedTasks + " task occurrences (still " +
+                        uniqueTasks.size() + " different tasks)");
+
+        appData.getStopWatch().dumpStatistics(System.out);
+        appData.getStopWatch().reset();
+    }
+
+    /**
+     * <p>
+     * searches for direct iterations of single tasks in all sequences and replaces them with
+     * {@link IIteration}s, respectively appropriate instances. Also all single occurrences of
+     * a task that is iterated somewhen are replaced with iterations to have again an efficient
+     * way for task comparisons. 
+     * </p>
+     * 
+     * @param appData the rule application data combining all data used for applying this rule
+     */
+    private void detectAndReplaceIterations(RuleApplicationData appData) {
+        Console.traceln(Level.FINE, "detecting iterations");
+        appData.getStopWatch().start("detecting iterations");
+        
+        List<IUserSession> sessions = appData.getSessions();
+        
+        Set<ITask> iteratedTasks = searchIteratedTasks(sessions);
+        
+        if (iteratedTasks.size() > 0) {
+            replaceIterationsOf(iteratedTasks, sessions, appData);
+        }
+        
+        appData.getStopWatch().stop("detecting iterations");
+        Console.traceln(Level.INFO, "replaced " + iteratedTasks.size() + " iterated tasks");
+    }
+
+    /**
+     * <p>
+     * searches the provided sessions for task iterations. If a task is iterated, it is added
+     * to the returned set.
+     * </p>
+     * 
+     * @param the session to search for iterations in
+     * 
+     * @return a set of tasks being iterated somewhere
+     */
+    private Set<ITask> searchIteratedTasks(List<IUserSession> sessions) {
+        Set<ITask> iteratedTasks = new HashSet<ITask>();
+        for (IUserSession session : sessions) {
+            for (int i = 0; i < (session.size() - 1); i++) {
+                // we prepared the task instances to refer to unique tasks, if they are treated
+                // as equal. Therefore, we just compare the identity of the tasks of the task
+                // instances
+                if (session.get(i).getTask() == session.get(i + 1).getTask()) {
+                    iteratedTasks.add(session.get(i).getTask());
+                }
+            }
+        }
+        
+        return iteratedTasks;
+    }
+
+    /**
+     * <p>
+     * replaces all occurrences of all tasks provided in the set with iterations
+     * </p>
+     *
+     * @param iteratedTasks the tasks to be replaced with iterations
+     * @param sessions      the sessions in which the tasks are to be replaced
+     * @param appData       the rule application data combining all data used for applying this rule
+     */
+    private void replaceIterationsOf(Set<ITask>          iteratedTasks,
+                                     List<IUserSession>  sessions,
+                                     RuleApplicationData appData)
+    {
+        Map<ITask, IIteration> iterations = new HashMap<ITask, IIteration>();
+        Map<IIteration, List<IIterationInstance>> iterationInstances =
+                new HashMap<IIteration, List<IIterationInstance>>();
+            
+        for (ITask iteratedTask : iteratedTasks) {
+            IIteration iteration = taskFactory.createNewIteration();
+            iterations.put(iteratedTask, iteration);
+            iterationInstances.put(iteration, new LinkedList<IIterationInstance>());
+        }
+        
+        IIterationInstance iterationInstance;
+        
+        for (IUserSession session : sessions) {
+            int index = 0;
+            iterationInstance = null;
+
+            while (index < session.size()) {
+                // we prepared the task instances to refer to unique tasks, if they are treated
+                // as equal. Therefore, we just compare the identity of the tasks of the task
+                // instances
+                ITask currentTask = session.get(index).getTask();
+                IIteration iteration = iterations.get(currentTask);
+                if (iteration != null) {
+                    if ((iterationInstance == null) || (iterationInstance.getTask() != iteration))
+                    {
+                        iterationInstance = taskFactory.createNewTaskInstance(iteration);
+                        iterationInstances.get(iteration).add(iterationInstance);
+                        taskBuilder.addTaskInstance(session, index, iterationInstance);
+                        index++;
+                    }
+                    
+                    taskBuilder.addChild(iterationInstance, session.get(index));
+                    taskBuilder.removeTaskInstance(session, index);
+                }
+                else {
+                    if (iterationInstance != null) {
+                        iterationInstance = null;
+                    }
+                    index++;
+                }
+            }
+        }
+        
+        for (Map.Entry<IIteration, List<IIterationInstance>> entry : iterationInstances.entrySet())
+        {
+            harmonizeIterationInstancesModel(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
+     * <p>
+     * TODO clarify why this is done
+     * </p>
+     */
+    private void harmonizeIterationInstancesModel(IIteration               iteration,
+                                                  List<IIterationInstance> iterationInstances)
+    {
+        List<ITask> iteratedTaskVariants = new LinkedList<ITask>();
+        TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator();
+        
+        // merge the lexically different variants of iterated task to a unique list 
+        for (IIterationInstance iterationInstance : iterationInstances) {
+            for (ITaskInstance executionVariant : iterationInstance) {
+                ITask candidate = executionVariant.getTask();
+            
+                boolean found = false;
+                for (ITask taskVariant : iteratedTaskVariants) {
+                    if (comparator.areLexicallyEqual(taskVariant, candidate)) {
+                        taskBuilder.setTask(executionVariant, taskVariant);
+                        found = true;
+                        break;
+                    }
+                }
+                
+                if (!found) {
+                    iteratedTaskVariants.add(candidate);
+                }
+            }
+        }
+        
+        // if there are more than one lexically different variant of iterated tasks, adapt the
+        // iteration model to be a selection of different variants. In this case also adapt
+        // the generated iteration instances to correctly contain selection instances. If there
+        // is only one variant of an iterated task, simply set this as the marked task of the
+        // iteration. In this case, the instances can be preserved as is
+        if (iteratedTaskVariants.size() > 1) {
+            ISelection selection = taskFactory.createNewSelection();
+            
+            for (ITask variant : iteratedTaskVariants) {
+                taskBuilder.addChild(selection, variant);
+            }
+            
+            taskBuilder.setMarkedTask(iteration, selection);
+            
+            for (IIterationInstance instance : iterationInstances) {
+                for (int i = 0; i < instance.size(); i++) {
+                    ISelectionInstance selectionInstance =
+                        taskFactory.createNewTaskInstance(selection);
+                    taskBuilder.setChild(selectionInstance, instance.get(i));
+                    taskBuilder.setTaskInstance(instance, i, selectionInstance);
+                }
+            }
+        }
+        else {
+            taskBuilder.setMarkedTask(iteration, iteratedTaskVariants.get(0));
+        }
+    }
+
+    /**
+     * TODO go on commenting
+     * @param appData the rule application data combining all data used for applying this rule
+     */
+    private void detectAndReplaceTasks(RuleApplicationData appData) {
+        Console.traceln(Level.FINE, "detecting and replacing tasks");
+        appData.getStopWatch().start("detecting tasks");
+        
+        getSequencesOccuringMostOften(appData);
+
+        appData.getStopWatch().stop("detecting tasks");
+        appData.getStopWatch().start("replacing tasks");
+        
+        replaceSequencesOccurringMostOften(appData);
+        
+        appData.getStopWatch().stop("replacing tasks");
+        Console.traceln(Level.INFO, "detected and replaced " + appData.getLastFoundTasks().size() +
+                        " tasks occuring " + appData.getLastFoundTasks().getOccurrenceCount() +
+                        " times");
+    }
+
+    /**
+     * @param appData the rule application data combining all data used for applying this rule
+     */
+    private void getSequencesOccuringMostOften(RuleApplicationData appData) {
+        Console.traceln(Level.FINE, "determining most prominent tasks");
+
+        Tasks tasks;
+        boolean createNewTrie = (appData.getLastTrie() == null) ||
+            appData.detectedAndReplacedTasks(); // tree has changed
+        
+        do {
+            if (createNewTrie) {
+                createNewTrie(appData);
+            }
+            
+            MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder();
+            appData.getLastTrie().process(finder);
+        
+            tasks = finder.getFoundTasks();
+            
+            createNewTrie = false;
+            
+            for (List<ITaskInstance> task : tasks) {
+                if (task.size() >= appData.getTrainedSequenceLength()) {
+                    // Trie must be recreated with a longer sequence length to be sure that
+                    // the found sequences occurring most often are found in their whole length
+                    appData.setTrainedSequenceLength(appData.getTrainedSequenceLength() + 1);
+                    createNewTrie = true;
+                    break;
+                }
+            }
+        }
+        while (createNewTrie);
+        
+        // create a normal trie for comparison
+        /*System.out.println("creating test trie for comparison");
+        
+        appData.getStopWatch().start("testtrie");
+        Trie<ITaskInstance> trie = new Trie<ITaskInstance>(identityTaskComparator);
+        
+        for (IUserSession session : appData.getSessions()) {
+            trie.train(session.getExecutedTasks(), appData.getTrainedSequenceLength());
+        }
+        
+        appData.getStopWatch().stop("testtrie");
+        
+        MaxCountAndLongestTasksFinder finder = new MaxCountAndLongestTasksFinder();
+        trie.process(finder);
+
+        boolean allTasksEqual = finder.getFoundTasks().size() == tasks.size();
+        
+        allTasksEqual &= finder.getFoundTasks().occurrenceCount == tasks.occurrenceCount;
+        
+        for (List<ITaskInstance> task1 : finder.getFoundTasks()) {
+            boolean foundTask = false;
+            for (List<ITaskInstance> task2 : tasks) {
+                boolean tasksEqual = false;
+                if (task1.size() == task2.size()) {
+                    tasksEqual = true;
+                    for (int i = 0; i < task1.size(); i++) {
+                        if (!identityTaskComparator.equals(task1.get(i).getTask(), task2.get(i).getTask()))
+                        {
+                            tasksEqual = false;
+                        }
+                    }
+                }
+                
+                if (tasksEqual) {
+                    foundTask = true;
+                    break;
+                }
+            }
+            
+            if (!foundTask) {
+                System.out.println("different is " + task1);
+                allTasksEqual = false;
+                break;
+            }
+        }
+        
+        if (!allTasksEqual) {
+            System.out.println(finder.getFoundTasks());
+            System.out.println(tasks);
+            
+            throw new IllegalArgumentException("both tries calculated different subsequences");
+        }
+        
+        /*TrieStatisticsDumper dumper = new TrieStatisticsDumper();
+        appData.getLastTrie().process(dumper);
+        dumper.dumpCounters();*/
+        
+        appData.setLastFoundTasks(tasks);
+
+        Console.traceln(Level.FINE, "found " + appData.getLastFoundTasks().size() + " tasks " +
+        		"occurring " + appData.getLastFoundTasks().getOccurrenceCount() + " times");
+    }
+
+    /**
+     * @param appData the rule application data combining all data used for applying this rule
+     */
+    private void createNewTrie(RuleApplicationData appData) {
+        Console.traceln(Level.FINER, "training trie with a maximum sequence length of " +
+                        appData.getTrainedSequenceLength());
+
+        appData.getStopWatch().start("training trie");
+        
+        // we prepared the task instances to refer to unique tasks, if they are treated
+        // as equal. Therefore, we just compare the identity of the tasks of the task
+        // instances
+        appData.setLastTrie(new TaskInstanceTrie(identityTaskHandlingStrategy));
+    
+        appData.getLastTrie().trainSessions
+            (appData.getSessions(), appData.getTrainedSequenceLength());
+        
+        appData.getStopWatch().stop("training trie");
+    }
+
+    /**
+     * @param appData the rule application data combining all data used for applying this rule
+     */
+    private void replaceSequencesOccurringMostOften(RuleApplicationData appData) {
+        appData.detectedAndReplacedTasks(false);
+
+        if ((appData.getLastFoundTasks().size() > 0) &&
+            (appData.getLastFoundTasks().getOccurrenceCount() > 1))
+        {
+            Console.traceln(Level.FINER, "replacing tasks occurrences");
+
+            for (List<ITaskInstance> task : appData.getLastFoundTasks()) {
+                ISequence sequence = taskFactory.createNewSequence();
+                
+                Console.traceln(Level.FINEST, "replacing " + sequence.getId() + ": " + task);
+
+                List<ISequenceInstance> sequenceInstances =
+                    replaceTaskOccurrences(task, appData.getSessions(), sequence);
+                
+                harmonizeSequenceInstancesModel(sequence, sequenceInstances,task.size());
+                appData.detectedAndReplacedTasks
+                    (appData.detectedAndReplacedTasks() || (sequenceInstances.size() > 0));
+
+                if (sequenceInstances.size() < appData.getLastFoundTasks().getOccurrenceCount()) {
+                    Console.traceln(Level.FINE, sequence.getId() + ": replaced task only " +
+                                    sequenceInstances.size() + " times instead of expected " +
+                                    appData.getLastFoundTasks().getOccurrenceCount());
+                }
+            }
+        }
+        
+    }
+
+    /**
+     *
+     */
+    private void harmonizeSequenceInstancesModel(ISequence               sequence,
+                                                 List<ISequenceInstance> sequenceInstances,
+                                                 int                     sequenceLength)
+    {
+        TaskInstanceComparator comparator = preparationTaskHandlingStrategy.getTaskComparator();
+        
+        // ensure for each subtask that lexically different variants are preserved
+        for (int subTaskIndex = 0; subTaskIndex < sequenceLength; subTaskIndex++) {
+            List<ITask> subTaskVariants = new LinkedList<ITask>();
+            
+            for (ISequenceInstance sequenceInstance : sequenceInstances) {
+                ITask candidate = sequenceInstance.get(subTaskIndex).getTask();
+                
+                boolean found = false;
+                
+                for (int i = 0; i < subTaskVariants.size(); i++) {
+                    if (comparator.areLexicallyEqual(subTaskVariants.get(i), candidate)) {
+                        taskBuilder.setTask
+                            (sequenceInstance.get(subTaskIndex), subTaskVariants.get(i));
+                        
+                        found = true;
+                        break;
+                    }
+                }
+                
+                if (!found) {
+                    subTaskVariants.add(candidate);
+                }
+            }
+            
+            // if there are more than one lexically different variant of the sub task at
+            // the considered position, adapt the sequence model at that position to have
+            // a selection of the different variants. In this case also adapt the
+            // generated sequence instances to correctly contain selection instances. If
+            // there is only one variant of sub tasks at the given position, simply set
+            // this variant as the sub task of the selection. In this case, the instances
+            // can be preserved as is
+            if (subTaskVariants.size() > 1) {
+                ISelection selection = taskFactory.createNewSelection();
+                
+                for (ITask variant : subTaskVariants) {
+                    taskBuilder.addChild(selection, variant);
+                }
+                
+                taskBuilder.addChild(sequence, selection);
+                
+                for (ISequenceInstance instance : sequenceInstances) {
+                    ISelectionInstance selectionInstance =
+                        taskFactory.createNewTaskInstance(selection);
+                    taskBuilder.setChild(selectionInstance, instance.get(subTaskIndex));
+                    taskBuilder.setTaskInstance(instance, subTaskIndex, selectionInstance);
+                }
+            }
+            else if (subTaskVariants.size() == 1) {
+                taskBuilder.addChild(sequence, subTaskVariants.get(0));
+            }
+        }
+    }
+
+    /**
+     * @param tree
+     */
+    private List<ISequenceInstance> replaceTaskOccurrences(List<ITaskInstance> task,
+                                                           List<IUserSession>  sessions,
+                                                           ISequence           temporalTaskModel)
+    {
+        List<ISequenceInstance> sequenceInstances = new LinkedList<ISequenceInstance>();
+        
+        for (IUserSession session : sessions) {
+            int index = -1;
+                
+            do {
+                index = getSubListIndex(session, task, ++index);
+
+                if (index > -1) {
+                    sequenceInstances.add
+                        (RuleUtils.createNewSubSequenceInRange
+                             (session, index, index + task.size() - 1, temporalTaskModel,
+                              taskFactory, taskBuilder));
+                }
+            }
+            while (index > -1);
+        }
+        
+        return sequenceInstances;
+    }
+
+    /**
+     * @param trie
+     * @param object
+     * @return
+     */
+    private int getSubListIndex(ITaskInstanceList   list,
+                                List<ITaskInstance> subList,
+                                int                 startIndex)
+    {
+        boolean matchFound;
+        int result = -1;
+        
+        for (int i = startIndex; i <= list.size() - subList.size(); i++) {
+            matchFound = true;
+            
+            for (int j = 0; j < subList.size(); j++) {
+                // we prepared the task instances to refer to unique tasks, if they are treated
+                // as equal. Therefore, we just compare the identity of the tasks of the task
+                // instances
+                if (list.get(i + j).getTask() != subList.get(j).getTask()) {
+                    matchFound = false;
+                    break;
+                }
+            }
+            
+            if (matchFound) {
+                result = i;
+                break;
+            }
+        }
+        
+        return result;
+    }
+
+    /**
+     * @param trie
+     * @param object
+     * @return
+     */
+    private int getSubListIndex(List<ITaskInstance> list,
+                                List<ITaskInstance> subList,
+                                int                 startIndex)
+    {
+        boolean matchFound;
+        int result = -1;
+        
+        for (int i = startIndex; i <= list.size() - subList.size(); i++) {
+            matchFound = true;
+            
+            for (int j = 0; j < subList.size(); j++) {
+                // we prepared the task instances to refer to unique tasks, if they are treated
+                // as equal. Therefore, we just compare the identity of the tasks of the task
+                // instances
+                if (list.get(i + j) != subList.get(j)) {
+                    matchFound = false;
+                    break;
+                }
+            }
+            
+            if (matchFound) {
+                result = i;
+                break;
+            }
+        }
+        
+        return result;
+    }
+    
+    /**
+     * @author Patrick Harms
+     */
+    private class MaxCountAndLongestTasksFinder implements TrieProcessor<ITaskInstance> {
+        
+        /**
+         * 
+         */
+        private int currentCount;
+        
+        /**
+         * 
+         */
+        private List<List<ITaskInstance>> foundTasks = new LinkedList<List<ITaskInstance>>();
+
+        /**
+         *
+         */
+        public MaxCountAndLongestTasksFinder() {
+            super();
+            this.currentCount = 0;
+        }
+
+        /* (non-Javadoc)
+         * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int)
+         */
+        @Override
+        public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) {
+            if (foundTask.size() < 2) {
+                // ignore single tasks
+                return TrieProcessor.Result.CONTINUE;
+            }
+            
+            if (count < 2) {
+                // ignore singular occurrences
+                return TrieProcessor.Result.SKIP_NODE;
+            }
+
+            if (this.currentCount > count) {
+                // ignore this children of this task, as they may have only smaller counts than
+                // the already found tasks
+                return TrieProcessor.Result.SKIP_NODE;
+            }
+            
+            if (this.currentCount < count) {
+                // the provided task occurs more often that all tasks found so far.
+                // clear all found tasks and use the new count as the one searched for
+                foundTasks.clear();
+                this.currentCount = count;
+            }
+            
+            if (this.currentCount == count) {
+                // the task is of interest. Sort it into the other found tasks so that
+                // the longest come first
+                boolean added = false;
+                for (int i = 0; i < foundTasks.size(); i++) {
+                    if (foundTasks.get(i).size() < foundTask.size()) {
+                        // defensive copy
+                        foundTasks.add(i, new LinkedList<ITaskInstance>(foundTask)); // defensive copy
+                        added = true;
+                        break;
+                    }
+                }
+                
+                if (!added) {
+                    foundTasks.add(new LinkedList<ITaskInstance>(foundTask)); // defensive copy
+                }
+            }
+            
+            return TrieProcessor.Result.CONTINUE;
+        }
+
+        /**
+         *  @return
+         */
+        public Tasks getFoundTasks() {
+            removePermutationsOfShorterTasks();
+            return new Tasks(currentCount, foundTasks);
+        }
+
+        /**
+         *
+         */
+        private void removePermutationsOfShorterTasks() {
+            // now iterate the sorted list and for each task remove all other tasks that are shorter
+            // (i.e. come later in the sorted list) and that represent a subpart of the task
+            for (int i = 0; i < foundTasks.size(); i++) {
+                for (int j = i + 1; j < foundTasks.size();) {
+                    if (foundTasks.get(j).size() < foundTasks.get(i).size()) {
+                        // found a task that is a potential subtask. Check for this and remove the
+                        // subtask if needed
+                        List<ITaskInstance> longTask = foundTasks.get(i);
+                        List<ITaskInstance> shortTask = foundTasks.get(j);
+                        
+                        if (getSubListIndex(longTask, shortTask, 0) > -1) {
+                            foundTasks.remove(j);
+                        }
+                        else {
+                            j++;
+                        }
+                    }
+                    else {
+                        j++;
+                    }
+                }
+            }
+        }
+
+    }
+    
+//    /**
+//     * @author Patrick Harms
+//     */
+//    private class TrieStatisticsDumper implements TrieProcessor<ITaskInstance> {
+//        
+//        /**
+//         * 
+//         */
+//        private Map<Integer, Integer> counters = new HashMap<Integer, Integer>();
+//        
+//        /* (non-Javadoc)
+//         * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int)
+//         */
+//        @Override
+//        public TrieProcessor.Result process(List<ITaskInstance> subsequence, int count) {
+//            if (subsequence.size() == 1) {
+//                Integer value = counters.get(count);
+//                
+//                if (value == null) {
+//                    value = 0;
+//                }
+//                
+//                counters.put(count, value + 1);
+//                
+//                return TrieProcessor.Result.CONTINUE;
+//            }
+//            else {
+//                // ignore singular occurrences
+//                return TrieProcessor.Result.SKIP_NODE;
+//            }
+//        }
+//
+//        /**
+//         *  @return
+//         */
+//        public void dumpCounters() {
+//            int dumpedCounters = 0;
+//            
+//            int count = 1;
+//            while (dumpedCounters < counters.size()) {
+//                Integer value = counters.get(count++);
+//                if (value != null) {
+//                    System.out.println(value + " symbols occurred " + count + " times");
+//                    dumpedCounters++;
+//                }
+//            }
+//        }
+//
+//    }
+    
+    /**
+     * 
+     */
+    private static class RuleApplicationData {
+        
+        /**
+         * 
+         */
+        private List<IUserSession> sessions;
+        
+        /**
+         * 
+         */
+        private TaskInstanceTrie lastTrie;
+        
+        /**
+         * default and minimum trained sequence length is 3
+         */
+        private int trainedSequenceLength = 3;
+        
+        /**
+         * 
+         */
+        private Tasks lastFoundTasks = new Tasks(Integer.MAX_VALUE, null);
+        
+        /**
+         * 
+         */
+        private boolean detectedAndReplacedTasks;
+        
+        /**
+         * 
+         */
+        private RuleApplicationResult result = new RuleApplicationResult();
+        
+        /**
+         * 
+         */
+        private StopWatch stopWatch = new StopWatch();
+        
+        /**
+         * 
+         */
+        private RuleApplicationData(List<IUserSession> sessions) {
+            this.sessions = sessions;
+        }
+
+        /**
+         * @return the tree
+         */
+        private List<IUserSession> getSessions() {
+            return sessions;
+        }
+
+        /**
+         * @param lastTrie the lastTrie to set
+         */
+        private void setLastTrie(TaskInstanceTrie lastTrie) {
+            this.lastTrie = lastTrie;
+        }
+
+        /**
+         * @return the lastTrie
+         */
+        private TaskInstanceTrie getLastTrie() {
+            return lastTrie;
+        }
+
+        /**
+         * @param trainedSequenceLength the trainedSequenceLength to set
+         */
+        private void setTrainedSequenceLength(int trainedSequenceLength) {
+            this.trainedSequenceLength = trainedSequenceLength;
+        }
+
+        /**
+         * @return the trainedSequenceLength
+         */
+        private int getTrainedSequenceLength() {
+            return trainedSequenceLength;
+        }
+
+        /**
+         * @param lastFoundSequences the lastFoundSequences to set
+         */
+        private void setLastFoundTasks(Tasks lastFoundSequences) {
+            this.lastFoundTasks = lastFoundSequences;
+        }
+
+        /**
+         * @return the lastFoundSequences
+         */
+        private Tasks getLastFoundTasks() {
+            return lastFoundTasks;
+        }
+
+        /**
+         *
+         */
+        private void detectedAndReplacedTasks(boolean detectedAndReplacedTasks) {
+            this.detectedAndReplacedTasks = detectedAndReplacedTasks;
+        }
+
+        /**
+         *
+         */
+        private boolean detectedAndReplacedTasks() {
+            return detectedAndReplacedTasks;
+        }
+        
+        /**
+         * @return the result
+         */
+        private RuleApplicationResult getResult() {
+            return result;
+        }
+
+        /**
+         * @return the stopWatch
+         */
+        private StopWatch getStopWatch() {
+            return stopWatch;
+        }
+
+    }
+    
+
+    /**
+     * @author Patrick Harms
+     */
+    private static class Tasks implements Iterable<List<ITaskInstance>> {
+        
+        /**
+         * 
+         */
+        private int occurrenceCount;
+        
+        /**
+         * 
+         */
+        private List<List<ITaskInstance>> sequences;
+
+        /**
+         * @param occurrenceCount
+         * @param sequences
+         */
+        private Tasks(int occurrenceCount, List<List<ITaskInstance>> sequences) {
+            super();
+            this.occurrenceCount = occurrenceCount;
+            this.sequences = sequences;
+        }
+
+        /**
+         * @return
+         */
+        private int getOccurrenceCount() {
+            return occurrenceCount;
+        }
+
+        /**
+         * @return
+         */
+        private int size() {
+            return this.sequences.size();
+        }
+
+        /**
+         * 
+         */
+
+        /* (non-Javadoc)
+         * @see java.lang.Iterable#iterator()
+         */
+        @Override
+        public Iterator<List<ITaskInstance>> iterator() {
+            return this.sequences.iterator();
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#toString()
+         */
+        @Override
+        public String toString() {
+            StringBuffer result = new StringBuffer();
+            result.append(this.occurrenceCount);
+            result.append(" occurrences:\n");
+            
+            for (List<ITaskInstance> task : sequences) {
+                result.append(task);
+                result.append("\n");
+            }
+            
+            return result.toString();
+        }
+
+    }
+    
+    // methods for internal testing
+//    private void checkMatchingOfSessions(List<List<Event>>  flattenedSessions,
+//                                         List<IUserSession> sessions,
+//                                         String             when)
+//    {
+//        List<List<Event>> currentFlattenedSessions = flattenSessions(sessions);
+//        if (flattenedSessions.size() != currentFlattenedSessions.size()) {
+//            System.out.println("################## number of sessions changed after " + when);
+//        }
+//        else {
+//            for (int i = 0; i < flattenedSessions.size(); i++) {
+//                List<Event> expected = flattenedSessions.get(i);
+//                List<Event> current = currentFlattenedSessions.get(i);
+//            
+//                if (expected.size() != current.size()) {
+//                    System.out.println
+//                        ("################## length of session " + i + " changed after " + when);
+//                }
+//                else {
+//                    for (int j = 0; j < expected.size(); j++) {
+//                        if (!expected.get(j).equals(current.get(j))) {
+//                            System.out.println("################## event " + j + " of session " +
+//                                               i + " changed after " + when);
+//                        }
+//                    }
+//                }
+//            }     
+//        }
+//    }
+//
+//    private List<List<Event>> flattenSessions(List<IUserSession> sessions) {
+//        List<List<Event>> flattenedSessions = new ArrayList<List<Event>>();
+//        for (IUserSession session : sessions) {
+//            List<Event> flattenedUserSession = new ArrayList<Event>();
+//            flatten(session, flattenedUserSession);
+//            flattenedSessions.add(flattenedUserSession);
+//        }
+//
+//        return flattenedSessions;
+//    }
+//
+//    private void flatten(IUserSession iUserSession, List<Event> flattenedUserSession) {
+//        for (ITaskInstance instance : iUserSession) {
+//            flatten(instance, flattenedUserSession);
+//        }
+//    }
+//
+//    private void flatten(ITaskInstance instance, List<Event> flattenedUserSession) {
+//        if (instance instanceof ITaskInstanceList) {
+//            for (ITaskInstance child : (ITaskInstanceList) instance) {
+//                flatten(child, flattenedUserSession);
+//            }
+//        }
+//        else if (instance instanceof ISelectionInstance) {
+//            flatten(((ISelectionInstance) instance).getChild(), flattenedUserSession);
+//        }
+//        else if (instance instanceof IOptionalInstance) {
+//            flatten(((IOptionalInstance) instance).getChild(), flattenedUserSession);
+//        }
+//        else if (instance instanceof IEventTaskInstance) {
+//            flattenedUserSession.add(((IEventTaskInstance) instance).getEvent());
+//        }
+//    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskHandlingStrategy.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskHandlingStrategy.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskHandlingStrategy.java	(revision 1551)
@@ -0,0 +1,115 @@
+//   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;
+
+import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.usageprofiles.SymbolComparator;
+import de.ugoe.cs.autoquest.usageprofiles.SymbolMap;
+import de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy;
+
+/**
+ * <p>
+ * concrete implementation of a symbol strategy required in the creation of a
+ * {@link de.ugoe.cs.autoquest.usageprofiles.Trie}. The strategy can be parameterized with a
+ * considered task equality. It uses task instance comparators to perform task comparison.
+ * It creates task specific symbol maps, which are {@link TaskSymbolIdentityMap} and
+ * {@link TaskSymbolBucketedMap} depending on the level of considered task equality.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class TaskHandlingStrategy implements SymbolStrategy<ITaskInstance> {
+    
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * the level of task equality considered in this task handling strategy
+     * </p>
+     */
+    private TaskEquality consideredEquality;
+
+    /**
+     * <p>
+     * the comparator used for task comparisons
+     * </p>
+     */
+    private TaskInstanceComparator comparator;
+
+    /**
+     * <p>
+     * initializes this strategy with a task equality to be considered for task comparisons
+     * g</p>
+     *
+     * @param consideredEquality the task equality to be considered for task comparisons
+     */
+    public TaskHandlingStrategy(TaskEquality consideredEquality) {
+        this.consideredEquality = consideredEquality;
+        
+        if (this.consideredEquality == TaskEquality.IDENTICAL) {
+            comparator = new TaskIdentityComparator();
+        }
+        else {
+            comparator = new TaskInstanceComparator(this.consideredEquality);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy#getSymbolComparator()
+     */
+    @Override
+    public SymbolComparator<ITaskInstance> getSymbolComparator() {
+        return comparator;
+    }
+
+    /**
+     * <p>
+     * convenience method to have a correctly typed return value as alternative to
+     * {@link #getSymbolComparator()};
+     * </p>
+     */
+    public TaskInstanceComparator getTaskComparator() {
+        return comparator;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy#createSymbolMap()
+     */
+    @Override
+    public <V> SymbolMap<ITaskInstance, V> createSymbolMap() {
+        if (consideredEquality == TaskEquality.IDENTICAL) {
+            return new TaskSymbolIdentityMap<V>();
+        }
+        else {
+            return new TaskSymbolBucketedMap<V>(comparator);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolStrategy#copySymbolMap(SymbolMap)
+     */
+    @Override
+    public <V> SymbolMap<ITaskInstance, V> copySymbolMap(SymbolMap<ITaskInstance, V> other) {
+        if (consideredEquality == TaskEquality.IDENTICAL) {
+            return new TaskSymbolIdentityMap<V>(other);
+        }
+        else {
+            return new TaskSymbolBucketedMap<V>(comparator);
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskIdentityComparator.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskIdentityComparator.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskIdentityComparator.java	(revision 1551)
@@ -0,0 +1,48 @@
+//   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;
+
+import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * symbol comparator implementation for task instances considering to task instances as equal if
+ * they refer to the identical task object (comparison of object references).
+ * </p>
+ */
+class TaskIdentityComparator extends TaskInstanceComparator {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * <p>
+     * initializes the parent class with the task equality {@link TaskEquality#IDENTICAL}.
+     * </p>
+     */
+    public TaskIdentityComparator() {
+        super(TaskEquality.IDENTICAL);
+    }
+    
+    /* (non-Javadoc)
+     * @see SymbolComparator#equals(Object, Object)
+     */
+    @Override
+    public boolean equals(ITaskInstance taskInstance1, ITaskInstance taskInstance2) {
+        return taskInstance1.getTask() == taskInstance2.getTask();
+    }        
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskInstanceComparator.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskInstanceComparator.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskInstanceComparator.java	(revision 1551)
@@ -0,0 +1,313 @@
+//   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;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.HashMap;
+
+import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
+import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEqualityRuleManager;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.usageprofiles.SymbolComparator;
+
+/**
+ * <p>
+ * implementation of a symbol comparator for task instances. Internally, it uses comparison buffers
+ * to prevent comparing two tasks or task instances several times. It internally instantiates
+ * comparers being the implementation strategy of the comparisons required for a specific level
+ * of task equality. The comparers internally use the {@link TaskEqualityRuleManager} for
+ * performing comparisons.
+ * </p>
+ */
+public class TaskInstanceComparator implements SymbolComparator<ITaskInstance> {
+    
+    /**  */
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * the maximum size of the internal buffer used for storing comparison results
+     */
+    private static final int MAX_BUFFER_SIZE = 2 * 1024 * 1024;
+
+    /**
+     * the considered level of task equality
+     */
+    private TaskEquality minimalTaskEquality;
+
+    /**
+     * the comparer used internally for comparing two tasks
+     */
+    private transient Comparer comparer;
+
+    /**
+     * the comparer used for comparing two tasks on the lexical level
+     */
+    private transient Comparer lexicalComparer;
+
+    /**
+     * internal buffer used for storing comparison results
+     */
+    private transient HashMap<Long, Boolean> equalityBuffer = new HashMap<Long, Boolean>();
+
+    /**
+     * internal buffer used for storing comparison results only for lexical comparisons
+     */
+    private transient HashMap<Long, Boolean> lexicalEqualityBuffer;
+
+    /**
+     * <p>
+     * initializes the comparator with a considered task equality level
+     * </p>
+     * 
+     * @param minimalTaskEquality the considered task equality level
+     */
+    public TaskInstanceComparator(TaskEquality minimalTaskEquality) {
+        this.minimalTaskEquality = minimalTaskEquality;
+        init();
+    }
+
+    /* (non-Javadoc)
+     * @see SymbolComparator#equals(Object, Object)
+     */
+    @Override
+    public boolean equals(ITaskInstance taskInstance1, ITaskInstance taskInstance2) {
+        return equals(taskInstance1.getTask(), taskInstance2.getTask());
+    }        
+
+    /**
+     * <p>
+     * returns true, if this comparator considers the provided tasks as equal, false else
+     * </p>
+     * 
+     * @param task1 the first task to compare
+     * @param task2 the second task to compare
+     * 
+     * @return as described
+     */
+    public boolean equals(ITask task1, ITask task2) {
+        Boolean result;
+        
+        if (task1 != task2) {
+            //if ((task1 instanceof IEventTask) && (task2 instanceof IEventTask)) {
+                long key = ((long) System.identityHashCode(task1)) << 32;
+                key += System.identityHashCode(task2);
+            
+                result = equalityBuffer.get(key);
+            
+                if (result == null) {
+                    result = comparer.compare(task1, task2);
+                    
+                    if (equalityBuffer.size() < MAX_BUFFER_SIZE) {
+                        equalityBuffer.put(key, result);
+                    }
+                }
+            /*}
+            else {
+                result = false;
+            }*/
+        }
+        else {
+            result = true;
+        }
+        
+        return result;
+    }
+
+    /**
+     * <p>
+     * returns true, if this comparator considers the provided tasks as lexically equal, false else
+     * </p>
+     * 
+     * @param task1 the first task to compare
+     * @param task2 the second task to compare
+     * 
+     * @return as described
+     */
+    public boolean areLexicallyEqual(ITask task1, ITask task2) {
+        Boolean result;
+        
+        if (task1 != task2) {
+            long key = ((long) System.identityHashCode(task1)) << 32;
+            key += System.identityHashCode(task2);
+            
+            result = lexicalEqualityBuffer.get(key);
+            
+            if (result == null) {
+                result = lexicalComparer.compare(task1, task2);
+                if (equalityBuffer.size() < MAX_BUFFER_SIZE) {
+                    lexicalEqualityBuffer.put(key, result);
+                }
+            }
+        }
+        else {
+            result = true;
+        }
+        
+        return result;
+    }
+    
+    /**
+     * <p>
+     * can be called externally to clear the internal comparison buffers
+     * </p>
+     */
+    public void clearBuffers() {
+        equalityBuffer.clear();
+        init();
+    }
+    
+    /**
+     * <p>
+     * initializes the comparator with comparers depending on the different comparison levels as
+     * well as with the required comparison buffers. Comparers and buffers for lexical comparison
+     * may be reused if the considered equality level is also lexical.
+     * </p>
+     */
+    private void init() {
+        if (minimalTaskEquality == TaskEquality.LEXICALLY_EQUAL) {
+            comparer = new LexicalComparer();
+        }
+        else if (minimalTaskEquality == TaskEquality.SYNTACTICALLY_EQUAL) {
+            comparer = new SyntacticalComparer();
+        }
+        else if (minimalTaskEquality == TaskEquality.SEMANTICALLY_EQUAL) {
+            comparer = new SemanticalComparer();
+        }
+        else {
+            comparer = new DefaultComparer(this.minimalTaskEquality);
+        }
+        
+        if (minimalTaskEquality == TaskEquality.LEXICALLY_EQUAL) {
+            lexicalComparer = comparer;
+            lexicalEqualityBuffer = equalityBuffer;
+        }
+        else {
+            lexicalComparer = new LexicalComparer();
+            lexicalEqualityBuffer = new HashMap<Long, Boolean>();
+        }
+    }
+    
+    /**
+     * <p>
+     * deserialize this object and reinitialize the buffers
+     * </p>
+     */
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        init();
+    }
+
+
+    /**
+     * <p>
+     * interface for internally used comparers containing only a compare method
+     * </p>
+     */
+    private static interface Comparer {
+        
+        /**
+         * <p>
+         * returns true, if this comparator considers the provided tasks as equal, false else
+         * </p>
+         * 
+         * @param task1 the first task to compare
+         * @param task2 the second task to compare
+         * 
+         * @return as described
+         */
+        boolean compare(ITask task1, ITask task2);
+    }
+
+    /**
+     * <p>
+     * comparer that performs comparisons only on the lexical level
+     * </p>
+     */
+    private static class LexicalComparer implements Comparer {
+        
+        /* (non-Javadoc)
+         * @see Comparer#compare(ITask, ITask)
+         */
+        public boolean compare(ITask task1, ITask task2) {
+            return TaskEqualityRuleManager.getInstance().areLexicallyEqual(task1, task2);
+        }
+    }
+
+    /**
+     * <p>
+     * comparer that performs comparisons only on the syntactical level
+     * </p>
+     * 
+     */
+    private static class SyntacticalComparer implements Comparer {
+        
+        /* (non-Javadoc)
+         * @see Comparer#compare(ITask, ITask)
+         */
+        public boolean compare(ITask task1, ITask task2) {
+            return TaskEqualityRuleManager.getInstance().areSyntacticallyEqual(task1, task2);
+        }
+    }
+
+    /**
+     * <p>
+     * comparer that performs comparisons only on the semantical level
+     * </p>
+     */
+    private static class SemanticalComparer implements Comparer {
+        
+        /* (non-Javadoc)
+         * @see Comparer#compare(ITask, ITask)
+         */
+        public boolean compare(ITask task1, ITask task2) {
+            return TaskEqualityRuleManager.getInstance().areSemanticallyEqual(task1, task2);
+        }
+    }
+
+    /**
+     * <p>
+     * comparer that performs comparisons only on the provided level
+     * </p>
+     */
+    private static class DefaultComparer implements Comparer {
+        
+        /**
+         * <p>
+         * the minimal task equality considered by this comparer
+         * </p>
+         */
+        private TaskEquality minimalTaskEquality;
+        
+        /**
+         * <p>
+         * initializes this comparer with the task equality to be considered
+         * </p>
+         */
+        public DefaultComparer(TaskEquality minimalTaskEquality) {
+           this.minimalTaskEquality = minimalTaskEquality;
+        }
+        
+        /* (non-Javadoc)
+         * @see Comparer#compare(ITask, ITask)
+         */
+        public boolean compare(ITask task1, ITask task2) {
+            return TaskEqualityRuleManager.getInstance().areAtLeastEqual
+                (task1, task2, minimalTaskEquality);
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskInstanceTrie.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskInstanceTrie.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskInstanceTrie.java	(revision 1551)
@@ -0,0 +1,260 @@
+//   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;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+import de.ugoe.cs.autoquest.usageprofiles.SymbolMap;
+import de.ugoe.cs.autoquest.usageprofiles.Trie;
+import de.ugoe.cs.autoquest.usageprofiles.TrieProcessor;
+
+/**
+ * <p>
+ * This trie implementation is a performance optimization for generating task trees. It does not
+ * create a full trie but adds only those subsequences having a chance of occurring most often.
+ * For this, it initially counts the number of occurrences of each task instance. Then, during
+ * training, it regularly determines the number of the currently most often occurring sequence. If
+ * this number is higher than the count of a task instance to be trained, the task instance is
+ * skipped the not added to the trie.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class TaskInstanceTrie extends Trie<ITaskInstance> {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * the task handling strategy to be used for comparing tasks
+     * </p>
+     */
+    private TaskHandlingStrategy taskStrategy;
+    
+    /**
+     * <p>
+     * instantiated the trie with the task handling strategy to be used
+     * </p>
+     *
+     * @param taskStrategy the task handling strategy to be used for comparing tasks
+     */
+    public TaskInstanceTrie(TaskHandlingStrategy taskStrategy) {
+        super(taskStrategy);
+        this.taskStrategy = taskStrategy;
+    }
+
+    /**
+     * <p>
+     * trains this trie with the provided user sessions up to the provided maximum depth using
+     * the optimization described in the description of this class.
+     * </p>
+     * 
+     * @param userSessions the sessions for which this trie is to be trained
+     * @param maxOrder     the depth of the trie
+     */
+    public void trainSessions(List<IUserSession> userSessions, int maxOrder) {
+        if (maxOrder < 1) {
+            return;
+        }
+        
+        SymbolMap<ITaskInstance, Counter> equalTaskInstancesMap =
+            taskStrategy.createSymbolMap();
+        
+        Map<ITask, Counter> instanceCountMap = new HashMap<ITask, Counter>();
+        
+        System.out.println("preparing training");
+        int noOfTaskInstances = 0;
+        for (IUserSession session : userSessions) {
+            for (ITaskInstance taskInstance : session) {
+                Counter counter = equalTaskInstancesMap.getValue(taskInstance);
+                
+                if (counter == null) {
+                    counter = new Counter();
+                    equalTaskInstancesMap.addSymbol(taskInstance, counter);
+                }
+                
+                counter.count++;
+                instanceCountMap.put(taskInstance.getTask(), counter);
+                
+                noOfTaskInstances++;
+            }
+        }
+        
+        System.out.println("performing training of " + noOfTaskInstances + " task instances");
+        Counter processedTaskInstances = new Counter();
+        int counterRecheckAt = noOfTaskInstances / 10; // recheck the maximum count after each
+                                                       // 10% of processed task instances
+        for (IUserSession session : userSessions) {
+            train(session, maxOrder, instanceCountMap, processedTaskInstances, counterRecheckAt);
+        }      
+        
+        updateKnownSymbols();
+    }
+    
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.Trie#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+        else if (other instanceof TaskInstanceTrie) {
+            return super.equals(other);
+        }
+        else {
+            return false;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.Trie#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    /**
+     * <p>
+     * internally used convenience method for implementing the training optimization
+     * </p>
+     */
+    private void train(IUserSession        userSession,
+                       int                 maxOrder,
+                       Map<ITask, Counter> taskInstanceCountMap,
+                       Counter             processedTaskInstances,
+                       int                 counterRecheckAt)
+    {
+        List<ITaskInstance> subsequence = new LinkedList<ITaskInstance>();
+        
+        int sequenceMaxCount = 0;
+        
+        for (ITaskInstance currentTaskInstance : userSession) {
+            
+            int occurrenceCount = taskInstanceCountMap.get(currentTaskInstance.getTask()).count;
+            
+            if (processedTaskInstances.count >= counterRecheckAt) {
+                sequenceMaxCount = getCurrentSequenceMaxCount();
+                processedTaskInstances.count = 0;
+            }
+            
+            if (occurrenceCount < sequenceMaxCount) {
+                // this task instance does not need to be considered, as it occurs not often enough
+                // to be part of a sequence, that occurs most often. Therefore train all remaining
+                // sequences so far and go on, until the next useful sequence is found.
+                
+                while (subsequence.size() > 1) {
+                    add(subsequence);
+                    subsequence.remove(0);
+                }
+                
+                subsequence.clear();
+            }
+            else {
+                subsequence.add(currentTaskInstance);
+
+                if (subsequence.size() == maxOrder) {
+                    add(subsequence);
+                    subsequence.remove(0);
+                }
+            }
+            
+            processedTaskInstances.count++;
+        }
+        
+        // add shorter remaining subsequences, if any
+        while (subsequence.size() > 1) {
+            add(subsequence);
+            subsequence.remove(0);
+        }
+    }
+
+    /**
+     * <p>
+     * determines the current maximum count of sequences of a minimal length of two. Task instances
+     * occuring more seldom do not have to be considered anymore
+     * </p>
+     *
+     * @return the current maximum count of sequences of a minimal length of two
+     */
+    private int getCurrentSequenceMaxCount() {
+        MaxSequenceCountFinder processor = new MaxSequenceCountFinder();
+        super.process(processor);
+        return processor.getMaxCount();
+    }
+
+    /**
+     * <p>
+     * trie processor identifying the current maximum count of sequences of a minimal length of two
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private static class MaxSequenceCountFinder implements TrieProcessor<ITaskInstance> {
+        
+        /**
+         * <p>
+         * the current maximum count
+         * </p>
+         */
+        private int currentCount = 0;
+        
+        /* (non-Javadoc)
+         * @see de.ugoe.cs.autoquest.usageprofiles.TrieProcessor#process(java.util.List, int)
+         */
+        @Override
+        public TrieProcessor.Result process(List<ITaskInstance> foundTask, int count) {
+            if (foundTask.size() == 2) {
+                this.currentCount = Math.max(this.currentCount, count);
+                
+                // do not consider children
+                return TrieProcessor.Result.SKIP_NODE;
+            }
+            else {
+                return TrieProcessor.Result.CONTINUE;
+            }
+        }
+
+        /**
+         * <p>
+         * returns the current maximum count
+         * </p>
+         */
+        private int getMaxCount() {
+            return currentCount;
+        }
+
+    }
+    
+    /**
+     * <p>
+     * counter object to be able to call something by the counters reference
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private static class Counter {
+        int count = 0;
+    }
+        
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskSymbolBucketedMap.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskSymbolBucketedMap.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskSymbolBucketedMap.java	(revision 1551)
@@ -0,0 +1,920 @@
+//   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;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import de.ugoe.cs.autoquest.eventcore.Event;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.usageprofiles.SymbolMap;
+
+/**
+ * <p>
+ * This class is a data structure for holding task instances in form of a symbol map. It is more
+ * efficient than a simple list. This data structure can be used with a comparator to adapt the
+ * effective list behavior and to define the equals strategy for comparing task instances. After a
+ * certain size ({@link #MAX_LIST_SIZE}), the map creates an index consisting of buckets of similar
+ * task instances. This allows searching for task instances in a more efficient order as the search
+ * can start in the most appropriate of the internal buckets.
+ * </p>
+ * <p>
+ * The class is called a map, although it is not. It may contain the same task instances as
+ * separate keys. This implementation is done for performance improvements. If it is required to
+ * really assure, that a key exists only once, then each call to the
+ * {@link #addSymbol(Object, Object)} method should be done only, if the
+ * {@link #containsSymbol(Object)} method for the same symbol returns false.
+ * </p>
+ * 
+ * @see SymbolComparator
+ * 
+ * @author Patrick Harms
+ * @param <V>
+ */
+class TaskSymbolBucketedMap<V> implements SymbolMap<ITaskInstance, V>, Serializable {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * the maximum number of task instances in this map which is still only treated as list
+     * instead of using buckets.
+     * </p>
+     */
+    private static final int MAX_LIST_SIZE = 15;
+    
+    /**
+     * <p>
+     * Comparator to be used for comparing the task instances with each other
+     * </p>
+     */
+    private TaskInstanceComparator comparator;
+
+    /**
+     * <p>
+     * Internally maintained plain list of task instances and associated values
+     * </p>
+     */
+    private List<Map.Entry<ITaskInstance, V>> symbolList;
+
+    /**
+     * <p>
+     * If the size of the map exceeds {@link #MAX_LIST_SIZE}, this is the index using buckets
+     * for optimizing the search order.
+     * </p>
+     */
+    private Map<Integer, List<Map.Entry<ITaskInstance, V>>> symbolBuckets;
+    
+    /**
+     * <p>
+     * When using buckets, not any task instance may be associated a correct bucket. Therefore, we
+     * set a default bucket for all such task instances. This may change if the same bucket for a
+     * specific symbol is selected.
+     * </p>
+     */
+    private int defaultBucket = 0;
+    
+    /**
+     * <p>
+     * Instantiates a task instance map with a comparator
+     * </p>
+     *
+     * @param comparator the comparator to use for comparing task instances
+     * 
+     * @throws IllegalArgumentException if the provided comparator is null
+     */
+    public TaskSymbolBucketedMap(TaskInstanceComparator comparator) {
+        if (comparator == null) {
+            throw new IllegalArgumentException("comparator must not be null");
+        }
+        
+        this.comparator = comparator;
+        this.symbolList = new ArrayList<Map.Entry<ITaskInstance, V>>();
+    }
+
+    /**
+     * <p>
+     * Copy constructor
+     * </p>
+     * 
+     * @param otherMap the other map to be copied including its comparator
+     * 
+     * @throws IllegalArgumentException if the provided other map is null
+     */
+    public TaskSymbolBucketedMap(TaskSymbolBucketedMap<V> otherMap) {
+        if (otherMap == null) {
+            throw new IllegalArgumentException("otherMap must not be null");
+        }
+
+        this.comparator = otherMap.comparator;
+        this.symbolList = new ArrayList<Map.Entry<ITaskInstance, V>>(otherMap.symbolList);
+        
+        if (this.symbolList.size() > MAX_LIST_SIZE) {
+            createSymbolBuckets();
+        }
+    }
+
+    /**
+     * <p>
+     * Returns the size of the map, i.e. the number of task instance entries
+     * </p>
+     * 
+     * @return as described
+     */
+    public int size() {
+        return symbolList.size();
+    }
+
+    /**
+     * <p>
+     * Returns true if this map is empty, i.e. if {@link #size()} returns 0
+     * </p>
+     * 
+     * @return as described
+     */
+    public boolean isEmpty() {
+        return symbolList.isEmpty();
+    }
+
+    /**
+     * <p>
+     * Returns true if the provided task instance was stored in this map.
+     * </p>
+     * 
+     * @param symbol the task instance to check if it was stored in this map
+     * 
+     * @return as described
+     * 
+     * @throws IllegalArgumentException if the provided task instance is null
+     */
+    public boolean containsSymbol(ITaskInstance symbol) {
+        if (symbol == null) {
+            throw new IllegalArgumentException("symbol must not be null");
+        }
+        
+        return getEntry(symbol) != null;
+    }
+
+    /**
+     * <p>
+     * Returns the value associated to the provided task instance in this map. If there is no value
+     * associated to the given task instance or if the task instance is not stored in this map,
+     * the method returns null.
+     * </p>
+     * 
+     * @param symbol the task instance to return the value for
+     * 
+     * @return as described
+     * 
+     * @throws IllegalArgumentException if the provided task instance is null
+     */
+    public V getValue(ITaskInstance symbol) {
+        if (symbol == null) {
+            throw new IllegalArgumentException("symbol must not be null");
+        }
+        
+        Map.Entry<ITaskInstance, V> entry = getEntry(symbol);
+        
+        if (entry != null) {
+            return entry.getValue();
+        }
+        else {
+            return null;
+        }
+    }
+
+    /**
+     * <p>
+     * Adds a task instance and an associated value to the map. If the value is null, the task
+     * instance is added, anyway and {@link #containsSymbol(Object)} will return true for that
+     * task instance. Adding the same task instance twice will produce two entries. This is
+     * contradictory to typical map implementations. To prevent this, the
+     * {@link #containsSymbol(Object)} and {@link #removeSymbol(Object)} methods should be used to
+     * ensure map behavior.
+     * </p>
+     * 
+     * @param symbol the task instance to add to the map
+     * @param value  the value to associate to the task instance in this map
+     * 
+     * @return as described
+     * 
+     * @throws IllegalArgumentException if the provided task instance is null
+     */
+    public void addSymbol(ITaskInstance symbol, V value) {
+        if (symbol == null) {
+            throw new IllegalArgumentException("symbol must not be null");
+        }
+        
+        Map.Entry<ITaskInstance, V> entry = new SymbolMapEntry(symbol, value);
+        
+        symbolList.add(entry);
+            
+        if (symbolList.size() > MAX_LIST_SIZE) {
+            if (symbolBuckets == null) {
+                createSymbolBuckets();
+            }
+            else {
+                addToSymbolBucket(entry);
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * Removes a task instance and its associated value from the map. If the task instance is
+     * stored several times, only the first of its occurrences is removed. 
+     * </p>
+     * 
+     * @param symbol the task instance to be removed from the map
+     * 
+     * @return as described
+     * 
+     * @throws IllegalArgumentException if the provided task instance is null
+     */
+    public V removeSymbol(ITaskInstance symbol) {
+        if (symbol == null) {
+            throw new IllegalArgumentException("symbol must not be null");
+        }
+        
+        for (int i = 0; i < symbolList.size(); i++) {
+            if (comparator.equals(symbolList.get(i).getKey(), symbol)) {
+                // found the symbol. Remove it from the list, and if required, also from the map.
+                V value = symbolList.remove(i).getValue();
+                
+                if (symbolList.size() > MAX_LIST_SIZE) {
+                    removeFromSymbolBuckets(symbol);
+                }
+                
+                return value;
+            }
+        }
+        
+        return null;
+    }
+
+    /**
+     * <p>
+     * Returns a collection of all task instances in this map.
+     * </p>
+     *
+     * @return as described
+     */
+    public Collection<ITaskInstance> getSymbols() {
+        return new ReadOnlyCollectionFacade<ITaskInstance>(symbolList, new SymbolFacade());
+    }
+    
+    /**
+     * <p>
+     * Returns a collection of all values associated to task instances in this map. May contain
+     * null values, if some of the task instances are mapped to null. The length of the returned
+     * collection is in any case the same as the size of the map.
+     * </p>
+     *
+     * @return as described
+     */
+    public Collection<V> getValues() {
+        return new ReadOnlyCollectionFacade<V>(symbolList, new ValueFacade());
+    }
+    
+    /**
+     * <p>
+     * Removes all task instances and associated values from the map.
+     * </p>
+     */
+    public void clear() {
+        symbolList.clear();
+        symbolBuckets = null;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return symbolList.size();
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        else if (this.getClass().isInstance(obj)) {
+            TaskSymbolBucketedMap<V> other = (TaskSymbolBucketedMap<V>) obj;
+            
+            return (symbolList.size() == other.symbolList.size()) &&
+                   (symbolList.containsAll(other.symbolList));
+        }
+        else {
+            return false;
+        }
+    }
+
+    /**
+     * <p>
+     * Internally used to create task instance buckets in case the number of stored task instances
+     * increased above {@link #MAX_LIST_SIZE}.
+     * </p>
+     */
+    private void createSymbolBuckets() {
+        //System.out.println("creating symbol buckets");
+        symbolBuckets = new HashMap<Integer, List<Map.Entry<ITaskInstance, V>>>();
+        
+        for (Map.Entry<ITaskInstance, V> symbol : symbolList) {
+            addToSymbolBucket(symbol);
+        }
+    }
+
+    /**
+     * <p>
+     * Adds a task instance and its value to its corresponding bucket. The corresponding bucket is
+     * the first element of the array returned by the method
+     * {@link #getBucketSearchOrder(ITaskInstance)}. If no search order for a task instance is
+     * defined, the entry is added to the default bucket. If the bucket id identical to the default
+     * bucket id, the default bucket id is shifted to another value.
+     * </p>
+     */
+    private void addToSymbolBucket(Map.Entry<ITaskInstance, V> symbolEntry) {
+        int bucketId = defaultBucket;
+        int[] bucketSearchOrder = getBucketSearchOrder(symbolEntry.getKey());
+        
+        if ((bucketSearchOrder != null) && (bucketSearchOrder.length > 0)) {
+            bucketId = bucketSearchOrder[0];
+            
+            if (bucketId == defaultBucket) {
+                setNewDefaultBucketId();
+            }
+        }
+        
+        List<Map.Entry<ITaskInstance, V>> list = symbolBuckets.get(bucketId);
+        
+        if (list == null) {
+            list = new LinkedList<Map.Entry<ITaskInstance, V>>();
+            symbolBuckets.put(bucketId, list);
+        }
+        
+        list.add(symbolEntry);
+    }
+    
+    /**
+     * <p>
+     * returns the search order for a task instance which is different for event task instances,
+     * sequence instances, selection instances, and iteration instances
+     * </p>
+     */
+    private int[] getBucketSearchOrder(ITaskInstance taskInstance) {
+        // 0 = sequence; 1 = selection; 2 = iteration; 3 = optional; 4 = event task in general;
+        // other = hashCode of name of event type
+        
+        if (taskInstance instanceof IEventTaskInstance) {
+            // event tasks are most likely equal to those of the same type happening on the same
+            // target. Afterwards, they should be equal to those of the event type with the same
+            // name. Afterwards, they may be equal to iterations, optionals, other event tasks,
+            // selections, and finally the rest.
+            Event event = ((IEventTaskInstance) taskInstance).getEvent();
+            return new int[] { event.getTarget().hashCode() + event.getType().getName().hashCode(),
+                               event.getType().getName().hashCode(), 2, 3, 4, 1 };                       
+        }
+        else if (taskInstance instanceof ISequenceInstance) {
+            return new int[] { 0, 2, 3, 1 };                       
+        }
+        else if (taskInstance instanceof ISelectionInstance) {
+            return new int[] { 1, 4, 2, 3 };                       
+        }
+        else if (taskInstance instanceof IIterationInstance) {
+            return new int[] { 2, 1, 4 };                       
+        }
+        
+        return null;
+    }
+
+    /**
+     * <p>
+     * Removes the entry for a given task instance from the buckets. It uses the bucket search order
+     * defined to find the task instance as fast as possible.
+     * </p>
+     */
+    private Map.Entry<ITaskInstance, V> removeFromSymbolBuckets(ITaskInstance symbol) {
+        int bucketId = defaultBucket;
+        int[] bucketSearchOrder = getBucketSearchOrder(symbol);
+        
+        if ((bucketSearchOrder != null) && (bucketSearchOrder.length > 0)) {
+            bucketId = bucketSearchOrder[0];
+        }
+        
+        List<Map.Entry<ITaskInstance, V>> list = symbolBuckets.get(bucketId);
+        Map.Entry<ITaskInstance, V> result = null;
+        
+        if (list != null) {
+            for (int i = 0; i < list.size(); i++) {
+                if (comparator.equals(list.get(i).getKey(), symbol)) {
+                    result = list.remove(i);
+                    break;
+                }
+            }
+            
+            if (list.isEmpty()) {
+                symbolBuckets.remove(bucketId);
+            }
+        }
+        
+        return result;
+    }
+
+    /**
+     * <p>
+     * Updates the default bucket id to a new one
+     * </p>
+     */
+    private void setNewDefaultBucketId() {
+        int oldDefaultBucket = defaultBucket;
+        do {
+            defaultBucket += 1;
+        }
+        while (symbolBuckets.containsKey(defaultBucket));
+        
+        symbolBuckets.put(defaultBucket, symbolBuckets.remove(oldDefaultBucket));
+    }
+
+    /**
+     * <p>
+     * searches for the entry belonging to the given task instance. The method either uses the
+     * list if buckets are not used yet, or it uses the buckets and searches them in the order
+     * defined by the method {@link #getBucketSearchOrder(ITaskInstance)}. If the task instances
+     * isn't found and the bucket search order does not refer all buckets, then also the other
+     * buckets are searched for the task instance.
+     * </p>
+     */
+    private Map.Entry<ITaskInstance, V> getEntry(ITaskInstance symbol) {
+        Map.Entry<ITaskInstance, V> entry = null;
+        if (symbolBuckets == null) {
+            entry = lookup(symbol, symbolList);
+        }
+        else {
+            int[] bucketSearchOrder = getBucketSearchOrder(symbol);
+            for (int bucketId : bucketSearchOrder) {
+                List<Map.Entry<ITaskInstance, V>> list = symbolBuckets.get(bucketId);
+                if (list != null) {
+                    entry = lookup(symbol, list);
+                    if (entry != null) {
+                        break;
+                    }
+                }
+            }
+            
+            // try to search the other buckets
+            if (entry == null) {
+                Arrays.sort(bucketSearchOrder);
+                for (Map.Entry<Integer, List<Map.Entry<ITaskInstance, V>>> bucket : symbolBuckets.entrySet()) {
+                    if (Arrays.binarySearch(bucketSearchOrder, bucket.getKey()) < 0) {
+                        List<Map.Entry<ITaskInstance, V>> list = bucket.getValue();
+                        if (list != null) {
+                            entry = lookup(symbol, list);
+                            if (entry != null) {
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        
+        return entry;
+    }
+
+    /**
+     * <p>
+     * Convenience method to look up a symbol in a list of entries using the comparator.
+     * </p>
+     */
+    private Map.Entry<ITaskInstance, V> lookup(ITaskInstance symbol, List<Map.Entry<ITaskInstance, V>> list) {
+        for (Map.Entry<ITaskInstance, V> candidate : list) {
+            if (comparator.equals(candidate.getKey(), symbol)) {
+                return candidate;
+            }
+        }
+        
+        return null;
+    }
+
+    /**
+     * <p>
+     * Internally used data structure for storing task instance - value pairs
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private class SymbolMapEntry implements Map.Entry<ITaskInstance, V> {
+        
+        /**
+         * the task instance to map to a value
+         */
+        private ITaskInstance symbol;
+        
+        /**
+         * the value associated with the symbol
+         */
+        private V value;
+
+        /**
+         * <p>
+         * Simple constructor for initializing the entry with a task instance and its associated
+         * value.
+         * </p>
+         */
+        private SymbolMapEntry(ITaskInstance symbol, V value) {
+            super();
+            this.symbol = symbol;
+            this.value = value;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Map.Entry#getKey()
+         */
+        @Override
+        public ITaskInstance getKey() {
+            return symbol;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Map.Entry#getValue()
+         */
+        @Override
+        public V getValue() {
+            return value;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Map.Entry#setValue(java.lang.Object)
+         */
+        @Override
+        public V setValue(V value) {
+            V oldValue = this.value;
+            this.value = value;
+            return oldValue;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            return symbol.hashCode();
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            else if (this.getClass().isInstance(obj)) {
+                SymbolMapEntry other = (SymbolMapEntry) obj;
+                return (symbol.equals(other.symbol) &&
+                        (value == null ? other.value == null : value.equals(other.value)));
+            }
+            else {
+                return false;
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#toString()
+         */
+        @Override
+        public String toString() {
+            return symbol + "=" + value;
+        }
+
+    }
+
+    /**
+     * <p>
+     * Used to create an efficient facade for accessing the internal list of entries either only
+     * for the task instances or only for the values. It is a default implementation of the
+     * collection interface. The entry facade provided to the constructor decides, if either the
+     * list accesses only the task instances or only the values. 
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private class ReadOnlyCollectionFacade<TYPE> implements Collection<TYPE> {
+        
+        /**
+         * the list facaded by this facade
+         */
+        private List<Map.Entry<ITaskInstance, V>> list;
+        
+        /**
+         * the facade to be used for the entries
+         */
+        private EntryFacade<TYPE> entryFacade;
+        
+        /**
+         * <p>
+         * Initializes the facade with the facaded list and the facade to be used for the entries
+         * </p>
+         */
+        private ReadOnlyCollectionFacade(List<Map.Entry<ITaskInstance, V>> list,
+                                         EntryFacade<TYPE>                 entryFacade)
+        {
+            this.list = list;
+            this.entryFacade = entryFacade;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#size()
+         */
+        @Override
+        public int size() {
+            return list.size();
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#isEmpty()
+         */
+        @Override
+        public boolean isEmpty() {
+            return list.isEmpty();
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#contains(java.lang.Object)
+         */
+        @Override
+        public boolean contains(Object o) {
+            if (o == null) {
+                for (Map.Entry<ITaskInstance, V> entry : list) {
+                    if (entryFacade.getFacadedElement(entry) == null) {
+                        return true;
+                    }
+                }
+            }
+            else {
+                for (Map.Entry<ITaskInstance, V> entry : list) {
+                    if (o.equals(entryFacade.getFacadedElement(entry))) {
+                        return true;
+                    }
+                }
+            }
+            
+            return false;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#toArray()
+         */
+        @Override
+        public Object[] toArray() {
+            Object[] result = new Object[list.size()];
+            
+            for (int i = 0; i < list.size(); i++) {
+                result[i] = entryFacade.getFacadedElement(list.get(i));
+            }
+            
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#toArray(T[])
+         */
+        @SuppressWarnings("unchecked")
+        @Override
+        public <T> T[] toArray(T[] a) {
+            T[] result = a;
+            
+            for (int i = 0; i < list.size(); i++) {
+                result[i] = (T) entryFacade.getFacadedElement(list.get(i));
+            }
+            
+            return result;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#add(java.lang.Object)
+         */
+        @Override
+        public boolean add(TYPE e) {
+            throw new UnsupportedOperationException("this collection is read only");
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#remove(java.lang.Object)
+         */
+        @Override
+        public boolean remove(Object o) {
+            throw new UnsupportedOperationException("this collection is read only");
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#containsAll(java.util.Collection)
+         */
+        @Override
+        public boolean containsAll(Collection<?> c) {
+            for (Object candidate : c) {
+                if (!contains(candidate)) {
+                    return false;
+                }
+            }
+            
+            return true;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#addAll(java.util.Collection)
+         */
+        @Override
+        public boolean addAll(Collection<? extends TYPE> c) {
+            throw new UnsupportedOperationException("this collection is read only");
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#removeAll(java.util.Collection)
+         */
+        @Override
+        public boolean removeAll(Collection<?> c) {
+            throw new UnsupportedOperationException("this collection is read only");
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#retainAll(java.util.Collection)
+         */
+        @Override
+        public boolean retainAll(Collection<?> c) {
+            throw new UnsupportedOperationException("this collection is read only");
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#clear()
+         */
+        @Override
+        public void clear() {
+            throw new UnsupportedOperationException("this collection is read only");
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Collection#iterator()
+         */
+        @Override
+        public Iterator<TYPE> iterator() {
+            return new ReadOnlyCollectionIteratorFacade<TYPE>(list.iterator(), entryFacade);
+        }
+        
+    }
+
+    /**
+     * <p>
+     * Implementation of an iterator to facade an iterator on the internal list of task instance
+     * entries.
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private class ReadOnlyCollectionIteratorFacade<TYPE> implements Iterator<TYPE> {
+        
+        /**
+         * the facaded iterator
+         */
+        private Iterator<Map.Entry<ITaskInstance, V>> iterator;
+        
+        /**
+         * the facade for the entries provided by the facaded iterator
+         */
+        private EntryFacade<TYPE> entryFacade;
+        
+        /**
+         * <p>
+         * initialized this facade with the facaded iterator and the entry facade to be used for
+         * the entries.
+         * </p>
+         */
+        private ReadOnlyCollectionIteratorFacade(Iterator<Map.Entry<ITaskInstance, V>> iterator,
+                                                 EntryFacade<TYPE>                     entryFacade)
+        {
+            this.iterator = iterator;
+            this.entryFacade = entryFacade;
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Iterator#hasNext()
+         */
+        @Override
+        public boolean hasNext() {
+            return iterator.hasNext();
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Iterator#next()
+         */
+        @Override
+        public TYPE next() {
+            return entryFacade.getFacadedElement(iterator.next());
+        }
+
+        /* (non-Javadoc)
+         * @see java.util.Iterator#remove()
+         */
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException("this iterator is read only");
+        }
+        
+    }
+        
+    /**
+     * <p>
+     * Used to facade task instance entries and to return only this part of an entry, that is
+     * relevant.
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private abstract class EntryFacade<T> {
+        
+        /**
+         * <p>
+         * Returns only the part of an entry that is relevant or required.
+         * </p>
+         *
+         * @param entry of which the part shall be returned
+         * 
+         * @return the part of the entry to be returned
+         */
+        protected abstract T getFacadedElement(Entry<ITaskInstance, V> entry);
+        
+    }
+    
+    /**
+     * <p>
+     * Implementation of the entry facade returning the entries key, i.e. the symbol.
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private class SymbolFacade extends EntryFacade<ITaskInstance> {
+
+        /* (non-Javadoc)
+         * @see ReadOnlyCollectionIteratorFacade#getFacadedElement(Entry)
+         */
+        @Override
+        protected ITaskInstance getFacadedElement(Entry<ITaskInstance, V> entry) {
+            return entry.getKey();
+        }
+    }
+    
+    /**
+     * <p>
+     * Implementation of the entry facade returning the entries value, i.e. the value associated to
+     * the symbol.
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private class ValueFacade extends EntryFacade<V> {
+
+        /* (non-Javadoc)
+         * @see ReadOnlyCollectionIteratorFacade#getFacadedElement(Entry)
+         */
+        @Override
+        protected V getFacadedElement(Entry<ITaskInstance, V> entry) {
+            return entry.getValue();
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskSymbolIdentityMap.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskSymbolIdentityMap.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskSymbolIdentityMap.java	(revision 1551)
@@ -0,0 +1,198 @@
+//   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;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.usageprofiles.SymbolMap;
+
+/**
+ * <p>
+ * symbol map implementation for task instances considering two task instances as equal if their
+ * tasks are identical
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class TaskSymbolIdentityMap<V> implements SymbolMap<ITaskInstance, V> {
+
+    /**  */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * internally used map for implementing the symbol map interface
+     * </p>
+     */
+    private Map<ITask, V> delegate;
+
+    /**
+     * <p>
+     * mapping between the tasks and the real symbols stored in the map, i.e. the task instances
+     * </p>
+     */
+    private Map<ITask, ITaskInstance> symbols;
+
+    /**
+     * <p>
+     * initializes this map
+     * </p>
+     */
+    public TaskSymbolIdentityMap() {
+        delegate = new HashMap<ITask, V>();
+        symbols = new HashMap<ITask, ITaskInstance>();
+    }
+
+    /**
+     * <p>
+     * copy constructor
+     * </p>
+     *
+     * @param other the map to be copied
+     */
+    public TaskSymbolIdentityMap(SymbolMap<ITaskInstance, V> other) {
+        if (other == null) {
+            throw new IllegalArgumentException("other map must not be null");
+        }
+        
+        delegate = new HashMap<ITask, V>();
+        symbols = new HashMap<ITask, ITaskInstance>();
+        
+        for (ITaskInstance symbol : other.getSymbols()) {
+            delegate.put(symbol.getTask(), other.getValue(symbol));
+            symbols.put(symbol.getTask(), symbol);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#size()
+     */
+    @Override
+    public int size() {
+        return delegate.size();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#isEmpty()
+     */
+    @Override
+    public boolean isEmpty() {
+        return delegate.isEmpty();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#containsSymbol(java.lang.Object)
+     */
+    @Override
+    public boolean containsSymbol(ITaskInstance symbol) {
+        if (symbol == null) {
+            throw new IllegalArgumentException("symbol must not be null");
+        }
+        
+        return delegate.containsKey(symbol.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#getValue(java.lang.Object)
+     */
+    @Override
+    public V getValue(ITaskInstance symbol) {
+        if (symbol == null) {
+            throw new IllegalArgumentException("symbol must not be null");
+        }
+        
+        return delegate.get(symbol.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#addSymbol(java.lang.Object, java.lang.Object)
+     */
+    @Override
+    public void addSymbol(ITaskInstance symbol, V value) {
+        if (symbol == null) {
+            throw new IllegalArgumentException("symbol must not be null");
+        }
+        
+        delegate.put(symbol.getTask(), value);
+        symbols.put(symbol.getTask(), symbol);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#removeSymbol(java.lang.Object)
+     */
+    @Override
+    public V removeSymbol(ITaskInstance symbol) {
+        if (symbol == null) {
+            throw new IllegalArgumentException("symbol must not be null");
+        }
+        
+        symbols.remove(symbol.getTask());
+        return delegate.remove(symbol.getTask());
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#getSymbols()
+     */
+    @Override
+    public Collection<ITaskInstance> getSymbols() {
+        return symbols.values();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#getValues()
+     */
+    @Override
+    public Collection<V> getValues() {
+        return delegate.values();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.usageprofiles.SymbolMap#clear()
+     */
+    @Override
+    public void clear() {
+        delegate.clear();
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+        
+    /* (non-Javadoc)
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        else if (this.getClass().isInstance(obj)) {
+            return delegate.equals(((TaskSymbolIdentityMap<V>) obj).delegate);
+        }
+        else {
+            return false;
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java	(revision 1551)
@@ -0,0 +1,327 @@
+//   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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+import de.ugoe.cs.autoquest.eventcore.guimodel.IDialog;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IFrame;
+import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement;
+import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * TODO update comment
+ * 
+ * <p>
+ * This class is responsible for applying temporal relationship rules on a task tree. Through this,
+ * a flat task tree is restructured to have more depth but to include more temporal relationships
+ * between tasks which are not only a major sequence. I.e. through the application of the
+ * rules iterations and selections of tasks are detected. Which kind of temporal relations
+ * between tasks are detected depends on the {@link ITaskInstanceScopeRule}s known to
+ * this class.
+ * </p>
+ * <p>The class holds references to the appropriate {@link ITaskInstanceScopeRule}s and calls
+ * their {@link ITaskInstanceScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)}
+ * method for each task in the task tree it is needed for. The general behavior of this class is
+ * the following:
+ * <ol>
+ *   <li>
+ *     An instance of this class is created using the constructor and calling the
+ *     {@link #init()} method afterwards
+ *   </li>
+ *   <li>
+ *     then the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)}
+ *     method is called for a so far unstructured task
+ *   </li>
+ *   <li>
+ *     the class iterates its internal list of rules and calls their
+ *     {@link ITaskInstanceScopeRule#apply(ITask, ITaskBuilder, ITaskFactory, boolean)}
+ *     method.
+ *   </li>
+ *   <li>
+ *     the class evaluates the rule application result
+ *     <ul>
+ *       <li>
+ *         if a rule returns a rule application result that is null, the next rule is tried
+ *       </li>
+ *       <li>
+ *         if a rule returns that it would be feasible if more data was available and the rule
+ *         application shall not be finalized (see finalize parameter of the applyRules method)
+ *         the rule application is broken up 
+ *       </li>
+ *       <li>
+ *         if a rule returns, that it was applied, the same rule is applied again until it returns
+ *         null or feasible. For each newly created parent task provided in the rule application
+ *         result, the {@link #applyRules(ITask, ITaskBuilder, ITaskFactory, boolean)}
+ *         method is called.
+ *       </li>
+ *     </ul>
+ *   </li>
+ * </ol>
+ * Through this, all rules are tried to be applied at least once to the provided parent task and
+ * all parent tasks created during the rule application.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class TemporalRelationshipRuleManager {
+    
+    /**
+     * <p>
+     * the task factory to be used during rule application
+     * </p>
+     */
+    private ITaskFactory taskFactory;
+
+    /**
+     * <p>
+     * the task builder to be used during rule application
+     * </p>
+     */
+    private ITaskBuilder taskBuilder;
+
+    /**
+     * <p>
+     * the temporal relationship rules known to the manager that are executed on whole sessions.
+     * The rules are applied in the order they occur in this list.
+     * </p>
+     */
+    private ISessionScopeRule[] sessionScopeRules;
+
+    /**
+     * <p>
+     * the temporal relationship rules known to the manager that are executed on whole sub trees.
+     * The rules are applied in the order they occur in this list.
+     * </p>
+     */
+    private ITaskInstanceScopeRule[] taskScopeRules;
+
+    /**
+     * <p>
+     * initialize the manager
+     * </p>
+     * 
+     * @param taskFactory             the task factory to be used for instantiating new task tree
+     *                                tasks during rule application
+     * @param taskBuilder             the task builder to be used for linking tasks
+     *                                with each other during rule application
+     */
+    public TemporalRelationshipRuleManager(ITaskFactory taskFactory, ITaskBuilder taskBuilder) {
+        super();
+        this.taskFactory = taskFactory;
+        this.taskBuilder = taskBuilder;
+    }
+
+    /**
+     * <p>
+     * initialized the temporal relationship rule manager by instantiating the known rules and
+     * providing them with a reference to the task equality manager or other information they need.
+     * </p>
+     */
+    public void init() {
+        List<Class<? extends IGUIElement>> frameFilter =
+            new ArrayList<Class<? extends IGUIElement>>();
+        frameFilter.add(IFrame.class);
+        frameFilter.add(IDialog.class);
+        //frameFilter.add(ICanvas.class);
+
+        sessionScopeRules = new ISessionScopeRule[] {
+            new SequenceForTaskDetectionRule
+                (TaskEquality.SEMANTICALLY_EQUAL, taskFactory, taskBuilder),
+            /*new DefaultTaskSequenceDetectionRule
+                (NodeEquality.SYNTACTICALLY_EQUAL, taskFactory, taskTreeBuilder),
+            new DefaultTaskSequenceDetectionRule
+                (NodeEquality.LEXICALLY_EQUAL, taskFactory, taskTreeBuilder),*/
+            /*new TreeScopeWrapperRule
+                (new DefaultIterationDetectionRule
+                    (NodeEquality.LEXICALLY_EQUAL, taskFactory, taskTreeBuilder)),
+            new TreeScopeWrapperRule
+                (new DefaultIterationDetectionRule
+                    (NodeEquality.SYNTACTICALLY_EQUAL, taskFactory, taskTreeBuilder)),
+            new TreeScopeWrapperRule
+                (new DefaultIterationDetectionRule
+                    (NodeEquality.SEMANTICALLY_EQUAL, taskFactory, taskTreeBuilder))*/
+        };
+        
+        //treeScopeRules.add(new DefaultGuiElementSequenceDetectionRule(frameFilter));
+
+        taskScopeRules = new ITaskInstanceScopeRule[] {
+            //new SequenceOnGuiElementDetectionRule(taskFactory, taskTreeBuilder),
+            //new EventSequenceOnSameTargetDetectionRule(taskFactory, taskTreeBuilder),
+            //new TrackBarSelectionDetectionRule(taskFactory, taskBuilder),
+            //new DefaultGuiEventSequenceDetectionRule(taskFactory, taskTreeBuilder),
+        };
+
+    }
+
+    /**
+     * <p>
+     * applies the known rules to the provided sessions. For the creation of further tasks,
+     * the provided builder and task factory are utilized. The method expects, that no more data
+     * is available and, therefore, finalizes the rule application.
+     * </p>
+     * 
+     * @param taskFactory  the task factory to be used for instantiating new tasks.
+     */
+    public void applyRules(List<IUserSession> sessions) {
+        applyRules(sessionScopeRules, sessions, "");
+    }
+
+    /**
+     * <p>
+     * applies the known rules to the provided parent task. For the creation of further tasks,
+     * the provided builder and task factory are utilized. If the finalize parameter is true, the
+     * rule application is finalized as far as possible without waiting for further data. If it is
+     * false, the rule application is broken up at the first rule returning, that its application
+     * would be feasible. The method calls itself for each parent task created through the rule
+     * application. In this case, the finalize parameter is always true.
+     * </p>
+     * 
+     * @param parent       the parent task to apply the rules on
+     * @param finalize     used to indicate, if the rule application shall break up if a rule would
+     *                     be feasible if further data was available, or not.
+     * @param logIndent    simply used for logging purposes to indent the log messages depending
+     *                     on the recursion depth of calling this method.
+     */
+    private int applyRules(ISessionScopeRule[] rules,
+                           List<IUserSession>  sessions,
+                           String              logIndent)
+    {
+        Console.traceln
+            (Level.FINER, logIndent + "applying rules for " + sessions.size() + " sessions");
+
+        int noOfRuleApplications = 0;
+
+        for (ISessionScopeRule rule : rules) {
+            RuleApplicationResult result;
+            do {
+                Console.traceln(Level.FINER, logIndent + "trying rule " + rule);
+                result = rule.apply(sessions);
+
+                if ((result != null) &&
+                    (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED))
+                {
+                    Console.traceln(Level.FINE, logIndent + "applied rule " + rule);
+                    noOfRuleApplications++;
+                    
+                    //dumpTask(parent, "");
+
+                    for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) {
+                        noOfRuleApplications +=
+                            applyRules(taskScopeRules, newParent, logIndent + "  ");
+                    }
+                }
+            }
+            while ((result != null) &&
+                   (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED));
+
+        }
+
+        if (noOfRuleApplications <= 0) {
+            Console.traceln(Level.FINE, logIndent + "no rules applied --> no temporal " +
+                            "relationship generated");
+        }
+
+        return noOfRuleApplications;
+    }
+
+    /**
+     * <p>
+     * applies the known rules to the provided parent task. For the creation of further tasks,
+     * the provided builder and task factory are utilized. If the finalize parameter is true, the
+     * rule application is finalized as far as possible without waiting for further data. If it is
+     * false, the rule application is broken up at the first rule returning, that its application
+     * would be feasible. The method calls itself for each parent task created through the rule
+     * application. In this case, the finalize parameter is always true.
+     * </p>
+     * 
+     * @param parent       the parent task to apply the rules on
+     * @param finalize     used to indicate, if the rule application shall break up if a rule would
+     *                     be feasible if further data was available, or not.
+     * @param logIndent    simply used for logging purposes to indent the log messages depending
+     *                     on the recursion depth of calling this method.
+     */
+    private int applyRules(ITaskInstanceScopeRule[] rules,
+                           ITaskInstance                taskInstance,
+                           String                       logIndent)
+    {
+        Console.traceln(Level.FINER, logIndent + "applying rules on " + taskInstance);
+
+        int noOfRuleApplications = 0;
+
+        for (ITaskInstanceScopeRule rule : rules) {
+            RuleApplicationResult result;
+            do {
+                Console.traceln
+                    (Level.FINER, logIndent + "trying rule " + rule + " on " + taskInstance);
+                result = rule.apply(taskInstance);
+
+                if ((result != null) &&
+                    (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED))
+                {
+                    Console.traceln
+                        (Level.FINE, logIndent + "applied rule " + rule + " on " + taskInstance);
+                    noOfRuleApplications++;
+                    
+                    //dumpTask(parent, "");
+
+                    for (ITaskInstance newParent : result.getNewlyCreatedTaskInstances()) {
+                        noOfRuleApplications +=
+                            applyRules(taskScopeRules, newParent, logIndent + "  ");
+                    }
+                }
+            }
+            while ((result != null) &&
+                   (result.getRuleApplicationStatus() == RuleApplicationStatus.FINISHED));
+        }
+
+        if (noOfRuleApplications <= 0) {
+            Console.traceln(Level.FINE, logIndent + "no rules applied --> no temporal " +
+                            "relationship generated");
+        }
+
+        return noOfRuleApplications;
+    }
+
+    /**
+     *
+     */
+    /*private void dumpTask(ITask task, String indent) {
+        StringBuffer message = new StringBuffer();
+        message.append(indent);
+        message.append(task);
+        if (task.getDescription() != null) {
+            message.append('(');
+            message.append(task.getDescription());
+            message.append(')');
+        }
+        
+        Console.traceln(Level.FINER, message.toString());
+        
+        if ((task.getChildren() != null) && (task.getChildren().size() > 0)) {
+            for (ITask child : task.getChildren()) {
+                dumpTask(child, indent + "  ");
+            }
+        }
+    }*/
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/DefaultTaskInstanceTraversingVisitor.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/DefaultTaskInstanceTraversingVisitor.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/DefaultTaskInstanceTraversingVisitor.java	(revision 1551)
@@ -0,0 +1,103 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * Default implementation for a task instance visitor performing a traversal of the instances
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class DefaultTaskInstanceTraversingVisitor implements ITaskInstanceVisitor {
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(IEventTaskInstance)
+     */
+    @Override
+    public void visit(IEventTaskInstance eventTaskInstance) {
+        // do nothing
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(IIterationInstance)
+     */
+    @Override
+    public void visit(IIterationInstance iterationInstance) {
+        visit((ITaskInstanceList) iterationInstance);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(IOptionalInstance)
+     */
+    @Override
+    public void visit(IOptionalInstance optionalInstance) {
+        if (optionalInstance.getChild() != null) {
+            optionalInstance.getChild().accept(this);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(ISelectionInstance)
+     */
+    @Override
+    public void visit(ISelectionInstance selectionInstance) {
+        selectionInstance.getChild().accept(this);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(ISequenceInstance)
+     */
+    @Override
+    public void visit(ISequenceInstance sequenceInstance) {
+        visit((ITaskInstanceList) sequenceInstance);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor#visit(ITaskInstance)
+     */
+    @Override
+    public void visit(ITaskInstance taskInstance) {
+        if (taskInstance instanceof IEventTaskInstance) {
+            visit((IEventTaskInstance) taskInstance);
+        }
+        else if (taskInstance instanceof IIterationInstance) {
+            visit((IIterationInstance) taskInstance);
+        }
+        else if (taskInstance instanceof IOptionalInstance) {
+            visit((IOptionalInstance) taskInstance);
+        }
+        else if (taskInstance instanceof ISelectionInstance) {
+            visit((ISelectionInstance) taskInstance);
+        }
+        else if (taskInstance instanceof ISequenceInstance) {
+            visit((ISequenceInstance) taskInstance);
+        }
+    }
+
+
+    /**
+     * <p>
+     * common implementation for traversing task instance lists.
+     * </p>
+     * 
+     * @param taskInstanceList the task instance list to be traversed
+     */
+    public void visit(ITaskInstanceList taskInstanceList) {
+        for (ITaskInstance child : taskInstanceList) {
+            child.accept(this);
+        }
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/DefaultTaskTraversingVisitor.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/DefaultTaskTraversingVisitor.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/DefaultTaskTraversingVisitor.java	(revision 1551)
@@ -0,0 +1,113 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * Default implementation for a task visitor performing a traversal of the task
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class DefaultTaskTraversingVisitor implements ITaskVisitor {
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(IEventTask)
+     */
+    @Override
+    public void visit(IEventTask eventTask) {
+        // do nothing
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(IIteration)
+     */
+    @Override
+    public void visit(IIteration iteration) {
+        visit((IMarkingTemporalRelationship) iteration);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(IOptional)
+     */
+    @Override
+    public void visit(IOptional optional) {
+        visit((IMarkingTemporalRelationship) optional);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(ISelection)
+     */
+    @Override
+    public void visit(ISelection selection) {
+        visit((IStructuringTemporalRelationship) selection);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(ISequence)
+     */
+    @Override
+    public void visit(ISequence sequence) {
+        visit((IStructuringTemporalRelationship) sequence);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor#visit(ITask)
+     */
+    @Override
+    public void visit(ITask task) {
+        if (task instanceof IEventTask) {
+            visit((IEventTask) task);
+        }
+        else if (task instanceof IIteration) {
+            visit((IIteration) task);
+        }
+        else if (task instanceof IOptional) {
+            visit((IOptional) task);
+        }
+        else if (task instanceof ISelection) {
+            visit((ISelection) task);
+        }
+        else if (task instanceof ISequence) {
+            visit((ISequence) task);
+        }
+    }
+
+    /**
+     * <p>
+     * common implementation for traversing a structuring temporal relationship 
+     * </p>
+     * 
+     * @param relationship the structuring temporal relationship to be traversed
+     */
+    public void visit(IStructuringTemporalRelationship relationship) {
+        for (ITask child : relationship.getChildren()) {
+            child.accept(this);
+        }
+    }
+
+    /**
+     * <p>
+     * common implementation for traversing a marking temporal relationship 
+     * </p>
+     * 
+     * @param relationship the marking temporal relationship to be traversed
+     */
+    public void visit(IMarkingTemporalRelationship relationship) {
+        if (relationship.getMarkedTask() != null) {
+            relationship.getMarkedTask().accept(this);
+        }
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IEventTask.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IEventTask.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IEventTask.java	(revision 1551)
@@ -0,0 +1,40 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * Event tasks represent single events. They have no children and are therefore the leaf nodes of
+ * a task model. They provide information about the event they represent as a String description.
+ * They do not refer to events, as they may represented several semantically equal but lexically
+ * different events. Their description carries as much information as required to show the
+ * level of distinction.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface IEventTask extends ITask {
+    
+    /**
+     * <p>
+     * returns a clone of this task, i.e. another event task being identical to this. The event
+     * type and target are not cloned but reused.
+     * </p>
+     * 
+     * @return as described
+     */
+    public IEventTask clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IEventTaskInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IEventTaskInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IEventTaskInstance.java	(revision 1551)
@@ -0,0 +1,56 @@
+//   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.treeifc;
+
+import de.ugoe.cs.autoquest.eventcore.Event;
+
+/**
+ * <p>
+ * the instance of an {@link IEventTask}. The instance refers to the concrete event it represents.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface IEventTaskInstance extends ITaskInstance {
+
+    /**
+     * <p>
+     * returns the event represented by this event task instance
+     * </p>
+     * 
+     * @return as described
+     */
+    public Event getEvent();
+
+    /**
+     * <p>
+     * returns the task related to the instance, i.e. the event task.
+     * </p>
+     * 
+     * @return as described
+     */
+    public IEventTask getEventTask();
+
+    /**
+     * <p>
+     * clones this task instance by creating exact clones of itself. The referred task and event
+     * stay untouched
+     * </p>
+     * 
+     * @return a clone of the task instance
+     */
+    public IEventTaskInstance clone();
+    
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IIteration.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IIteration.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IIteration.java	(revision 1551)
@@ -0,0 +1,39 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * This temporal relationship defines that its single child may be executed zero or more times for
+ * fulfilling the task. This is most important for the parent node in the task model as this
+ * node may require that a specific subtask is executed several times.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface IIteration extends IMarkingTemporalRelationship {
+
+    /**
+     * <p>
+     * returns an exact copy of this temporal relationship. The clone has the same id. Its child
+     * is a clone of the child of the cloned task. A call on the method {@link #equals(ITask)}
+     * with the result of this method must return true.
+     * </p>
+     * 
+     * @return as described
+     */
+    public IIteration clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IIterationInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IIterationInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IIterationInstance.java	(revision 1551)
@@ -0,0 +1,46 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * the instance of an {@link IIteration}. The instance may have several children each being an
+ * instance of the task marked by the iteration of which this is an instance.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface IIterationInstance extends ITaskInstance, ITaskInstanceList {
+
+    /**
+     * <p>
+     * returns the task related to the instance, i.e. the iteration.
+     * </p>
+     * 
+     * @return as described
+     */
+    public IIteration getIteration();
+
+    /**
+     * <p>
+     * clones this task instance by creating exact clones of each contained instance in their
+     * order
+     * </p>
+     * 
+     * @return a clone of the task instance list
+     */
+    public IIterationInstance clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IMarkingTemporalRelationship.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IMarkingTemporalRelationship.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IMarkingTemporalRelationship.java	(revision 1551)
@@ -0,0 +1,48 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * A marking temporal relationship defines a temporal information for exactly one node in the task
+ * model. I.e., it has only one child for which it defines a special execution characteristic.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface IMarkingTemporalRelationship extends ITemporalRelationship {
+
+    /**
+     * <p>
+     * returns the task for which this relationship defines the execution characteristic. The
+     * task can be seen as the child node of this node.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ITask getMarkedTask();
+
+    /**
+     * <p>
+     * returns an exact copy of this temporal relationship. The clone has the same id. Its child
+     * is a clone of the child of the cloned task. A call on the method {@link #equals(ITask)}
+     * with the result of this method must return true.
+     * </p>
+     * 
+     * @return as described
+     */
+    public IMarkingTemporalRelationship clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IOptional.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IOptional.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IOptional.java	(revision 1551)
@@ -0,0 +1,39 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * This temporal relationship defines that its single child may or may not be executed for
+ * fulfilling the task. This is most important for the parent node in the task model as this
+ * node may require that a specific subtask is optional.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface IOptional extends IMarkingTemporalRelationship {
+
+    /**
+     * <p>
+     * returns an exact copy of this temporal relationship. The clone has the same id. Its child
+     * is a clone of the child of the cloned task. A call on the method {@link #equals(ITask)}
+     * with the result of this method must return true.
+     * </p>
+     * 
+     * @return as described
+     */
+    public IOptional clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IOptionalInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IOptionalInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IOptionalInstance.java	(revision 1551)
@@ -0,0 +1,55 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * the instance of an {@link IOptional}. The instance may have a child being an
+ * instance of the task marked by the optional of which this is an instance. If this instance
+ * does not have a child, the optional child task was not executed.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface IOptionalInstance extends ITaskInstance {
+
+    /**
+     * <p>
+     * returns the child of the optional of null if the optional was not executed
+     * </p>
+     * 
+     * @return as described
+     */
+    public ITaskInstance getChild();
+
+    /**
+     * <p>
+     * returns the task related to the instance, i.e. the optional.
+     * </p>
+     * 
+     * @return as described
+     */
+    public IOptional getOptional();
+
+    /**
+     * <p>
+     * clones this task instance by creating exact clones of each contained instance
+     * </p>
+     * 
+     * @return a clone of the task instance
+     */
+    public IOptionalInstance clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISelection.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISelection.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISelection.java	(revision 1551)
@@ -0,0 +1,38 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * This temporal relationship defines that only one of its children must be executed for
+ * fulfilling the represented task.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ISelection extends IStructuringTemporalRelationship {
+
+    /**
+     * <p>
+     * returns an exact copy of this temporal relationship. The clone has the same id. Its children
+     * are clones of the children of the cloned task. A call on the method {@link #equals(ITask)}
+     * with the result of this method must return true.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ISelection clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISelectionInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISelectionInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISelectionInstance.java	(revision 1551)
@@ -0,0 +1,54 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * the instance of an {@link ISelection}. The instance has a child being an instance of the child
+ * task of the selection that was selected for execution.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ISelectionInstance extends ITaskInstance {
+
+    /**
+     * <p>
+     * returns the selected child of the selection
+     * </p>
+     * 
+     * @return as described
+     */
+    public ITaskInstance getChild();
+
+    /**
+     * <p>
+     * returns the task related to the instance, i.e. the selection.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ISelection getSelection();
+
+    /**
+     * <p>
+     * clones this task instance by creating exact clones of the contained instance
+     * </p>
+     * 
+     * @return a clone of the task instance
+     */
+    public ISelectionInstance clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISequence.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISequence.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISequence.java	(revision 1551)
@@ -0,0 +1,38 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * This temporal relationship defines that its children must be executed in the order they are
+ * listed for fulfilling the represented task.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ISequence extends IStructuringTemporalRelationship {
+
+    /**
+     * <p>
+     * returns an exact copy of this temporal relationship. The clone has the same id. Its children
+     * are clones of the children of the cloned task. A call on the method {@link #equals(ITask)}
+     * with the result of this method must return true.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ISequence clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISequenceInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISequenceInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ISequenceInstance.java	(revision 1551)
@@ -0,0 +1,46 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * the instance of an {@link ISequence}. The instance has the same number of children as the
+ * sequence it represents.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ISequenceInstance extends ITaskInstance, ITaskInstanceList {
+
+    /**
+     * <p>
+     * returns the task related to the instance, i.e. the sequence.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ISequence getSequence();
+
+    /**
+     * <p>
+     * clones this task instance by creating exact clones of each contained instance in their
+     * order
+     * </p>
+     * 
+     * @return a clone of the task instance
+     */
+    public ISequenceInstance clone();
+  
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IStructuringTemporalRelationship.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IStructuringTemporalRelationship.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IStructuringTemporalRelationship.java	(revision 1551)
@@ -0,0 +1,49 @@
+//   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.treeifc;
+
+import java.util.List;
+
+/**
+ * <p>
+ * A structuring temporal relationship defines a temporal information for several nodes in the task
+ * model. I.e., it has several children and defines an execution order for them.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface IStructuringTemporalRelationship extends ITemporalRelationship {
+
+    /**
+     * <p>
+     * returns the children of this temporal relationship.
+     * </p>
+     * 
+     * @return as described
+     */
+    public List<ITask> getChildren();
+
+    /**
+     * <p>
+     * returns an exact copy of this temporal relationship. The clone has the same id. Its children
+     * are clones of the children of the cloned task. A call on the method {@link #equals(ITask)}
+     * with the result of this method must return true.
+     * </p>
+     * 
+     * @return as described
+     */
+    public IStructuringTemporalRelationship clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITask.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITask.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITask.java	(revision 1551)
@@ -0,0 +1,121 @@
+//   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.treeifc;
+
+import java.io.Serializable;
+import java.util.Collection;
+
+/**
+ * <p>
+ * A task represents a model for events that occur if the user interacts with a software for
+ * achieving a specific goal. A task can be a single event or a complex structure of events
+ * and temporal relationships defining the event order. Tasks may especially refer to other tasks
+ * to create task structures similar to trees. These structures fully define in which ways the
+ * events that form the task can occur. However, the structure of a task is not necessarily a
+ * tree as task structures may be reused several times in larger scale task structures.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ITask extends Cloneable, Serializable {
+
+    /**
+     * <p>
+     * every task is assigned a unique id which is returned by this method. The id is unique for
+     * the current runtime.
+     * </p>
+     * 
+     * @return as described
+     */
+    public int getId();
+
+    /**
+     * <p>
+     * returns a human readable type for the task. 
+     * </p>
+     * 
+     * @return as described
+     */
+    public String getType();
+
+    /**
+     * <p>
+     * returns a human readable description for the task. 
+     * </p>
+     * 
+     * @return as described
+     */
+    public String getDescription();
+
+    /**
+     * <p>
+     * returns a collection of all observed instances of this task
+     * </p>
+     * 
+     * @return as described
+     */
+    public Collection<ITaskInstance> getInstances();
+
+    /**
+     * <p>
+     * returns a collection of collections of all different execution variants of this task. This
+     * is a grouping of all instances where each group contains structurally identical instances.
+     * </p>
+     * 
+     * @return as described
+     */
+    public Collection<Collection<ITaskInstance>> getExecutionVariants();
+
+    /**
+     * <p>
+     * checks whether this task is equal to another one. Task equality is only given, if two
+     * tasks have the same id. This means, that this method must only return true if the other
+     * task is either the same object or a clone of it. 
+     * </p>
+     * 
+     * @return as described
+     */
+    public boolean equals(ITask task);
+
+    /**
+     * <p>
+     * returns a hash code for the task, which is usually the id returned by {@link #getId()}.
+     * </p>
+     * 
+     * @return as described
+     */
+    public int hashCode();
+
+    /**
+     * <p>
+     * returns an exact copy of this task. The clone has the same id. If the task has
+     * children, they are cloned as well. A call on the method {@link #equals(ITask)} with the
+     * result of this method must return true.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ITask clone();
+    
+    /**
+     * <p>
+     * implements the visitor pattern to be able to process tasks and their children.
+     * </p>
+     * 
+     * @param visitor the visitor used to process the task
+     */
+    public void accept(ITaskVisitor visitor);
+    
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskBuilder.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskBuilder.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskBuilder.java	(revision 1551)
@@ -0,0 +1,259 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * Builder for task models. Can be used to create and edit task models. May perform integrity
+ * checks, though they may be incomplete as the integrity of a task model can not be ensured during
+ * creation.
+ * </p>
+ */
+public interface ITaskBuilder {
+
+    /**
+     * <p>
+     * adds a child to a sequence instance. May ensure, that the child is a valid child considering
+     * the task model of the parent. In that case, an IllegalArgumentException is thrown.
+     * </p>
+     * 
+     * @param instance the instance of add the child to
+     * @param child    the child to be added
+     * 
+     * @throws IllegalArgumentException as described
+     */
+    void addChild(ISequenceInstance instance, ITaskInstance child) throws IllegalArgumentException;
+
+    /**
+     * <p>
+     * adds a child to an iteration instance. May ensure, that the child is a valid child
+     * considering the task model of the parent. In that case, an IllegalArgumentException is
+     * thrown.
+     * </p>
+     * 
+     * @param instance the instance of add the child to
+     * @param child    the child to be added
+     * 
+     * @throws IllegalArgumentException as described
+     */
+    void addChild(IIterationInstance instance, ITaskInstance child) throws IllegalArgumentException;
+
+    /**
+     * <p>
+     * sets the child of a selection instance. May ensure, that the child is a valid child
+     * considering the task model of the parent. In that case, an IllegalArgumentException is
+     * thrown.
+     * </p>
+     * 
+     * @param instance the instance of add the child to
+     * @param child    the child to be added
+     * 
+     * @throws IllegalArgumentException as described
+     */
+    void setChild(ISelectionInstance instance, ITaskInstance child) throws IllegalArgumentException;
+
+    /**
+     * <p>
+     * sets the child of an optional instance. May ensure, that the child is a valid child
+     * considering the task model of the parent. In that case, an IllegalArgumentException is
+     * thrown.
+     * </p>
+     * 
+     * @param instance the instance of add the child to
+     * @param child    the child to be added
+     * 
+     * @throws IllegalArgumentException as described
+     */
+    void setChild(IOptionalInstance instance, ITaskInstance child) throws IllegalArgumentException;
+
+    /**
+     * <p>
+     * adds a task instance to a user session
+     * </p>
+     *
+     * @param session      the session to add the task instance to
+     * @param taskInstance the task instance to add
+     */
+    void addExecutedTask(IUserSession session, ITaskInstance taskInstance);
+
+    /**
+     * <p>
+     * adds a task instance to a task instance list
+     * </p>
+     * 
+     * @param taskInstanceList the list to add the task instance to
+     * @param taskInstance     the task instance to add
+     */
+    void addTaskInstance(ITaskInstanceList taskInstanceList, ITaskInstance taskInstance);
+
+    /**
+     * <p>
+     * adds a task instance to a task instance list at a specific position. Subsequent task
+     * instances will be moved one index forward
+     * </p>
+     * 
+     * @param taskInstanceList the list to add the task instance to
+     * @param index            the index of the task instance to add
+     * @param taskInstance     the task instance to add
+     * 
+     * @throws IndexOutOfBoundsException if the index is invalid
+     */
+    void addTaskInstance(ITaskInstanceList taskInstanceList, int index, ITaskInstance taskInstance)
+        throws IndexOutOfBoundsException;
+
+    /**
+     * <p>
+     * sets a task instance in a task instance list at a specific position
+     * </p>
+     * 
+     * @param taskInstanceList the list to set the task instance in
+     * @param index            the index of the task instance to replace
+     * @param taskInstance     the replacement for the task instance at the index
+     * 
+     * @throws IndexOutOfBoundsException if the index is invalid
+     */
+    void setTaskInstance(ITaskInstanceList taskInstanceList, int index, ITaskInstance taskInstance)
+        throws IndexOutOfBoundsException;
+
+    /**
+     * <p>
+     * sets the task model of a task instance
+     * </p>
+     * 
+     * @param taskInstance the task instance to set the task model for
+     * @param task         the task model of the instance
+     */
+    void setTask(ITaskInstance taskInstance, ITask task);
+
+    /**
+     * <p>
+     * adds a child task to the end of a sequence
+     * </p>
+     * 
+     * @param parent the sequence to add the child to
+     * @param child  the child to be added
+     */
+    void addChild(ISequence parent, ITask child);
+
+    /**
+     * <p>
+     * adds a child task to a specific index of a sequence
+     * </p>
+     * 
+     * @param parent the sequence to add the child to
+     * @param index  the index to set the child at
+     * @param child  the child to be added
+     * 
+     * @throws IndexOutOfBoundsException if the index is invalid
+     */
+    void addChild(ISequence parent, int index, ITask child)
+        throws IndexOutOfBoundsException;
+
+    /**
+     * <p>
+     * replaces the child task of a sequence at a specific position
+     * </p>
+     * 
+     * @param parent the sequence to replace the child in
+     * @param index  the index to replace the child at
+     * @param child  the child to be added
+     * 
+     * @throws IndexOutOfBoundsException if the index is invalid
+     */
+    void setChild(ISequence parent, int index, ITask child)
+        throws IndexOutOfBoundsException;
+
+    /**
+     * <p>
+     * adds a child task to a selection
+     * </p>
+     * 
+     * @param parent the selection to add the child to
+     * @param child  the child to be added
+     */
+    void addChild(ISelection parent, ITask child);
+
+    /**
+     * <p>
+     * sets the child task of an iteration
+     * </p>
+     * 
+     * @param iteration the iteration to set the child of
+     * @param child     the child to be set
+     */
+    void setMarkedTask(IIteration iteration, ITask child);
+
+    /**
+     * <p>
+     * sets the child task of an optional
+     * </p>
+     * 
+     * @param optional the optional to set the child of
+     * @param child    the child to be set
+     */
+    void setMarkedTask(IOptional optional, ITask child);
+
+    /**
+     * <p>
+     * removes the child of a sequence at a specific position
+     * </p>
+     * 
+     * @param parent the sequence of which the child must be removed
+     * @param index  the index of the child to be removed
+     * 
+     * @throws IndexOutOfBoundsException if the index is invalid
+     */
+    void removeChild(ISequence parent, int index)
+        throws IndexOutOfBoundsException;
+
+    /**
+     * <p>
+     * removes a child of a selection. Ignores the call, if the child is not found
+     * (comparison using equals).
+     * </p>
+     * 
+     * @param parent the selection of which the child must be removed
+     * @param child  the child to be removes
+     */
+    void removeChild(ISelection parent, ITask child);
+
+    /**
+     * <p>
+     * removes the entry of a task instance list at a specific position
+     * </p>
+     * 
+     * @param taskInstanceList the task instance list of which the entry must be removed
+     * @param index            the index of the entry to be removed
+     * 
+     * @throws IndexOutOfBoundsException if the index is invalid
+     */
+    void removeTaskInstance(ITaskInstanceList taskInstanceList, int index)
+        throws IndexOutOfBoundsException;
+
+    /**
+     * <p>
+     * replaces a child of a selection. Throws an IllegalArgumentException if the child is not
+     * found (comparison using equals).
+     * </p>
+     * 
+     * @param parent   the selection of which the child must be replace
+     * @param oldChild the child to replace
+     * @param newChild the replacement for the child
+     * 
+     * @throws as described
+     */
+    void replaceChild(ISelection parent, ITask oldChild, ITask newChild);
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskFactory.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskFactory.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskFactory.java	(revision 1551)
@@ -0,0 +1,153 @@
+//   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.treeifc;
+
+import java.util.List;
+
+import de.ugoe.cs.autoquest.eventcore.Event;
+
+/**
+ * <p>
+ * factory for the different task types
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ITaskFactory {
+
+    /**
+     * <p>
+     * creates a new event task with the given description
+     * </p>
+     * 
+     * @param description the description for the represented events
+     * 
+     * @return the event task
+     */
+    IEventTask createNewEventTask(String description);
+
+    /**
+     * <p>
+     * creates a new empty sequence
+     * </p>
+     * 
+     * @return the sequence
+     */
+    ISequence createNewSequence();
+
+    /**
+     * <p>
+     * creates a new empty iteration
+     * </p>
+     * 
+     * @return the iteration
+     */
+    IIteration createNewIteration();
+
+    /**
+     * <p>
+     * creates a new empty optional
+     * </p>
+     * 
+     * @return the optional
+     */
+    IOptional createNewOptional();
+
+    /**
+     * <p>
+     * creates a new empty selection
+     * </p>
+     * 
+     * @return the selection
+     */
+    ISelection createNewSelection();
+
+    /**
+     * <p>
+     * creates a new task instance with the given task as its model representing the provided event
+     * </p>
+     * 
+     * @param task  the model of the task instance to be created
+     * @param event the event represented by the task instance
+     * 
+     * @return the task instance
+     */
+    IEventTaskInstance createNewTaskInstance(IEventTask task, Event event);
+
+    /**
+     * <p>
+     * creates a new task instance with the given sequence as its model
+     * </p>
+     * 
+     * @param sequence the model of the task instance to be created
+     * 
+     * @return the task instance
+     */
+    ISequenceInstance createNewTaskInstance(ISequence sequence);
+
+    /**
+     * <p>
+     * creates a new task instance with the given iteration as its model
+     * </p>
+     * 
+     * @param iteration the model of the task instance to be created
+     * 
+     * @return the task instance
+     */
+    IIterationInstance createNewTaskInstance(IIteration iteration);
+
+    /**
+     * <p>
+     * creates a new task instance with the given optional as its model
+     * </p>
+     * 
+     * @param optional the model of the task instance to be created
+     * 
+     * @return the task instance
+     */
+    IOptionalInstance createNewTaskInstance(IOptional optional);
+
+    /**
+     * <p>
+     * creates a new task instance with the given selection as its model
+     * </p>
+     * 
+     * @param selection the model of the task instance to be created
+     * 
+     * @return the task instance
+     */
+    ISelectionInstance createNewTaskInstance(ISelection selection);
+
+    /**
+     * <p>
+     * creates a new empty user session
+     * </p>
+     * 
+     * @return the user session
+     */
+    IUserSession createUserSession();
+
+    /**
+     * <p>
+     * creates a task model based on the provided user sessions
+     * </p>
+     * 
+     * @param userSessions the session based on which the task model shall be created
+     * 
+     * @return the task model
+     */
+    ITaskModel createTaskModel(List<IUserSession> userSessions);
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInfo.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInfo.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInfo.java	(revision 1551)
@@ -0,0 +1,109 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * Provides extended information about a specific task, such as statistics about task occurrences,
+ * etc. It contains measures for different metrics determined for a task.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ITaskInfo {
+
+    /**
+     * <p>
+     * returns the task to which these infos belong
+     * </p>
+     * 
+     * @return as described
+     */
+    public ITask getTask();
+
+    /**
+     * <p>
+     * returns all available measures
+     * </p>
+     * 
+     * @return as described
+     */
+    public IMeasure[] getMeasures();
+
+    /**
+     * <p>
+     * returns the value of the measure identified through the given metric
+     * </p>
+     *
+     * @param metric the metric for which the value is to be returned
+     * 
+     * @return as described
+     */
+    public int getMeasureValue(TaskMetric metric);
+
+    /**
+     * <p>
+     * returns the value of the measure identified through the given metric if the task is
+     * observed in the given context, i.e. parent task. The result is Integer.MIN_VALUE if there
+     * is no value for this measure in a context.
+     * </p>
+     *
+     * @param metric  the metric for which the value is to be returned
+     * @param context the context for which the measure value is to be returned
+     * 
+     * @return as described
+     */
+    public int getMeasureValue(TaskMetric metric, ITask context);
+
+    /**
+     * <p>
+     * represents a measure for a specific metric
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    public interface IMeasure {
+        
+        /**
+         * <p>
+         * returns the metric of the measure
+         * </p>
+         * 
+         * @return as described
+         */
+        public TaskMetric getMetric();
+        
+        /**
+         * <p>
+         * returns the value of the measure
+         * </p>
+         * 
+         * @return as described
+         */
+        public int getValue();
+        
+        /**
+         * <p>
+         * returns the value of the measure if the task was observed in a specific context, i.e.
+         * parent task
+         * </p>
+         * 
+         * @return as described
+         */
+        public int getValue(ITask context);
+        
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstance.java	(revision 1551)
@@ -0,0 +1,80 @@
+//   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.treeifc;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * a task instance represents the execution of a specific task within a user session. A task
+ * instance is always related to the task that was executed.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ITaskInstance extends Serializable, Cloneable {
+
+    /**
+     * <p>
+     * returns the task related to the instance.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ITask getTask();
+
+    /**
+     * <p>
+     * compares an instance to another one. Returns true if both instances are the same, i.e. not
+     * only the related task is equal but also all children and further characteristics of the
+     * task instance  
+     * </p>
+     * 
+     * @param taskInstance the instance to compare to
+     * 
+     * @return as described
+     */
+    public boolean equals(ITaskInstance taskInstance);
+
+    /**
+     * <p>
+     * returns a hash code for the task instance to be able to put it into hash maps
+     * </p>
+     * 
+     * @return as described
+     */
+    public int hashCode();
+
+    /**
+     * <p>
+     * clones a task instance by creating exact clones of each contained child instance as well
+     * as the related task. Furthermore, all other non transient information of the task
+     * instance must be cloned.
+     * </p>
+     * 
+     * @return a clone of the task instance
+     */
+    public ITaskInstance clone();
+
+    /**
+     * <p>
+     * implements the visitor pattern to be able to process task instances and their children.
+     * </p>
+     * 
+     * @param visitor the visitor used to process the task
+     */
+    public void accept(ITaskInstanceVisitor visitor);
+    
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstanceList.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstanceList.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstanceList.java	(revision 1551)
@@ -0,0 +1,50 @@
+//   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.treeifc;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * represents a serializable and iterable representation of a read only list of task
+ * instances. The list is ordered. It does not provide methods for changing it.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ITaskInstanceList extends Cloneable, Serializable, Iterable<ITaskInstance> {
+
+    /**
+     * <p>
+     * returns the task instance at the position with the given index. May throw an exception
+     * if the index is invalid.
+     * </p>
+     * 
+     * @param index the index of the task instance to be returned
+     * 
+     * @return the task instance at the given index
+     */
+    public ITaskInstance get(int index);
+
+    /**
+     * <p>
+     * returns the size of the list, i.e. the number of task instances in the list
+     * </p>
+     * 
+     * @return as described
+     */
+    public int size();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstanceVisitor.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstanceVisitor.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskInstanceVisitor.java	(revision 1551)
@@ -0,0 +1,83 @@
+//   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.treeifc;
+
+
+/**
+ * <p>
+ * This is an implementation of the visitor pattern. Through this, it is possible to effectively
+ * process a task instance tree. 
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ITaskInstanceVisitor {
+
+    /**
+     * <p>
+     * method called for each visited event task instance.
+     * </p>
+     * 
+     * @param eventTaskInstance the event task instance to be processed
+     */
+    public void visit(IEventTaskInstance eventTaskInstance);
+    
+    /**
+     * <p>
+     * method called for each visited iteration instance.
+     * </p>
+     * 
+     * @param iterationInstance the iteration instance to be processed
+     */
+    public void visit(IIterationInstance iterationInstance);
+    
+    /**
+     * <p>
+     * method called for each visited optional instance.
+     * </p>
+     * 
+     * @param optionalInstance the optional instance to be processed
+     */
+    public void visit(IOptionalInstance optionalInstance);
+    
+    /**
+     * <p>
+     * method called for each visited selection instance.
+     * </p>
+     * 
+     * @param selectionInstance the selection instance to be processed
+     */
+    public void visit(ISelectionInstance selectionInstance);
+    
+    /**
+     * <p>
+     * method called for each visited sequence instance.
+     * </p>
+     * 
+     * @param sequenceInstance the sequence instance to be processed
+     */
+    public void visit(ISequenceInstance sequenceInstance);
+
+    /**
+     * <p>
+     * method called for each other kind of visited task instance (implemented to support future
+     * versions).
+     * </p>
+     * 
+     * @param taskInstance the task instance to be processed
+     */
+    public void visit(ITaskInstance taskInstance);
+    
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskModel.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskModel.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskModel.java	(revision 1551)
@@ -0,0 +1,82 @@
+//   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.treeifc;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * <p>
+ * This class represents a complete task model. A task model within AutoQUEST is usually generated
+ * based on user sessions. Therefore, the task model consists of the user sessions, the models
+ * of the identified tasks, as well as further information about the tasks (e.g. their
+ * occurrence count) for statistical processing.
+ * </p>
+ * 
+ * @author 2012, Patrick Harms
+ */
+public interface ITaskModel extends Cloneable, Serializable {
+
+    /**
+     * <p>
+     * returns the user sessions belonging to the model. The return value may be null in the case
+     * no user sessions are associated the the tasks in the model.
+     * </p>
+     * 
+     * @return as described
+     */
+    public List<IUserSession> getUserSessions();
+
+    /**
+     * <p>
+     * returns the tasks belonging to the model. The return value must not be null. However,
+     * it may be an empty list, if the model is an empty model.
+     * </p>
+     * 
+     * @return as described
+     */
+    public Collection<ITask> getTasks();
+
+    /**
+     * <p>
+     * returns additional info for the provided task. The method returns null, if the provided
+     * task does not belong to the model.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ITaskInfo getTaskInfo(ITask task);
+
+    /**
+     * <p>
+     * returns a list of all metrics calculated by this model for the tasks and stored in the
+     * respective task infos
+     * </p>
+     *
+     * @return as described
+     */
+    public TaskMetric[] getAllMetrics();
+
+    /**
+     * <p>
+     * creates a deep clone of the model including all tasks and user sessions.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ITaskModel clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskVisitor.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskVisitor.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITaskVisitor.java	(revision 1551)
@@ -0,0 +1,82 @@
+//   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.treeifc;
+
+
+/**
+ * <p>
+ * This is an implementation of the visitor pattern. Through this, it is possible to effectively
+ * process a task model. 
+ * </p>
+ * 
+ * @author Alexander Deicke
+ */
+public interface ITaskVisitor {
+
+    /**
+     * <p>
+     * method called for each visited event task.
+     * </p>
+     * 
+     * @param eventTask the event task to be processed
+     */
+    public void visit(IEventTask eventTask);
+    
+    /**
+     * <p>
+     * method called for each visited iteration.
+     * </p>
+     * 
+     * @param iteration the iteration to be processed
+     */
+    public void visit(IIteration iteration);
+    
+    /**
+     * <p>
+     * method called for each visited optional.
+     * </p>
+     * 
+     * @param optional the optional to be processed
+     */
+    public void visit(IOptional optional);
+    
+    /**
+     * <p>
+     * method called for each visited selection.
+     * </p>
+     * 
+     * @param selection the selection to be processed
+     */
+    public void visit(ISelection selection);
+    
+    /**
+     * <p>
+     * method called for each visited sequence.
+     * </p>
+     * 
+     * @param sequence the sequence to be processed
+     */
+    public void visit(ISequence sequence);
+
+    /**
+     * <p>
+     * method called for each other kind of visited task (implemented to support future versions).
+     * </p>
+     * 
+     * @param task the task to be processed
+     */
+    public void visit(ITask task);
+    
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITemporalRelationship.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITemporalRelationship.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/ITemporalRelationship.java	(revision 1551)
@@ -0,0 +1,42 @@
+//   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.treeifc;
+
+/**
+ * <p>
+ * A temporal relationship is a node in a task model which is no leaf node. They are used to
+ * structure the tasks in a task model into useful orders. A temporal relationship defines through
+ * its type how its children can be executed to fulfill the task they represent themselves. E.g.,
+ * the task of filling out a form can be subdivided into several subtasks for filling out the
+ * different elements of the. The task itself will define the order, in which the fill out process
+ * can and must be done.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface ITemporalRelationship extends ITask {
+
+    /**
+     * <p>
+     * returns an exact copy of this temporal relationship. The clone has the same id. Its children
+     * are clones of the children of the cloned task. A call on the method {@link #equals(ITask)}
+     * with the result of this method must return true.
+     * </p>
+     * 
+     * @return as described
+     */
+    public ITemporalRelationship clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IUserSession.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IUserSession.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/IUserSession.java	(revision 1551)
@@ -0,0 +1,70 @@
+//   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.treeifc;
+
+import java.util.List;
+
+/**
+ * <p>
+ * A user session represents task executions, i.e. a task instances of a specific user that were
+ * executed in a coherent manner. Therefore, they are an ordered list of task instances where
+ * the order denotes the order of the task executions.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public interface IUserSession extends ITaskInstanceList {
+
+    /**
+     * <p>
+     * returns the list of task instances executed in the represented session.
+     * </p>
+     * 
+     * @return as described
+     */
+    public List<ITaskInstance> getExecutedTasks();
+    
+    /**
+     * <p>
+     * compares the user session with another one. Two user sessions are only equal, if they
+     * contain the same number of task instances and if each task instance at each position is
+     * equal to the respective other session. 
+     * </p>
+     * 
+     * @param userSession the session to compare the session to
+     * 
+     * @return true if both sessions are equal, false else
+     */
+    public boolean equals(IUserSession userSession);
+
+    /**
+     * <p>
+     * returns a hash code for the session to be able to store the session in a hash map.
+     * </p>
+     * 
+     * @return as described
+     */
+    public int hashCode();
+
+    /**
+     * <p>
+     * clones a user session by creating exact clones of each contained instance in their order
+     * </p>
+     * 
+     * @return a clone of the session
+     */
+    public IUserSession clone();
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/TaskMetric.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/TaskMetric.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeifc/TaskMetric.java	(revision 1551)
@@ -0,0 +1,141 @@
+//   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.treeifc;
+
+import java.text.DecimalFormat;
+
+/**
+ * <p>
+ * represents different metrics available or calculatable for tasks. Measure for the metrics
+ * are calculated by a task model and added to the task infos of a specific task.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public enum TaskMetric {
+
+    COUNT("count", "number of all occurrences of the task in the model"),
+    DEPTH("depth",
+          "the maximum depth of the task, i.e., the number of children levels including the " +
+          "level of the task itself"),
+    EVENT_COVERAGE("covered events", "number of all event task instances covered by the task"),
+    EVENT_COVERAGE_RATIO("event coverage ratio",
+                         "the ratio of events covered by this task in relation to all events " +
+                         "covered by all tasks in their instances in per mille", 0.1, "%"),
+    EVENT_COVERAGE_QUANTILE("event coverage ratio quantile",
+                            "the quantile of with respect to all event coverages begining with " +
+                            "the lowest", 0.1, "%");
+    
+    /**
+     * <p>
+     * the name of the metric
+     * </p>
+     */
+    private String name;
+    
+    /**
+     * <p>
+     * a human readable description of the metric
+     * </p>
+     */
+    private String description;
+
+    /**
+     * <p>
+     * a scale applied for the metric when formatting the value
+     * </p>
+     */
+    private double formatScale;
+    
+    /**
+     * <p>
+     * the unit of the metric used when formatting the value
+     * </p>
+     */
+    private String formatUnit;
+    
+    /**
+     * <p>
+     * initializes the metric with a name and a description
+     * </p>
+     */
+    private TaskMetric(String name, String description) {
+        this.name = name;
+        this.description = description;
+        this.formatScale = 1.0;
+        this.formatUnit = null;
+    }
+
+    /**
+     * <p>
+     * initializes the metric with a name and a description, as well as with a scale and a unit for
+     * formatting it.
+     * </p>
+     */
+    private TaskMetric(String name, String description, double formatScale, String formatUnit) {
+        this.name = name;
+        this.description = description;
+        this.formatScale = formatScale;
+        this.formatUnit = formatUnit;
+    }
+
+    /**
+     * <p>
+     * returns the name of the metric
+     * </p>
+     * 
+     * @return the name of the metric
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * <p>
+     * returns the human readable description of the metric
+     * </p>
+     * 
+     * @return the human readable description of the metric
+     */
+    public String getDescription() {
+        return description;
+    }
+    
+    /**
+     * <p>
+     * formats the provided value of a measure of the metric using the internal format scale and
+     * unit.
+     * </p>
+     * 
+     * @return the formatted value depending on the scale and unit of the metric
+     */
+    public String formatValue(int value) {
+        String formattedValue;
+        
+        if (formatScale != 1.0) {
+            double effectiveValue = formatScale * value;
+            formattedValue = new DecimalFormat( "#,##0.0;(#)").format(effectiveValue);
+        }
+        else {
+            formattedValue = Integer.toString(value);
+        }
+        
+        if (formatUnit != null) {
+            formattedValue += formatUnit;
+        }
+        
+        return formattedValue;
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/EventTask.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/EventTask.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/EventTask.java	(revision 1551)
@@ -0,0 +1,65 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskVisitor;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link IEventTask}. It does not do anything
+ * fancy except implementing the interface.
+ * </p> 
+ *
+ * @author Patrick Harms
+ */
+class EventTask extends Task implements IEventTask {
+    
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * simple constructor initializing this task with a description for the represented events
+     * </p>
+     * 
+     * @param type a type for the represented events
+     */
+    EventTask(String type) {
+        super(type);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#clone()
+     */
+    @Override
+    public EventTask clone() {
+        // Event type and target are unchangeable and do not need to be cloned
+        return (EventTask) super.clone();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#accept(ITaskVisitor)
+     */
+    @Override
+    public void accept(ITaskVisitor visitor) {
+        visitor.visit(this);
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/EventTaskInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/EventTaskInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/EventTaskInstance.java	(revision 1551)
@@ -0,0 +1,81 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.eventcore.Event;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+
+/**
+ * <p>
+ * Default implementation of {@link IEventTaskInstance}.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class EventTaskInstance extends TaskInstance implements IEventTaskInstance {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * <p>
+     * the event represented by this instance
+     * </p>
+     */
+    private Event event;
+
+    /**
+     * <p>
+     * initializes this instance with the respective task model and the represented event
+     * </p>
+     *
+     * @param task  the task of which this is an instance
+     * @param event the event represented by this instance
+     */
+    EventTaskInstance(IEventTask task, Event event) {
+        super(task);
+        this.event = event;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance#getEvent()
+     */
+    @Override
+    public Event getEvent() {
+        return event;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance#getEventTask()
+     */
+    @Override
+    public IEventTask getEventTask() {
+        return (IEventTask) super.getTask();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.IEventTaskInstance#clone()
+     */
+    @Override
+    public synchronized IEventTaskInstance clone() {
+        return (IEventTaskInstance) super.clone();
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Iteration.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Iteration.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Iteration.java	(revision 1551)
@@ -0,0 +1,73 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link IIteration}. It does not do anything
+ * fancy except implementing the interface.
+ * </p> 
+ *
+ * @author Patrick Harms
+ */
+class Iteration extends MarkingTemporalRelationship implements IIteration {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * simple constructor providing the base class with a human readable name of the type of this
+     * task
+     * </p>
+     */
+    Iteration() {
+        super("iteration");
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#setMarkedTask(ITask)
+     */
+    @Override
+    protected void setMarkedTask(ITask markedTask) {
+        if (markedTask instanceof IIteration) {
+            throw new IllegalArgumentException
+                ("the marked task of an iteration must not be an iteration");
+        }
+        else if (markedTask instanceof IOptional) {
+            throw new IllegalArgumentException
+                ("the marked task of an iteration must not be an optional");
+        }
+        
+        super.setMarkedTask(markedTask);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#clone()
+     */
+    @Override
+    public Iteration clone() {
+        return (Iteration) super.clone();
+    }
+    
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/IterationInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/IterationInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/IterationInstance.java	(revision 1551)
@@ -0,0 +1,181 @@
+//   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.treeimpl;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * Default implementation of {@link IIterationInstance}.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class IterationInstance extends TaskInstance implements IIterationInstance {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * the children of this task instance which are task instances, as well
+     * </p>
+     */
+    private List<ITaskInstance> children;
+
+    /**
+     * <p>
+     * initializes this instance with the respective task model
+     * </p>
+     *
+     * @param task  the task of which this is an instance
+     */
+    IterationInstance(IIteration task) {
+        super(task);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getChildren()
+     */
+    public synchronized List<ITaskInstance> getChildren() {
+        if (children == null) {
+            children = new LinkedList<ITaskInstance>();
+        }
+
+        return Collections.unmodifiableList(children);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int)
+     */
+    @Override
+    public ITaskInstance get(int index) {
+        if (children == null) {
+            throw new IndexOutOfBoundsException(Integer.toString(index));
+        }
+        else {
+            return children.get(index);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size()
+     */
+    @Override
+    public int size() {
+        if (children == null) {
+            return 0;
+        }
+        else {
+            return children.size();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Iterable#iterator()
+     */
+    @Override
+    public Iterator<ITaskInstance> iterator() {
+        return getChildren().iterator();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance#getIteration()
+     */
+    @Override
+    public IIteration getIteration() {
+        return (IIteration) super.getTask();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.IIterationInstance#clone()
+     */
+    @Override
+    public synchronized IIterationInstance clone() {
+        IterationInstance clone = (IterationInstance) super.clone();
+
+        if (children != null) {
+            clone.children = new LinkedList<ITaskInstance>();
+
+            for (ITaskInstance child : children) {
+                clone.children.add(child.clone());
+            }
+        }
+
+        return clone;
+    }
+
+    /**
+     * <p>
+     * used to add a child to this task instance
+     * </p>
+     * 
+     * @param child the new child of this instance
+     */
+    synchronized void addChild(ITaskInstance child) {
+        if (children == null) {
+            children = new LinkedList<ITaskInstance>();
+        }
+
+        children.add(child);
+    }
+
+    /**
+     * <p>
+     * used to add a child to this task instance at a specific position
+     * </p>
+     * 
+     * @param index the position of the new child in the list of children
+     * @param child the new child of this instance
+     */
+    synchronized void addChild(int index, ITaskInstance child) {
+        if (children == null) {
+            children = new LinkedList<ITaskInstance>();
+        }
+
+        children.add(index, child);
+    }
+
+    /**
+     * <p>
+     * removes a child from this task instance at a specific position
+     * </p>
+     * 
+     * @param index the position of the child to be removed
+     * 
+     * @return the child removed from the children of this instance
+     */
+    synchronized ITaskInstance removeChild(int index) {
+        if (children != null) {
+            return children.remove(index);
+        }
+        else {
+            throw new IllegalArgumentException
+                ("this task instance does not have children that can be removed");
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/MarkingTemporalRelationship.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/MarkingTemporalRelationship.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/MarkingTemporalRelationship.java	(revision 1551)
@@ -0,0 +1,98 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link IMarkingTemporalRelationship}. It
+ * does not do anything fancy except implementing the interface.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+abstract class MarkingTemporalRelationship extends Task
+    implements IMarkingTemporalRelationship
+{
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * the task marked through this marking temporal relationship
+     * </p>
+     */
+    private ITask markedTask;
+    
+    /**
+     * <p>
+     * initializes this temporal relationship with a human readable name
+     * </p>
+     *
+     * @param relationshipType the human readable name of this temporal relationship
+     */
+    MarkingTemporalRelationship(String relationshipType) {
+        super(relationshipType);
+        
+        if ((relationshipType == null) || ("".equals(relationshipType))) {
+            throw new IllegalArgumentException
+                ("the relationship type must be something meaningful");
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IMarkingTemporalRelationship#getMarkedTask()
+     */
+    @Override
+    public ITask getMarkedTask() {
+        return markedTask;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#clone()
+     */
+    @Override
+    public synchronized MarkingTemporalRelationship clone() {
+        MarkingTemporalRelationship clone = null;
+        clone = (MarkingTemporalRelationship) super.clone();
+            
+        if (markedTask != null) {
+            clone.markedTask = markedTask.clone();
+        }
+
+        return clone;
+    }
+
+    /**
+     * <p>
+     * used to set the marked task
+     * </p>
+     * 
+     * @param markedTask the marked task to set
+     */
+    protected void setMarkedTask(ITask markedTask) {
+        this.markedTask = markedTask;
+        
+        super.setDescription(markedTask.toString());
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Optional.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Optional.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Optional.java	(revision 1551)
@@ -0,0 +1,68 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link IOptional}. It does not do anything
+ * fancy except implementing the interface.
+ * </p> 
+ *
+ * @author Patrick Harms
+ */
+class Optional extends MarkingTemporalRelationship implements IOptional {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * simple constructor providing the base class with a human readable name of the type of this
+     * task
+     * </p>
+     */
+    Optional() {
+        super("optionality");
+    }
+    
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#setMarkedTask(ITask)
+     */
+    @Override
+    protected void setMarkedTask(ITask markedTask) {
+        if (markedTask instanceof IOptional) {
+            throw new IllegalArgumentException
+                ("the marked task of an optional must not be an optional");
+        }
+        
+        super.setMarkedTask(markedTask);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.MarkingTemporalRelationship#clone()
+     */
+    @Override
+    public Optional clone() {
+        return (Optional) super.clone();
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/OptionalInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/OptionalInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/OptionalInstance.java	(revision 1551)
@@ -0,0 +1,101 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptional;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * Default implementation of {@link IOptionalInstance}.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class OptionalInstance extends TaskInstance implements IOptionalInstance {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * the child of this task instance if any
+     * </p>
+     */
+    private ITaskInstance child;
+    
+    /**
+     * <p>
+     * initializes this instance with the respective task model
+     * </p>
+     *
+     * @param task  the task of which this is an instance
+     */
+    OptionalInstance(ITask task) {
+        super(task);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance#getChild()
+     */
+    @Override
+    public ITaskInstance getChild() {
+        return child;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance#getOptional()
+     */
+    @Override
+    public IOptional getOptional() {
+        return (IOptional) super.getTask();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone()
+     */
+    @Override
+    public synchronized IOptionalInstance clone() {
+        OptionalInstance clone = (OptionalInstance) super.clone();
+
+        if (child != null) {
+            clone.child = child.clone();
+        }
+
+        return clone;
+    }
+
+    /**
+     * <p>
+     * used to set the child of this task instance
+     * </p>
+     * 
+     * @param child the new child of this instance
+     */
+    void setChild(ITaskInstance child) {
+        if (child instanceof IOptionalInstance) {
+            throw new IllegalArgumentException("the child of an optional can not be an optional");
+        }
+        
+        this.child = child;
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Selection.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Selection.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Selection.java	(revision 1551)
@@ -0,0 +1,71 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link ISelection}. It does not do anything
+ * fancy except implementing the interface.
+ * </p> 
+ *
+ * @author Patrick Harms
+ */
+class Selection extends StructuringTemporalRelationship implements ISelection {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * simple constructor providing the base class with a human readable name of the type of this
+     * task
+     * </p>
+     */
+    Selection() {
+        super("selection");
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship#clone()
+     */
+    @Override
+    public Selection clone() {
+        return (Selection) super.clone();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship#addChild(ITask)
+     */
+    @Override
+    void addChild(ITask newChild) {
+        super.addChild(newChild);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship#addChild(int,ITask)
+     */
+    @Override
+    void addChild(int index, ITask newChild) {
+        super.addChild(index, newChild);
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/SelectionInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/SelectionInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/SelectionInstance.java	(revision 1551)
@@ -0,0 +1,101 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * Default implementation of {@link ISelectionInstance}.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class SelectionInstance extends TaskInstance implements ISelectionInstance {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * the child of this task instance
+     * </p>
+     */
+    private ITaskInstance child;
+    
+    /**
+     * <p>
+     * initializes this instance with the respective task model
+     * </p>
+     *
+     * @param task  the task of which this is an instance
+     */
+    SelectionInstance(ITask task) {
+        super(task);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance#getChild()
+     */
+    @Override
+    public ITaskInstance getChild() {
+        return child;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance#getSelection()
+     */
+    @Override
+    public ISelection getSelection() {
+        return (ISelection) super.getTask();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone()
+     */
+    @Override
+    public synchronized ISelectionInstance clone() {
+        SelectionInstance clone = (SelectionInstance) super.clone();
+
+        if (child != null) {
+            clone.child = child.clone();
+        }
+
+        return clone;
+    }
+
+    /**
+     * <p>
+     * used to set the child of this task instance
+     * </p>
+     * 
+     * @param child the new child of this instance
+     */
+    void setChild(ITaskInstance child) {
+        if (child instanceof ISelectionInstance) {
+            throw new IllegalArgumentException("the child of a selection can not be a selection");
+        }
+        
+        this.child = child;
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Sequence.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Sequence.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Sequence.java	(revision 1551)
@@ -0,0 +1,54 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link ISequence}. It does not do anything
+ * fancy except implementing the interface.
+ * </p> 
+ *
+ * @author Patrick Harms
+ */
+class Sequence extends StructuringTemporalRelationship implements ISequence {
+    
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * simple constructor providing the base class with a human readable name of the type of this
+     * task
+     * </p>
+     */
+    Sequence() {
+        super("sequence");
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.StructuringTemporalRelationship#clone()
+     */
+    @Override
+    public Sequence clone() {
+        return (Sequence) super.clone();
+    }
+    
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/SequenceInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/SequenceInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/SequenceInstance.java	(revision 1551)
@@ -0,0 +1,182 @@
+//   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.treeimpl;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+
+/**
+ * <p>
+ * Default implementation of {@link IIterationInstance}.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class SequenceInstance extends TaskInstance implements ISequenceInstance {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * the children of this task instance which are task instances, as well
+     * </p>
+     */
+    private List<ITaskInstance> children;
+
+    /**
+     * <p>
+     * initializes this instance with the respective task model
+     * </p>
+     *
+     * @param task  the task of which this is an instance
+     */
+    SequenceInstance(ISequence task) {
+        super(task);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getChildren()
+     */
+    public synchronized List<ITaskInstance> getChildren() {
+        if (children == null) {
+            children = new LinkedList<ITaskInstance>();
+        }
+
+        return Collections.unmodifiableList(children);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int)
+     */
+    @Override
+    public ITaskInstance get(int index) {
+        if (children == null) {
+            throw new IndexOutOfBoundsException(Integer.toString(index));
+        }
+        else {
+            return children.get(index);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size()
+     */
+    @Override
+    public int size() {
+        if (children == null) {
+            return 0;
+        }
+        else {
+            return children.size();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Iterable#iterator()
+     */
+    @Override
+    public Iterator<ITaskInstance> iterator() {
+        return getChildren().iterator();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ISequenceInstance#getSequence()
+     */
+    @Override
+    public ISequence getSequence() {
+        return (ISequence) super.getTask();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.ISequenceInstance#clone()
+     */
+    @Override
+    public synchronized ISequenceInstance clone() {
+        SequenceInstance clone = (SequenceInstance) super.clone();
+
+        if (children != null) {
+            clone.children = new LinkedList<ITaskInstance>();
+
+            for (ITaskInstance child : children) {
+                clone.children.add(child.clone());
+            }
+        }
+
+        return clone;
+    }
+
+    /**
+     * <p>
+     * used to add a child to this task instance
+     * </p>
+     * 
+     * @param child the new child of this instance
+     */
+    synchronized void addChild(ITaskInstance child) {
+        if (children == null) {
+            children = new LinkedList<ITaskInstance>();
+        }
+
+        children.add(child);
+    }
+
+    /**
+     * <p>
+     * used to add a child to this task instance at a specific position
+     * </p>
+     * 
+     * @param index the position of the new child in the list of children
+     * @param child the new child of this instance
+     */
+    synchronized void addChild(int index, ITaskInstance child) {
+        if (children == null) {
+            children = new LinkedList<ITaskInstance>();
+        }
+
+        children.add(index, child);
+    }
+
+    /**
+     * <p>
+     * removes a child from this task instance at a specific position
+     * </p>
+     * 
+     * @param index the position of the child to be removed
+     * 
+     * @return the child removed from the children of this instance
+     */
+    synchronized ITaskInstance removeChild(int index) {
+        if (children != null) {
+            return children.remove(index);
+        }
+        else {
+            throw new IllegalArgumentException
+                ("this task instance does not have children that can be removed");
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/StructuringTemporalRelationship.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/StructuringTemporalRelationship.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/StructuringTemporalRelationship.java	(revision 1551)
@@ -0,0 +1,123 @@
+//   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.treeimpl;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link IStructuringTemporalRelationship}. It
+ * does not do anything fancy except implementing the interface.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+abstract class StructuringTemporalRelationship extends Task
+    implements IStructuringTemporalRelationship
+{
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * <p>
+     * the list of children of this temporal relationship
+     * </p>
+     */
+    private List<ITask> children = new LinkedList<ITask>();
+
+    /**
+     * <p>
+     * initializes this temporal relationship with a human readable name
+     * </p>
+     *
+     * @param relationshipType the human readable name of this temporal relationship
+     */
+    StructuringTemporalRelationship(String relationshipType) {
+        super(relationshipType);
+        
+        if ((relationshipType == null) || ("".equals(relationshipType))) {
+            throw new IllegalArgumentException
+                ("the relationship type must be something meaningful");
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship#getChildren()
+     */
+    @Override
+    public List<ITask> getChildren() {
+        return children;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeimpl.Task#clone()
+     */
+    @Override
+    public synchronized StructuringTemporalRelationship clone() {
+        StructuringTemporalRelationship clone = null;
+        clone = (StructuringTemporalRelationship) super.clone();
+            
+        clone.children = new LinkedList<ITask>();
+        
+        for (ITask child : this.children) {
+            clone.children.add(child.clone());
+        }
+
+        return clone;
+    }
+
+    /**
+     * <p>
+     * used to add a new child to this temporal relationship.
+     * </p>
+     *
+     * @param newChild the new child to be added
+     */
+    void addChild(ITask newChild) {
+        children.add(newChild);
+    }
+
+    /**
+     * <p>
+     * used to add a new child to this temporal relationship at a specific position.
+     * </p>
+     *
+     * @param index    the index of the new child to be added.
+     * @param newChild the new child to be added
+     */
+    void addChild(int index, ITask newChild) {
+        children.add(index, newChild);
+    }
+    
+    /**
+     * <p>
+     * removes a child from this temporal relationship at a specific position.
+     * </p>
+     *
+     * @param index the index of the child to be removed.
+     */
+    void removeChild(int index) {
+        children.remove(index);
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Task.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Task.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/Task.java	(revision 1551)
@@ -0,0 +1,367 @@
+//   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.treeimpl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IOptionalInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelectionInstance;
+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.ITaskVisitor;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link ITask}. It
+ * does not do anything fancy except implementing the interface.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+abstract class Task implements ITask {
+
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * used as a counter to generate new ids for each newly created task. May overflow.
+     * </p>
+     */
+    private static int temporalId = 0;
+
+    /**
+     * <p>
+     * the id of the task (unique throughout the system as long as {@link #temporalId} does not
+     * overflow.
+     * </p>
+     */
+    private int id;
+    
+    /**
+     * <p>
+     * a human readable type of the task (used for visualization purposes)
+     * </p>
+     */
+    private String type;
+
+    /**
+     * <p>
+     * a human readable description of the task
+     * </p>
+     */
+    private String description;
+    
+    /**
+     * <p>
+     * the instances of this task
+     * </p>
+     */
+    private Collection<ITaskInstance> instances = new HashSet<ITaskInstance>();
+    
+    /**
+     * <p>
+     * the execution variants of this task
+     * </p>
+     */
+    private Collection<Collection<ITaskInstance>> executionVariants;
+
+    /**
+     * <p>
+     * constructs a new task with a new id. The id is generated using the {@link #getNewId()}
+     * method
+     * </p>
+     * 
+     * @param type the human readable type of the task
+     * 
+     * @throws IllegalArgumentException in the case the provided type is null
+     */
+    Task(String type) {
+        this.id = getNewId();
+        this.type = type;
+        
+        if (type == null) {
+            throw new IllegalArgumentException("type must not be null");
+        }
+    }
+
+    /**
+     * <p>
+     * creates a new id for a task using {@link #temporalId} by incrementing it an returning its
+     * current value. Resets the counter if {@link Integer.MAX_VALUE} is reached.
+     * </p>
+     * 
+     * @return a new unique id for a task as long as {@link #temporalId} does not overflow
+     */
+    private static synchronized int getNewId() {
+        if (temporalId == Integer.MAX_VALUE) {
+            temporalId = 0;
+        }
+
+        return temporalId++;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#geId()
+     */
+    @Override
+    public int getId() {
+        return id;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getType()
+     */
+    @Override
+    public String getType() {
+        return type;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getDescription()
+     */
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getInstances()
+     */
+    @Override
+    public Collection<ITaskInstance> getInstances() {
+        return Collections.unmodifiableCollection(instances);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#getExecutionVariants()
+     */
+    @Override
+    public synchronized Collection<Collection<ITaskInstance>> getExecutionVariants() {
+        if (executionVariants == null) {
+            executionVariants = new LinkedList<Collection<ITaskInstance>>();
+            determineExecutionVariants(executionVariants);
+        }
+        
+        return executionVariants;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#equals(ITask)
+     */
+    @Override
+    public final boolean equals(ITask task) {
+        // tasks are only equal if they are identical or if they have the same id
+        // (may happen, if they are cloned)
+        return (this == task) || (this.hashCode() == task.hashCode());
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#hashCode()
+     */
+    @Override
+    public synchronized int hashCode() {
+        return id;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public synchronized String toString() {
+        StringBuffer result = new StringBuffer();
+        result.append(type);
+        result.append(" #");
+        result.append(id);
+        
+        if (description != null) {
+            result.append(" (");
+            result.append(description);
+            result.append(')');
+        }
+        
+        return result.toString();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#clone()
+     */
+    @Override
+    public synchronized ITask clone() {
+        Task clone = null;
+        try {
+            clone = (Task) super.clone();
+        }
+        catch (CloneNotSupportedException e) {
+            // this should never happen. Therefore simply dump the exception
+            e.printStackTrace();
+        }
+
+        return clone;
+    }
+
+    /**
+     * <p>
+     * internally used to set the human readable description of the task
+     * </p>
+     * 
+     * @param description the new human readable description of the task
+     */
+    void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * <p>
+     * internally used to remove an instance from this task
+     * </p>
+     * 
+     * @param instance the instance to be removed from this task
+     */
+    synchronized void removeInstance(ITaskInstance instance) {
+        this.instances.remove(instance);
+        this.executionVariants = null;
+    }
+
+    /**
+     * <p>
+     * internally used to add an instance to this task
+     * </p>
+     * 
+     * @param instance the instance belonging to this task
+     */
+    synchronized void addInstance(ITaskInstance instance) {
+        this.instances.add(instance);
+        this.executionVariants = null;
+    }
+    
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITask#accept(ITaskVisitor)
+     */
+    @Override
+    public void accept(ITaskVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    /**
+     *
+     */
+    private void determineExecutionVariants(Collection<Collection<ITaskInstance>> executionVariants)
+    {
+        for (ITaskInstance instance : instances) {
+            boolean added = false;
+            for (Collection<ITaskInstance> variant : executionVariants) {
+                if (!variant.isEmpty() && (isSameExecution(variant.iterator().next(), instance))) {
+                    variant.add(instance);
+                    added = true;
+                }
+            }
+            
+            if (!added) {
+                Collection<ITaskInstance> variant = new HashSet<ITaskInstance>();
+                variant.add(instance);
+                executionVariants.add(variant);
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    private boolean isSameExecution(ITaskInstance instance1, ITaskInstance instance2) {
+        if (instance1 instanceof IIterationInstance) {
+            if (!(instance2 instanceof IIterationInstance)) {
+                return false;
+            }
+            
+            ITaskInstanceList iteration1 = (ITaskInstanceList) instance1;
+            ITaskInstanceList iteration2 = (ITaskInstanceList) instance2;
+            
+            return isSameExecutionList(iteration1, iteration2);
+        }
+        else if (instance1 instanceof ISequenceInstance) {
+            if (!(instance2 instanceof ISequenceInstance)) {
+                return false;
+            }
+            
+            ITaskInstanceList selection1 = (ITaskInstanceList) instance1;
+            ITaskInstanceList selection2 = (ITaskInstanceList) instance2;
+            
+            return isSameExecutionList(selection1, selection2);
+        }
+        else if (instance1 instanceof ISelectionInstance) {
+            if (!(instance2 instanceof ISelectionInstance)) {
+                return false;
+            }
+            else {
+                return isSameExecution(((ISelectionInstance) instance1).getChild(),
+                                       ((ISelectionInstance) instance2).getChild());
+            }
+        }
+        else if (instance1 instanceof IOptionalInstance) {
+            if (!(instance2 instanceof IOptionalInstance)) {
+                return false;
+            }
+            else {
+                return isSameExecution(((IOptionalInstance) instance1).getChild(),
+                                       ((IOptionalInstance) instance2).getChild());
+            }
+        }
+        else if (instance1 instanceof IEventTaskInstance) {
+            if (!(instance2 instanceof IEventTaskInstance)) {
+                return false;
+            }
+            else {
+                return ((IEventTaskInstance) instance1).getTask().equals
+                    (((IEventTaskInstance) instance2).getTask());
+            }
+        }
+        else if (instance1 == null) {
+            return instance2 == null;
+        }
+        else {
+            throw new IllegalArgumentException("unknown type of task instance: " + instance1);
+        }
+    }
+
+    /**
+     *
+     */
+    private boolean isSameExecutionList(ITaskInstanceList list1, ITaskInstanceList list2) {
+        if (list1.size() == list2.size()) {
+            for (int i = 0; i < list1.size(); i++) {
+                if (!isSameExecution(list1.get(i), list2.get(i))) {
+                    return false;
+                }
+            }
+            
+            return true;
+        }
+        else {
+            return false;
+        }
+    }
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskBuilder.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskBuilder.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskBuilder.java	(revision 1551)
@@ -0,0 +1,550 @@
+//   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.treeimpl;
+
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
+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.ISequenceInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IStructuringTemporalRelationship;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskBuilder;
+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>
+ * this is the default implementation of the interface {@link ITaskBuilder}. It
+ * does not do anything fancy except implementing the interface. In some situations, it performs
+ * a check if the model or instances to be created a valid. However, this can not be done
+ * in any situation of the creation process.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class TaskBuilder implements ITaskBuilder {
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addChild(ISequenceInstance, ITaskInstance)
+     */
+    @Override
+    public void addChild(ISequenceInstance instance, ITaskInstance child)
+        throws IllegalArgumentException
+    {
+        if (!(instance instanceof SequenceInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of sequence instance provided: " + instance.getClass());
+        }
+
+        if (!(child instanceof TaskInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of task instance provided: " + child.getClass());
+        }
+        
+        SequenceInstance seqInstance = (SequenceInstance) instance;
+        
+        // check if new child instance matches the model, if this can be checked
+        IStructuringTemporalRelationship parentTask =
+            (IStructuringTemporalRelationship) instance.getTask();
+        
+        if (((parentTask.getChildren() != null) && (parentTask.getChildren().size() > 0)) &&
+            ((parentTask.getChildren().size() <= seqInstance.size()) ||
+             (!parentTask.getChildren().get(seqInstance.size()).equals(child.getTask()))))
+        {
+            throw new IllegalArgumentException
+                ("the task of the child instance to be added does not belong to the children " +
+                 "of the task of the parent instance");
+        }
+
+        seqInstance.addChild(child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addChild(ISequenceInstance, int, ITaskInstance)
+     */
+    public void addChild(ISequenceInstance instance, int index, ITaskInstance child)
+        throws IllegalArgumentException
+    {
+        if (!(instance instanceof SequenceInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of sequence instance provided: " + instance.getClass());
+        }
+
+        if (!(child instanceof TaskInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of task instance provided: " + child.getClass());
+        }
+        
+        SequenceInstance seqInstance = (SequenceInstance) instance;
+        
+        // check if new child instance matches the model, if this can be checked
+        IStructuringTemporalRelationship parentTask =
+            (IStructuringTemporalRelationship) instance.getTask();
+        
+        if (((parentTask.getChildren() != null) && (parentTask.getChildren().size() > 0)) &&
+            ((parentTask.getChildren().size() <= index) ||
+             (!parentTask.getChildren().get(index).equals(child.getTask()))))
+        {
+            throw new IllegalArgumentException
+                ("the task of the child instance to be added does not belong to the children " +
+                 "of the task of the parent instance");
+        }
+        
+        seqInstance.addChild(index, child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addChild(IIterationInstance, ITaskInstance)
+     */
+    @Override
+    public void addChild(IIterationInstance instance, ITaskInstance child)
+        throws IllegalArgumentException
+    {
+        if (!(instance instanceof IterationInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of iteration instance provided: " + instance.getClass());
+        }
+
+        if (!(child instanceof TaskInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of task instance provided: " + child.getClass());
+        }
+        
+        // check if new child instance matches the model, if this can be checked
+        IMarkingTemporalRelationship parentTask =
+            (IMarkingTemporalRelationship) instance.getTask();
+                
+        boolean foundChildTask = parentTask.getMarkedTask() != null ?
+            parentTask.getMarkedTask().equals(child.getTask()) : true;
+                
+        if (!foundChildTask) {
+            throw new IllegalArgumentException
+                ("the task of the child instance does not match the model of the task of the " +
+                 "iteration instance: " + parentTask.getMarkedTask() + " <> " + child.getTask());
+        }
+
+        ((IterationInstance) instance).addChild(child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addChild(IIterationInstance, int, ITaskInstance)
+     */
+    public void addChild(IIterationInstance instance, int index, ITaskInstance child)
+        throws IllegalArgumentException
+    {
+        if (!(instance instanceof IterationInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of iteration instance provided: " + instance.getClass());
+        }
+
+        if (!(child instanceof TaskInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of task instance provided: " + child.getClass());
+        }
+        
+        // check if new child instance matches the model, if this can be checked
+        IMarkingTemporalRelationship parentTask =
+            (IMarkingTemporalRelationship) instance.getTask();
+                
+        boolean foundChildTask = parentTask.getMarkedTask() != null ?
+            parentTask.getMarkedTask().equals(child.getTask()) : true;
+                
+        if (!foundChildTask) {
+            throw new IllegalArgumentException
+                ("the task of the child instance does not match the model of the task of the " +
+                 "iteration instance: " + parentTask.getMarkedTask() + " <> " + child.getTask());
+        }
+
+        ((IterationInstance) instance).addChild(index, child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#setChild(ISelectionInstance, ITaskInstance)
+     */
+    @Override
+    public void setChild(ISelectionInstance instance, ITaskInstance child)
+        throws IllegalArgumentException
+    {
+        if (!(instance instanceof SelectionInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of selection instance provided: " + instance.getClass());
+        }
+
+        if (!(child instanceof TaskInstance)) {
+            throw new IllegalArgumentException("illegal type of task instance provided: " +
+                                               (child == null ? null : child.getClass()));
+        }
+        
+        // check if new child instance matches the model, if this can be checked
+        IStructuringTemporalRelationship parentTask =
+            (IStructuringTemporalRelationship) instance.getTask();
+        
+        boolean foundChildTask = false;
+        for (ITask parentTaskChild : parentTask.getChildren()) {
+            if (parentTaskChild.equals(child.getTask())) {
+                foundChildTask = true;
+                break;
+            }
+        }
+            
+        if (!foundChildTask) {
+            throw new IllegalArgumentException
+                ("the task of the child instance to be added does not belong to the children " +
+                 "of the selection task model of the parent instance");
+        }
+
+        ((SelectionInstance) instance).setChild(child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#setChild(IOptionalInstance, ITaskInstance)
+     */
+    @Override
+    public void setChild(IOptionalInstance instance, ITaskInstance child)
+        throws IllegalArgumentException
+    {
+        if (!(instance instanceof OptionalInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of optional instance provided: " + instance.getClass());
+        }
+
+        if (!(child instanceof TaskInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of task instance provided: " + child.getClass());
+        }
+        
+        // check if new child instance matches the model, if this can be checked
+        IMarkingTemporalRelationship parentTask =
+            (IMarkingTemporalRelationship) instance.getTask();
+            
+        boolean foundChildTask = parentTask.getMarkedTask() != null ?
+            parentTask.getMarkedTask().equals(child.getTask()) : true;
+            
+        if (!foundChildTask) {
+            throw new IllegalArgumentException
+                ("the task of the child instance does not match the model of the task of the " +
+                 "optional instance: " + parentTask.getMarkedTask() + " <> " + child.getTask());
+        }
+
+        ((OptionalInstance) instance).setChild(child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addExecutedTask(IUserSession, ITaskInstance)
+     */
+    @Override
+    public void addExecutedTask(IUserSession session, ITaskInstance taskInstance) {
+        if (!(session instanceof UserSession)) {
+            throw new IllegalArgumentException
+                ("illegal type of session provided: " + session.getClass());
+        }
+
+        if (!(taskInstance instanceof TaskInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of task instance provided: " + taskInstance.getClass());
+        }
+        
+        ((UserSession) session).addExecutedTask(taskInstance);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addExecutedTask(IUserSession, int, ITaskInstance)
+     */
+    public void addExecutedTask(IUserSession session, int index, ITaskInstance taskInstance) {
+        if (!(session instanceof UserSession)) {
+            throw new IllegalArgumentException
+                ("illegal type of session provided: " + session.getClass());
+        }
+
+        if (!(taskInstance instanceof TaskInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of task instance provided: " + taskInstance.getClass());
+        }
+        
+        ((UserSession) session).addExecutedTask(index, taskInstance);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addTaskInstance(ITaskInstanceList, ITaskInstance)
+     */
+    @Override
+    public void addTaskInstance(ITaskInstanceList taskInstanceList, ITaskInstance taskInstance) {
+        if (taskInstanceList instanceof SequenceInstance) {
+            addChild((SequenceInstance) taskInstanceList, taskInstance);
+        }
+        else if (taskInstanceList instanceof IterationInstance) {
+            addChild((IterationInstance) taskInstanceList, taskInstance);
+        }
+        else if (taskInstanceList instanceof UserSession) {
+            addExecutedTask((UserSession) taskInstanceList, taskInstance);
+        }
+        else {
+            throw new IllegalArgumentException
+                ("illegal type of task instance list provided: " + taskInstanceList.getClass());
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addTaskInstance(ITaskInstanceList, int, ITaskInstance)
+     */
+    @Override
+    public void addTaskInstance(ITaskInstanceList taskInstanceList,
+                                int               index,
+                                ITaskInstance     taskInstance)
+    {
+        if (taskInstanceList instanceof SequenceInstance) {
+            addChild((SequenceInstance) taskInstanceList, index, taskInstance);
+        }
+        else if (taskInstanceList instanceof IterationInstance) {
+            addChild((IterationInstance) taskInstanceList, index, taskInstance);
+        }
+        else if (taskInstanceList instanceof UserSession) {
+            addExecutedTask((UserSession) taskInstanceList, index, taskInstance);
+        }
+        else {
+            throw new IllegalArgumentException
+                ("illegal type of task instance list provided: " + taskInstanceList.getClass());
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#setTaskInstance(ITaskInstanceList, int, ITaskInstance)
+     */
+    @Override
+    public void setTaskInstance(ITaskInstanceList taskInstanceList,
+                                int               index,
+                                ITaskInstance     taskInstance)
+    {
+        removeTaskInstance(taskInstanceList, index);
+        addTaskInstance(taskInstanceList, index, taskInstance);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#setTask(ITaskInstance, ITask)
+     */
+    @Override
+    public void setTask(ITaskInstance taskInstance, ITask task) {
+        if (!(taskInstance instanceof TaskInstance)) {
+            throw new IllegalArgumentException
+                ("illegal type of task instance provided: " + taskInstance.getClass());
+        }
+        if (!(task instanceof Task)) {
+            throw new IllegalArgumentException("illegal type of task provided: " + task.getClass());
+        }
+        
+        if (((TaskInstance) taskInstance).getTask() instanceof Task) {
+            ((Task) ((TaskInstance) taskInstance).getTask()).removeInstance(taskInstance);
+        }
+        ((TaskInstance) taskInstance).setTask(task);
+        
+        ((Task) task).addInstance(taskInstance);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addChild(ISequence, ITask)
+     */
+    @Override
+    public void addChild(ISequence parent, ITask child) {
+        if (!(parent instanceof Sequence)) {
+            throw new IllegalArgumentException
+                ("illegal type of sequence provided: " + parent.getClass());
+        }
+
+        addChildInternal((Sequence) parent, -1, child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addChild(ISequence, int, ITask)
+     */
+    @Override
+    public void addChild(ISequence parent, int index, ITask child) {
+        if (!(parent instanceof Sequence)) {
+            throw new IllegalArgumentException
+                ("illegal type of sequence provided: " + parent.getClass());
+        }
+
+        addChildInternal((Sequence) parent, index, child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#setChild(ISequence, int, ITask)
+     */
+    @Override
+    public void setChild(ISequence parent, int index, ITask child) {
+        if (!(parent instanceof Sequence)) {
+            throw new IllegalArgumentException
+                ("illegal type of sequence provided: " + parent.getClass());
+        }
+
+        ((Sequence) parent).removeChild(index);
+        addChildInternal((Sequence) parent, index, child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#addChild(ISelection, ITask)
+     */
+    @Override
+    public void addChild(ISelection parent, ITask child) {
+        if (!(parent instanceof Selection)) {
+            throw new IllegalArgumentException
+                ("illegal type of selection provided: " + parent.getClass());
+        }
+
+        addChildInternal((Selection) parent, -1, child);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#setMarkedTask(IIteration, ITask)
+     */
+    @Override
+    public void setMarkedTask(IIteration iteration, ITask newChild) {
+        if (!(iteration instanceof Iteration)) {
+            throw new IllegalArgumentException
+                ("illegal type of iteration provided: " + iteration.getClass());
+        }
+
+        if (!(newChild instanceof Task)) {
+            throw new IllegalArgumentException
+                ("illegal type of task provided: " + newChild.getClass());
+        }
+
+        ((Iteration) iteration).setMarkedTask(newChild);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskTreeBuilder#setChild(IOptional, ITaskTreeNode)
+     */
+    @Override
+    public void setMarkedTask(IOptional optional, ITask newChild) {
+        if (!(optional instanceof Optional)) {
+            throw new IllegalArgumentException
+                ("illegal type of optional provided: " + optional.getClass());
+        }
+
+        if (!(newChild instanceof Task)) {
+            throw new IllegalArgumentException
+                ("illegal type of task provided: " + newChild.getClass());
+        }
+
+        ((Optional) optional).setMarkedTask(newChild);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#removeChild(ISequence, int)
+     */
+    @Override
+    public void removeChild(ISequence parent, int index) {
+        if (!(parent instanceof Sequence)) {
+            throw new IllegalArgumentException
+                ("illegal type of sequence provided: " + parent.getClass());
+        }
+
+        ((Sequence) parent).removeChild(index);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#removeChild(ISelection, ITask)
+     */
+    @Override
+    public void removeChild(ISelection parent, ITask child) {
+        if (!(parent instanceof Selection)) {
+            throw new IllegalArgumentException
+                ("illegal type of selection provided: " + parent.getClass());
+        }
+
+        List<ITask> children = parent.getChildren();
+        
+        for (int i = 0; i < children.size(); i++) {
+            if ((children.get(i) == child) ||
+                ((children.get(i) != null) && (children.get(i).equals(child))))
+            {
+                ((Selection) parent).removeChild(i);
+                break;
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskBuilder#removeTaskInstance(ITaskInstanceList, int)
+     */
+    @Override
+    public void removeTaskInstance(ITaskInstanceList taskInstanceList, int index) {
+        if (taskInstanceList instanceof SequenceInstance) {
+            ((SequenceInstance) taskInstanceList).removeChild(index);
+        }
+        else if (taskInstanceList instanceof IterationInstance) {
+            ((IterationInstance) taskInstanceList).removeChild(index);
+        }
+        else if (taskInstanceList instanceof UserSession) {
+            ((UserSession) taskInstanceList).removeExecutedTask(index);
+        }
+        else {
+            throw new IllegalArgumentException
+                ("illegal type of task instance list provided: " + taskInstanceList.getClass());
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskTreeBuilder#replaceChild(ISelection, ITaskTreeNode, ITaskTreeNode)
+     */
+    @Override
+    public void replaceChild(ISelection parent, ITask oldChild, ITask newChild) {
+        if (!(parent instanceof Selection)) {
+            throw new IllegalArgumentException
+                ("illegal type of selection provided: " + parent.getClass());
+        }
+
+        List<ITask> children = parent.getChildren();
+        
+        for (int i = 0; i < children.size(); i++) {
+            if ((children.get(i) == oldChild) ||
+                ((children.get(i) != null) && (children.get(i).equals(oldChild))))
+            {
+                ((Selection) parent).removeChild(i);
+                ((Selection) parent).addChild(i, newChild);
+                break;
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * internal convenience method for adding children to a structuring temporal relationship
+     * including a check for the child type.
+     * </p>
+     */
+    private void addChildInternal(StructuringTemporalRelationship parent, int index, ITask child) {
+        if (!(child instanceof Task)) {
+            throw new IllegalArgumentException
+                ("illegal type of task provided: " + child.getClass());
+        }
+
+        if (index > -1) {
+            parent.addChild(index, child);
+        }
+        else {
+            parent.addChild(child);
+        }
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskFactory.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskFactory.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskFactory.java	(revision 1551)
@@ -0,0 +1,181 @@
+//   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.treeimpl;
+
+import java.util.List;
+
+import de.ugoe.cs.autoquest.eventcore.Event;
+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.ITaskModel;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskFactory;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link ITaskFactory}. It
+ * does not do anything fancy except implementing the interface. It instantiates the other
+ * implementations of the tree ifc in this package.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class TaskFactory implements ITaskFactory {
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewEventTask(String)
+     */
+    @Override
+    public IEventTask createNewEventTask(String description) {
+        return new EventTask(description);
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewSequence()
+     */
+    @Override
+    public ISequence createNewSequence() {
+        return new Sequence();
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewIteration()
+     */
+    @Override
+    public IIteration createNewIteration() {
+        return new Iteration();
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewOptional()
+     */
+    @Override
+    public IOptional createNewOptional() {
+        return new Optional();
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewSelection()
+     */
+    @Override
+    public ISelection createNewSelection() {
+        return new Selection();
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewTaskInstance(IEventTask, Event)
+     */
+    @Override
+    public IEventTaskInstance createNewTaskInstance(IEventTask task, Event event) {
+        if (!(task instanceof EventTask)) {
+            throw new IllegalArgumentException
+                ("illegal type of event task provided: " + task.getClass());
+        }
+        
+        EventTaskInstance instance = new EventTaskInstance(task, event);
+        ((EventTask) task).addInstance(instance);
+        
+        return instance;
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewTaskInstance(ISequence)
+     */
+    @Override
+    public ISequenceInstance createNewTaskInstance(ISequence sequence) {
+        if (!(sequence instanceof Sequence)) {
+            throw new IllegalArgumentException
+                ("illegal type of sequence provided: " + sequence.getClass());
+        }
+        
+        SequenceInstance instance = new SequenceInstance(sequence);
+        ((Sequence) sequence).addInstance(instance);
+        
+        return instance;
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewTaskInstance(IIteration)
+     */
+    @Override
+    public IIterationInstance createNewTaskInstance(IIteration iteration) {
+        if (!(iteration instanceof Iteration)) {
+            throw new IllegalArgumentException
+                ("illegal type of iteration provided: " + iteration.getClass());
+        }
+        
+        IterationInstance instance = new IterationInstance(iteration);
+        ((Iteration) iteration).addInstance(instance);
+        
+        return instance;
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewTaskInstance(IOptional)
+     */
+    @Override
+    public IOptionalInstance createNewTaskInstance(IOptional optional) {
+        if (!(optional instanceof Optional)) {
+            throw new IllegalArgumentException
+                ("illegal type of optional provided: " + optional.getClass());
+        }
+        
+        OptionalInstance instance = new OptionalInstance(optional);
+        ((Optional) optional).addInstance(instance);
+        
+        return instance;
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createNewTaskInstance(ISelection)
+     */
+    @Override
+    public ISelectionInstance createNewTaskInstance(ISelection selection) {
+        if (!(selection instanceof Selection)) {
+            throw new IllegalArgumentException
+                ("illegal type of optional provided: " + selection.getClass());
+        }
+        
+        SelectionInstance instance = new SelectionInstance(selection);
+        ((Selection) selection).addInstance(instance);
+        
+        return instance;
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createUserSession()
+     */
+    @Override
+    public IUserSession createUserSession() {
+        return new UserSession();
+    }
+
+    /* (non-Javadoc)
+     * @see ITaskFactory#createTaskModel(List<IUserSession>)
+     */
+    @Override
+    public ITaskModel createTaskModel(List<IUserSession> userSessions) {
+        return new TaskModel(userSessions);
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskInfo.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskInfo.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskInfo.java	(revision 1551)
@@ -0,0 +1,303 @@
+//   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.treeimpl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link ITaskInfo}. It
+ * does not do anything fancy except implementing the interface.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class TaskInfo implements ITaskInfo {
+    
+    /**
+     * <p>
+     * the task to which the infos belong
+     * </p>
+     */
+    private ITask task;
+    
+    /**
+     * <p>
+     * all available measures for the task
+     * </p>
+     */
+    private ArrayList<Measure> measures = new ArrayList<Measure>();
+
+    /**
+     * <p>
+     * initialized the task infos with the task to which they belong.
+     * </p>
+     * 
+     * @param task
+     */
+    TaskInfo(ITask task) {
+        this.task = task;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getTask()
+     */
+    @Override
+    public ITask getTask() {
+        return task;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasures()
+     */
+    @Override
+    public IMeasure[] getMeasures() {
+        measures.trimToSize();
+        return measures.toArray(new IMeasure[measures.size()]);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasureValue(java.lang.String)
+     */
+    @Override
+    public int getMeasureValue(TaskMetric metric) {
+        Measure measure = getMeasure(metric);
+        
+        if (measure == null) {
+            throw new IllegalArgumentException("unknown metric " + metric);
+        }
+        
+        return measure.getValue();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo#getMeasureValue(java.lang.String, de.ugoe.cs.autoquest.tasktrees.treeifc.ITask)
+     */
+    @Override
+    public int getMeasureValue(TaskMetric metric, ITask context) {
+        Measure measure = getMeasure(metric);
+        
+        if (measure == null) {
+            throw new IllegalArgumentException("unknown metric " + metric);
+        }
+        
+        return measure.getValue(context);
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public synchronized String toString() {
+        return "TaskInfo(" + task + ")";
+    }
+
+    /**
+     * <p>
+     * must be called to indicate that a new new measures for the provided metric are about to
+     * be calculated and added.
+     * </p>
+     *
+     * @param metric the metric for which measures are about to be provided
+     */
+    void addMeasure(TaskMetric metric) {
+        Measure measure = getMeasure(metric);
+        
+        if (measure != null) {
+            throw new IllegalArgumentException("measure for metric " + metric + " already exists.");
+        }
+        
+        measure = new Measure(metric);
+        measures.add(measure);
+    }
+
+    /**
+     * <p>
+     * sets a specific value for a measure of a specific metric in the provided context of the task
+     * </p>
+     * 
+     * @param metric  the metric to which the value belongs
+     * @param context the context of the task in which the measure was recorded
+     * @param value   the value of the measure
+     */
+    void setCount(TaskMetric metric, ITask context, int value) {
+        Measure measure = getMeasure(metric);
+        
+        if (measure == null) {
+            throw new IllegalArgumentException("unknown metric. Please create a measure " +
+                                               "for the metric before using it.");
+        }
+        
+        measure.set(context, value);
+    }
+
+    /**
+     * <p>
+     * increases a specific value for a measure of a specific metric in the provided context of the
+     * task
+     * </p>
+     * 
+     * @param metric    the metric to which the value belongs
+     * @param context   the context of the task in which the measure was recorded
+     * @param increment the increment to be added to the value of the measure
+     */
+    void increaseCount(TaskMetric metric, ITask context, int increment) {
+        Measure measure = getMeasure(metric);
+        
+        if (measure == null) {
+            throw new IllegalArgumentException("unknown metric. Please create a measure " +
+                                               "for the metric before using it.");
+        }
+        
+        measure.increase(context, increment);
+    }
+
+    /**
+     * <p>
+     * convenience method to internally determine the measure for a specific metric
+     * </p>
+     */
+    private Measure getMeasure(TaskMetric metric) {
+        for (Measure candidate : measures) {
+            if (candidate.getMetric().equals(metric)) {
+                return candidate;
+            }
+        }
+        
+        return null;
+    }
+
+    /**
+     * <p>
+     * implementation for the measure interface of the task info interface. Does nothing fancy
+     * except implementing the interface
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private static class Measure implements IMeasure {
+
+        /**
+         * <p>
+         * the metric to which the measure belongs
+         * </p>
+         */
+        private TaskMetric metric;
+        
+        /**
+         * <p>
+         * the observed values for the difference contexts of the task
+         * </p>
+         */
+        private HashMap<ITask, Integer> values;
+        
+        /**
+         * <p>
+         * the context free value of the measure independent of the task context
+         * </p>
+         */
+        private int contextFreeValue = 0;
+        
+        /**
+         * <p>
+         * initializes the measure with a specific metric
+         * </p>
+         */
+        private Measure(TaskMetric metric) {
+            super();
+            this.metric = metric;
+        }
+
+        /* (non-Javadoc)
+         * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getMetric()
+         */
+        @Override
+        public TaskMetric getMetric() {
+            return metric;
+        }
+
+        /* (non-Javadoc)
+         * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getValue()
+         */
+        @Override
+        public int getValue() {
+            return contextFreeValue;
+        }
+
+        /* (non-Javadoc)
+         * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo.IMeasure#getValue(de.ugoe.cs.autoquest.tasktrees.treeifc.ITask)
+         */
+        @Override
+        public int getValue(ITask context) {
+            if ((context != null) && (values != null)) {
+                Integer currentValue = values.get(context);
+                
+                if (currentValue != null) {
+                    return currentValue;
+                }
+            }
+            
+            return Integer.MIN_VALUE;
+        }
+
+        /**
+         * <p>
+         * sets the value of the measure context free as well as specific to the provided context
+         * </p>
+         */
+        private void set(ITask context, int value) {
+            contextFreeValue = value;
+            
+            if (context != null) {
+                if (values == null) {
+                    values = new HashMap<ITask, Integer>();
+                }
+                
+                values.put(context, value);
+            }
+        }
+
+        /**
+         * <p>
+         * increases the value of the measure context free as well as specific to the provided
+         * context according to the provided increment
+         * </p>
+         */
+        private void increase(ITask context, int increment) {
+            contextFreeValue += increment;
+            
+            if (context != null) {
+                if (values == null) {
+                    values = new HashMap<ITask, Integer>();
+                }
+                
+                Integer currentValue = values.get(context);
+                
+                if (currentValue == null) {
+                    currentValue = 0;
+                }
+                
+                values.put(context, currentValue + increment);
+            }
+        }
+
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskInstance.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskInstance.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskInstance.java	(revision 1551)
@@ -0,0 +1,176 @@
+//   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.treeimpl;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceVisitor;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link ITaskInstance}. It
+ * does not do anything fancy except implementing the interface.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class TaskInstance implements ITaskInstance {
+    
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * used as a counter to generate new ids for each newly created task instance. May overflow.
+     * </p>
+     */
+    private static int temporalId = 0;
+
+    /**
+     * <p>
+     * the task instantiated by this task instance
+     * </p>
+     */
+    private ITask task;
+    
+    /**
+     * <p>
+     * the id of the task instance (unique throughout the system as long as {@link #temporalId}
+     * does not overflow.
+     * </p>
+     */
+    private int id;
+
+    /**
+     * <p>
+     * instantiated the task instance with the task that is instantiated by the instance. It also
+     * assigns a unique id to the instance using {@link #getNewId()}.
+     * </p>
+     */
+    TaskInstance(ITask task) {
+        this.task = task;
+        id = getNewId();
+    }
+
+    /**
+     * <p>
+     * creates a new id for a task instance using {@link #temporalId} by incrementing it an
+     * returning its current value. Resets the counter if {@link Integer.MAX_VALUE} is reached.
+     * </p>
+     * 
+     * @return a new unique id for a task instance as long as {@link #temporalId} does not overflow
+     */
+    private static synchronized int getNewId() {
+        if (temporalId == Integer.MAX_VALUE) {
+            temporalId = 0;
+        }
+
+        return temporalId++;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#getTask()
+     */
+    @Override
+    public ITask getTask() {
+        return task;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.TaskTreeNode#equals(TaskTreeNode)
+     */
+    @Override
+    public boolean equals(ITaskInstance taskInstance) {
+        // task instances are only equal if they are identical or if they have the same id
+        // (may happen, if they are cloned)
+        return (this == taskInstance) || (this.hashCode() == taskInstance.hashCode());
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public synchronized int hashCode() {
+        return id;
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public synchronized String toString() {
+        StringBuffer result = new StringBuffer();
+        result.append(task.getType());
+        result.append(" #");
+        result.append(task.getId());
+        
+        if (task.getDescription() != null) {
+            result.append(" (");
+            result.append(task.getDescription());
+            result.append(')');
+        }
+        
+        /*if (children != null) {
+            result.append(", ");
+            result.append(children.size());
+            result.append(" children");
+        }*/
+        
+        return result.toString();
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public synchronized ITaskInstance clone() {
+        TaskInstance clone = null;
+        try {
+            clone = (TaskInstance) super.clone();
+        }
+        catch (CloneNotSupportedException e) {
+            // this should never happen. Therefore simply dump the exception
+            e.printStackTrace();
+        }
+
+        return clone;
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance#accept(ITaskInstanceVisitor)
+     */
+    @Override
+    public void accept(ITaskInstanceVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    /**
+     * <p>
+     * used to update the task represented through this instance
+     * </p>
+     * 
+     * @param task the task to set
+     */
+    void setTask(ITask task) {
+        this.task = task;
+    }
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskModel.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskModel.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/TaskModel.java	(revision 1551)
@@ -0,0 +1,393 @@
+//   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.treeimpl;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.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.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.ITaskModel;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInfo;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.TaskMetric;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link ITaskModel}. It
+ * does not do anything fancy except implementing the interface. It also calculates on
+ * initialisations the measures for diverse metrics of the task belonging to the model
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class TaskModel implements ITaskModel {
+    
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * <p>
+     * all metrics calculated by this type of task model
+     * </p>
+     */
+    private static final TaskMetric[] taskMetrics = new TaskMetric[]
+        { TaskMetric.COUNT,
+          TaskMetric.DEPTH,
+          TaskMetric.EVENT_COVERAGE,
+          TaskMetric.EVENT_COVERAGE_RATIO,
+          TaskMetric.EVENT_COVERAGE_QUANTILE };
+
+    /**
+     * <p>
+     * the user sessions belonging to the model
+     * </p>
+     */
+    private List<IUserSession> userSessions;
+
+    /**
+     * <p>
+     * index for effectively accessing the model and calculating statistics about it
+     * </p>
+     */
+    private transient TaskModelIndex index = null;
+    
+    /**
+     * <p>
+     * initializes the task model with the user sessions out of which the tasks are extracted
+     * </p>
+     * 
+     * @param userSessions as described
+     */
+    TaskModel(List<IUserSession> userSessions) {
+        if ((userSessions == null) || (userSessions.size() == 0)) {
+            throw new IllegalArgumentException("user sessions must not be null");
+        }
+        
+        this.userSessions = userSessions;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getUserSessions()
+     */
+    @Override
+    public List<IUserSession> getUserSessions() {
+        ensureInitialized();
+        return Collections.unmodifiableList(userSessions);
+    }
+
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTasks()
+     */
+    @Override
+    public Collection<ITask> getTasks() {
+        ensureInitialized();
+        return Collections.unmodifiableCollection(index.taskMap.keySet());
+    }
+
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getTaskInfo(ITask)
+     */
+    @Override
+    public ITaskInfo getTaskInfo(ITask task) {
+        ensureInitialized();
+        return index.taskMap.get(task);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel#getAllMetrics()
+     */
+    @Override
+    public TaskMetric[] getAllMetrics() {
+        return taskMetrics;
+    }
+
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public TaskModel clone() {
+        return new TaskModel(userSessions);
+    }
+
+    /**
+     * <p>
+     * internal convenience method that initializes the internal index and calculates all measures
+     * for metrics available for the tasks
+     * </p>
+     */
+    private synchronized void ensureInitialized() {
+        if (index == null) {
+            index = new TaskModelIndex();
+            
+            for (IUserSession session : this.userSessions) {
+                for (ITaskInstance taskInstance : session) {
+                    index.handleTaskInstance(taskInstance, null);
+                }
+            }
+            
+            // count all events covered
+            int allEventsCovered = 0;
+            Collection<ITask> tasks = getTasks();
+            for (ITask task : tasks) {
+                if (task instanceof IEventTask) {
+                    allEventsCovered += task.getInstances().size();
+                }
+            }
+            
+            int[] eventCoverageRatios = new int[tasks.size()];
+            int i = 0;
+
+            // add some further measures
+            for (ITask task : tasks) {
+                TaskInfo info = index.taskMap.get(task);
+                info.addMeasure(TaskMetric.EVENT_COVERAGE_RATIO);
+                
+                int coveredEvents = info.getMeasureValue(TaskMetric.EVENT_COVERAGE);
+                int coverageRatio = 0;
+                
+                if (allEventsCovered > 0) {
+                    coverageRatio = (coveredEvents * 1000) / allEventsCovered;
+                }
+                
+                eventCoverageRatios[i++] = coverageRatio;
+                info.setCount(TaskMetric.EVENT_COVERAGE_RATIO, null, coverageRatio);
+            }
+            
+            Arrays.sort(eventCoverageRatios);
+            
+            // add some further measures
+            for (ITask task : tasks) {
+                TaskInfo info = index.taskMap.get(task);
+                info.addMeasure(TaskMetric.EVENT_COVERAGE_QUANTILE);
+                int quantile = Arrays.binarySearch
+                    (eventCoverageRatios, info.getMeasureValue(TaskMetric.EVENT_COVERAGE_RATIO));
+                
+                quantile = 1000 * quantile / eventCoverageRatios.length;
+                
+                info.setCount(TaskMetric.EVENT_COVERAGE_QUANTILE, null, quantile);
+            }
+            
+            //index.dumpToCSV(System.out);
+            /*try {
+                OutputStream stream = new FileOutputStream(new File("tasks.csv"));
+                index.dumpToCSV(new PrintStream(stream));
+                stream.close();
+            }
+            catch (FileNotFoundException e) {
+                e.printStackTrace();
+            }*/
+        }
+        
+    }
+
+    /**
+     * <p>
+     * the index of task infos used internally. The index is created once and while that filled
+     * with task infos for each observed task containing all measures for metrics belonging
+     * to the tasks. 
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private static class TaskModelIndex {
+
+        /**
+         * <p>
+         * the tasks contained in the user session belonging to the model as well as statistical
+         * infos about them
+         * </p>
+         */
+        private Map<ITask, TaskInfo> taskMap = new HashMap<ITask, TaskInfo>();
+
+        /**
+         * <p>
+         * called on initialization to fill the index with infos about the given task instance
+         * as well as to calculate the appropriate metrics
+         * </p>
+         */
+        private int[] handleTaskInstance(ITaskInstance taskInstance, ITask context) {
+            int eventTaskInstancesCovered = 0;
+            int depth = 0;
+            
+            if (taskInstance instanceof ITaskInstanceList) {
+                for (ITaskInstance child : (ITaskInstanceList) taskInstance) {
+                    int[] measures = handleTaskInstance(child, taskInstance.getTask());
+                    eventTaskInstancesCovered += measures[0];
+                    depth = Math.max(depth, measures[1]);
+                }
+                
+                if ((((ITaskInstanceList) taskInstance).size() == 0) &&
+                    (taskInstance instanceof IIterationInstance))
+                {
+                    // ensure also empty task infos for unselected variants
+                    ensureTaskInfo(((IIteration) taskInstance.getTask()).getMarkedTask(), context);
+                }
+            }
+            else if (taskInstance instanceof ISelectionInstance) {
+                ITaskInstance child = ((ISelectionInstance) taskInstance).getChild();
+                int[] measures = handleTaskInstance(child, taskInstance.getTask());
+                eventTaskInstancesCovered += measures[0];
+                depth = Math.max(depth, measures[1]);
+                
+                // ensure also empty task infos for unselected variants
+                for (ITask otherChildTask : ((ISelection) taskInstance.getTask()).getChildren()) {
+                    ensureTaskInfo(otherChildTask, context);
+                }
+            }
+            else if (taskInstance instanceof IOptionalInstance) {
+                ITaskInstance child = ((IOptionalInstance) taskInstance).getChild();
+                if (child != null) {
+                    int[] measures = handleTaskInstance(child, taskInstance.getTask());
+                    eventTaskInstancesCovered += measures[0];
+                    depth = Math.max(depth, measures[1]);
+                }
+                else {
+                    // ensure also empty task infos for unselected variants
+                    ensureTaskInfo(((IOptional) taskInstance.getTask()).getMarkedTask(), context);
+                }
+            }
+            else if (taskInstance instanceof IEventTaskInstance) {
+                eventTaskInstancesCovered = 1;
+            }
+            
+            depth++;
+            
+            ensureTaskInfo(taskInstance.getTask(), context, eventTaskInstancesCovered, depth);
+            
+            return new int[] { eventTaskInstancesCovered, depth };
+        }
+        
+        /**
+         * <p>
+         * internal convenience method to build the task model during initialization
+         * </p>
+         */
+        private void ensureTaskInfo(ITask task, ITask context) {
+            ensureTaskInfo(task, context, 0, 0);
+            
+            if (task instanceof IStructuringTemporalRelationship) {
+                for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) {
+                    ensureTaskInfo(child, task);
+                }
+            }
+            else if (task instanceof IMarkingTemporalRelationship) {
+                ensureTaskInfo(((IMarkingTemporalRelationship) task).getMarkedTask(), task);
+            }
+        
+        }
+        
+        /**
+         * <p>
+         * internal convenience method to build the task model during initialization. Adds a new
+         * task info object to the map for the provided task and fills it with measures. If there
+         * are already some task infos for the task, the contained measures are updated according
+         * to the parameters.
+         * </p>
+         */
+        private void ensureTaskInfo(ITask task,
+                                    ITask context,
+                                    int   eventTaskInstancesCovered,
+                                    int   depth)
+        {
+            TaskInfo taskInfo = taskMap.get(task);
+
+            if (taskInfo == null) {
+                taskInfo = new TaskInfo(task);
+                taskInfo.addMeasure(TaskMetric.COUNT);
+                taskInfo.addMeasure(TaskMetric.EVENT_COVERAGE);
+                taskInfo.addMeasure(TaskMetric.DEPTH);
+                taskMap.put(task, taskInfo);
+                
+                taskInfo.setCount(TaskMetric.DEPTH, null, getDepth(task));
+            }
+
+            taskInfo.increaseCount(TaskMetric.COUNT, context, 1);
+            taskInfo.increaseCount(TaskMetric.EVENT_COVERAGE, context, eventTaskInstancesCovered);
+
+            taskInfo.setCount(TaskMetric.DEPTH, context, depth);
+        }
+
+        /**
+         * <p>
+         * internal convenience method to calculate the maximum depth of a task
+         * </p>
+         */
+        private int getDepth(ITask task) {
+            if (task instanceof IMarkingTemporalRelationship) {
+                return getDepth(((IMarkingTemporalRelationship) task).getMarkedTask()) + 1;
+            }
+            else if (task instanceof IStructuringTemporalRelationship) {
+                int maxDepth = 0;
+                
+                for (ITask child : ((IStructuringTemporalRelationship) task).getChildren()) {
+                    maxDepth = Math.max(maxDepth, getDepth(child));
+                }
+                
+                return maxDepth + 1;
+            }
+            else {
+                // event tasks
+                return 1;
+            }
+        }
+
+        /**
+         *
+         */
+        /*private void dumpToCSV(PrintStream out) {
+            out.println("taskid;depth;count;eventcoverage;eventcoverageratio");
+            
+            for (Map.Entry<ITask, TaskInfo> entry : taskMap.entrySet()) {
+                out.print(entry.getKey().getId());
+                out.print(';');
+                out.print(entry.getValue().getMeasureValue(TaskMetric.DEPTH));
+                out.print(';');
+                out.print(entry.getValue().getMeasureValue(TaskMetric.COUNT));
+                out.print(';');
+                out.print(entry.getValue().getMeasureValue(TaskMetric.EVENT_COVERAGE));
+                out.print(';');
+                out.print(entry.getValue().getMeasureValue(TaskMetric.EVENT_COVERAGE_RATIO));
+                out.println();
+            }
+        }*/
+
+    }
+
+
+}
Index: /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/UserSession.java
===================================================================
--- /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/UserSession.java	(revision 1551)
+++ /branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/treeimpl/UserSession.java	(revision 1551)
@@ -0,0 +1,166 @@
+//   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.treeimpl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
+import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession;
+
+/**
+ * <p>
+ * this is the default implementation of the interface {@link IUserSession}. It
+ * does not do anything fancy except implementing the interface.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class UserSession implements IUserSession {
+    
+    /**
+     * <p>
+     * default serial version UID
+     * </p>
+     */
+    private static final long serialVersionUID = 1L;
+    
+    /**
+     * <p>
+     * the task instances belonging to the user session
+     * </p>
+     */
+    private List<ITaskInstance> executedTasks = new ArrayList<ITaskInstance>();
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#get(int)
+     */
+    @Override
+    public ITaskInstance get(int index) {
+        return executedTasks.get(index);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstanceList#size()
+     */
+    @Override
+    public int size() {
+        return executedTasks.size();
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Iterable#iterator()
+     */
+    @Override
+    public Iterator<ITaskInstance> iterator() {
+        return executedTasks.iterator();
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession#getExecutedTasks()
+     */
+    @Override
+    public List<ITaskInstance> getExecutedTasks() {
+        return Collections.unmodifiableList(executedTasks);
+    }
+
+    /* (non-Javadoc)
+     * @see de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession#equals(IUserSession)
+     */
+    @Override
+    public boolean equals(IUserSession userSession) {
+        // task instances are only equal if they are identical or if they have the same id
+        // (may happen, if they are cloned)
+        return (this == userSession) || (this.hashCode() == userSession.hashCode());
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public synchronized int hashCode() {
+        return super.hashCode();
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public synchronized String toString() {
+        return "session (" + executedTasks.size() + " task instances)";
+    }
+
+    /* (non-Javadoc)
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public synchronized IUserSession clone() {
+        UserSession clone = null;
+        try {
+            clone = (UserSession) super.clone();
+
+            clone.executedTasks = new LinkedList<ITaskInstance>();
+            
+            for (ITaskInstance child : executedTasks) {
+                clone.executedTasks.add(child.clone());
+            }
+
+        }
+        catch (CloneNotSupportedException e) {
+            // this should never happen. Therefore simply dump the exception
+            e.printStackTrace();
+        }
+
+        return clone;
+    }
+
+    /**
+     * <p>
+     * used internally to add a task instance to the user session
+     * </p>
+     * 
+     * @param taskInstance the task instance to be added
+     */
+    void addExecutedTask(ITaskInstance taskInstance) {
+        executedTasks.add(taskInstance);
+    }
+
+    /**
+     * <p>
+     * used internally to add a task instance to the user session at a specific position
+     * </p>
+     * 
+     * @param index        the index the task instance shall be added to
+     * @param taskInstance the task instance to be added
+     */
+    void addExecutedTask(int index, ITaskInstance taskInstance) {
+        executedTasks.add(index, taskInstance);
+    }
+
+    /**
+     * <p>
+     * used internally to remove a task instance from the user session
+     * </p>
+     * 
+     * @param index the index of the task instance to be removed
+     */
+    void removeExecutedTask(int index) {
+        executedTasks.remove(index);
+    }
+
+}
