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

Last change on this file since 1113 was 1113, checked in by pharms, 11 years ago
  • added license statement
  • Property svn:executable set to *
File size: 7.9 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.Stack;
18
19import de.ugoe.cs.autoquest.eventcore.gui.IInteraction;
20import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
21import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
22import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder;
23import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode;
24import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory;
25
26/**
27 * This rule generates sequences of events depending on the event types, more concrete, the
28 * {@link IInteraction}s and the return values of their {@link IInteraction#startsLogicalSequence()}
29 * and {@link IInteraction#finishesLogicalSequence()}. If a new logical sequence is started by
30 * an interaction, then a real sequence is instantiated. The sequence is finished, if an
31 * interaction finishes a logical sequence. Examples include keyboard focus changes.
32 *
33 * @version $Revision: $ $Date: 18.03.2012$
34 * @author 2012, last modified by $Author: patrick$
35 */
36class DefaultGuiEventSequenceDetectionRule implements TemporalRelationshipRule {
37
38    /**
39     * <p>
40     * the task tree node factory to be used for creating substructures for the temporal
41     * relationships identified during rule
42     * </p>
43     */
44    private ITaskTreeNodeFactory taskTreeNodeFactory;
45    /**
46     * <p>
47     * the task tree builder to be used for creating substructures for the temporal relationships
48     * identified during rule application
49     * </p>
50     */
51    private ITaskTreeBuilder taskTreeBuilder;
52   
53    /**
54     * <p>
55     * instantiates the rule with a task tree node factory and builder to be used during rule
56     * application.
57     * </p>
58     *
59     * @param taskTreeNodeFactory the task tree node factory to be used for creating substructures
60     *                            for the temporal relationships identified during rule
61     *                            application
62     * @param taskTreeBuilder     the task tree builder to be used for creating substructures for
63     *                            the temporal relationships identified during rule application
64     */
65    DefaultGuiEventSequenceDetectionRule(ITaskTreeNodeFactory taskTreeNodeFactory,
66                                         ITaskTreeBuilder     taskTreeBuilder)
67    {
68        this.taskTreeNodeFactory = taskTreeNodeFactory;
69        this.taskTreeBuilder = taskTreeBuilder;
70    }
71   
72    /*
73     * (non-Javadoc)
74     *
75     * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode,
76     * boolean)
77     */
78    @Override
79    public RuleApplicationResult apply(ITaskTreeNode parent, boolean finalize) {
80        if (!(parent instanceof ISequence)) {
81            return null;
82        }
83
84        RuleApplicationResult result = new RuleApplicationResult();
85        Stack<Integer> sequenceStartingIndex = new Stack<Integer>();
86
87        int index = 0;
88        while (index < parent.getChildren().size()) {
89            ITaskTreeNode child = parent.getChildren().get(index);
90
91            if ((child instanceof IEventTask) &&
92                (((IEventTask) child).getEventType() instanceof IInteraction))
93            {
94                IInteraction eventType = (IInteraction) ((IEventTask) child).getEventType();
95
96                if (eventType.finishesLogicalSequence() && (sequenceStartingIndex.size() > 0)) {
97                    index = handleLogicalSequence(sequenceStartingIndex, index, parent, result);
98                }
99
100                if (eventType.startsLogicalSequence()) {
101                    sequenceStartingIndex.push(index);
102                }
103            }
104
105            index++;
106        }
107
108        if (sequenceStartingIndex.size() > 0) {
109            if (!finalize) {
110                result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
111            }
112            else {
113                ITaskTreeNode lastChild = parent.getChildren().get(parent.getChildren().size() - 1);
114               
115                if (lastChild instanceof IEventTask) {
116                    handleLogicalSequence
117                        (sequenceStartingIndex, parent.getChildren().size() - 1, parent, result);
118                }
119            }
120        }
121
122        return result;
123    }
124
125    /**
126     * <p>
127     * TODO: comment
128     * </p>
129     *
130     */
131    private int handleLogicalSequence(Stack<Integer>        sequenceStartingIndex,
132                                      int                   index,
133                                      ITaskTreeNode         parent,
134                                      RuleApplicationResult result)
135    {
136        int newIndex = index;
137        IInteraction eventType =
138            (IInteraction) ((IEventTask) parent.getChildren().get(index)).getEventType();
139
140        // There are several situations in which this implementation may cause infinite
141        // loops. This is because the rule manager will reapply rules until
142        // no rule is applied anymore. A sequence identified in a first iteration will
143        // be identified as a sequence also in a second iteration. As an example
144        // many sequences start with an interaction starting that sequence and end
145        // with an interaction ending that sequence. This will be reidentified as
146        // further subsequence. It must therefore be assured, that a sequence, that
147        // was once identified is not reidentified in a further application of the rule.
148        // For this, the implementation performs a kind of dry run. It creates a list of
149        // children that would belong to an identified sequence. Only if this list is
150        // not a reidentification then a new sequence is created and added to the
151        // parent. If it is a reidentification can be identified, if the list of
152        // children will contain all children of the parent, or if the list of children
153        // only consists of one sequence. Further, an identified sequence must at least
154        // have one child.
155       
156        boolean allChildrenBelongToSubSequence =
157            (sequenceStartingIndex.peek() == 0) && (index == (parent.getChildren().size() - 1));
158       
159        boolean atLeastOneChildToCondense = index - sequenceStartingIndex.peek() > 0;
160       
161        if (!allChildrenBelongToSubSequence && atLeastOneChildToCondense) {
162            int startIndex = sequenceStartingIndex.pop();
163            ISequence sequence = taskTreeNodeFactory.createNewSequence();
164
165            for (int j = startIndex; j < index; j++) {
166                taskTreeBuilder.addChild(sequence, parent.getChildren().get(startIndex));
167                taskTreeBuilder.removeChild((ISequence) parent, startIndex);
168            }
169
170            if (!eventType.startsLogicalSequence()) {
171                taskTreeBuilder.addChild(sequence, parent.getChildren().get(startIndex));
172                taskTreeBuilder.removeChild((ISequence) parent, startIndex);
173                newIndex = startIndex;
174            }
175            else {
176                newIndex = startIndex + 1;
177            }
178
179            taskTreeBuilder.addChild((ISequence) parent, startIndex, sequence);
180
181            result.addNewlyCreatedParentNode(sequence);
182               
183            taskTreeBuilder.setDescription(sequence, "logical sequence started by the first event");
184               
185            result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);
186        }
187       
188        return newIndex;
189    }
190
191}
Note: See TracBrowser for help on using the repository browser.