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

Last change on this file since 1131 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
RevLine 
[1113]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
[922]15package de.ugoe.cs.autoquest.tasktrees.temporalrelation;
[439]16
[1127]17import java.util.List;
[1107]18import java.util.Stack;
19
[922]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;
[439]26
27/**
[972]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.
[439]33 *
34 * @version $Revision: $ $Date: 18.03.2012$
35 * @author 2012, last modified by $Author: patrick$
36 */
[1127]37class SequenceDependingOnEventTypeDetectionRule implements TemporalRelationshipRule {
[439]38
[1107]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     */
[1127]66    SequenceDependingOnEventTypeDetectionRule(ITaskTreeNodeFactory taskTreeNodeFactory,
67                                              ITaskTreeBuilder     taskTreeBuilder)
[1107]68    {
69        this.taskTreeNodeFactory = taskTreeNodeFactory;
70        this.taskTreeBuilder = taskTreeBuilder;
71    }
72   
[1117]73    /* (non-Javadoc)
74     * @see java.lang.Object#toString()
75     */
76    @Override
77    public String toString() {
[1127]78        return "SequenceDependingOnEventTypeDetectionRule";
[1117]79    }
80
[557]81    /*
82     * (non-Javadoc)
83     *
84     * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode,
[1107]85     * boolean)
[557]86     */
87    @Override
[1107]88    public RuleApplicationResult apply(ITaskTreeNode parent, boolean finalize) {
[557]89        if (!(parent instanceof ISequence)) {
90            return null;
91        }
92
93        RuleApplicationResult result = new RuleApplicationResult();
[1107]94        Stack<Integer> sequenceStartingIndex = new Stack<Integer>();
[557]95
[1127]96        List<ITaskTreeNode> children = parent.getChildren();
97       
[557]98        int index = 0;
[1127]99        while (index < children.size()) {
100            ITaskTreeNode child = children.get(index);
[557]101
102            if ((child instanceof IEventTask) &&
103                (((IEventTask) child).getEventType() instanceof IInteraction))
[439]104            {
[557]105                IInteraction eventType = (IInteraction) ((IEventTask) child).getEventType();
[439]106
[1107]107                if (eventType.finishesLogicalSequence() && (sequenceStartingIndex.size() > 0)) {
108                    index = handleLogicalSequence(sequenceStartingIndex, index, parent, result);
[1127]109                    // the parents child list will have changed, retrieve it again
110                    children = parent.getChildren();
[557]111                }
112
113                if (eventType.startsLogicalSequence()) {
[1107]114                    sequenceStartingIndex.push(index);
[557]115                }
[439]116            }
[557]117
118            index++;
[439]119        }
[557]120
[1107]121        if (sequenceStartingIndex.size() > 0) {
122            if (!finalize) {
[1127]123                result.setRuleApplicationStatus(RuleApplicationStatus.FEASIBLE);
[1107]124            }
125            else {
[1127]126                ITaskTreeNode lastChild = children.get(children.size() - 1);
[1107]127               
128                if (lastChild instanceof IEventTask) {
129                    handleLogicalSequence
[1127]130                        (sequenceStartingIndex, children.size() - 1, parent, result);
[1107]131                }
132            }
[439]133        }
[557]134
135        return result;
[439]136    }
137
[1107]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;
[1127]150       
151        List<ITaskTreeNode> children = parent.getChildren();
152       
[1107]153        IInteraction eventType =
[1127]154            (IInteraction) ((IEventTask) children.get(index)).getEventType();
[1107]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 =
[1127]173            (sequenceStartingIndex.peek() == 0) && (index == (children.size() - 1));
[1107]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++) {
[1127]182                taskTreeBuilder.addChild(sequence, children.get(startIndex));
[1107]183                taskTreeBuilder.removeChild((ISequence) parent, startIndex);
184            }
185
186            if (!eventType.startsLogicalSequence()) {
[1127]187                taskTreeBuilder.addChild(sequence, children.get(startIndex));
[1107]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               
[1127]201            result.setRuleApplicationStatus(RuleApplicationStatus.FINISHED);
[1107]202        }
203       
204        return newIndex;
205    }
206
[439]207}
Note: See TracBrowser for help on using the repository browser.