source: trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/SequenceDependingOnEventTypeDetectionRule.java @ 1127

Last change on this file since 1127 was 1127, checked in by pharms, 11 years ago
  • complete refactoring of task detection
  • many performance improvements in task detection
  • improved merging of sequences using Myers diff algorithm
  • Property svn:executable set to *
File size: 8.3 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
16
17import java.util.List;
18import java.util.Stack;
19
20import de.ugoe.cs.autoquest.eventcore.gui.IInteraction;
21import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
22import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
23import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder;
24import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode;
25import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory;
26
27/**
28 * This rule generates sequences of events depending on the event types, more concrete, the
29 * {@link IInteraction}s and the return values of their {@link IInteraction#startsLogicalSequence()}
30 * and {@link IInteraction#finishesLogicalSequence()}. If a new logical sequence is started by
31 * an interaction, then a real sequence is instantiated. The sequence is finished, if an
32 * interaction finishes a logical sequence. Examples include keyboard focus changes.
33 *
34 * @version $Revision: $ $Date: 18.03.2012$
35 * @author 2012, last modified by $Author: patrick$
36 */
37class SequenceDependingOnEventTypeDetectionRule implements TemporalRelationshipRule {
38
39    /**
40     * <p>
41     * the task tree node factory to be used for creating substructures for the temporal
42     * relationships identified during rule
43     * </p>
44     */
45    private ITaskTreeNodeFactory taskTreeNodeFactory;
46    /**
47     * <p>
48     * the task tree builder to be used for creating substructures for the temporal relationships
49     * identified during rule application
50     * </p>
51     */
52    private ITaskTreeBuilder taskTreeBuilder;
53   
54    /**
55     * <p>
56     * instantiates the rule with a task tree node factory and builder to be used during rule
57     * application.
58     * </p>
59     *
60     * @param taskTreeNodeFactory the task tree node factory to be used for creating substructures
61     *                            for the temporal relationships identified during rule
62     *                            application
63     * @param taskTreeBuilder     the task tree builder to be used for creating substructures for
64     *                            the temporal relationships identified during rule application
65     */
66    SequenceDependingOnEventTypeDetectionRule(ITaskTreeNodeFactory taskTreeNodeFactory,
67                                              ITaskTreeBuilder     taskTreeBuilder)
68    {
69        this.taskTreeNodeFactory = taskTreeNodeFactory;
70        this.taskTreeBuilder = taskTreeBuilder;
71    }
72   
73    /* (non-Javadoc)
74     * @see java.lang.Object#toString()
75     */
76    @Override
77    public String toString() {
78        return "SequenceDependingOnEventTypeDetectionRule";
79    }
80
81    /*
82     * (non-Javadoc)
83     *
84     * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode,
85     * boolean)
86     */
87    @Override
88    public RuleApplicationResult apply(ITaskTreeNode parent, boolean finalize) {
89        if (!(parent instanceof ISequence)) {
90            return null;
91        }
92
93        RuleApplicationResult result = new RuleApplicationResult();
94        Stack<Integer> sequenceStartingIndex = new Stack<Integer>();
95
96        List<ITaskTreeNode> children = parent.getChildren();
97       
98        int index = 0;
99        while (index < children.size()) {
100            ITaskTreeNode child = children.get(index);
101
102            if ((child instanceof IEventTask) &&
103                (((IEventTask) child).getEventType() instanceof IInteraction))
104            {
105                IInteraction eventType = (IInteraction) ((IEventTask) child).getEventType();
106
107                if (eventType.finishesLogicalSequence() && (sequenceStartingIndex.size() > 0)) {
108                    index = handleLogicalSequence(sequenceStartingIndex, index, parent, result);
109                    // the parents child list will have changed, retrieve it again
110                    children = parent.getChildren();
111                }
112
113                if (eventType.startsLogicalSequence()) {
114                    sequenceStartingIndex.push(index);
115                }
116            }
117
118            index++;
119        }
120
121        if (sequenceStartingIndex.size() > 0) {
122            if (!finalize) {
123                result.setRuleApplicationStatus(RuleApplicationStatus.FEASIBLE);
124            }
125            else {
126                ITaskTreeNode lastChild = children.get(children.size() - 1);
127               
128                if (lastChild instanceof IEventTask) {
129                    handleLogicalSequence
130                        (sequenceStartingIndex, children.size() - 1, parent, result);
131                }
132            }
133        }
134
135        return result;
136    }
137
138    /**
139     * <p>
140     * TODO: comment
141     * </p>
142     *
143     */
144    private int handleLogicalSequence(Stack<Integer>        sequenceStartingIndex,
145                                      int                   index,
146                                      ITaskTreeNode         parent,
147                                      RuleApplicationResult result)
148    {
149        int newIndex = index;
150       
151        List<ITaskTreeNode> children = parent.getChildren();
152       
153        IInteraction eventType =
154            (IInteraction) ((IEventTask) children.get(index)).getEventType();
155
156        // There are several situations in which this implementation may cause infinite
157        // loops. This is because the rule manager will reapply rules until
158        // no rule is applied anymore. A sequence identified in a first iteration will
159        // be identified as a sequence also in a second iteration. As an example
160        // many sequences start with an interaction starting that sequence and end
161        // with an interaction ending that sequence. This will be reidentified as
162        // further subsequence. It must therefore be assured, that a sequence, that
163        // was once identified is not reidentified in a further application of the rule.
164        // For this, the implementation performs a kind of dry run. It creates a list of
165        // children that would belong to an identified sequence. Only if this list is
166        // not a reidentification then a new sequence is created and added to the
167        // parent. If it is a reidentification can be identified, if the list of
168        // children will contain all children of the parent, or if the list of children
169        // only consists of one sequence. Further, an identified sequence must at least
170        // have one child.
171       
172        boolean allChildrenBelongToSubSequence =
173            (sequenceStartingIndex.peek() == 0) && (index == (children.size() - 1));
174       
175        boolean atLeastOneChildToCondense = index - sequenceStartingIndex.peek() > 0;
176       
177        if (!allChildrenBelongToSubSequence && atLeastOneChildToCondense) {
178            int startIndex = sequenceStartingIndex.pop();
179            ISequence sequence = taskTreeNodeFactory.createNewSequence();
180
181            for (int j = startIndex; j < index; j++) {
182                taskTreeBuilder.addChild(sequence, children.get(startIndex));
183                taskTreeBuilder.removeChild((ISequence) parent, startIndex);
184            }
185
186            if (!eventType.startsLogicalSequence()) {
187                taskTreeBuilder.addChild(sequence, children.get(startIndex));
188                taskTreeBuilder.removeChild((ISequence) parent, startIndex);
189                newIndex = startIndex;
190            }
191            else {
192                newIndex = startIndex + 1;
193            }
194
195            taskTreeBuilder.addChild((ISequence) parent, startIndex, sequence);
196
197            result.addNewlyCreatedParentNode(sequence);
198               
199            taskTreeBuilder.setDescription(sequence, "logical sequence started by the first event");
200               
201            result.setRuleApplicationStatus(RuleApplicationStatus.FINISHED);
202        }
203       
204        return newIndex;
205    }
206
207}
Note: See TracBrowser for help on using the repository browser.