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

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