source: trunk/quest-core-tasktrees/src/main/java/de/ugoe/cs/quest/tasktrees/temporalrelation/DefaultIterationDetectionRule.java @ 805

Last change on this file since 805 was 805, checked in by pharms, 12 years ago
  • added support for more fine grained iteration detection with distinction of the different levels of GUI design, i.e. lexical, syntactical and semantical.
  • Property svn:executable set to *
File size: 10.2 KB
Line 
1package de.ugoe.cs.quest.tasktrees.temporalrelation;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import de.ugoe.cs.quest.tasktrees.nodeequality.NodeEquality;
7import de.ugoe.cs.quest.tasktrees.nodeequality.NodeEqualityRuleManager;
8import de.ugoe.cs.quest.tasktrees.treeifc.IIteration;
9import de.ugoe.cs.quest.tasktrees.treeifc.ISelection;
10import de.ugoe.cs.quest.tasktrees.treeifc.ISequence;
11import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeBuilder;
12import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNode;
13import de.ugoe.cs.quest.tasktrees.treeifc.ITaskTreeNodeFactory;
14
15/**
16 * TODO comment
17 *
18 * @version $Revision: $ $Date: 19.02.2012$
19 * @author 2012, last modified by $Author: patrick$
20 */
21public class DefaultIterationDetectionRule implements TemporalRelationshipRule {
22   
23    /** */
24    private NodeEqualityRuleManager nodeEqualityRuleManager;
25
26    /** */
27    private NodeEquality minimalNodeEquality;
28
29    /**
30     * TODO: comment
31     *
32     */
33    DefaultIterationDetectionRule(NodeEqualityRuleManager nodeEqualityRuleManager,
34                                  NodeEquality            minimalNodeEquality)
35    {
36        super();
37        this.nodeEqualityRuleManager = nodeEqualityRuleManager;
38        this.minimalNodeEquality = minimalNodeEquality;
39    }
40
41    /*
42     * (non-Javadoc)
43     *
44     * @see TemporalRelationshipRule#apply(TaskTreeNode, TaskTreeBuilder, TaskTreeNodeFactory)
45     */
46    @Override
47    public RuleApplicationResult apply(ITaskTreeNode        parent,
48                                       ITaskTreeBuilder     treeBuilder,
49                                       ITaskTreeNodeFactory nodeFactory,
50                                       boolean              finalize)
51    {
52        if (!(parent instanceof ISequence)) {
53            return null;
54        }
55
56        // parent must already have at least 2 children
57        if ((parent.getChildren() == null) || (parent.getChildren().size() < 2)) {
58            return null;
59        }
60
61        // iterations represent as a list of nodes that splits up in several equal sublists. If
62        // the remaining nodes also start an equal sublist, then the iteration may not be completed
63        // yet. So wait for further events to only identify completed iterations.
64
65        // to find longer iterations first, start with long sequences
66        for (int end = parent.getChildren().size() - 1; end > 0; end--) {
67            for (int start = 0; start < end; start++) {
68                List<ITaskTreeNode[]> equalVariants =
69                    getEqualSublistVariantsInBoundaries(parent, start, end);
70
71                if (equalVariants != null) {
72                    RuleApplicationResult result = new RuleApplicationResult();
73                   
74                    if ((!finalize) && (iterationMayContinue(equalVariants, parent, end + 1))) {
75                        result.setRuleApplicationStatus
76                              (RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);
77                        return result;
78                    }
79
80                    IIteration newIteration = createIterationBasedOnIdentifiedVariants
81                         (equalVariants, treeBuilder, nodeFactory, result);
82                   
83
84                    // remove iterated children
85                    for (int j = end; j >= start; j--) {
86                        treeBuilder.removeChild((ISequence) parent, j);
87                    }
88
89                    // add the new iteration instead
90                    treeBuilder.addChild((ISequence) parent, start, newIteration);
91
92                    result.setRuleApplicationStatus
93                        (RuleApplicationStatus.RULE_APPLICATION_FINISHED);
94                    return result;
95                }
96            }
97        }
98
99        return null;
100    }
101
102    /**
103     * TODO: comment
104     *
105     * @return
106     */
107    private List<ITaskTreeNode[]> getEqualSublistVariantsInBoundaries(ITaskTreeNode parent,
108                                                                      int           start,
109                                                                      int           end)
110    {
111        List<ITaskTreeNode[]> equalVariants = null;
112
113        int noOfChildrenInBoundaries = end - start + 1;
114
115        for (int subListLen = 1; subListLen <= (noOfChildrenInBoundaries / 2); subListLen++)
116        {
117            if ((noOfChildrenInBoundaries % subListLen) == 0) {
118                equalVariants =
119                    getEqualSublistVariantsForSubListLength(parent, start, end, subListLen);
120
121                if (equalVariants != null) {
122                    return equalVariants;
123                }
124            }
125        }
126
127        return null;
128    }
129
130    /**
131     *
132     */
133    private List<ITaskTreeNode[]> getEqualSublistVariantsForSubListLength(ITaskTreeNode parent,
134                                                                          int           start,
135                                                                          int           end,
136                                                                          int           subListLen)
137    {
138        List<ITaskTreeNode[]> equalVariants = new ArrayList<ITaskTreeNode[]>();
139        ITaskTreeNode[] firstVariant = new ITaskTreeNode[subListLen];
140
141        for (int i = 0; i < subListLen; i++) {
142            firstVariant[i] = parent.getChildren().get(start + i);
143        }
144
145        equalVariants.add(firstVariant);
146
147        for (int parentIdx = (start + subListLen); parentIdx <= end; parentIdx += subListLen)
148        {
149            ITaskTreeNode[] otherVariant = new ITaskTreeNode[subListLen];
150
151            for (int i = 0; i < subListLen; i++) {
152                NodeEquality nodeEquality = nodeEqualityRuleManager.applyRules
153                    (firstVariant[i], parent.getChildren().get(parentIdx + i));
154
155                if (!nodeEquality.isAtLeast(minimalNodeEquality)) {
156                    return null;
157                }
158                else if (!nodeEquality.isAtLeast(NodeEquality.LEXICALLY_EQUAL)) {
159                    // if the node is a syntactical or semantical equivalent of the first variant,
160                    // then store it.
161                    otherVariant[i] = parent.getChildren().get(parentIdx + i);
162                }
163            }
164
165            // check, if there is a syntactically or semantically equal other variant. If so, add
166            // it to the list of variants
167            boolean semanticallyUnequal = false;
168            for (int i = 0; i < subListLen; i++) {
169                if (otherVariant[i] == null) {
170                    otherVariant[i] = firstVariant[i];
171                }
172                else {
173                    semanticallyUnequal = true;
174                }
175            }
176
177            if (semanticallyUnequal) {
178                equalVariants.add(otherVariant);
179            }
180        }
181
182        return equalVariants;
183    }
184
185    /**
186     * <p>
187     * TODO: comment
188     * </p>
189     *
190     * @param equalVariants
191     * @param parent
192     * @return
193     */
194    private boolean iterationMayContinue(List<ITaskTreeNode[]> equalVariants,
195                                         ITaskTreeNode         parent,
196                                         int                   remainderIndex)
197    {
198        // check, if the iteration may go on. This may be the case, if the
199        // remaining children, which were not identified as part of the iteration,
200        // start a further occurrence of the iteration
201
202        boolean allNodesEqual = true;
203        for (int i = 0; ((allNodesEqual) && (i < equalVariants.get(0).length)); i++)
204        {
205            if ((remainderIndex + i) >= parent.getChildren().size()) {
206                break;
207            }
208
209            NodeEquality nodeEquality = nodeEqualityRuleManager.applyRules
210                (equalVariants.get(0)[i], parent.getChildren().get(remainderIndex + i));
211
212            allNodesEqual &= nodeEquality.isAtLeast(minimalNodeEquality);
213        }
214
215        return allNodesEqual;
216    }
217   
218    /**
219     * <p>
220     * TODO: comment
221     * </p>
222     *
223     * @param equalVariants
224     * @param result
225     * @return
226     */
227    private IIteration createIterationBasedOnIdentifiedVariants(List<ITaskTreeNode[]> equalVariants,
228                                                                ITaskTreeBuilder      treeBuilder,
229                                                                ITaskTreeNodeFactory  nodeFactory,
230                                                                RuleApplicationResult result)
231    {
232        IIteration newIteration = nodeFactory.createNewIteration();
233        result.addNewlyCreatedParentNode(newIteration);
234
235        if (equalVariants.size() == 1) {
236            // all children are the same. Create an iteration of this child
237            if (equalVariants.get(0).length == 1) {
238                // all children are the same. Create an iteration of this child
239                treeBuilder.setChild(newIteration, equalVariants.get(0)[0]);
240            }
241            else {
242                // there was an iteration of structurally equal sequences
243                ISequence sequence = nodeFactory.createNewSequence();
244                result.addNewlyCreatedParentNode(sequence);
245
246                for (ITaskTreeNode node : equalVariants.get(0)) {
247                    treeBuilder.addChild(sequence, node);
248                }
249
250                treeBuilder.setChild(newIteration, sequence);
251            }
252        }
253        else {
254            // there are distinct variants of semantically equal subsequences or
255            // children -->
256            // create an iterated selection
257            ISelection selection = nodeFactory.createNewSelection();
258            result.addNewlyCreatedParentNode(selection);
259
260            for (ITaskTreeNode[] variant : equalVariants) {
261                if (variant.length == 1) {
262                    treeBuilder.addChild(selection, variant[0]);
263                }
264                else {
265                    ISequence sequence = nodeFactory.createNewSequence();
266                    result.addNewlyCreatedParentNode(sequence);
267
268                    for (ITaskTreeNode node : variant) {
269                        treeBuilder.addChild(sequence, node);
270                    }
271
272                    treeBuilder.addChild(selection, sequence);
273                }
274            }
275
276            treeBuilder.setChild(newIteration, selection);
277        }
278       
279        return newIteration;
280    }
281
282}
Note: See TracBrowser for help on using the repository browser.