Index: /trunk/autoquest-core-tasktrees/.classpath
===================================================================
--- /trunk/autoquest-core-tasktrees/.classpath	(revision 893)
+++ /trunk/autoquest-core-tasktrees/.classpath	(revision 893)
@@ -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.6">
+		<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: /trunk/autoquest-core-tasktrees/.project
===================================================================
--- /trunk/autoquest-core-tasktrees/.project	(revision 893)
+++ /trunk/autoquest-core-tasktrees/.project	(revision 893)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>quest-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: /trunk/autoquest-core-tasktrees/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- /trunk/autoquest-core-tasktrees/.settings/org.eclipse.jdt.core.prefs	(revision 893)
+++ /trunk/autoquest-core-tasktrees/.settings/org.eclipse.jdt.core.prefs	(revision 893)
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
Index: /trunk/autoquest-core-tasktrees/.settings/org.eclipse.m2e.core.prefs
===================================================================
--- /trunk/autoquest-core-tasktrees/.settings/org.eclipse.m2e.core.prefs	(revision 893)
+++ /trunk/autoquest-core-tasktrees/.settings/org.eclipse.m2e.core.prefs	(revision 893)
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
Index: /trunk/autoquest-core-tasktrees/pom.xml
===================================================================
--- /trunk/autoquest-core-tasktrees/pom.xml	(revision 893)
+++ /trunk/autoquest-core-tasktrees/pom.xml	(revision 893)
@@ -0,0 +1,20 @@
+<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.quest</groupId>
+    <artifactId>quest</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>quest-core-tasktrees</artifactId>
+  <name>quest-core-tasktrees</name>
+  <scm>
+    <url>${quest-scm-trunk-dir}/quest-core-tasktrees</url>
+  </scm>
+  <dependencies>
+    <dependency>
+      <groupId>de.ugoe.cs.quest</groupId>
+      <artifactId>quest-core-events</artifactId>
+      <version>${project.parent.version}</version>
+    </dependency>
+  </dependencies>
+</project>
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/manager/ComponentManager.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/manager/ComponentManager.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/manager/ComponentManager.java	(revision 893)
@@ -0,0 +1,107 @@
+package de.ugoe.cs.quest.tasktrees.manager;
+
+import de.ugoe.cs.quest.tasktrees.nodeequality.NodeEqualityRuleManager;
+import de.ugoe.cs.quest.tasktrees.temporalrelation.TemporalRelationshipRuleManager;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+import de.ugoe.cs.quest.tasktrees.treeimpl.TaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeimpl.TaskTreeNodeFactory;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 12.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class ComponentManager {
+    
+    /** */
+    private static ComponentManager instance;
+
+    /** */
+    private TemporalRelationshipRuleManager temporalRelationshipRuleManager;
+
+    /** */
+    private NodeEqualityRuleManager nodeEqualityRuleManager;
+
+    /** */
+    private ITaskTreeBuilder taskTreeBuilder;
+
+    /** */
+    private ITaskTreeNodeFactory taskTreeNodeFactory;
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public static TemporalRelationshipRuleManager getTemporalRelationshipRuleManager() {
+        return getInstance().temporalRelationshipRuleManager;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public static NodeEqualityRuleManager getNodeEqualityRuleManager() {
+        return getInstance().nodeEqualityRuleManager;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public static ITaskTreeBuilder getDefaultTaskTreeBuilder() {
+        return getInstance().taskTreeBuilder;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public static ITaskTreeNodeFactory getDefaultTaskTreeNodeFactory() {
+        return getInstance().taskTreeNodeFactory;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public static synchronized void clearInstance() {
+        instance = null;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    private static synchronized ComponentManager getInstance() {
+        if (instance == null) {
+            instance = new ComponentManager();
+            instance.init();
+        }
+        return instance;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     */
+    private void init() {
+        nodeEqualityRuleManager = new NodeEqualityRuleManager();
+        nodeEqualityRuleManager.init();
+
+        temporalRelationshipRuleManager =
+            new TemporalRelationshipRuleManager(nodeEqualityRuleManager);
+        temporalRelationshipRuleManager.init();
+
+        taskTreeBuilder = new TaskTreeBuilder();
+        taskTreeNodeFactory = new TaskTreeNodeFactory();
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/manager/TaskTreeManager.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/manager/TaskTreeManager.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/manager/TaskTreeManager.java	(revision 893)
@@ -0,0 +1,119 @@
+package de.ugoe.cs.quest.tasktrees.manager;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Level;
+
+import de.ugoe.cs.quest.eventcore.Event;
+import de.ugoe.cs.quest.eventcore.gui.KeyboardFocusChange;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTree;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+public class TaskTreeManager {
+    
+    /** */
+    private static final int MAX_EVENTS_TILL_RULE_APPLICATION = 100;
+
+    /** */
+    private ITaskTreeBuilder taskTreeBuilder = ComponentManager.getDefaultTaskTreeBuilder();
+
+    /** */
+    private ITaskTreeNodeFactory taskTreeNodeFactory =
+        ComponentManager.getDefaultTaskTreeNodeFactory();
+
+    /** */
+    private int eventsTillRuleApplication = MAX_EVENTS_TILL_RULE_APPLICATION;
+
+    /** */
+    private ISequence rootSequence;
+
+    /**
+     * TODO: comment
+     * 
+     */
+    public TaskTreeManager() {
+        rootSequence = taskTreeNodeFactory.createNewSequence();
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param sequences
+     * @return
+     */
+    public synchronized ITaskTree createTaskTree(Collection<List<Event>> sequences) {
+        
+        for (List<Event> sequence : sequences) {
+            for (Event event : sequence) {
+                handleNewEvent(event);
+            }
+        }
+        
+        return getTaskTree();
+    }
+
+    /**
+     *
+     */
+    public void handleNewEvent(Event event) {
+        handleEventTask(taskTreeNodeFactory.createNewEventTask(event.getType(), event.getTarget()));
+    }
+
+    /**
+     *
+     */
+    public synchronized ITaskTree getTaskTree() {
+        Console.traceln(Level.INFO, "applying temporal relationship generation rules");
+
+        ISequence currentRootSequence = rootSequence.clone();
+        ComponentManager.getTemporalRelationshipRuleManager().applyRules
+          (currentRootSequence, taskTreeBuilder, taskTreeNodeFactory, true);
+
+        return taskTreeNodeFactory.createTaskTree(currentRootSequence);
+    }
+
+    /**
+     * adds the task to the current or the new sequence. The decision depends on the type of task.
+     * If the task finishes the current sequence, the sequence is marked as finished If the task
+     * does not start a new sequence, it is added to the current sequence, before it is marked s
+     * finished. Otherwise it is added to a new sequence.
+     */
+    private synchronized void handleEventTask(IEventTask eventTask) {
+        if (!(eventTask.getEventType() instanceof KeyboardFocusChange)) {
+            Console.traceln(Level.INFO, "handling interaction event task \"" + eventTask + "\"");
+            addTaskToSequence(eventTask);
+        }
+    }
+
+    /**
+     *
+     */
+    private void addTaskToSequence(ITaskTreeNode task)
+    {
+        taskTreeBuilder.addChild(rootSequence, task);
+
+        if (--eventsTillRuleApplication == 0) {
+            eventsTillRuleApplication = MAX_EVENTS_TILL_RULE_APPLICATION;
+
+            Console.traceln(Level.INFO, "applying temporal relationship generation rules");
+            ComponentManager.getTemporalRelationshipRuleManager().applyRules(rootSequence,
+                                                                             taskTreeBuilder,
+                                                                             taskTreeNodeFactory,
+                                                                             false);
+        }
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/EventTaskComparisonRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/EventTaskComparisonRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/EventTaskComparisonRule.java	(revision 893)
@@ -0,0 +1,44 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <p>
+ * This rule identifies two task tree nodes 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 NodeComparisonRule {
+    
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
+     */
+    @Override
+    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
+        if ((!(node1 instanceof IEventTask)) || (!(node2 instanceof IEventTask))) {
+            return null;
+        }
+
+        if (node1 == node2) {
+            return NodeEquality.IDENTICAL;
+        }
+
+        IEventTask task1 = (IEventTask) node1;
+        IEventTask task2 = (IEventTask) node2;
+        
+        if (task1.getEventType().equals(task2.getEventType()) &&
+            task1.getEventTarget().equals(task2.getEventTarget()))
+        {
+            return NodeEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return NodeEquality.UNEQUAL;
+        }
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/GUIEventTaskComparisonRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/GUIEventTaskComparisonRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/GUIEventTaskComparisonRule.java	(revision 893)
@@ -0,0 +1,147 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import de.ugoe.cs.quest.eventcore.gui.IInteraction;
+import de.ugoe.cs.quest.eventcore.gui.TextInput;
+import de.ugoe.cs.quest.eventcore.gui.ValueSelection;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <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 NodeComparisonRule {
+    
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
+     */
+    @Override
+    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
+        if ((!(node1 instanceof IEventTask)) || (!(node2 instanceof IEventTask))) {
+            return null;
+        }
+        
+        IEventTask task1 = (IEventTask) node1;
+        IEventTask task2 = (IEventTask) node2;
+        
+        if ((!(task1.getEventType() instanceof IInteraction)) ||
+            (!(task2.getEventType() instanceof IInteraction)))
+        {
+            return null;
+        }
+
+        if (node1 == node2) {
+            return NodeEquality.IDENTICAL;
+        }
+
+        if (!task1.getEventTarget().equals(task2.getEventTarget())) {
+            return NodeEquality.UNEQUAL;
+        }
+        
+        IInteraction interaction1 = (IInteraction) task1.getEventType();
+        IInteraction interaction2 = (IInteraction) task2.getEventType();
+        
+        return compareInteractions(interaction1, interaction2);
+    }
+
+    /**
+     * <p>
+     * compares two interactions. The method delegates two
+     * {@link #compareTextInputs(TextInput, TextInput)} and
+     * {@link #compareValueSelections(ValueSelection, ValueSelection)} for text inputs and value
+     * selections. Otherwise it uses the equal method of the interactions for comparison. In this
+     * case, if the interactions equal method returns true, this method returns lexical equality.
+     * </p>
+     *
+     * @param interaction1 the first interaction to compare
+     * @param interaction2 the second interaction to compare
+     * 
+     * @return as described
+     */
+    private NodeEquality compareInteractions(IInteraction interaction1, IInteraction interaction2) {
+        if (interaction1 == interaction2) {
+            return NodeEquality.LEXICALLY_EQUAL;
+        }
+        else if ((interaction1 instanceof TextInput) && (interaction2 instanceof TextInput)) {
+            return compareTextInputs((TextInput) interaction1, (TextInput) interaction2);
+        }
+        else if ((interaction1 instanceof ValueSelection) &&
+                 (interaction2 instanceof ValueSelection))
+        {
+            return compareValueSelections
+                ((ValueSelection<?>) interaction1, (ValueSelection<?>) interaction2);
+        }
+        else if (interaction1.equals(interaction2)) {
+            return NodeEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return NodeEquality.UNEQUAL;
+        }
+    }
+
+    /**
+     * <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>
+     *
+     * @param interaction1 the first text input to compare
+     * @param interaction2 the second text input to compare
+     * 
+     * @return as described
+     */
+    private NodeEquality compareTextInputs(TextInput interaction1, TextInput interaction2) {
+        if (interaction1.getEnteredText().equals(interaction2.getEnteredText())) {
+            if (interaction1.getTextInputEvents().equals(interaction2.getTextInputEvents())) {
+                return NodeEquality.LEXICALLY_EQUAL;
+            }
+            else {
+                return NodeEquality.SYNTACTICALLY_EQUAL;
+            }
+        }
+        else {
+            return NodeEquality.SEMANTICALLY_EQUAL;
+        }
+    }
+
+    /**
+     * <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>
+     *
+     * @param interaction1 the first value selection to compare
+     * @param interaction2 the second value selection to compare
+     * 
+     * @return as described
+     */
+    private NodeEquality compareValueSelections(ValueSelection<?> interaction1,
+                                                ValueSelection<?> interaction2)
+    {
+        Object value1 = interaction1.getSelectedValue();
+        Object value2 = interaction2.getSelectedValue();
+        
+        if ((value1 == value2) || ((value1 != null) && (value1.equals(value2)))) {
+            return NodeEquality.SYNTACTICALLY_EQUAL;
+        }
+        else {
+            return NodeEquality.SEMANTICALLY_EQUAL;
+        }
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/IterationComparisonRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/IterationComparisonRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/IterationComparisonRule.java	(revision 893)
@@ -0,0 +1,191 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <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 NodeComparisonRule {
+    
+    /** the rule manager for internally comparing task tree nodes */
+    private NodeEqualityRuleManager mRuleManager;
+
+    /**
+     * <p>
+     * simple constructor to provide the rule with the node equality rule manager to be able
+     * to perform comparisons of the children of provided task tree nodes
+     * </p>
+     * 
+     * @param ruleManager the rule manager for comparing task tree nodes
+     */
+    IterationComparisonRule(NodeEqualityRuleManager ruleManager) {
+        super();
+        mRuleManager = ruleManager;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
+     */
+    @Override
+    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
+        if ((!(node1 instanceof IIteration)) || (!(node2 instanceof IIteration))) {
+            return null;
+        }
+
+        if (node1 == node2) {
+            return NodeEquality.IDENTICAL;
+        }
+
+        // if both iterations do not have children, they are equal although this doesn't make sense
+        if ((node1.getChildren().size() == 0) && (node2.getChildren().size() == 0)) {
+            return NodeEquality.LEXICALLY_EQUAL;
+        }
+        else if ((node1.getChildren().size() == 0) || (node2.getChildren().size() == 0)) {
+            return NodeEquality.UNEQUAL;
+        }
+
+        ITaskTreeNode child1 = node1.getChildren().get(0);
+        ITaskTreeNode child2 = node2.getChildren().get(0);
+
+        // 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 nodes 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.
+        NodeEquality nodeEquality = mRuleManager.applyRules(child1, child2);
+
+        if (nodeEquality.isAtLeast(NodeEquality.SEMANTICALLY_EQUAL)) {
+            // prevent, that identical is returned, because the iterations itself are not identical
+            // although the iterated tasks are
+            if (nodeEquality == NodeEquality.IDENTICAL) {
+                return NodeEquality.LEXICALLY_EQUAL;
+            }
+            else {
+                return nodeEquality;
+            }
+        }
+
+        // compare one iteration with a single node as a child and another one with a selection of
+        // semantically equal nodes
+        return selectionChildrenSemanticallyEqualNode(child1, child2);
+        
+        // all other combinations (i.e. sequence with single child and sequence with selection)
+        // can not match
+    }
+
+    /**
+     * <p>
+     * compares two task tree nodes. One of them must be a selection, the other one can be any task
+     * tree node. The method returns a node equality that is not <code>NodeEquality.UNEQUAL</code>
+     * if the other node is at least semantically equal to the children of the selection. It
+     * returns more concrete equalities, if the equality between the other node and the children
+     * of the selection is more concrete.
+     * </p> 
+     * 
+     * @param taskTreeNode  the first task tree node to compare
+     * @param taskTreeNode2 the second task tree node to compare
+     * 
+     * @return as described
+     */
+    private NodeEquality selectionChildrenSemanticallyEqualNode(ITaskTreeNode taskTreeNode,
+                                                                ITaskTreeNode taskTreeNode2)
+    {
+        ISelection selection = null;
+        ITaskTreeNode node = null;
+        if (taskTreeNode instanceof ISelection) {
+            selection = (ISelection) taskTreeNode;
+            node = taskTreeNode2;
+        }
+        else if (taskTreeNode2 instanceof ISelection) {
+            selection = (ISelection) taskTreeNode2;
+            node = taskTreeNode;
+        }
+        else {
+            return NodeEquality.UNEQUAL;
+        }
+
+        // Iterations, where one has a selection and the other one not can at most be syntactically
+        // equal but not identical
+        NodeEquality commonDenominatorForAllComparisons = NodeEquality.SYNTACTICALLY_EQUAL;
+
+        for (ITaskTreeNode child : selection.getChildren()) {
+            NodeEquality nodeEquality = mRuleManager.applyRules(node, child);
+
+            if ((nodeEquality == null) || (nodeEquality == NodeEquality.UNEQUAL))
+            {
+                return NodeEquality.UNEQUAL;
+            }
+            
+            commonDenominatorForAllComparisons =
+                commonDenominatorForAllComparisons.getCommonDenominator(nodeEquality);
+        }
+
+        return commonDenominatorForAllComparisons;
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeAndIterationComparisonRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeAndIterationComparisonRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeAndIterationComparisonRule.java	(revision 893)
@@ -0,0 +1,86 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <p>
+ * This class is capable of comparing any task tree node which is not an iteration with an
+ * iteration. This is needed, because iterations may iterate exactly that node. In this
+ * case, the iteration would be equal to that node if it was executed exactly once. The rule
+ * returns lexically equal, it the child of the iteration is lexically equal to the node
+ * or if the child of the iteration is a selection and this selections contains a lexically equal
+ * node. The same applies for syntactical and semantical equality.
+ * </p>
+
+ * @author Patrick Harms
+ */
+public class NodeAndIterationComparisonRule implements NodeComparisonRule {
+    
+    /** the rule manager for internally comparing task tree nodes */
+    private NodeEqualityRuleManager mRuleManager;
+
+    /**
+     * <p>
+     * simple constructor to provide the rule with the node equality rule manager to be able
+     * to perform comparisons of the children of provided task tree nodes
+     * </p>
+     * 
+     * @param ruleManager the rule manager for comparing task tree nodes
+     */
+    NodeAndIterationComparisonRule(NodeEqualityRuleManager ruleManager) {
+        super();
+        mRuleManager = ruleManager;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
+     */
+    @Override
+    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
+        IIteration iteration = null;
+        ITaskTreeNode node = null;
+        
+        if (node1 instanceof IIteration) {
+            if (node2 instanceof IIteration) {
+                // the rule is not responsible for two iterations
+                return null;
+            }
+            
+            iteration = (IIteration) node1;
+            node = node2;
+        }
+        else if (node2 instanceof IIteration) {
+            if (node1 instanceof IIteration) {
+                // the rule is not responsible for two iterations
+                return null;
+            }
+            
+            iteration = (IIteration) node2;
+            node = node1;
+        }
+        else {
+            return null;
+        }
+
+        // now, that we found the iteration and the node, lets compare the child of the iteration
+        // with the node.
+        if (iteration.getChildren().size() < 1) {
+            return null;
+        }
+
+        NodeEquality nodeEquality = mRuleManager.applyRules(iteration.getChildren().get(0), node);
+
+        // although the subtask may be identical to the node, we can not return identical, as
+        // the iteration is not identical to the node, but at most lexically equal
+        if (nodeEquality == NodeEquality.IDENTICAL) {
+            return NodeEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return nodeEquality;
+        }
+
+    }
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeAndSelectionComparisonRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeAndSelectionComparisonRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeAndSelectionComparisonRule.java	(revision 893)
@@ -0,0 +1,99 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <p>
+ * This class is capable of comparing any task tree node which is not a selection with a
+ * selection. This is needed, because selections may contain exactly that node. Therefore, if
+ * this node is selected out of a selection the selection is equal to the node itself. 
+ * The rule returns lexically equal, it the selection contains a lexically equal node. The same
+ * applies for syntactical and semantical equality.
+ * </p>
+
+ * @author Patrick Harms
+ */
+public class NodeAndSelectionComparisonRule implements NodeComparisonRule {
+    
+    /** the rule manager for internally comparing task tree nodes */
+    private NodeEqualityRuleManager mRuleManager;
+
+    /**
+     * <p>
+     * simple constructor to provide the rule with the node equality rule manager to be able
+     * to perform comparisons of the children of provided task tree nodes
+     * </p>
+     * 
+     * @param ruleManager the rule manager for comparing task tree nodes
+     */
+    NodeAndSelectionComparisonRule(NodeEqualityRuleManager ruleManager) {
+        super();
+        mRuleManager = ruleManager;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
+     */
+    @Override
+    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
+        ISelection selection = null;
+        ITaskTreeNode node = null;
+        
+        if (node1 instanceof ISelection) {
+            if (node2 instanceof ISelection) {
+                // the rule is not responsible for two iterations
+                return null;
+            }
+            
+            selection = (ISelection) node1;
+            node = node2;
+        }
+        else if (node2 instanceof ISelection) {
+            if (node1 instanceof ISelection) {
+                // the rule is not responsible for two iterations
+                return null;
+            }
+            
+            selection = (ISelection) node2;
+            node = node1;
+        }
+        else {
+            return null;
+        }
+
+        // now, that we found the iteration and the node, lets compare the child of the iteration
+        // with the node.
+        if (selection.getChildren().size() < 1) {
+            return null;
+        }
+
+        NodeEquality mostConcreteNodeEquality = null;
+        
+        for (ITaskTreeNode child : selection.getChildren()) {
+            NodeEquality nodeEquality = mRuleManager.applyRules(child, node);
+            
+            if (nodeEquality != NodeEquality.UNEQUAL) {
+                if (mostConcreteNodeEquality == null) {
+                    mostConcreteNodeEquality = nodeEquality;
+                }
+                else {
+                    mostConcreteNodeEquality =
+                        mostConcreteNodeEquality.getCommonDenominator(nodeEquality);
+                }
+            }
+        }
+        
+        // although the subtask may be identical to the node, we can not return identical, as
+        // the selection is not identical to the node, but at most lexically equal
+        if (mostConcreteNodeEquality == NodeEquality.IDENTICAL) {
+            return NodeEquality.LEXICALLY_EQUAL;
+        }
+        else {
+            return mostConcreteNodeEquality;
+        }
+
+    }
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeComparisonRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeComparisonRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeComparisonRule.java	(revision 893)
@@ -0,0 +1,30 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <p>
+ * A node comparison rule is used by the {@link NodeEqualityRuleManager} to compare task tree
+ * nodes with each other. It provides one method to be called for a comparison.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface NodeComparisonRule {
+
+    /**
+     * <p>
+     * compares two nodes with each other. The result of the method is either a node equality or
+     * null. If it is null, it means, that the rule is not able to correctly compare the two given
+     * nodes
+     * </p>
+     * 
+     * @param node1 the first task tree node to compare
+     * @param node2 the second task tree node to compare
+     * 
+     * @return as described
+     */
+    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2);
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeEquality.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeEquality.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeEquality.java	(revision 893)
@@ -0,0 +1,113 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+/**
+ * <p>
+ * A node equality denotes, how equal two task tree nodes 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 task nodes conceptually. But the other design levels can be
+ * identified and compared.
+ * </p>
+ * <p>
+ * Nodes 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>
+ * Nodes are lexically equal, if they represent the same events on a key stroke level to be
+ * carried out to execute the task. Identical nodes 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 nodes are also syntactically equal.  
+ * </p>
+ * <p>
+ * Task tree nodes 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 task tree nodes are syntactically and, therefore, also lexically different, but
+ * semantically equal. Syntactically equal task tree nodes are always also semantically equal.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public enum NodeEquality {
+    IDENTICAL,
+    LEXICALLY_EQUAL,
+    SYNTACTICALLY_EQUAL,
+    SEMANTICALLY_EQUAL,
+    UNEQUAL;
+
+    /**
+     * <p>
+     * Checks for the current node equality, if it is at least identical to the
+     * provided one or even more concrete. As an example, the node equality identical also
+     * indicates, that the nodes 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 nodeEquality the node equality to compare with.
+     * 
+     * @return as described
+     */
+    public boolean isAtLeast(NodeEquality nodeEquality)
+    {
+        switch (nodeEquality) {
+            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 node 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 equality the equality, to compare this with
+     * @return
+     */
+    public NodeEquality getCommonDenominator(NodeEquality otherEquality) {
+        if (this.isAtLeast(otherEquality)) {
+            return otherEquality;
+        }
+        else if (otherEquality.isAtLeast(this)) {
+            return this;
+        }
+        else {
+            return NodeEquality.UNEQUAL;
+        }
+    }
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeEqualityRuleManager.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeEqualityRuleManager.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeEqualityRuleManager.java	(revision 893)
@@ -0,0 +1,84 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <p>
+ * The node equality rule manager is capable of comparing task tree nodes based on its internal list
+ * of comparison rules. The current list of rules contains the {@link NodeIdentityRule}, the
+ * {@link IterationComparisonRule}, the {@link SequenceComparisonRule}, and
+ * {@link SelectionComparisonRule}. These rules are asked for comparing the two provided task tree
+ * nodes in the mentioned order. If a rule returns a node equality other than null, this equality is
+ * returned. Otherwise the next rule is asked.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class NodeEqualityRuleManager {
+
+    /** */
+    private List<NodeComparisonRule> mRuleIndex = null;
+
+    /**
+     * <p>
+     * initializes the node equality rule manager by filling the internal list of comparison rules.
+     * This method must be called before any other method is called on the rule manager.
+     * </p>
+     */
+    public void init() {
+        mRuleIndex = new ArrayList<NodeComparisonRule>();
+        mRuleIndex.add(new NodeIdentityRule());
+        mRuleIndex.add(new GUIEventTaskComparisonRule());
+        mRuleIndex.add(new EventTaskComparisonRule());
+        mRuleIndex.add(new IterationComparisonRule(this));
+        mRuleIndex.add(new SequenceComparisonRule(this));
+        mRuleIndex.add(new SelectionComparisonRule(this));
+        mRuleIndex.add(new NodeAndIterationComparisonRule(this));
+        mRuleIndex.add(new NodeAndSelectionComparisonRule(this));
+    }
+
+    /**
+     * <p>
+     * this method performs a comparison of the two provided task tree nodes. It iterates its
+     * internal comparison rules. If the first rule returns a node 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 node1 the first task tree node to be compared
+     * @param node2 the second task tree node 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 NodeEquality applyRules(ITaskTreeNode node1, ITaskTreeNode node2)
+        throws IllegalStateException
+    {
+        if (mRuleIndex == null) {
+            throw new IllegalStateException("not initialized");
+        }
+        
+        // LOG.info("checking for equality of " + node1 + " and " + node2);
+        NodeEquality nodeEquality = null;
+
+        for (NodeComparisonRule rule : mRuleIndex) {
+            nodeEquality = rule.compare(node1, node2);
+
+            if (nodeEquality != null) {
+                // LOG.warning("used rule " + rule + " for equality check");
+                return nodeEquality;
+            }
+        }
+
+        // LOG.warning("no rule could be applied --> handling nodes as unequal");
+
+        return NodeEquality.UNEQUAL;
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeIdentityRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeIdentityRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/NodeIdentityRule.java	(revision 893)
@@ -0,0 +1,32 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <p>
+ * This comparison rule returns <code>NodeEquality.IDENTICAL</code> if the comparison of the two
+ * task tree nodes using the <code>==</code> operator or the <code>equals</code> method return true.
+ * Else it returns null to denote, that it can not compare the nodes.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class NodeIdentityRule implements NodeComparisonRule {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
+     */
+    @Override
+    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
+        if (node1 == node2) {
+            return NodeEquality.IDENTICAL;
+        }
+        else {
+            return null;
+        }
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/SelectionComparisonRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/SelectionComparisonRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/SelectionComparisonRule.java	(revision 893)
@@ -0,0 +1,116 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <p>
+ * this node comparison rule is capable of comparing selections. If both selections do not have
+ * children, they are treated as identical. 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.
+ * </p>
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class SelectionComparisonRule implements NodeComparisonRule {
+
+    /** the rule manager for internally comparing task tree nodes */
+    private NodeEqualityRuleManager mRuleManager;
+
+    /**
+     * <p>
+     * simple constructor to provide the rule with the node equality rule manager to be able
+     * to perform comparisons of the children of provided task tree nodes
+     * </p>
+     * 
+     * @param ruleManager the rule manager for comparing task tree nodes
+     */
+    SelectionComparisonRule(NodeEqualityRuleManager ruleManager) {
+        super();
+        mRuleManager = ruleManager;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
+     */
+    @Override
+    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
+        if ((!(node1 instanceof ISelection)) || (!(node2 instanceof ISelection))) {
+            return null;
+        }
+
+        if (node1 == node2) {
+            return NodeEquality.IDENTICAL;
+        }
+
+        // if both sequences do not have children, they are identical. If only one of them has
+        // children, they are unequal.
+        if ((node1.getChildren().size() == 0) && (node2.getChildren().size() == 0)) {
+            return NodeEquality.LEXICALLY_EQUAL;
+        }
+        else if ((node1.getChildren().size() == 0) || (node2.getChildren().size() == 0)) {
+            return NodeEquality.UNEQUAL;
+        }
+
+        NodeEquality selectionEquality = NodeEquality.LEXICALLY_EQUAL;
+
+        // compare each child of selection one with each child of selection two
+        NodeEquality childEquality;
+        NodeEquality currentEquality;
+        for (ITaskTreeNode child1 : node1.getChildren()) {
+            childEquality = null;
+            for (ITaskTreeNode child2 : node2.getChildren()) {
+                currentEquality = mRuleManager.applyRules(child1, child2);
+                if ((currentEquality != null) && (currentEquality != NodeEquality.UNEQUAL)) {
+                    if (childEquality == null) {
+                        childEquality = currentEquality;
+                    }
+                    else {
+                        childEquality = childEquality.getCommonDenominator(currentEquality);
+                    }
+                }
+            }
+            
+            if (childEquality != null) {
+                selectionEquality = selectionEquality.getCommonDenominator(childEquality);
+            }
+            else {
+                return NodeEquality.UNEQUAL;
+            }
+        }
+
+        // compare each child of selection two with each child of selection one
+        for (ITaskTreeNode child2 : node2.getChildren()) {
+            childEquality = null;
+            for (ITaskTreeNode child1 : node1.getChildren()) {
+                currentEquality = mRuleManager.applyRules(child1, child2);
+                if ((currentEquality != null) && (currentEquality != NodeEquality.UNEQUAL)) {
+                    if (childEquality == null) {
+                        childEquality = currentEquality;
+                    }
+                    else {
+                        childEquality = childEquality.getCommonDenominator(currentEquality);
+                    }
+                }
+            }
+            
+            if (childEquality != null) {
+                selectionEquality = selectionEquality.getCommonDenominator(childEquality);
+            }
+            else {
+                return NodeEquality.UNEQUAL;
+            }
+        }
+
+        return selectionEquality;
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/SequenceComparisonRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/SequenceComparisonRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/nodeequality/SequenceComparisonRule.java	(revision 893)
@@ -0,0 +1,76 @@
+package de.ugoe.cs.quest.tasktrees.nodeequality;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <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 NodeComparisonRule {
+
+    /** the rule manager for internally comparing task tree nodes */
+    private NodeEqualityRuleManager mRuleManager;
+
+    /**
+     * <p>
+     * simple constructor to provide the rule with the node equality rule manager to be able
+     * to perform comparisons of the children of provided task tree nodes
+     * </p>
+     * 
+     * @param ruleManager the rule manager for comparing task tree nodes
+     */
+    SequenceComparisonRule(NodeEqualityRuleManager ruleManager) {
+        super();
+        mRuleManager = ruleManager;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.nodeequality.NodeEqualityRule#apply(TaskTreeNode, TaskTreeNode)
+     */
+    @Override
+    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
+        if ((!(node1 instanceof ISequence)) || (!(node2 instanceof ISequence))) {
+            return null;
+        }
+
+        if (node1 == node2) {
+            return NodeEquality.IDENTICAL;
+        }
+
+        // if both sequences do not have children, they are equal although this doesn't make sense
+        if ((node1.getChildren().size() == 0) && (node2.getChildren().size() == 0)) {
+            return NodeEquality.LEXICALLY_EQUAL;
+        }
+
+        if (node1.getChildren().size() != node2.getChildren().size()) {
+            return NodeEquality.UNEQUAL;
+        }
+
+        NodeEquality resultingEquality = NodeEquality.LEXICALLY_EQUAL;
+        for (int i = 0; i < node1.getChildren().size(); i++) {
+            ITaskTreeNode child1 = node1.getChildren().get(i);
+            ITaskTreeNode child2 = node2.getChildren().get(i);
+
+            NodeEquality nodeEquality = mRuleManager.applyRules(child1, child2);
+
+            if ((nodeEquality == null) || (nodeEquality == NodeEquality.UNEQUAL)) {
+                return NodeEquality.UNEQUAL;
+            }
+            
+            resultingEquality = resultingEquality.getCommonDenominator(nodeEquality);
+        }
+
+        return resultingEquality;
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultEventTargetSequenceDetectionRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultEventTargetSequenceDetectionRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultEventTargetSequenceDetectionRule.java	(revision 893)
@@ -0,0 +1,153 @@
+package de.ugoe.cs.quest.tasktrees.temporalrelation;
+
+import de.ugoe.cs.quest.eventcore.IEventTarget;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 18.03.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class DefaultEventTargetSequenceDetectionRule implements TemporalRelationshipRule {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode,
+     * TaskTreeBuilder, TaskTreeNodeFactory)
+     */
+    @Override
+    public RuleApplicationResult apply(ITaskTreeNode        parent,
+                                       ITaskTreeBuilder     builder,
+                                       ITaskTreeNodeFactory nodeFactory,
+                                       boolean              finalize)
+    {
+        if (!(parent instanceof ISequence)) {
+            return null;
+        }
+
+        RuleApplicationResult result = new RuleApplicationResult();
+
+        IEventTarget currentEventTarget = null;
+        int startingIndex = -1;
+
+        int index = 0;
+        while (index < parent.getChildren().size()) {
+            ITaskTreeNode child = parent.getChildren().get(index);
+
+            IEventTarget eventTarget = determineEventTarget(child);
+
+            if (((eventTarget == null) && (currentEventTarget != null)) ||
+                ((eventTarget != null) && (!eventTarget.equals(currentEventTarget))))
+            {
+                if (startingIndex < 0) {
+                    startingIndex = index;
+                    currentEventTarget = eventTarget;
+                }
+                else {
+                    int endIndex = index - 1;
+                    
+                    // only reduce to a sequence, if it is not a sequence with only one child
+                    // or if this child is not a sequence itself
+                    if ((startingIndex != endIndex) ||
+                        (!(parent.getChildren().get(startingIndex) instanceof ISequence)))
+                    {
+                        handleEventTargetSequence
+                            (parent, startingIndex, endIndex, builder, nodeFactory, result);
+
+                        result.setRuleApplicationStatus
+                            (RuleApplicationStatus.RULE_APPLICATION_FINISHED);
+                        return result;
+                    }
+                    else {
+                        // here a new sequence on a new target begins
+                        startingIndex = index;
+                        currentEventTarget = eventTarget;
+                    }
+                }
+            }
+
+            index++;
+        }
+
+        if (startingIndex > -1) {
+            int endIndex = parent.getChildren().size() - 1;
+            
+            if (finalize) {
+                // only reduce to a sequence, if it is not a sequence with only one child
+                // or if this child is not a sequence itself
+                if ((startingIndex > 0) &&
+                    ((startingIndex != endIndex) ||
+                     (!(parent.getChildren().get(startingIndex) instanceof ISequence))))
+                {
+                    handleEventTargetSequence
+                        (parent, startingIndex, endIndex, builder, nodeFactory, result);
+                
+                    result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
+                }
+            }
+            else {
+                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param child
+     * @return
+     */
+    private IEventTarget determineEventTarget(ITaskTreeNode node) {
+        if (node instanceof IEventTask) {
+            return ((IEventTask) node).getEventTarget();
+        }
+        else {
+            IEventTarget commonTarget = null;
+            
+            for (ITaskTreeNode child : node.getChildren()) {
+                if (commonTarget == null) {
+                    commonTarget = determineEventTarget(child);
+                }
+                else {
+                    if (!commonTarget.equals(determineEventTarget(child))) {
+                        return null;
+                    }
+                }
+            }
+            
+            return commonTarget;
+        }
+    }
+
+    /**
+     * TODO: comment
+     * 
+     */
+    private void handleEventTargetSequence(ITaskTreeNode         parent,
+                                           int                   startIndex,
+                                           int                   endIndex,
+                                           ITaskTreeBuilder      builder,
+                                           ITaskTreeNodeFactory  nodeFactory,
+                                           RuleApplicationResult result)
+    {
+        ISequence sequence = nodeFactory.createNewSequence();
+
+        for (int i = startIndex; i <= endIndex; i++) {
+            builder.addChild(sequence, parent.getChildren().get(startIndex));
+            builder.removeChild((ISequence) parent, startIndex);
+        }
+
+        builder.addChild((ISequence) parent, startIndex, sequence);
+
+        result.addNewlyCreatedParentNode(sequence);
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultGuiElementSequenceDetectionRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultGuiElementSequenceDetectionRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultGuiElementSequenceDetectionRule.java	(revision 893)
@@ -0,0 +1,345 @@
+package de.ugoe.cs.quest.tasktrees.temporalrelation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.quest.eventcore.guimodel.IGUIElement;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 18.03.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class DefaultGuiElementSequenceDetectionRule implements TemporalRelationshipRule {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode,
+     * TaskTreeBuilder, TaskTreeNodeFactory)
+     */
+    @Override
+    public RuleApplicationResult apply(ITaskTreeNode        parent,
+                                       ITaskTreeBuilder     builder,
+                                       ITaskTreeNodeFactory nodeFactory,
+                                       boolean              finalize)
+    {
+        if (!(parent instanceof ISequence)) {
+            return null;
+        }
+
+        RuleApplicationResult result = new RuleApplicationResult();
+        
+        IGUIElement lastGuiElement = null;
+        int index = 0;
+        while (index < parent.getChildren().size()) {
+            ITaskTreeNode child = parent.getChildren().get(index);
+            IGUIElement currentGuiElement = getGUIElement(child);
+            if ((index > 0) && (!lastGuiElement.equals(currentGuiElement))) {
+                ReducableCommonDenominator commonDenominator =
+                    getNextReducableCommonDenominator(parent, index - 1);
+                    
+                if (commonDenominator != null) {
+                    // condense only if not all children would be condensed or if we can be sure,
+                    // that there will be no further child that should be included in the condensed
+                    // sequence
+                    if ((commonDenominator.noOfTasks < parent.getChildren().size()) &&
+                        (!isOnGuiElementPath(commonDenominator.commonGuiElement, currentGuiElement)))
+                    {
+                        condenseTasksToSequence(parent, index, commonDenominator.noOfTasks,
+                                                builder, nodeFactory, result);
+
+                        result.setRuleApplicationStatus
+                            (RuleApplicationStatus.RULE_APPLICATION_FINISHED);
+                        return result;
+                    }
+                    else {
+                        // the common denominator is on the parent path of the next GUI element.
+                        // Therefore, the current sequences is not finished yet. So break up.
+                        result.setRuleApplicationStatus
+                            (RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
+                    }
+                }
+            }
+
+            lastGuiElement = currentGuiElement;
+            index++;
+        }
+
+        ReducableCommonDenominator commonDenominator =
+            getNextReducableCommonDenominator(parent, parent.getChildren().size() - 1);
+        
+        if ((commonDenominator != null) &&
+            (commonDenominator.noOfTasks < parent.getChildren().size()))
+        {
+            if (finalize) {
+                condenseTasksToSequence
+                    (parent, index, commonDenominator.noOfTasks, builder, nodeFactory, result);
+                
+                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
+                
+                return result;
+            }
+            else {
+                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param guiElement
+     * @param detectedTasks
+     * @param parent
+     * @param index
+     * @param builder
+     * @param nodeFactory
+     * @return
+     */
+    private void condenseTasksToSequence(ITaskTreeNode         parent,
+                                         int                   parentIndex,
+                                         int                   noOfTasks,
+                                         ITaskTreeBuilder      builder,
+                                         ITaskTreeNodeFactory  nodeFactory,
+                                         RuleApplicationResult result)
+    {
+        ISequence newSequence = nodeFactory.createNewSequence();
+        for (int i = 0; i < noOfTasks; i++) {
+            builder.addChild(newSequence, parent.getChildren().get(parentIndex - noOfTasks));
+            // remove exactly the same number of children from the parent.
+            builder.removeChild((ISequence) parent, parentIndex - noOfTasks);
+        }
+                
+        builder.addChild((ISequence) parent, parentIndex - noOfTasks, newSequence);
+        result.addNewlyCreatedParentNode(newSequence);
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param detectedTasks
+     * @return
+     */
+    private ReducableCommonDenominator getNextReducableCommonDenominator(ITaskTreeNode parent,
+                                                                         int           childIndex)
+    {
+        ReducableCommonDenominator commonDenominator = null;
+        
+        // a common denominator can only exist for at least two task tree nodes
+        if (childIndex > 0) {
+            // start with the last one
+            int pos = childIndex;
+
+            commonDenominator = new ReducableCommonDenominator();
+            
+            // check for further predecessors, if they match the same common denominator
+            IGUIElement currentCommonDenominator = null;
+            do {
+                if (--pos < 0) {
+                    currentCommonDenominator = null;
+                }
+                else {
+                    currentCommonDenominator = getCommonDenominator
+                        (getGUIElement(parent.getChildren().get(pos)),
+                         getGUIElement(parent.getChildren().get(pos + 1)));
+                }
+                
+                if (commonDenominator.commonGuiElement == null) {
+                    commonDenominator.commonGuiElement = currentCommonDenominator;
+                }
+            }
+            while ((commonDenominator.commonGuiElement != null) &&
+                   (commonDenominator.commonGuiElement.equals(currentCommonDenominator)));
+            
+            if (commonDenominator.commonGuiElement != null) {
+                // pos points to the last element, that has not the same common denominator.
+                // This one must be subtracted from the task number as well
+                commonDenominator.noOfTasks = childIndex - pos;
+            }
+            else {
+                commonDenominator = null;
+            }
+        }
+        
+        return commonDenominator;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param child
+     * @return
+     */
+    private IGUIElement getGUIElement(ITaskTreeNode node) {
+        List<IGUIElement> terminalGUIElements = new ArrayList<IGUIElement>();
+        getTerminalGUIElements(node, terminalGUIElements);
+        return getCommonDenominator(terminalGUIElements);
+    }
+        
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param detectedTaskGroups
+     * @return
+     */
+    /*private IGUIElement getCommonDenominator(Stack<Task> detectedTasks, int start) {
+        List<IGUIElement> allGUIElements = new ArrayList<IGUIElement>();
+        
+        for (int i = start; i < detectedTasks.size(); i++) {
+            allGUIElements.add(detectedTasks.get(i).commonGuiElement);
+        }
+        
+        return getCommonDenominator(allGUIElements);
+    }*/
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param child
+     * @return
+     */
+    private IGUIElement getCommonDenominator(IGUIElement guiElement1, IGUIElement guiElement2) {
+        List<IGUIElement> allGUIElements = new ArrayList<IGUIElement>();
+        allGUIElements.add(guiElement1);
+        allGUIElements.add(guiElement2);
+        return getCommonDenominator(allGUIElements);
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param child
+     * @return
+     */
+    private IGUIElement getCommonDenominator(List<IGUIElement> guiElements) {
+        IGUIElement commonDenominator = null;
+        
+        if (guiElements.size() > 0) {
+            List<IGUIElement> commonDenominatorPath = new ArrayList<IGUIElement>();
+            
+            // create a reference list using the first GUI element
+            IGUIElement guiElement = guiElements.get(0);
+            while (guiElement != null) {
+                commonDenominatorPath.add(0, guiElement);
+                guiElement = guiElement.getParent();
+            }
+            
+            // for each other GUI element, check the reference list for the first element in the
+            // path, that is not common to the current one, and delete it as well as it subsequent
+            // siblings
+            List<IGUIElement> currentPath = new ArrayList<IGUIElement>();
+            for (int i = 1; i < guiElements.size(); i++) {
+                currentPath.clear();
+                guiElement = guiElements.get(i);
+                while (guiElement != null) {
+                    currentPath.add(0, guiElement);
+                    guiElement = guiElement.getParent();
+                }
+                
+                // determine the index of the first unequal path element
+                int index = 0;
+                while ((index < commonDenominatorPath.size()) && (index < currentPath.size()) &&
+                        commonDenominatorPath.get(index).equals(currentPath.get(index)))
+                {
+                    index++;
+                }
+                
+                // remove all elements from the common denonimator path, that do not match
+                while (index < commonDenominatorPath.size()) {
+                    commonDenominatorPath.remove(index);
+                }
+            }
+            
+            if (commonDenominatorPath.size() > 0) {
+                commonDenominator = commonDenominatorPath.get(commonDenominatorPath.size() - 1);
+            }
+        }
+        
+        return commonDenominator;
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param child
+     * @return
+     */
+    private void getTerminalGUIElements(ITaskTreeNode node, List<IGUIElement> terminalGUIElements) {
+        if (node instanceof IEventTask) {
+            if (((IEventTask) node).getEventTarget() instanceof IGUIElement) {
+                terminalGUIElements.add((IGUIElement) ((IEventTask) node).getEventTarget());
+            }
+        }
+        else {
+            for (ITaskTreeNode child : node.getChildren()) {
+                getTerminalGUIElements(child, terminalGUIElements);
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     * @param currentCommonDenominator
+     * @param guiElement
+     * @return
+     */
+    private boolean isOnGuiElementPath(IGUIElement potentialPathElement, IGUIElement child) {
+        IGUIElement guiElement = child;
+        
+        while (guiElement != null) {
+            if (guiElement.equals(potentialPathElement)) {
+                return true;
+            }
+            guiElement = guiElement.getParent();
+        }
+        
+        return false;
+    }
+
+    /**
+     * 
+     */
+    private static class ReducableCommonDenominator {
+        
+        /** the GUI element being the common denominator */
+        private IGUIElement commonGuiElement;
+        
+        /** the number of tasks that match the common denominator */
+        private int noOfTasks;
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#toString()
+         */
+        @Override
+        public String toString() {
+            return noOfTasks + " tasks on " + commonGuiElement;
+        }
+        
+    }
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultGuiEventSequenceDetectionRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultGuiEventSequenceDetectionRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultGuiEventSequenceDetectionRule.java	(revision 893)
@@ -0,0 +1,118 @@
+package de.ugoe.cs.quest.tasktrees.temporalrelation;
+
+import de.ugoe.cs.quest.eventcore.gui.IInteraction;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 18.03.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class DefaultGuiEventSequenceDetectionRule implements TemporalRelationshipRule {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode,
+     * TaskTreeBuilder, TaskTreeNodeFactory)
+     */
+    @Override
+    public RuleApplicationResult apply(ITaskTreeNode        parent,
+                                       ITaskTreeBuilder     builder,
+                                       ITaskTreeNodeFactory nodeFactory,
+                                       boolean              finalize)
+    {
+        if (!(parent instanceof ISequence)) {
+            return null;
+        }
+
+        RuleApplicationResult result = new RuleApplicationResult();
+        int sequenceStartingIndex = -1;
+
+        int index = 0;
+        while (index < parent.getChildren().size()) {
+            ITaskTreeNode child = parent.getChildren().get(index);
+
+            if ((child instanceof IEventTask) &&
+                (((IEventTask) child).getEventType() instanceof IInteraction))
+            {
+                IInteraction eventType = (IInteraction) ((IEventTask) child).getEventType();
+                
+                if (eventType.finishesLogicalSequence() && (sequenceStartingIndex > -1))
+                {
+                    // There are several situations in which this implementation may cause infinite
+                    // loops. This is because the rule manager will reapply rules until
+                    // no rule is applied anymore. A sequence identified in a first iteration will
+                    // be identified as a sequence also in a second iteration. As an example
+                    // many sequences start with an interaction starting that sequence and end
+                    // with an interaction ending that sequence. This will be reidentified as
+                    // further subsequence. It must therefore be assured, that a sequence, that
+                    // was once identified is not reidentified in a further application of the rule.
+                    // For this, the implementation performs a kind of dry run. It creates a list of
+                    // children that would belong to an identified sequence. Only if this list is
+                    // not a reidentification then a new sequence is created and added to the
+                    // parent. If it is a reidentification can be identified, if the list of
+                    // children will contain all children of the parent, or if the list of children
+                    // only consists of one sequence. Further, an identified sequence must at least
+                    // have one child.
+                    if (((sequenceStartingIndex != 0) ||
+                         (index != (parent.getChildren().size() - 1))) &&
+                        (((index - sequenceStartingIndex) > 0) ||
+                          (((index - sequenceStartingIndex) == 0) &&
+                           (!eventType.startsLogicalSequence()))))
+                    {
+                        boolean allNewChildrenAreSequences = true;
+
+                        for (int j = sequenceStartingIndex;
+                             ((allNewChildrenAreSequences) && (j < index)); j++)
+                        {
+                            allNewChildrenAreSequences &=
+                                (parent.getChildren().get(j) instanceof ISequence);
+                        }
+
+                        if (!allNewChildrenAreSequences) {
+                            ISequence sequence = nodeFactory.createNewSequence();
+
+                            for (int j = sequenceStartingIndex; j < index; j++) {
+                                builder.addChild
+                                    (sequence, parent.getChildren().get(sequenceStartingIndex));
+                                builder.removeChild((ISequence) parent, sequenceStartingIndex);
+                            }
+
+                            if (!eventType.startsLogicalSequence()) {
+                                builder.addChild
+                                    (sequence, parent.getChildren().get(sequenceStartingIndex));
+                                builder.removeChild((ISequence) parent, sequenceStartingIndex);
+                            }
+
+                            builder.addChild((ISequence) parent, sequenceStartingIndex, sequence);
+
+                            result.addNewlyCreatedParentNode(sequence);
+                            result.setRuleApplicationStatus
+                                (RuleApplicationStatus.RULE_APPLICATION_FINISHED);
+                            return result;
+                        }
+                    }
+                }
+
+                if (eventType.startsLogicalSequence()) {
+                    sequenceStartingIndex = index;
+                }
+            }
+
+            index++;
+        }
+
+        if (sequenceStartingIndex >= 0) {
+            result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
+        }
+
+        return result;
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultIterationDetectionRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultIterationDetectionRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultIterationDetectionRule.java	(revision 893)
@@ -0,0 +1,727 @@
+package de.ugoe.cs.quest.tasktrees.temporalrelation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.quest.tasktrees.nodeequality.NodeEquality;
+import de.ugoe.cs.quest.tasktrees.nodeequality.NodeEqualityRuleManager;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+
+/**
+ * <p>
+ * iterations in a list of nodes are equal subsequences following each other directly. The
+ * subsequences can be of any length depending on the type of equality they need to have. If the
+ * subsequences have to be lexically equal, then they have to have the same length if they only
+ * contain event tasks. As an example entering text can be done through appropriate keystrokes or
+ * through pasting the text. As a result, two syntactically different sequences are semantically
+ * equal. If both follow each other, then they are an iteration of semantically equal children.
+ * But they are not lexically equal.
+ * </p>
+ * <p>
+ * This class determines equal subsequences following each other. It is provided with a minimal node
+ * equality the equal nodes should have. Through this, it is possible to find e.g. lexically
+ * equal subsequence through a first application of this rule and semantically equal children to 
+ * a later application of this rule. This is used by the {@link TemporalRelationshipRuleManager}
+ * which instantiates this rule three times, each with a different minimal equality.
+ * </p>
+ * <p>
+ * The equal subsequences are determined through trial and error. This algorithm has a high effort
+ * as it tries in the worst case all possible combinations of sub lists in all possible parts of
+ * the list of children of a provided parent node. The steps for each trial are.
+ * <ul>
+ *   <li>for all possible subparts of the children of the provided parent
+ *   <ul>
+ *     <li>for all possible first sublists in the subpart
+ *     <ul>
+ *       <li>for all succeeding next sublists in this part</li>
+ *       <ul>
+ *         <li>check if this sublist is equal to all previously identified sublist in this part</li>
+ *       </ul>
+ *     </ul>
+ *     <li>
+ *       if a combination of sublists is found in this subpart which are all equal to each other
+ *       at the provided minimal equality level, an iteration in this subpart was found.
+ *     </li>
+ *       <ul>
+ *         <li>merge the identified equal sublists to an iteration</li>
+ *       </ul>
+ *   </ul>
+ * </ul>
+ * The algorithm tries to optimize if all children are event tasks and if the sublists shall be
+ * lexically equal. In this case, the sublist all have to have the same length. The trial and
+ * error reduces to a minimum of possible sublists.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class DefaultIterationDetectionRule implements TemporalRelationshipRule {
+    
+    /**
+     * <p>
+     * the node equality manager needed for comparing task tree nodes with each other
+     * </p>
+     */
+    private NodeEqualityRuleManager nodeEqualityRuleManager;
+
+    /**
+     * <p>
+     * the minimal node equality two identified sublists need to have to consider them as equal
+     * and to create an iteration for
+     * </p>
+     */
+    private NodeEquality minimalNodeEquality;
+
+    /**
+     * <p>
+     * instantiates the rule and initializes it with a node equality rule manager and the minimal
+     * node equality identified sublist must have to consider them as iterated.
+     * </p>
+     */
+    DefaultIterationDetectionRule(NodeEqualityRuleManager nodeEqualityRuleManager,
+                                  NodeEquality            minimalNodeEquality)
+    {
+        super();
+        this.nodeEqualityRuleManager = nodeEqualityRuleManager;
+        this.minimalNodeEquality = minimalNodeEquality;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see TemporalRelationshipRule#apply(TaskTreeNode, TaskTreeBuilder, TaskTreeNodeFactory)
+     */
+    @Override
+    public RuleApplicationResult apply(ITaskTreeNode        parent,
+                                       ITaskTreeBuilder     treeBuilder,
+                                       ITaskTreeNodeFactory nodeFactory,
+                                       boolean              finalize)
+    {
+        if (!(parent instanceof ISequence)) {
+            return null;
+        }
+
+        if (!finalize) {
+            // the rule is always feasible as iterations may occur at any time
+            RuleApplicationResult result = new RuleApplicationResult();
+            result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
+            return result;
+        }
+
+        // parent must already have at least 2 children
+        if ((parent.getChildren() == null) || (parent.getChildren().size() < 2)) {
+            return null;
+        }
+        
+        
+        // to find longer iterations first, start with long sequences
+        SubSequences subSequences = getEqualSubsequences(parent, treeBuilder, nodeFactory);
+
+        if (subSequences != null) {
+            RuleApplicationResult result = new RuleApplicationResult();
+
+            mergeEqualNodes(subSequences.equalVariants, treeBuilder, nodeFactory);
+            IIteration newIteration = createIterationBasedOnIdentifiedVariants
+                (subSequences, treeBuilder, nodeFactory, result);
+
+            determineNewlyCreatedParentTasks(parent, newIteration, result);
+            
+            // remove iterated children
+            for (int j = subSequences.start; j < subSequences.end; j++) {
+                treeBuilder.removeChild((ISequence) parent, subSequences.start);
+            }
+
+            // add the new iteration instead
+            treeBuilder.addChild((ISequence) parent, subSequences.start, newIteration);
+
+            result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
+            return result;
+        }
+
+        return null;
+    }
+
+    /**
+     * <p>
+     * this method initiates the trial and error algorithm denoted in the description of this class.
+     * Its main purpose is the selection of a subpart of all children in the parent node in which
+     * equal sublists shall be searched. It is important, to always find the last iterations in a
+     * part first. The reason for this are iterations of iterations. If we always found the first
+     * iteration in a subpart first, then this may be an iteration of iterations. However, there
+     * may be subsequent iterations to be included in this iteration. But these iterations are not
+     * found yet, as they occur later in the sequence. Therefore, if we always find the last
+     * iteration in a sequence first, iterations of iterations are identified, last.
+     * </p>
+     * 
+     * @param parent      the parent node in which iterations of children shall be found
+     * @param treeBuilder the tree builder that can be used for connecting task tree nodes
+     * @param nodeFactory the node factory that can be used for instantiating task tree nodes
+     * 
+     * @return the iterated subsequences identified in a specific part (contains the equal
+     *         subsequences as well as the start (inclusive) and end (exclusive) index of the
+     *         subpart in which the sequences were found) 
+     */
+    private SubSequences getEqualSubsequences(ITaskTreeNode        parent,
+                                              ITaskTreeBuilder     treeBuilder,
+                                              ITaskTreeNodeFactory nodeFactory)
+    {
+        SubSequences subSequences = null;
+
+        FIND_ITERATION:
+        for (int end = parent.getChildren().size(); end > 0; end--) {
+            for (int start = 0; start < end; start++) {
+                boolean useEqualSublistLengths = equalSublistLengthsCanBeUsed(parent, start, end);
+
+                subSequences = new SubSequences();
+                subSequences.start = start;
+
+                boolean foundFurtherVariants = findFurtherVariants
+                    (subSequences, parent, start, end, treeBuilder, nodeFactory,
+                     useEqualSublistLengths);
+
+                if (foundFurtherVariants) {
+                    break FIND_ITERATION;
+                }
+                else {
+                    subSequences = null;
+                }
+            }
+        }
+        
+        return subSequences;
+    }
+
+    /**
+     * <p>
+     * for optimization purposes, we check if the length of the sublists to be identified as
+     * iterations has to be the same for any sublist. This only applies, if the minimum node
+     * equality to be checked for is lexical equality. If the children of the parent are all event
+     * tasks, then sublists can only be lexically equal, if they all have the same length.
+     * Therefore we check, if the minimal node equality is lexical equality. And if so, we also
+     * check if all children of the parent in which an iteration shall be searched for are event
+     * tasks.
+     * </p>
+     *
+     * @param parent the parent node to search for iterations of its children
+     * @param start  the beginning of the subpart (inclusive) to be considered
+     * @param end    the end of the subpart (exclusive) to be considered
+     * 
+     * @return true, if the sublists must have the same lengths, false else
+     */
+    private boolean equalSublistLengthsCanBeUsed(ITaskTreeNode parent, int start, int end) {
+        boolean equalLengthsCanBeUsed = minimalNodeEquality.isAtLeast(NodeEquality.LEXICALLY_EQUAL);
+        
+        if (equalLengthsCanBeUsed) {
+            for (int i = start; i < end; i++) {
+                if (!(parent.getChildren().get(i) instanceof IEventTask)) {
+                    equalLengthsCanBeUsed = false;
+                    break;
+                }
+            }
+        }
+
+        return equalLengthsCanBeUsed;
+    }
+
+    /**
+     * <p>
+     * this method starts at a specific position in the list of children of the provided parent
+     * and checks, if it finds a further sublist, that matches the already found sublists. If
+     * the sublist lengths must be equal, it only searches for a sublist of the same length of the
+     * already found sublists. The method calls itself if it identifies a further equal sublist but
+     * if the end of the subpart of children is not yet reached.
+     * </p>
+     * 
+     * @param subSequences           the sublist found so far against which equality of the next
+     *                               sublist must be checked
+     * @param parent                 the parent node of which the children are analyzed
+     * @param start                  the starting index from which to start the next sublist to be
+     *                               identified
+     * @param end                    the end index (exclusive) of the current subpart of children
+     *                               in which iterations are searched for
+     * @param treeBuilder            the tree builder that can be used for connecting task tree
+     *                               nodes
+     * @param nodeFactory            the node factory that can be used for instantiating task tree
+     *                               nodes
+     * @param useEqualSublistLengths true if the sublists to be searched for all need to have the
+     *                               same length
+     * 
+     * @return true if a further equal variant was found, false else
+     */
+    private boolean findFurtherVariants(SubSequences         subSequences,
+                                        ITaskTreeNode        parent,
+                                        int                  start,
+                                        int                  end,
+                                        ITaskTreeBuilder     treeBuilder,
+                                        ITaskTreeNodeFactory nodeFactory,
+                                        boolean              useEqualSublistLengths)
+    {
+        boolean foundFurtherVariants = (start == end) && (subSequences.equalVariants.size() > 1);
+        
+        int minChildCount = 1;
+        int maxChildCount = end - start;
+        
+        if (useEqualSublistLengths && (subSequences.equalVariants.size() > 0)) {
+            minChildCount = subSequences.equalVariants.get(0).getChildren().size();
+            maxChildCount = Math.min(minChildCount, maxChildCount);
+        }
+        
+        for (int childCount = minChildCount; childCount <= maxChildCount; childCount++) {
+            if (useEqualSublistLengths && (((end - start) % childCount) != 0)) {
+                continue;
+            }
+            
+            ISequence furtherVariant = nodeFactory.createNewSequence();
+            
+            for (int j = start; j < start + childCount; j++) {
+                treeBuilder.addChild(furtherVariant, parent.getChildren().get(j));
+            }
+            
+            boolean allVariantsEqual = true;
+            
+            for (ITaskTreeNode equalVariant : subSequences.equalVariants) {
+                NodeEquality nodeEquality =
+                    nodeEqualityRuleManager.applyRules(equalVariant, furtherVariant);
+                
+                if (!nodeEquality.isAtLeast(minimalNodeEquality)) {
+                    allVariantsEqual = false;
+                    break;
+                }
+            }
+            
+            if (allVariantsEqual) {
+                
+                // we found a further variant. Add it to the list of variants and try to find
+                // further variants. Ignore, if none is available
+                int index = subSequences.equalVariants.size();
+                subSequences.equalVariants.add(index, furtherVariant);
+                
+                foundFurtherVariants = findFurtherVariants
+                    (subSequences, parent, start + childCount, end, treeBuilder, nodeFactory,
+                     useEqualSublistLengths);
+
+                if (foundFurtherVariants) {
+                    subSequences.end = end;
+                    break;
+                }
+                else {
+                    subSequences.equalVariants.remove(index);
+                }
+            }
+        }
+        
+        return foundFurtherVariants;
+    }
+
+    /**
+     * <p>
+     * this method merges task tree nodes in a list, if they can be merged. for this, it tries
+     * to merge every node with every other node in the provided list using the
+     * {@link #mergeEqualTasks(ITaskTreeNode, ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory)}
+     * method. If a merge is possible, it removes the merged nodes from the list and adds the
+     * merge result. 
+     * </p>
+     *
+     * @param nodes       the list of nodes to be merged
+     * @param treeBuilder the tree builder that can be used for connecting task tree nodes
+     * @param nodeFactory the node factory that can be used for instantiating task tree nodes
+     */
+    private void mergeEqualNodes(List<ITaskTreeNode>   nodes,
+                                 ITaskTreeBuilder      treeBuilder,
+                                 ITaskTreeNodeFactory  nodeFactory)
+    {
+        int index1 = 0;
+        int index2 = 0;
+        ITaskTreeNode variant1;
+        ITaskTreeNode variant2;
+        
+        while (index1 < nodes.size()) {
+            variant1 = nodes.get(index1);
+            index2 = index1 + 1;
+            
+            while (index2 < nodes.size()) {
+                variant2 = nodes.get(index2);
+                ITaskTreeNode mergedChild =
+                    mergeEqualTasks(variant1, variant2, treeBuilder, nodeFactory);
+                
+                if (mergedChild != null) {
+                    // if we merged something start from the beginning to perform the next merge
+                    nodes.remove(index2);
+                    nodes.remove(index1);
+                    nodes.add(index1, mergedChild);
+                    index1 = -1;
+                    break;
+                }
+                else {
+                    index2++;
+                }
+            }
+            
+            index1++;
+        }
+    }
+
+    /**
+     * <p>
+     * this method merges two equal tasks with each other if possible. If the tasks are lexically
+     * equal, the first of them is returned as merge result. If both tasks are of the same
+     * temporal relationship type, the appropriate merge method is called to merge them. If one
+     * of the nodes is a selection, the other one is added as a variant of this selection.
+     * (However, if both nodes are selections, they are merged using the appropriate merge method.)
+     * If merging is not possible, then a selection of both provided nodes is created and
+     * returned as merge result.
+     * </p>
+     *
+     * @param node1       the first task to be merged
+     * @param node2       the second task to be merged
+     * @param treeBuilder the tree builder that can be used for connecting task tree nodes
+     * @param nodeFactory the node factory that can be used for instantiating task tree nodes
+     * 
+     * @return the result of the merge
+     */
+    private ITaskTreeNode mergeEqualTasks(ITaskTreeNode         node1,
+                                          ITaskTreeNode         node2,
+                                          ITaskTreeBuilder      treeBuilder,
+                                          ITaskTreeNodeFactory  nodeFactory)
+    {
+        ITaskTreeNode mergeResult = null;
+        
+        if ((node1 instanceof ISequence) && (node2 instanceof ISequence)) {
+            mergeResult = mergeEqualSequences
+                ((ISequence) node1, (ISequence) node2, treeBuilder, nodeFactory);
+        }
+        else if ((node1 instanceof ISelection) && (node2 instanceof ISelection)) {
+            mergeResult = mergeEqualSelections
+                ((ISelection) node1, (ISelection) node2, treeBuilder, nodeFactory);
+        }
+        else if ((node1 instanceof IIteration) && (node2 instanceof IIteration)) {
+            mergeResult = mergeEqualIterations
+                ((IIteration) node1, (IIteration) node2, treeBuilder, nodeFactory);
+        }
+        else if (node1 instanceof ISelection) {
+            treeBuilder.addChild((ISelection) node1, node2);
+            mergeResult = node1;
+        }
+        else if (node2 instanceof ISelection) {
+            treeBuilder.addChild((ISelection) node2, node1);
+            mergeResult = node2;
+        }
+        else if (node1 instanceof IIteration) {
+            mergeResult = mergeEqualTasks
+                (((IIteration) node1).getChildren().get(0), node2, treeBuilder, nodeFactory);
+            
+            if (mergeResult != null) {
+                IIteration iteration = nodeFactory.createNewIteration();
+                treeBuilder.setChild(iteration, mergeResult);
+                mergeResult = iteration;
+            }
+        }
+        else if (node2 instanceof IIteration) {
+            mergeResult = mergeEqualTasks
+                (((IIteration) node2).getChildren().get(0), node1, treeBuilder, nodeFactory);
+            
+            if (mergeResult != null) {
+                IIteration iteration = nodeFactory.createNewIteration();
+                treeBuilder.setChild(iteration, mergeResult);
+                mergeResult = iteration;
+            }
+        }
+        else {
+            NodeEquality nodeEquality = nodeEqualityRuleManager.applyRules(node1, node2);
+            
+            if (nodeEquality.isAtLeast(NodeEquality.LEXICALLY_EQUAL)) {
+                mergeResult = node1;
+            }
+        }
+
+        if (mergeResult == null) {
+            mergeResult = nodeFactory.createNewSelection();
+            treeBuilder.addChild((ISelection) mergeResult, node1);
+            treeBuilder.addChild((ISelection) mergeResult, node2);
+        }
+        
+        return mergeResult;
+    }
+
+    /**
+     * <p>
+     * merges equal sequences. This is done through trying to merge each node of sequence 1 with
+     * the node in sequence 2 being located at the same position. If not all children can be merged
+     * or if the sequences have different lengths, null is returned to indicate, that merging is
+     * not possible. For merging children, the
+     * {@link #mergeEqualTasks(ITaskTreeNode, ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory)}
+     * method is called.
+     * </p>
+     *
+     * @param sequence1   the first sequence to be merged
+     * @param sequence2   the second sequence to be merged
+     * @param treeBuilder the tree builder that can be used for connecting task tree nodes
+     * @param nodeFactory the node factory that can be used for instantiating task tree nodes
+     * 
+     * @return the result of the merge or null if merging was not possible
+     */
+    private ISequence mergeEqualSequences(ISequence             sequence1,
+                                          ISequence             sequence2,
+                                          ITaskTreeBuilder      treeBuilder,
+                                          ITaskTreeNodeFactory  nodeFactory)
+    {
+        ISequence mergeResult = null;
+        
+        if (sequence1.getChildren().size() == sequence2.getChildren().size()) {
+            mergeResult = nodeFactory.createNewSequence();
+            
+            for (int i = 0; i < sequence1.getChildren().size(); i++) {
+                ITaskTreeNode mergedNode = mergeEqualTasks
+                    (sequence1.getChildren().get(i), sequence2.getChildren().get(i),
+                     treeBuilder, nodeFactory);
+                
+                if (mergedNode != null) {
+                    treeBuilder.addChild(mergeResult, mergedNode);
+                }
+                else {
+                    mergeResult = null;
+                    break;
+                }
+            }
+        }
+        
+        return mergeResult;
+    }
+
+    /**
+     * <p>
+     * merges equal selections. This is done through trying to merge each node of selections with
+     * each other. For this, the method
+     * {@link #mergeEqualNodes(List, ITaskTreeBuilder, ITaskTreeNodeFactory)} is called with a
+     * join of the child list of both selections.
+     * </p>
+     *
+     * @param selection1  the first selection to be merged
+     * @param selection2  the second selection to be merged
+     * @param treeBuilder the tree builder that can be used for connecting task tree nodes
+     * @param nodeFactory the node factory that can be used for instantiating task tree nodes
+     * 
+     * @return the result of the merge which is not null
+     */
+    private ITaskTreeNode mergeEqualSelections(ISelection            selection1,
+                                               ISelection            selection2,
+                                               ITaskTreeBuilder      treeBuilder,
+                                               ITaskTreeNodeFactory  nodeFactory)
+    {
+        ISelection mergeResult = nodeFactory.createNewSelection();
+            
+        for (int i = 0; i < selection1.getChildren().size(); i++) {
+            treeBuilder.addChild(mergeResult, selection1.getChildren().get(i));
+        }
+        
+        for (int i = 0; i < selection2.getChildren().size(); i++) {
+            treeBuilder.addChild(mergeResult, selection2.getChildren().get(i));
+        }
+        
+        mergeEqualNodes(mergeResult.getChildren(), treeBuilder, nodeFactory);
+        
+        return mergeResult;
+    }
+
+    /**
+     * <p>
+     * merges equal iterations. This is done through merging the children of both iterations. If
+     * this is possible, a resulting iteration with the merge result of the children as its own
+     * child is returned. Otherwise null is returned to indicate that merging was not possible.
+     * </p>
+     *
+     * @param selection1  the first iteration to be merged
+     * @param selection2  the second iteration to be merged
+     * @param treeBuilder the tree builder that can be used for connecting task tree nodes
+     * @param nodeFactory the node factory that can be used for instantiating task tree nodes
+     * 
+     * @return the result of the merge or null if merging is not possible
+     */
+    private ITaskTreeNode mergeEqualIterations(IIteration            iteration1,
+                                               IIteration            iteration2,
+                                               ITaskTreeBuilder      treeBuilder,
+                                               ITaskTreeNodeFactory  nodeFactory)
+    {
+        ITaskTreeNode mergedChild = mergeEqualTasks
+            (iteration1.getChildren().get(0), iteration2.getChildren().get(0),
+             treeBuilder, nodeFactory);
+        
+        IIteration mergeResult = null;
+        
+        if (mergedChild != null) {
+            mergeResult = nodeFactory.createNewIteration();
+            treeBuilder.setChild(mergeResult, mergedChild);
+        }
+        
+        return mergeResult;
+    }
+
+    /**
+     * <p>
+     * this is a convenience method to create an iteration based on the identified and already
+     * merged iterated subsequences. This method creates the simplest iteration possible. As an
+     * example, if always the same task tree node is iterated, it becomes the child of the
+     * iteration. If a sequence of tasks is iterated, this sequence becomes the child of the
+     * iteration. It several equal sublists or nodes which are not lexically equal are iterated
+     * they become a selection which in turn become the child of the iteration.
+     * </p>
+     *
+     * @param subsequences the identified and already merged equal subsequences
+     * @param treeBuilder  the tree builder that can be used for connecting task tree nodes
+     * @param nodeFactory  the node factory that can be used for instantiating the iteration
+     * 
+     * @return the resulting iteration
+     */
+    private IIteration createIterationBasedOnIdentifiedVariants(SubSequences          subsequences,
+                                                                ITaskTreeBuilder      treeBuilder,
+                                                                ITaskTreeNodeFactory  nodeFactory,
+                                                                RuleApplicationResult result)
+    {
+        IIteration newIteration = nodeFactory.createNewIteration();
+        result.addNewlyCreatedParentNode(newIteration);
+
+        if (subsequences.equalVariants.size() == 1) {
+            // all children are the same. Create an iteration of this child
+            if (subsequences.equalVariants.get(0).getChildren().size() == 1) {
+                // there is only one equal variant and this has only one child. So create an
+                // iteration of this child
+                treeBuilder.setChild
+                    (newIteration, subsequences.equalVariants.get(0).getChildren().get(0));
+            }
+            else {
+                // there was an iteration of one equal sequence
+                treeBuilder.setChild(newIteration, subsequences.equalVariants.get(0));
+                result.addNewlyCreatedParentNode(subsequences.equalVariants.get(0));
+            }
+        }
+        else {
+            // there are distinct variants of equal subsequences or children --> create an
+            // iterated selection
+            ISelection selection = nodeFactory.createNewSelection();
+            result.addNewlyCreatedParentNode(selection);
+
+            for (ITaskTreeNode variant : subsequences.equalVariants) {
+                if (variant.getChildren().size() == 1) {
+                    treeBuilder.addChild(selection, variant.getChildren().get(0));
+                }
+                else {
+                    treeBuilder.addChild(selection, variant);
+                    result.addNewlyCreatedParentNode(variant);
+                }
+            }
+
+            treeBuilder.setChild(newIteration, selection);
+        }
+        
+        return newIteration;
+    }
+
+    /**
+     * <p>
+     * as the method has to denote all newly created parent nodes this method identifies them by
+     * comparing the existing subtree with the newly created iteration. Only those parent nodes
+     * in the new iteration, which are not already found in the existing sub tree are denoted as
+     * newly created. We do this in this way, as during the iteration detection algorithm, many
+     * parent nodes are created, which may be discarded later. It is easier to identify the
+     * remaining newly created parent nodes through this way than to integrate it into the
+     * algorithm.
+     * </p>
+     * 
+     * @param existingSubTree the existing subtree
+     * @param newSubTree      the identified iteration
+     * @param result          the rule application result into which the newly created parent nodes
+     *                        shall be stored.
+     */
+    private void determineNewlyCreatedParentTasks(ITaskTreeNode         existingSubTree,
+                                                  ITaskTreeNode         newSubTree,
+                                                  RuleApplicationResult result)
+    {
+        List<ITaskTreeNode> existingParentNodes = getParentNodes(existingSubTree);
+        List<ITaskTreeNode> newParentNodes = getParentNodes(newSubTree);
+        
+        boolean foundNode;
+        for (ITaskTreeNode newParentNode : newParentNodes) {
+            foundNode = false;
+            for (ITaskTreeNode existingParentNode : existingParentNodes) {
+                // It is sufficient to compare the references. The algorithm reuses nodes as they
+                // are. So any node existing in the new structure that is also in the old structure
+                // was unchanged an therefore does not need to be handled as a newly created one.
+                // but every node in the new structure that is not included in the old structure
+                // must be treated as a newly created one.
+                if (newParentNode == existingParentNode) {
+                    foundNode = true;
+                    break;
+                }
+            }
+            
+            if (!foundNode) {
+                result.addNewlyCreatedParentNode(newParentNode);
+            }
+        }
+        
+    }
+
+    /**
+     * <p>
+     * convenience method to determine all parent nodes existing in a subtree
+     * </p>
+     *
+     * @param subtree the subtree to search for parent nodes in
+     * 
+     * @return a list of parent nodes existing in the subtree
+     */
+    private List<ITaskTreeNode> getParentNodes(ITaskTreeNode subtree) {
+        List<ITaskTreeNode> parentNodes = new ArrayList<ITaskTreeNode>();
+        
+        if (subtree.getChildren().size() > 0) {
+            parentNodes.add(subtree);
+            
+            for (ITaskTreeNode child : subtree.getChildren()) {
+                parentNodes.addAll(getParentNodes(child));
+            }
+        }
+        
+        return parentNodes;
+    }
+
+    /**
+     * <p>
+     * used to have a container for equal sublists identified in a sub part of the children of
+     * a parent node.
+     * </p>
+     * 
+     * @author Patrick Harms
+     */
+    private static class SubSequences {
+
+        /**
+         * <p>
+         * the beginning of the subpart of the children of the parent node in which the sublists
+         * are found (inclusive)
+         * </p>
+         */
+        public int start;
+        
+        /**
+         * <p>
+         * the end of the subpart of the children of the parent node in which the sublists
+         * are found (exclusive)
+         * </p>
+         */
+        public int end;
+        
+        /**
+         * <p>
+         * the equal sublists found in the subpart of the children of the parent node
+         * </p>
+         */
+        List<ITaskTreeNode> equalVariants = new ArrayList<ITaskTreeNode>();
+        
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/RuleApplicationResult.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/RuleApplicationResult.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/RuleApplicationResult.java	(revision 893)
@@ -0,0 +1,71 @@
+package de.ugoe.cs.quest.tasktrees.temporalrelation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * <p>
+ * The rule application result describes the result of applying a {@link TemporalRelationshipRule}
+ * on a task tree node. It contains a {@link RuleApplicationStatus} and a list of all parent
+ * task tree nodes that were created during a rule application. See the description of
+ * {@link TemporalRelationshipRule} for more details.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+class RuleApplicationResult {
+
+    /** */
+    private RuleApplicationStatus status = RuleApplicationStatus.RULE_NOT_APPLIED;
+
+    /** */
+    private List<ITaskTreeNode> newParents = new ArrayList<ITaskTreeNode>();
+
+    /**
+     * <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 node created during the rule application
+     * </p>
+     */
+    void addNewlyCreatedParentNode(ITaskTreeNode newParent) {
+        newParents.add(newParent);
+    }
+
+    /**
+     * <p>
+     * return all parent nodes created during the rule application
+     * </p>
+     */
+    List<ITaskTreeNode> getNewlyCreatedParentNodes() {
+        return newParents;
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/RuleApplicationStatus.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/RuleApplicationStatus.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/RuleApplicationStatus.java	(revision 893)
@@ -0,0 +1,15 @@
+package de.ugoe.cs.quest.tasktrees.temporalrelation;
+
+/**
+ * <p>
+ * The rule application status describes the result of applying a {@link TemporalRelationshipRule}
+ * on a task tree node. See the description of {@link TemporalRelationshipRule} for more details.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+enum RuleApplicationStatus {
+    RULE_APPLICATION_FINISHED,
+    RULE_APPLICATION_FEASIBLE,
+    RULE_NOT_APPLIED;
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/TemporalRelationshipRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/TemporalRelationshipRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/TemporalRelationshipRule.java	(revision 893)
@@ -0,0 +1,55 @@
+package de.ugoe.cs.quest.tasktrees.temporalrelation;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+
+/**
+ * <p>
+ * a temporal relation ship is able to detected temporal relationships between the child nodes
+ * of the parent node provided to the
+ * {@link #apply(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)} method. A rule
+ * created temporal relationships between the child nodes, i.e. substructures in the task tree, if
+ * it detects a temporal relationship and it can be sure that it is complete. Incomplete but
+ * detected temporal relationships may occur, if there can be more children expected to be added
+ * to the provided parent node. This could be the case during parsing a interaction log file of
+ * a GUI.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+interface TemporalRelationshipRule {
+
+  /**
+   * <p>
+   * applies the rule to the given parent node. The provided builder and node factory are used
+   * to create substructures in the task tree for the identified temporal relationships. The
+   * finalize parameter is used to command the rule to finish rule applications, in the case it
+   * is known that no further data will be available. 
+   * </p>
+   * <p>
+   * 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 nodes. It returns a rule application result with status
+   * {@link RuleApplicationStatus#RULE_APPLICATION_FEASIBLE} if the rule would be applicable if
+   * further children would be available in the parent node. This status MUST not be returned if 
+   * the finalize parameter is true. In this case the rule must be applied or not. 
+   * </p>
+   * 
+   * @param parent      the parent node with the children to apply the rule on
+   * @param builder     the builder to be used for creating substructures for the identified
+   *                    temporal relationships
+   * @param nodeFactory the node factory to be used for creating substructures for the identified
+   *                    temporal relationships
+   * @param finalize    true, if the rule shall not expect further children to come and that it
+   *                    should therefore be applied in any case
+   *                    
+   * @return the rule application result as described.
+   */
+  RuleApplicationResult apply(ITaskTreeNode        parent,
+                              ITaskTreeBuilder     builder,
+                              ITaskTreeNodeFactory nodeFactory,
+                              boolean              finalize);
+  
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java	(revision 893)
@@ -0,0 +1,221 @@
+package de.ugoe.cs.quest.tasktrees.temporalrelation;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+
+import de.ugoe.cs.quest.tasktrees.nodeequality.NodeEquality;
+import de.ugoe.cs.quest.tasktrees.nodeequality.NodeEqualityRuleManager;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+import de.ugoe.cs.util.console.Console;
+
+/**
+ * <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 task tree nodes which are not only a major sequence. I.e. through the application of
+ * rule iterations and selections of task tree nodes are detected. Which kind of temporal relations
+ * between task tree nodes are detected depends on the {@link TemporalRelationshipRule}s known to
+ * this class.
+ * </p>
+ * <p>The class holds references to the appropriate {@link TemporalRelationshipRule}s and calls
+ * their {@link TemporalRelationshipRule#apply(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}
+ * method for each node 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(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}
+ *     method is called for a so far unstructured task tree node
+ *   </li>
+ *   <li>
+ *     the class iterates its internal list of rules and calls their
+ *     {@link TemporalRelationshipRule#apply(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, 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 node provided in the rule application
+ *         result, the {@link #applyRules(ITaskTreeNode, ITaskTreeBuilder, ITaskTreeNodeFactory, boolean)}
+ *         method is called.
+ *       </li>
+ *     </ul>
+ *   </li>
+ * </ol>
+ * Through this, all rules are tried to be applied at least once to the provided parent node and
+ * all parent nodes created during the rule application.
+ * </p>
+ * 
+ * @author Patrick Harms
+ */
+public class TemporalRelationshipRuleManager {
+    
+    /**
+     * <p>
+     * the node equality manager needed by the rules to compare task tree nodes with each other
+     * </p>
+     */
+    private NodeEqualityRuleManager nodeEqualityRuleManager;
+
+    /**
+     * <p>
+     * the temporal relationship rule known to the manager. The rules are applied in the order
+     * they occur in this list.
+     * </p>
+     */
+    private List<TemporalRelationshipRule> rules = new ArrayList<TemporalRelationshipRule>();
+
+    /**
+     * <p>
+     * initialize the manager with a node equality rule manager to be used by the known rules
+     * for task tree node comparison.
+     * </p>
+     */
+    public TemporalRelationshipRuleManager(NodeEqualityRuleManager nodeEqualityRuleManager) {
+        super();
+        this.nodeEqualityRuleManager = nodeEqualityRuleManager;
+    }
+
+    /**
+     * <p>
+     * initialized the temporal relationship rule manager by instantiating the known rules and
+     * providing them with a reference to the node equality manager or other information they need.
+     * </p>
+     */
+    public void init() {
+        rules.add(new DefaultGuiElementSequenceDetectionRule());
+        rules.add(new DefaultEventTargetSequenceDetectionRule());
+        rules.add(new TrackBarSelectionDetectionRule(nodeEqualityRuleManager));
+        rules.add(new DefaultGuiEventSequenceDetectionRule());
+        
+        rules.add(new DefaultIterationDetectionRule
+                      (nodeEqualityRuleManager, NodeEquality.LEXICALLY_EQUAL));
+        rules.add(new DefaultIterationDetectionRule
+                      (nodeEqualityRuleManager, NodeEquality.SYNTACTICALLY_EQUAL));
+        rules.add(new DefaultIterationDetectionRule
+                      (nodeEqualityRuleManager, NodeEquality.SEMANTICALLY_EQUAL));
+    }
+
+    /**
+     * <p>
+     * applies the known rules to the provided parent node. For the creation of further nodes,
+     * the provided builder and node 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. 
+     * </p>
+     * 
+     * @param parent       the parent node to apply the rules on
+     * @param builder      the task tree builder to be used for linking task tree nodes with each
+     *                     other
+     * @param nodeFactory  the node factory to be used for instantiating new task tree nodes.
+     * @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.
+     */
+    public void applyRules(ITaskTreeNode        parent,
+                           ITaskTreeBuilder     builder,
+                           ITaskTreeNodeFactory nodeFactory,
+                           boolean              finalize)
+    {
+        applyRules(parent, builder, nodeFactory, finalize, "");
+    }
+
+    /**
+     * <p>
+     * applies the known rules to the provided parent node. For the creation of further nodes,
+     * the provided builder and node 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 node created through the rule
+     * application. In this case, the finalize parameter is always true.
+     * </p>
+     * 
+     * @param parent       the parent node to apply the rules on
+     * @param builder      the task tree builder to be used for linking task tree nodes with each
+     *                     other
+     * @param nodeFactory  the node factory to be used for instantiating new task tree nodes.
+     * @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 loggin purposes to indent the log messages depending
+     *                     on the recursion depth of calling this method.
+     */
+    private int applyRules(ITaskTreeNode        parent,
+                           ITaskTreeBuilder     builder,
+                           ITaskTreeNodeFactory nodeFactory,
+                           boolean              finalize,
+                           String               logIndent)
+    {
+        Console.traceln(Level.FINER, logIndent + "applying rules for " + parent);
+
+        int noOfRuleApplications = 0;
+
+        for (TemporalRelationshipRule rule : rules) {
+            RuleApplicationResult result;
+            do {
+                // LOG.info(logIndent + "trying to apply rule " + rule + " on " + parent);
+                result = rule.apply(parent, builder, nodeFactory, finalize);
+
+                if ((result != null) &&
+                    (result.getRuleApplicationStatus() ==
+                     RuleApplicationStatus.RULE_APPLICATION_FINISHED))
+                {
+                    Console.traceln
+                        (Level.FINE, logIndent + "applied rule " + rule + " on " + parent);
+                    noOfRuleApplications++;
+
+                    for (ITaskTreeNode newParent : result.getNewlyCreatedParentNodes()) {
+                        noOfRuleApplications +=
+                            applyRules(newParent, builder, nodeFactory, true, logIndent + "  ");
+                    }
+                }
+            }
+            while ((result != null) &&
+                   (result.getRuleApplicationStatus() ==
+                    RuleApplicationStatus.RULE_APPLICATION_FINISHED));
+
+            if ((!finalize) &&
+                (result != null) &&
+                (result.getRuleApplicationStatus() ==
+                 RuleApplicationStatus.RULE_APPLICATION_FEASIBLE))
+            {
+                // in this case, don't go on applying rules, which should not be applied yet
+                break;
+            }
+        }
+
+        if (noOfRuleApplications <= 0) {
+            Console.traceln(Level.INFO, logIndent + "no rules applied --> no temporal " +
+                            "relationship generated");
+        }
+
+        return noOfRuleApplications;
+    }
+
+    /**
+     *
+     */
+    /*
+     * private void dumpTask(TaskTreeNode task, String indent) { System.err.print(indent);
+     * System.err.print(task); System.err.println(" ");
+     * 
+     * if ((task.getChildren() != null) && (task.getChildren().size() > 0)) { for (TaskTreeNode
+     * child : task.getChildren()) { dumpTask(child, indent + "  "); } } }
+     */
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/TrackBarSelectionDetectionRule.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/TrackBarSelectionDetectionRule.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/TrackBarSelectionDetectionRule.java	(revision 893)
@@ -0,0 +1,147 @@
+package de.ugoe.cs.quest.tasktrees.temporalrelation;
+
+import de.ugoe.cs.quest.eventcore.gui.ValueSelection;
+import de.ugoe.cs.quest.eventcore.guimodel.ITrackBar;
+import de.ugoe.cs.quest.tasktrees.nodeequality.NodeEquality;
+import de.ugoe.cs.quest.tasktrees.nodeequality.NodeEqualityRuleManager;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 28.04.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class TrackBarSelectionDetectionRule implements TemporalRelationshipRule {
+
+    /** */
+    private NodeEqualityRuleManager nodeEqualityRuleManager;
+
+    /**
+     * TODO: comment
+     * 
+     */
+    TrackBarSelectionDetectionRule(NodeEqualityRuleManager nodeEqualityRuleManager) {
+        super();
+        this.nodeEqualityRuleManager = nodeEqualityRuleManager;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see TemporalRelationshipRule#apply(TaskTreeNode, TaskTreeBuilder, TaskTreeNodeFactory)
+     */
+    @Override
+    public RuleApplicationResult apply(ITaskTreeNode        parent,
+                                       ITaskTreeBuilder     builder,
+                                       ITaskTreeNodeFactory nodeFactory,
+                                       boolean              finalize)
+    {
+        if (!(parent instanceof ISequence)) {
+            return null;
+        }
+
+        RuleApplicationResult result = new RuleApplicationResult();
+
+        int valueSelectionStartIndex = -1;
+
+        int index = 0;
+        while (index < parent.getChildren().size()) {
+            ITaskTreeNode child = parent.getChildren().get(index);
+
+            if ((child instanceof IEventTask) &&
+                (((IEventTask) child).getEventTarget() instanceof ITrackBar) &&
+                (((IEventTask) child).getEventType() instanceof ValueSelection))
+            {
+                if (valueSelectionStartIndex < 0) {
+                    // let the show begin
+                    valueSelectionStartIndex = index;
+                }
+            }
+            else if (valueSelectionStartIndex >= 0) {
+                // current child is no more value selection. But the preceding tasks were.
+                // Therefore,
+                // create an iteration with the different selectable values as selection children
+                handleValueSelections(valueSelectionStartIndex, index - 1, parent, builder,
+                                      nodeFactory, result);
+
+                return result;
+            }
+
+            index++;
+        }
+
+        if (valueSelectionStartIndex >= 0) {
+            if (finalize) {
+                handleValueSelections(valueSelectionStartIndex, parent.getChildren().size() - 1,
+                                      parent, builder, nodeFactory, result);
+            }
+            else {
+                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param valueSelectionStartIndex
+     * @param i
+     */
+    private void handleValueSelections(int                   startIndex,
+                                       int                   endIndex,
+                                       ITaskTreeNode         parent,
+                                       ITaskTreeBuilder      builder,
+                                       ITaskTreeNodeFactory  nodeFactory,
+                                       RuleApplicationResult result)
+    {
+        IIteration iteration = nodeFactory.createNewIteration();
+        result.addNewlyCreatedParentNode(iteration);
+
+        ISelection selection = nodeFactory.createNewSelection();
+        result.addNewlyCreatedParentNode(selection);
+        builder.setChild(iteration, selection);
+
+        for (int i = endIndex - startIndex; i >= 0; i--) {
+            addChildIfNecessary(selection, parent.getChildren().get(startIndex), builder,
+                                nodeFactory, result);
+            builder.removeChild((ISequence) parent, startIndex);
+        }
+
+        builder.addChild((ISequence) parent, startIndex, iteration);
+
+        result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
+    }
+
+    /**
+     *
+     */
+    private void addChildIfNecessary(ISelection            parentSelection,
+                                     ITaskTreeNode         node,
+                                     ITaskTreeBuilder      builder,
+                                     ITaskTreeNodeFactory  nodeFactory,
+                                     RuleApplicationResult result)
+    {
+        for (int i = 0; i < parentSelection.getChildren().size(); i++) {
+            ITaskTreeNode child = parentSelection.getChildren().get(i);
+
+            // check, if the new node is a variant for the current event task
+            NodeEquality nodeEquality = nodeEqualityRuleManager.applyRules(child, node);
+            if (nodeEquality.isAtLeast(NodeEquality.SYNTACTICALLY_EQUAL)) {
+                return;
+            }
+        }
+
+        // if we did not return in the previous checks, then the node must be added
+        builder.addChild(parentSelection, node);
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/IEventTask.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/IEventTask.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/IEventTask.java	(revision 893)
@@ -0,0 +1,31 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+import de.ugoe.cs.quest.eventcore.IEventTarget;
+import de.ugoe.cs.quest.eventcore.IEventType;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+public interface IEventTask extends ITaskTreeNode {
+    
+    /**
+     * @return Returns the event type.
+     */
+    public IEventType getEventType();
+
+    /**
+     * @return Returns the event target.
+     */
+    public IEventTarget getEventTarget();
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public IEventTask clone();
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/IIteration.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/IIteration.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/IIteration.java	(revision 893)
@@ -0,0 +1,18 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface IIteration extends ITemporalRelationship {
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public IIteration clone();
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ISelection.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ISelection.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ISelection.java	(revision 893)
@@ -0,0 +1,18 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface ISelection extends ITemporalRelationship {
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public ISelection clone();
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ISequence.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ISequence.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ISequence.java	(revision 893)
@@ -0,0 +1,18 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface ISequence extends ITemporalRelationship {
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public ISequence clone();
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTree.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTree.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTree.java	(revision 893)
@@ -0,0 +1,31 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+import java.util.Map;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface ITaskTree extends Cloneable {
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public ITaskTreeNode getRoot();
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    public Map<ITaskTreeNode, ITaskTreeNodeInfo> getTaskMap();
+
+    /**
+     *
+     */
+    public ITaskTree clone();
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeBuilder.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeBuilder.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeBuilder.java	(revision 893)
@@ -0,0 +1,68 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface ITaskTreeBuilder {
+
+    /**
+     * TODO: comment
+     * 
+     * @param sequence
+     * @param task
+     */
+    void addChild(ISequence parent, ITaskTreeNode child);
+
+    /**
+     * TODO: comment
+     * 
+     * @param parent
+     * @param index
+     * @param sequence
+     */
+    void addChild(ISequence parent, int index, ITaskTreeNode child);
+
+    /**
+     * TODO: comment
+     * 
+     * @param sequence
+     * @param task
+     */
+    void addChild(ISelection parent, ITaskTreeNode child);
+
+    /**
+     * TODO: comment
+     * 
+     * @param iteration
+     * @param newChild
+     */
+    void setChild(IIteration iteration, ITaskTreeNode newChild);
+
+    /**
+     * TODO: comment
+     * 
+     * @param parent
+     * @param i
+     */
+    void removeChild(ISequence parent, int index);
+
+    /**
+     * TODO: comment
+     * 
+     * @param parent
+     * @param i
+     */
+    void removeChild(ISelection parent, ITaskTreeNode child);
+
+    /**
+     * TODO: comment
+     * 
+     * @param parent
+     * @param i
+     */
+    void setDescription(ITaskTreeNode node, String description);
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeNode.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeNode.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeNode.java	(revision 893)
@@ -0,0 +1,43 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+import java.util.List;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+public interface ITaskTreeNode extends Cloneable {
+
+    /**
+     *
+     */
+    public String getName();
+
+    /**
+     *
+     */
+    public String getDescription();
+
+    /**
+     *
+     */
+    public List<ITaskTreeNode> getChildren();
+
+    /**
+     *
+     */
+    public boolean equals(ITaskTreeNode taskTreeNode);
+
+    /**
+     *
+     */
+    public int hashCode();
+
+    /**
+     *
+     */
+    public ITaskTreeNode clone();
+    
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeNodeFactory.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeNodeFactory.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeNodeFactory.java	(revision 893)
@@ -0,0 +1,53 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+import de.ugoe.cs.quest.eventcore.IEventTarget;
+import de.ugoe.cs.quest.eventcore.IEventType;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface ITaskTreeNodeFactory
+{
+
+  /**
+   * TODO: comment
+   *
+   * @param eventType
+   * @param eventTarget
+   * @return
+   */
+  IEventTask createNewEventTask(IEventType eventType, IEventTarget eventTarget);
+
+  /**
+   * TODO: comment
+   *
+   * @return
+   */
+  ISequence createNewSequence();
+
+  /**
+   * TODO: comment
+   *
+   * @return
+   */
+  IIteration createNewIteration();
+
+  /**
+   * TODO: comment
+   *
+   * @return
+   */
+  ISelection createNewSelection();
+
+  /**
+   * TODO: comment
+   *
+   * @param rootSequence
+   * @return
+   */
+  ITaskTree createTaskTree(ITaskTreeNode root);
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeNodeInfo.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeNodeInfo.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITaskTreeNodeInfo.java	(revision 893)
@@ -0,0 +1,26 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface ITaskTreeNodeInfo {
+
+    /**
+     * 
+     */
+    public ITaskTreeNode getTask();
+
+    /**
+     * 
+     */
+    public int getNoOfOccurencesInTree();
+
+    /**
+     *
+     */
+    public long getLastUpdate();
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITemporalRelationship.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITemporalRelationship.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeifc/ITemporalRelationship.java	(revision 893)
@@ -0,0 +1,16 @@
+package de.ugoe.cs.quest.tasktrees.treeifc;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 12.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public interface ITemporalRelationship extends ITaskTreeNode {
+
+    /**
+     *
+     */
+    public ITemporalRelationship clone();
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/EventTask.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/EventTask.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/EventTask.java	(revision 893)
@@ -0,0 +1,83 @@
+package de.ugoe.cs.quest.tasktrees.treeimpl;
+
+import de.ugoe.cs.quest.eventcore.IEventTarget;
+import de.ugoe.cs.quest.eventcore.IEventType;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+public class EventTask extends TaskTreeNode implements IEventTask {
+    
+    /** */
+    private IEventType eventType;
+
+    /** */
+    private IEventTarget eventTarget;
+
+    /**
+     * @param eventType
+     * @param eventTarget
+     */
+    EventTask(IEventType eventType, IEventTarget eventTarget) {
+        super(eventType.getName() + "(" + eventTarget + ")");
+        super.setDescription(eventType + " on " + eventTarget);
+        this.eventType = eventType;
+        this.eventTarget = eventTarget;
+    }
+
+    /**
+     * @return Returns the interaction.
+     */
+    public IEventType getEventType() {
+        return eventType;
+    }
+
+    /**
+     * @return Returns the GUIElement.
+     */
+    public IEventTarget getEventTarget() {
+        return eventTarget;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.harms.ctte.Task#equals(de.harms.ctte.Task)
+     */
+    @Override
+    public boolean equals(ITaskTreeNode task) {
+        if (!(task instanceof IEventTask)) {
+            return false;
+        }
+
+        IEventType otherType = ((IEventTask) task).getEventType();
+        IEventTarget otherTarget = ((IEventTask) task).getEventTarget();
+
+        if (((eventType == otherType) ||
+             ((eventType != null) && (eventType.equals(otherType)))) &&
+            ((eventTarget == otherTarget) ||
+             ((eventTarget != null) && (eventTarget.equals(otherTarget)))))
+        {
+            return true;
+        }
+
+        return false;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.harms.tasktrees.TreeNode#clone()
+     */
+    @Override
+    public EventTask clone() {
+        // Event type and target are unchangeable and do not need to be cloned
+        return (EventTask) super.clone();
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/Iteration.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/Iteration.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/Iteration.java	(revision 893)
@@ -0,0 +1,56 @@
+package de.ugoe.cs.quest.tasktrees.treeimpl;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class Iteration extends TaskTreeNode implements IIteration {
+
+    /**
+     *
+     */
+    Iteration() {
+        super("Iteration");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeNode#addChild(TaskTreeNode)
+     */
+    @Override
+    public void addChild(ITaskTreeNode child) {
+        // adding more children is not allowed
+        throw new UnsupportedOperationException
+          ("iterations may not have a list of children. Use setChild() instead.");
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param selection
+     * @return
+     */
+    public void setChild(ITaskTreeNode child) {
+        if (super.getChildren().size() > 0) {
+            super.removeChild(0);
+        }
+        super.addChild(child);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public Iteration clone() {
+        return (Iteration) super.clone();
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/NodeInfo.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/NodeInfo.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/NodeInfo.java	(revision 893)
@@ -0,0 +1,90 @@
+package de.ugoe.cs.quest.tasktrees.treeimpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeInfo;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+public class NodeInfo implements ITaskTreeNodeInfo {
+    
+    /** */
+    private ITaskTreeNode task;
+
+    /** */
+    private long lastUpdate;
+
+    /** */
+    private List<ITaskTreeNode> parentNodes = new ArrayList<ITaskTreeNode>();
+
+    /**
+     * @param node
+     */
+    NodeInfo(ITaskTreeNode task) {
+        this.task = task;
+        lastUpdate = System.currentTimeMillis();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.NodeInfo#getTask()
+     */
+    @Override
+    public ITaskTreeNode getTask() {
+        return task;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeimpl.NodeInfo#getNoOfOccurencesInTree()
+     */
+    @Override
+    public int getNoOfOccurencesInTree() {
+        return parentNodes.size();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeimpl.NodeInfo#getLastUpdate()
+     */
+    @Override
+    public long getLastUpdate() {
+        return lastUpdate;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     */
+    void addParent(ITaskTreeNode parent) {
+        parentNodes.add(parent);
+    }
+
+    /**
+     * TODO: comment
+     * 
+     */
+    void removeParent(ITaskTreeNode parent) {
+        parentNodes.remove(parent);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public synchronized String toString() {
+        return "NodeInfo(" + task + ", " + parentNodes.size() + " parents)";
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/Selection.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/Selection.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/Selection.java	(revision 893)
@@ -0,0 +1,32 @@
+package de.ugoe.cs.quest.tasktrees.treeimpl;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class Selection extends TaskTreeNode implements ISelection {
+
+    /**
+     * TODO: comment
+     * 
+     * @param name
+     */
+    Selection() {
+        super("Selection");
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public Selection clone() {
+        return (Selection) super.clone();
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/Sequence.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/Sequence.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/Sequence.java	(revision 893)
@@ -0,0 +1,41 @@
+package de.ugoe.cs.quest.tasktrees.treeimpl;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 19.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class Sequence extends TaskTreeNode implements ISequence {
+    
+    /**
+     * TODO: comment
+     * 
+     * @param name
+     */
+    Sequence() {
+        super("Sequence");
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param name
+     */
+    Sequence(String name) {
+        super(name);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeimpl.TaskTreeNodeImpl#clone()
+     */
+    @Override
+    public Sequence clone() {
+        return (Sequence) super.clone();
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTree.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTree.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTree.java	(revision 893)
@@ -0,0 +1,107 @@
+package de.ugoe.cs.quest.tasktrees.treeimpl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeInfo;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTree;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class TaskTree implements ITaskTree {
+    
+    /** the map of nodes */
+    private Map<ITaskTreeNode, ITaskTreeNodeInfo> taskMap;
+
+    /** the root node of the task tree */
+    private ITaskTreeNode rootNode;
+
+    /**
+     * TODO: comment
+     * 
+     */
+    TaskTree(ITaskTreeNode rootNode) {
+        this.rootNode = rootNode;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTree#getRoot()
+     */
+    @Override
+    public ITaskTreeNode getRoot() {
+        return rootNode;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTree#getTaskMap()
+     */
+    @Override
+    public synchronized Map<ITaskTreeNode, ITaskTreeNodeInfo> getTaskMap() {
+        if (taskMap == null) {
+            taskMap = new HashMap<ITaskTreeNode, ITaskTreeNodeInfo>();
+            addNodeToMap(rootNode, null);
+        }
+        return taskMap;
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param rootNode
+     */
+    private void addNodeToMap(ITaskTreeNode node, ITaskTreeNode parent) {
+        NodeInfo nodeInfo = (NodeInfo) taskMap.get(node);
+
+        if (nodeInfo == null) {
+            nodeInfo = new NodeInfo(node);
+            taskMap.put(node, nodeInfo);
+        }
+
+        if (parent != null) {
+            // through first removing an existing parent it is assured, that a parent is recorded
+            // only once. This is needed, because parent may be reused in a tree as well, but we
+            // always iterate the whole tree
+            nodeInfo.removeParent(parent);
+            nodeInfo.addParent(parent);
+        }
+
+        for (ITaskTreeNode child : node.getChildren()) {
+            addNodeToMap(child, node);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public TaskTree clone() {
+        TaskTree clone = null;
+        try {
+            clone = (TaskTree) super.clone();
+
+            clone.rootNode = rootNode.clone();
+
+            // the clone will create the task map itself, when it is first retrieved
+            clone.taskMap = null;
+
+        }
+        catch (CloneNotSupportedException e) {
+            // this should never happen. Therefore simply dump the exception
+            e.printStackTrace();
+        }
+
+        return clone;
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTreeBuilder.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTreeBuilder.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTreeBuilder.java	(revision 893)
@@ -0,0 +1,152 @@
+package de.ugoe.cs.quest.tasktrees.treeimpl;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class TaskTreeBuilder implements ITaskTreeBuilder {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeBuilder#addChild(Sequence, TaskTreeNode)
+     */
+    @Override
+    public void addChild(ISequence parent, ITaskTreeNode child) {
+        if (!(parent instanceof Sequence)) {
+            throw new IllegalArgumentException
+                ("illegal type of task tree node provided: " + parent.getClass());
+        }
+
+        addChildInternal(parent, -1, child);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeBuilder#addChild(Sequence, int, TaskTreeNode)
+     */
+    @Override
+    public void addChild(ISequence parent, int index, ITaskTreeNode child) {
+        if (!(parent instanceof Sequence)) {
+            throw new IllegalArgumentException
+                ("illegal type of task tree node provided: " + parent.getClass());
+        }
+
+        addChildInternal(parent, index, child);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeBuilder#addChild(Selection, TaskTreeNode)
+     */
+    @Override
+    public void addChild(ISelection parent, ITaskTreeNode child) {
+        if (!(parent instanceof Selection)) {
+            throw new IllegalArgumentException
+                ("illegal type of task tree node provided: " + parent.getClass());
+        }
+
+        addChildInternal(parent, -1, child);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeBuilder#setChild(Iteration, TaskTreeNode)
+     */
+    @Override
+    public void setChild(IIteration iteration, ITaskTreeNode newChild) {
+        if (!(iteration instanceof Iteration)) {
+            throw new IllegalArgumentException
+                ("illegal type of iteration provided: " + iteration.getClass());
+        }
+
+        if (!(newChild instanceof TaskTreeNode)) {
+            throw new IllegalArgumentException
+                ("illegal type of task tree node provided: " + newChild.getClass());
+        }
+
+        ((Iteration) iteration).setChild(newChild);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeBuilder#removeChild(Sequence, int)
+     */
+    @Override
+    public void removeChild(ISequence parent, int index) {
+        if (!(parent instanceof TaskTreeNode)) {
+            throw new IllegalArgumentException
+                ("illegal type of task tree node provided: " + parent.getClass());
+        }
+
+        ((TaskTreeNode) parent).removeChild(index);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeBuilder#removeChild(Selection, TaskTreeNode)
+     */
+    @Override
+    public void removeChild(ISelection parent, ITaskTreeNode child) {
+        if (!(parent instanceof TaskTreeNode)) {
+            throw new IllegalArgumentException
+                ("illegal type of task tree node provided: " + parent.getClass());
+        }
+
+        for (int i = 0; i < parent.getChildren().size(); i++) {
+            if ((parent.getChildren().get(i) == child) ||
+                ((parent.getChildren().get(i) != null) &&
+                 (parent.getChildren().get(i).equals(child))))
+            {
+                ((TaskTreeNode) parent).removeChild(i);
+                break;
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeBuilder#setDescription(TaskTreeNode, String)
+     */
+    @Override
+    public void setDescription(ITaskTreeNode parent, String description) {
+        if (!(parent instanceof TaskTreeNode)) {
+            throw new IllegalArgumentException
+                ("illegal type of task tree node provided: " + parent.getClass());
+        }
+
+        ((TaskTreeNode) parent).setDescription(description);
+    }
+
+    /**
+   * 
+   */
+    private void addChildInternal(ITaskTreeNode parent, int index, ITaskTreeNode child) {
+        if (!(child instanceof TaskTreeNode)) {
+            throw new IllegalArgumentException
+                ("illegal type of task tree node provided: " + child.getClass());
+        }
+
+        if (index > -1) {
+            ((TaskTreeNode) parent).addChild(index, child);
+        }
+        else {
+            ((TaskTreeNode) parent).addChild(child);
+        }
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTreeNode.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTreeNode.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTreeNode.java	(revision 893)
@@ -0,0 +1,220 @@
+package de.ugoe.cs.quest.tasktrees.treeimpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: $
+ * @author 2011, last modified by $Author: $
+ */
+public class TaskTreeNode implements ITaskTreeNode {
+    /** */
+    private static int temporalId = 0;
+
+    /** */
+    private String name;
+
+    /** */
+    private String description;
+
+    /** */
+    private int id;
+
+    /** children */
+    private List<ITaskTreeNode> children;
+
+    /**
+     * 
+     */
+    public TaskTreeNode(String name) {
+        this.name = name;
+        id = getNewId();
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @return
+     */
+    private static synchronized int getNewId() {
+        if (temporalId == Integer.MAX_VALUE) {
+            temporalId = 0;
+        }
+
+        return temporalId++;
+    }
+
+    /**
+     * @return Returns the name.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeNode#getDescription()
+     */
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * 
+     */
+    public synchronized List<ITaskTreeNode> getChildren() {
+        if ((children == null) || (children.size() == 0)) {
+            return new ArrayList<ITaskTreeNode>();
+        }
+
+        return children.subList(0, children.size());
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.quest.tasktrees.treeifc.TaskTreeNode#equals(TaskTreeNode)
+     */
+    @Override
+    public boolean equals(ITaskTreeNode taskTreeNode) {
+        if (!this.getClass().isInstance(taskTreeNode)) {
+            return false;
+        }
+
+        if (taskTreeNode.hashCode() != hashCode()) {
+            return false;
+        }
+
+        TaskTreeNode other = (TaskTreeNode) taskTreeNode;
+
+        if (id != other.id) {
+            return false;
+        }
+
+        if (!name.equals(other.name)) {
+            return false;
+        }
+
+        synchronized (other) {
+            if (children == null) {
+                return (other.children == null);
+            }
+            else if (other.children == null) {
+                return (children == null);
+            }
+            else if (other.children.size() != children.size()) {
+                return false;
+            }
+
+            for (int i = 0; i < children.size(); i++) {
+                if (!children.get(i).equals(other.children.get(i))) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public synchronized int hashCode() {
+        return getClass().getSimpleName().hashCode();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public synchronized String toString() {
+        if (children == null) {
+            return name + "(" + id + ")";
+        }
+        else {
+            return name + "(" + id + ", " + children.size() + " children)";
+        }
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param i
+     * @return
+     */
+    void setDescription(String description) {
+        this.description = description;
+    }
+
+    /**
+     * 
+     */
+    synchronized void addChild(ITaskTreeNode child) {
+        if (children == null) {
+            children = new ArrayList<ITaskTreeNode>();
+        }
+
+        children.add(child);
+    }
+
+    /**
+     * 
+     */
+    synchronized void addChild(int index, ITaskTreeNode child) {
+        if (children == null) {
+            children = new ArrayList<ITaskTreeNode>();
+        }
+
+        children.add(index, child);
+    }
+
+    /**
+     * TODO: comment
+     * 
+     * @param i
+     * @return
+     */
+    synchronized ITaskTreeNode removeChild(int index) {
+        return children.remove(index);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#clone()
+     */
+    @Override
+    public ITaskTreeNode clone() {
+        TaskTreeNode clone = null;
+        try {
+            clone = (TaskTreeNode) super.clone();
+
+            if (children != null) {
+                clone.children = new ArrayList<ITaskTreeNode>();
+
+                for (ITaskTreeNode child : children) {
+                    clone.children.add(child.clone());
+                }
+            }
+
+        }
+        catch (CloneNotSupportedException e) {
+            // this should never happen. Therefore simply dump the exception
+            e.printStackTrace();
+        }
+
+        return clone;
+    }
+
+}
Index: /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTreeNodeFactory.java
===================================================================
--- /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTreeNodeFactory.java	(revision 893)
+++ /trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/treeimpl/TaskTreeNodeFactory.java	(revision 893)
@@ -0,0 +1,73 @@
+package de.ugoe.cs.quest.tasktrees.treeimpl;
+
+import de.ugoe.cs.quest.eventcore.IEventTarget;
+import de.ugoe.cs.quest.eventcore.IEventType;
+import de.ugoe.cs.quest.tasktrees.treeifc.IEventTask;
+import de.ugoe.cs.quest.tasktrees.treeifc.IIteration;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
+import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTree;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
+import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
+
+/**
+ * TODO comment
+ * 
+ * @version $Revision: $ $Date: 21.02.2012$
+ * @author 2012, last modified by $Author: patrick$
+ */
+public class TaskTreeNodeFactory implements ITaskTreeNodeFactory {
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see TaskTreeNodeFactory#createNewEventTask(IEventType, IEventTarget)
+     */
+    @Override
+    public IEventTask createNewEventTask(IEventType eventType, IEventTarget eventTarget) {
+        return new EventTask(eventType, eventTarget);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeNodeFactory#createNewSequence()
+     */
+    @Override
+    public ISequence createNewSequence() {
+        return new Sequence();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeNodeFactory#createNewIteration()
+     */
+    @Override
+    public IIteration createNewIteration() {
+        return new Iteration();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see de.ugoe.cs.tasktree.treeifc.TaskTreeNodeFactory#createNewSelection()
+     */
+    @Override
+    public ISelection createNewSelection() {
+        return new Selection();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * de.ugoe.cs.tasktree.treeifc.TaskTreeNodeFactory#createTaskTree(de.ugoe.cs.tasktree.treeifc
+     * .TaskTreeNode)
+     */
+    @Override
+    public ITaskTree createTaskTree(ITaskTreeNode root) {
+        return new TaskTree(root);
+    }
+
+}
