Index: trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/DefaultGuiEventSequenceDetectionRule.java
===================================================================
--- trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/DefaultGuiEventSequenceDetectionRule.java	(revision 987)
+++ trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/DefaultGuiEventSequenceDetectionRule.java	(revision 1107)
@@ -1,3 +1,5 @@
 package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
+
+import java.util.Stack;
 
 import de.ugoe.cs.autoquest.eventcore.gui.IInteraction;
@@ -18,18 +20,48 @@
  * @author 2012, last modified by $Author: patrick$
  */
-public class DefaultGuiEventSequenceDetectionRule implements TemporalRelationshipRule {
+class DefaultGuiEventSequenceDetectionRule implements TemporalRelationshipRule {
 
+    /**
+     * <p>
+     * the task tree node factory to be used for creating substructures for the temporal
+     * relationships identified during rule
+     * </p>
+     */
+    private ITaskTreeNodeFactory taskTreeNodeFactory;
+    /**
+     * <p>
+     * the task tree builder to be used for creating substructures for the temporal relationships
+     * identified during rule application
+     * </p>
+     */
+    private ITaskTreeBuilder taskTreeBuilder;
+    
+    /**
+     * <p>
+     * instantiates the rule with a task tree node factory and builder to be used during rule
+     * application.
+     * </p>
+     * 
+     * @param taskTreeNodeFactory the task tree node factory to be used for creating substructures
+     *                            for the temporal relationships identified during rule
+     *                            application
+     * @param taskTreeBuilder     the task tree builder to be used for creating substructures for
+     *                            the temporal relationships identified during rule application
+     */
+    DefaultGuiEventSequenceDetectionRule(ITaskTreeNodeFactory taskTreeNodeFactory,
+                                         ITaskTreeBuilder     taskTreeBuilder)
+    {
+        this.taskTreeNodeFactory = taskTreeNodeFactory;
+        this.taskTreeBuilder = taskTreeBuilder;
+    }
+    
     /*
      * (non-Javadoc)
      * 
      * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode,
-     * TaskTreeBuilder, TaskTreeNodeFactory)
+     * boolean)
      */
     @Override
-    public RuleApplicationResult apply(ITaskTreeNode        parent,
-                                       ITaskTreeBuilder     builder,
-                                       ITaskTreeNodeFactory nodeFactory,
-                                       boolean              finalize)
-    {
+    public RuleApplicationResult apply(ITaskTreeNode parent, boolean finalize) {
         if (!(parent instanceof ISequence)) {
             return null;
@@ -37,5 +69,5 @@
 
         RuleApplicationResult result = new RuleApplicationResult();
-        int sequenceStartingIndex = -1;
+        Stack<Integer> sequenceStartingIndex = new Stack<Integer>();
 
         int index = 0;
@@ -47,68 +79,11 @@
             {
                 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);
-                            
-                            builder.setDescription
-                                (sequence, "logical sequence started by the first event");
-                            
-                            result.setRuleApplicationStatus
-                                (RuleApplicationStatus.RULE_APPLICATION_FINISHED);
-                            return result;
-                        }
-                    }
+                if (eventType.finishesLogicalSequence() && (sequenceStartingIndex.size() > 0)) {
+                    index = handleLogicalSequence(sequenceStartingIndex, index, parent, result);
                 }
 
                 if (eventType.startsLogicalSequence()) {
-                    sequenceStartingIndex = index;
+                    sequenceStartingIndex.push(index);
                 }
             }
@@ -117,6 +92,16 @@
         }
 
-        if (sequenceStartingIndex >= 0) {
-            result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
+        if (sequenceStartingIndex.size() > 0) {
+            if (!finalize) {
+                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
+            }
+            else {
+                ITaskTreeNode lastChild = parent.getChildren().get(parent.getChildren().size() - 1);
+                
+                if (lastChild instanceof IEventTask) {
+                    handleLogicalSequence
+                        (sequenceStartingIndex, parent.getChildren().size() - 1, parent, result);
+                }
+            }
         }
 
@@ -124,3 +109,69 @@
     }
 
+    /**
+     * <p>
+     * TODO: comment
+     * </p>
+     *
+     */
+    private int handleLogicalSequence(Stack<Integer>        sequenceStartingIndex,
+                                      int                   index,
+                                      ITaskTreeNode         parent,
+                                      RuleApplicationResult result)
+    {
+        int newIndex = index;
+        IInteraction eventType =
+            (IInteraction) ((IEventTask) parent.getChildren().get(index)).getEventType();
+
+        // 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.
+        
+        boolean allChildrenBelongToSubSequence =
+            (sequenceStartingIndex.peek() == 0) && (index == (parent.getChildren().size() - 1));
+        
+        boolean atLeastOneChildToCondense = index - sequenceStartingIndex.peek() > 0;
+        
+        if (!allChildrenBelongToSubSequence && atLeastOneChildToCondense) {
+            int startIndex = sequenceStartingIndex.pop();
+            ISequence sequence = taskTreeNodeFactory.createNewSequence();
+
+            for (int j = startIndex; j < index; j++) {
+                taskTreeBuilder.addChild(sequence, parent.getChildren().get(startIndex));
+                taskTreeBuilder.removeChild((ISequence) parent, startIndex);
+            }
+
+            if (!eventType.startsLogicalSequence()) {
+                taskTreeBuilder.addChild(sequence, parent.getChildren().get(startIndex));
+                taskTreeBuilder.removeChild((ISequence) parent, startIndex);
+                newIndex = startIndex;
+            }
+            else {
+                newIndex = startIndex + 1;
+            }
+
+            taskTreeBuilder.addChild((ISequence) parent, startIndex, sequence);
+
+            result.addNewlyCreatedParentNode(sequence);
+                
+            taskTreeBuilder.setDescription(sequence, "logical sequence started by the first event");
+                
+            result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
+        }
+        
+        return newIndex;
+    }
+
 }
