1 | package de.ugoe.cs.autoquest.tasktrees.temporalrelation; |
---|
2 | |
---|
3 | import java.util.ArrayList; |
---|
4 | import java.util.List; |
---|
5 | |
---|
6 | import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; |
---|
7 | import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; |
---|
8 | import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence; |
---|
9 | import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder; |
---|
10 | import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode; |
---|
11 | import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory; |
---|
12 | |
---|
13 | /** |
---|
14 | * TODO: comment or delete |
---|
15 | * |
---|
16 | * @version $Revision: $ $Date: 18.03.2012$ |
---|
17 | * @author 2012, last modified by $Author: patrick$ |
---|
18 | */ |
---|
19 | public class DefaultGuiElementSequenceDetectionRuleBad implements TemporalRelationshipRule { |
---|
20 | |
---|
21 | /** |
---|
22 | * |
---|
23 | */ |
---|
24 | private List<Class<? extends IGUIElement>> guiElementFilter; |
---|
25 | |
---|
26 | /** |
---|
27 | * |
---|
28 | */ |
---|
29 | DefaultGuiElementSequenceDetectionRuleBad() { |
---|
30 | this.guiElementFilter = null; |
---|
31 | } |
---|
32 | |
---|
33 | /** |
---|
34 | * |
---|
35 | */ |
---|
36 | DefaultGuiElementSequenceDetectionRuleBad(List<Class<? extends IGUIElement>> guiElementFilter) { |
---|
37 | this.guiElementFilter = guiElementFilter; |
---|
38 | } |
---|
39 | |
---|
40 | /* |
---|
41 | * (non-Javadoc) |
---|
42 | * |
---|
43 | * @see de.ugoe.cs.tasktree.temporalrelation.TemporalRelationshipRule#apply(TaskTreeNode, |
---|
44 | * TaskTreeBuilder, TaskTreeNodeFactory) |
---|
45 | */ |
---|
46 | @Override |
---|
47 | public RuleApplicationResult apply(ITaskTreeNode parent, |
---|
48 | ITaskTreeBuilder builder, |
---|
49 | ITaskTreeNodeFactory nodeFactory, |
---|
50 | boolean finalize) |
---|
51 | { |
---|
52 | if (!(parent instanceof ISequence)) { |
---|
53 | return null; |
---|
54 | } |
---|
55 | |
---|
56 | List<ITaskTreeNode> children = parent.getChildren(); |
---|
57 | RuleApplicationResult result = new RuleApplicationResult(); |
---|
58 | |
---|
59 | IGUIElement lastGuiElement = null; |
---|
60 | int index = 0; |
---|
61 | while (index <= children.size()) { |
---|
62 | ITaskTreeNode child = index < children.size() ? children.get(index) : null; |
---|
63 | IGUIElement currentGuiElement = getGuiElement(child); |
---|
64 | if ((index > 0) && (!guiElementsEqual(lastGuiElement, currentGuiElement))) { |
---|
65 | ReducableCommonDenominator commonDenominator = |
---|
66 | getNextReducableCommonDenominator(parent, index - 1); |
---|
67 | |
---|
68 | RuleApplicationStatus status = handleCommonDenominator |
---|
69 | (commonDenominator, parent, index, lastGuiElement, currentGuiElement, builder, |
---|
70 | nodeFactory, finalize, result); |
---|
71 | |
---|
72 | if (status != null) { |
---|
73 | result.setRuleApplicationStatus(status); |
---|
74 | return result; |
---|
75 | } |
---|
76 | // else go on |
---|
77 | } |
---|
78 | |
---|
79 | lastGuiElement = currentGuiElement; |
---|
80 | index++; |
---|
81 | } |
---|
82 | |
---|
83 | return result; |
---|
84 | } |
---|
85 | |
---|
86 | /** |
---|
87 | * |
---|
88 | */ |
---|
89 | private ReducableCommonDenominator getNextReducableCommonDenominator(ITaskTreeNode parent, |
---|
90 | int childIndex) |
---|
91 | { |
---|
92 | ReducableCommonDenominator commonDenominator = null; |
---|
93 | |
---|
94 | // a common denominator can only exist for at least two task tree nodes |
---|
95 | if (childIndex > 0) { |
---|
96 | // start with the last one |
---|
97 | int pos = childIndex; |
---|
98 | |
---|
99 | commonDenominator = new ReducableCommonDenominator(); |
---|
100 | |
---|
101 | // check for further predecessors, if they match the same common denominator |
---|
102 | IGUIElement currentCommonDenominator = null; |
---|
103 | do { |
---|
104 | if (--pos < 0) { |
---|
105 | currentCommonDenominator = null; |
---|
106 | } |
---|
107 | else { |
---|
108 | currentCommonDenominator = getCommonDenominator |
---|
109 | (getGuiElement(parent.getChildren().get(pos)), |
---|
110 | getGuiElement(parent.getChildren().get(pos + 1))); |
---|
111 | } |
---|
112 | |
---|
113 | if (commonDenominator.commonGuiElement == null) { |
---|
114 | commonDenominator.commonGuiElement = currentCommonDenominator; |
---|
115 | } |
---|
116 | } |
---|
117 | while ((commonDenominator.commonGuiElement != null) && |
---|
118 | (commonDenominator.commonGuiElement.equals(currentCommonDenominator))); |
---|
119 | |
---|
120 | if (commonDenominator.commonGuiElement != null) { |
---|
121 | // pos points to the last element, that has not the same common denominator. |
---|
122 | // This one must be subtracted from the task number as well |
---|
123 | commonDenominator.noOfTasks = childIndex - pos; |
---|
124 | } |
---|
125 | else { |
---|
126 | commonDenominator = null; |
---|
127 | } |
---|
128 | } |
---|
129 | |
---|
130 | return commonDenominator; |
---|
131 | } |
---|
132 | |
---|
133 | /** |
---|
134 | * |
---|
135 | */ |
---|
136 | private RuleApplicationStatus handleCommonDenominator(ReducableCommonDenominator commonDenominator, |
---|
137 | ITaskTreeNode parent, |
---|
138 | int currentIndex, |
---|
139 | IGUIElement lastGuiElement, |
---|
140 | IGUIElement currentGuiElement, |
---|
141 | ITaskTreeBuilder builder, |
---|
142 | ITaskTreeNodeFactory nodeFactory, |
---|
143 | boolean finalize, |
---|
144 | RuleApplicationResult result) |
---|
145 | { |
---|
146 | List<ITaskTreeNode> children = parent.getChildren(); |
---|
147 | |
---|
148 | boolean sequenceHasOnlyOneChild = children.size() == 1; |
---|
149 | boolean reachedEndOfSequence = currentIndex == children.size(); |
---|
150 | boolean haveCommonDenominator = commonDenominator != null; |
---|
151 | boolean allChildrenShareDenominator = |
---|
152 | haveCommonDenominator && commonDenominator.noOfTasks == children.size(); |
---|
153 | boolean nextChildSharesDenominator = |
---|
154 | haveCommonDenominator && !reachedEndOfSequence && |
---|
155 | isOnGuiElementPath(commonDenominator.commonGuiElement, currentGuiElement); |
---|
156 | |
---|
157 | IGUIElement denominatorOfPreviousAndCurrentChild = |
---|
158 | !reachedEndOfSequence ? getCommonDenominator(lastGuiElement, currentGuiElement) : null; |
---|
159 | |
---|
160 | boolean previousAndCurrentChildHaveDenominator = |
---|
161 | denominatorOfPreviousAndCurrentChild != null; |
---|
162 | |
---|
163 | if (haveCommonDenominator) { |
---|
164 | if (!reachedEndOfSequence) { |
---|
165 | if (nextChildSharesDenominator) { |
---|
166 | // the last child, although matching the identified common denominator, may |
---|
167 | // stand on its own because it is even deeper in the hierarchy, than the |
---|
168 | // common denominator as well as the common denominator with the next child. |
---|
169 | // So there need to appropriate subsequences to distinguish the child from |
---|
170 | // the hierarchy of the next one. |
---|
171 | if (isOnGuiElementPath(denominatorOfPreviousAndCurrentChild, lastGuiElement)) { |
---|
172 | return condenseChildToSequencesRepresentingHierarchy |
---|
173 | (parent, lastGuiElement, denominatorOfPreviousAndCurrentChild, |
---|
174 | currentIndex - 1, builder, nodeFactory, result); |
---|
175 | } |
---|
176 | else { |
---|
177 | // go on |
---|
178 | return null; |
---|
179 | } |
---|
180 | } |
---|
181 | else { |
---|
182 | condenseTasksToSequencesRepresentingHierarchy |
---|
183 | (commonDenominator.commonGuiElement, currentGuiElement, parent, |
---|
184 | currentIndex, commonDenominator.noOfTasks, builder, nodeFactory, result); |
---|
185 | |
---|
186 | return RuleApplicationStatus.RULE_APPLICATION_FINISHED; |
---|
187 | } |
---|
188 | } |
---|
189 | else { |
---|
190 | // end of sequence is reached and denominator is found |
---|
191 | if (!allChildrenShareDenominator) { |
---|
192 | condenseTasksToSequencesRepresentingHierarchy |
---|
193 | (commonDenominator.commonGuiElement, currentGuiElement, parent, |
---|
194 | currentIndex, commonDenominator.noOfTasks, builder, nodeFactory, result); |
---|
195 | |
---|
196 | return RuleApplicationStatus.RULE_APPLICATION_FINISHED; |
---|
197 | } |
---|
198 | else { |
---|
199 | // all children share denominator |
---|
200 | if (finalize) { |
---|
201 | if (ensureSequencesRepresentingHierarchy |
---|
202 | (parent, commonDenominator.commonGuiElement, |
---|
203 | builder, nodeFactory, result)) |
---|
204 | { |
---|
205 | return RuleApplicationStatus.RULE_APPLICATION_FINISHED; |
---|
206 | } |
---|
207 | else { |
---|
208 | return condenseChildToSequencesRepresentingHierarchy |
---|
209 | (parent, lastGuiElement, getGuiElement(parent), currentIndex - 1, |
---|
210 | builder, nodeFactory, result); |
---|
211 | } |
---|
212 | } |
---|
213 | else { |
---|
214 | return RuleApplicationStatus.RULE_APPLICATION_FEASIBLE; |
---|
215 | } |
---|
216 | } |
---|
217 | } |
---|
218 | } |
---|
219 | else { |
---|
220 | // no common denominator found |
---|
221 | if (!reachedEndOfSequence) { |
---|
222 | if (previousAndCurrentChildHaveDenominator) { |
---|
223 | // go on |
---|
224 | return null; |
---|
225 | } |
---|
226 | else { |
---|
227 | return condenseChildToSequencesRepresentingHierarchy |
---|
228 | (parent, lastGuiElement, getGuiElement(parent), currentIndex - 1, |
---|
229 | builder, nodeFactory, result); |
---|
230 | } |
---|
231 | } |
---|
232 | else { |
---|
233 | // last child has its own GUI hierarchy |
---|
234 | if (sequenceHasOnlyOneChild) { |
---|
235 | if (finalize) { |
---|
236 | if (ensureSequencesRepresentingHierarchy |
---|
237 | (parent, lastGuiElement, builder, nodeFactory, result)) |
---|
238 | { |
---|
239 | return RuleApplicationStatus.RULE_APPLICATION_FINISHED; |
---|
240 | } |
---|
241 | else { |
---|
242 | return RuleApplicationStatus.RULE_NOT_APPLIED; |
---|
243 | } |
---|
244 | } |
---|
245 | else { |
---|
246 | return RuleApplicationStatus.RULE_APPLICATION_FEASIBLE; |
---|
247 | } |
---|
248 | } |
---|
249 | else { |
---|
250 | if (finalize) { |
---|
251 | return condenseChildToSequencesRepresentingHierarchy |
---|
252 | (parent, lastGuiElement, getGuiElement(parent), currentIndex - 1, |
---|
253 | builder, nodeFactory, result); |
---|
254 | } |
---|
255 | else { |
---|
256 | return RuleApplicationStatus.RULE_APPLICATION_FEASIBLE; |
---|
257 | } |
---|
258 | } |
---|
259 | } |
---|
260 | } |
---|
261 | } |
---|
262 | |
---|
263 | /** |
---|
264 | * |
---|
265 | */ |
---|
266 | private IGUIElement getCommonDenominator(List<IGUIElement> guiElements) { |
---|
267 | IGUIElement commonDenominator = null; |
---|
268 | |
---|
269 | if (guiElements.size() > 0) { |
---|
270 | List<IGUIElement> commonDenominatorPath = new ArrayList<IGUIElement>(); |
---|
271 | |
---|
272 | // create a reference list using the first GUI element |
---|
273 | IGUIElement guiElement = guiElements.get(0); |
---|
274 | while (guiElement != null) { |
---|
275 | if (guiElementMatchesConsideredTypes(guiElement)) { |
---|
276 | commonDenominatorPath.add(0, guiElement); |
---|
277 | } |
---|
278 | guiElement = guiElement.getParent(); |
---|
279 | } |
---|
280 | |
---|
281 | if (commonDenominatorPath.size() == 0) { |
---|
282 | return null; |
---|
283 | } |
---|
284 | |
---|
285 | // for each other GUI element, check the reference list for the first element in the |
---|
286 | // path, that is not common to the current one, and delete it as well as it subsequent |
---|
287 | // siblings |
---|
288 | List<IGUIElement> currentPath = new ArrayList<IGUIElement>(); |
---|
289 | for (int i = 1; i < guiElements.size(); i++) { |
---|
290 | currentPath.clear(); |
---|
291 | guiElement = guiElements.get(i); |
---|
292 | while (guiElement != null) { |
---|
293 | if (guiElementMatchesConsideredTypes(guiElement)) { |
---|
294 | currentPath.add(0, guiElement); |
---|
295 | } |
---|
296 | guiElement = guiElement.getParent(); |
---|
297 | } |
---|
298 | |
---|
299 | // determine the index of the first unequal path element |
---|
300 | int index = 0; |
---|
301 | while ((index < commonDenominatorPath.size()) && (index < currentPath.size()) && |
---|
302 | commonDenominatorPath.get(index).equals(currentPath.get(index))) |
---|
303 | { |
---|
304 | index++; |
---|
305 | } |
---|
306 | |
---|
307 | // remove all elements from the common denonimator path, that do not match |
---|
308 | while (index < commonDenominatorPath.size()) { |
---|
309 | commonDenominatorPath.remove(index); |
---|
310 | } |
---|
311 | } |
---|
312 | |
---|
313 | if (commonDenominatorPath.size() > 0) { |
---|
314 | commonDenominator = commonDenominatorPath.get(commonDenominatorPath.size() - 1); |
---|
315 | } |
---|
316 | } |
---|
317 | |
---|
318 | return commonDenominator; |
---|
319 | } |
---|
320 | |
---|
321 | /** |
---|
322 | * |
---|
323 | */ |
---|
324 | private IGUIElement getCommonDenominator(IGUIElement guiElement1, IGUIElement guiElement2) { |
---|
325 | if ((guiElement1 == null) || (guiElement2 == null)) { |
---|
326 | return null; |
---|
327 | } |
---|
328 | |
---|
329 | List<IGUIElement> allGuiElements = new ArrayList<IGUIElement>(); |
---|
330 | allGuiElements.add(guiElement1); |
---|
331 | allGuiElements.add(guiElement2); |
---|
332 | return getCommonDenominator(allGuiElements); |
---|
333 | } |
---|
334 | |
---|
335 | /** |
---|
336 | * |
---|
337 | */ |
---|
338 | private void condenseTasksToSequencesRepresentingHierarchy(IGUIElement lastGuiElement, |
---|
339 | IGUIElement currentGuiElement, |
---|
340 | ITaskTreeNode parent, |
---|
341 | int parentIndex, |
---|
342 | int noOfTasks, |
---|
343 | ITaskTreeBuilder builder, |
---|
344 | ITaskTreeNodeFactory nodeFactory, |
---|
345 | RuleApplicationResult result) |
---|
346 | { |
---|
347 | List<IGUIElement> lastHierarchy = getGuiElementHierarchy(lastGuiElement); |
---|
348 | List<IGUIElement> currentHierarchy = getGuiElementHierarchy(currentGuiElement); |
---|
349 | int index = parentIndex; |
---|
350 | |
---|
351 | ITaskTreeNode generatedSequence = parent; |
---|
352 | |
---|
353 | for (int i = 0; i < lastHierarchy.size(); i++) { |
---|
354 | // add sequence for each element in the previous hierarchy, that does not occur in the |
---|
355 | // current hierarchy |
---|
356 | if ((currentHierarchy == null) || (i >= currentHierarchy.size()) || |
---|
357 | (!currentHierarchy.get(i).equals(lastHierarchy.get(i)))) |
---|
358 | { |
---|
359 | condenseTasksToSequence(generatedSequence, lastHierarchy.get(i), index, |
---|
360 | noOfTasks, builder, nodeFactory, result); |
---|
361 | |
---|
362 | // only in the first iteration, we condense tasks in the parent. Afterwards, |
---|
363 | // we always condense all tasks in the created sequence to a new subsequence. |
---|
364 | // Therefore, adapt all indexes appropriately |
---|
365 | generatedSequence = generatedSequence.getChildren().get(index - noOfTasks); |
---|
366 | index = noOfTasks; |
---|
367 | } |
---|
368 | } |
---|
369 | } |
---|
370 | |
---|
371 | /** |
---|
372 | * |
---|
373 | */ |
---|
374 | private boolean ensureSequencesRepresentingHierarchy(ITaskTreeNode parent, |
---|
375 | IGUIElement elementToRepresent, |
---|
376 | ITaskTreeBuilder builder, |
---|
377 | ITaskTreeNodeFactory nodeFactory, |
---|
378 | RuleApplicationResult result) |
---|
379 | { |
---|
380 | boolean applied = false; |
---|
381 | IGUIElement currentlyConsideredElement = elementToRepresent; |
---|
382 | IGUIElement elementRepresentedByParent = getGuiElement(parent); |
---|
383 | |
---|
384 | while ((currentlyConsideredElement != null) && |
---|
385 | (!currentlyConsideredElement.equals(elementRepresentedByParent))) |
---|
386 | { |
---|
387 | condenseTasksToSequence(parent, currentlyConsideredElement, parent.getChildren().size(), |
---|
388 | parent.getChildren().size(), builder, nodeFactory, result); |
---|
389 | applied = true; |
---|
390 | currentlyConsideredElement = currentlyConsideredElement.getParent(); |
---|
391 | } |
---|
392 | |
---|
393 | if (currentlyConsideredElement != null) { |
---|
394 | applied |= updateDescription(parent, currentlyConsideredElement, builder); |
---|
395 | } |
---|
396 | |
---|
397 | return applied; |
---|
398 | } |
---|
399 | |
---|
400 | /** |
---|
401 | * |
---|
402 | */ |
---|
403 | private RuleApplicationStatus condenseChildToSequencesRepresentingHierarchy(ITaskTreeNode parent, |
---|
404 | IGUIElement childGuiElement, |
---|
405 | IGUIElement parentGuiElement, |
---|
406 | int childIndex, |
---|
407 | ITaskTreeBuilder builder, |
---|
408 | ITaskTreeNodeFactory nodeFactory, |
---|
409 | RuleApplicationResult result) |
---|
410 | { |
---|
411 | ITaskTreeNode child = parent.getChildren().get(childIndex); |
---|
412 | boolean childIsSequence = child instanceof ISequence; |
---|
413 | boolean childHasGuiElement = childGuiElement != null; |
---|
414 | |
---|
415 | if (childIsSequence) { |
---|
416 | if (childHasGuiElement) { |
---|
417 | if (updateDescription(child, childGuiElement, builder)) { |
---|
418 | return RuleApplicationStatus.RULE_APPLICATION_FINISHED; |
---|
419 | } |
---|
420 | } |
---|
421 | } |
---|
422 | else { |
---|
423 | boolean applied = false; |
---|
424 | IGUIElement currentlyConsideredElement = childGuiElement; |
---|
425 | |
---|
426 | while ((currentlyConsideredElement != null) && |
---|
427 | (!currentlyConsideredElement.equals(parentGuiElement))) |
---|
428 | { |
---|
429 | condenseTasksToSequence(parent, currentlyConsideredElement, childIndex + 1, 1, |
---|
430 | builder, nodeFactory, result); |
---|
431 | applied = true; |
---|
432 | currentlyConsideredElement = currentlyConsideredElement.getParent(); |
---|
433 | } |
---|
434 | |
---|
435 | if (currentlyConsideredElement != null) { |
---|
436 | IGUIElement parentCommonDenominator = getGuiElement(parent); |
---|
437 | if (currentlyConsideredElement.equals(parentCommonDenominator)) { |
---|
438 | applied |= updateDescription(parent, currentlyConsideredElement, builder); |
---|
439 | } |
---|
440 | } |
---|
441 | |
---|
442 | if (applied) { |
---|
443 | return RuleApplicationStatus.RULE_APPLICATION_FINISHED; |
---|
444 | } |
---|
445 | } |
---|
446 | |
---|
447 | return null; |
---|
448 | } |
---|
449 | |
---|
450 | /** |
---|
451 | * <p> |
---|
452 | * condensed a subsequence of the children of the provided parent to a sequence. The |
---|
453 | * subsequence in the list of children defined by the index of the succeeding child |
---|
454 | * (parentIndex) and the number of tasks to be condensed (noOfTasks). |
---|
455 | * </p> |
---|
456 | * |
---|
457 | * @param parent the parent node whose children are to be condensed |
---|
458 | * @param target the GUI element in which all condensed interactions take place |
---|
459 | * @param parentIndex the index of the child in the parent, which follows the children |
---|
460 | * to be condensed |
---|
461 | * @param noOfTasks the number of children to be condensed |
---|
462 | * @param builder the builder to create the new subsequence |
---|
463 | * @param nodeFactory the node factory to instantiate the new subsequence |
---|
464 | * @param result the result of the rule application to store newly created parent nodes |
---|
465 | */ |
---|
466 | private void condenseTasksToSequence(ITaskTreeNode parent, |
---|
467 | IGUIElement target, |
---|
468 | int parentIndex, |
---|
469 | int noOfTasks, |
---|
470 | ITaskTreeBuilder builder, |
---|
471 | ITaskTreeNodeFactory nodeFactory, |
---|
472 | RuleApplicationResult result) |
---|
473 | { |
---|
474 | ISequence newSequence = nodeFactory.createNewSequence(); |
---|
475 | updateDescription(newSequence, target, builder); |
---|
476 | |
---|
477 | for (int i = 0; i < noOfTasks; i++) { |
---|
478 | builder.addChild(newSequence, parent.getChildren().get(parentIndex - noOfTasks)); |
---|
479 | // remove exactly the same number of children from the parent. |
---|
480 | builder.removeChild((ISequence) parent, parentIndex - noOfTasks); |
---|
481 | } |
---|
482 | |
---|
483 | builder.addChild((ISequence) parent, parentIndex - noOfTasks, newSequence); |
---|
484 | result.addNewlyCreatedParentNode(newSequence); |
---|
485 | } |
---|
486 | |
---|
487 | /** |
---|
488 | * |
---|
489 | */ |
---|
490 | private boolean updateDescription(ITaskTreeNode node, |
---|
491 | IGUIElement commonGuiElement, |
---|
492 | ITaskTreeBuilder builder) |
---|
493 | { |
---|
494 | String newDescription = "interactions on " + commonGuiElement.getStringIdentifier(); |
---|
495 | |
---|
496 | String currentDescription = node.getDescription(); |
---|
497 | |
---|
498 | if ((currentDescription == null) || (currentDescription.indexOf(newDescription) == -1)) { |
---|
499 | if ((currentDescription != null) && (!"".equals(currentDescription))) { |
---|
500 | newDescription = currentDescription + "; " + newDescription; |
---|
501 | } |
---|
502 | |
---|
503 | builder.setDescription(node, newDescription); |
---|
504 | return true; |
---|
505 | } |
---|
506 | else { |
---|
507 | return false; |
---|
508 | } |
---|
509 | } |
---|
510 | |
---|
511 | /** |
---|
512 | * |
---|
513 | */ |
---|
514 | private IGUIElement getGuiElement(ITaskTreeNode node) { |
---|
515 | if (node != null) { |
---|
516 | List<IGUIElement> terminalGuiElements = new ArrayList<IGUIElement>(); |
---|
517 | getTerminalGuiElements(node, terminalGuiElements); |
---|
518 | return getCommonDenominator(terminalGuiElements); |
---|
519 | } |
---|
520 | else { |
---|
521 | return null; |
---|
522 | } |
---|
523 | } |
---|
524 | |
---|
525 | /** |
---|
526 | * |
---|
527 | */ |
---|
528 | private void getTerminalGuiElements(ITaskTreeNode node, List<IGUIElement> terminalGuiElements) { |
---|
529 | if (node instanceof IEventTask) { |
---|
530 | if (((IEventTask) node).getEventTarget() instanceof IGUIElement) { |
---|
531 | IGUIElement terminalGuiElement = (IGUIElement) ((IEventTask) node).getEventTarget(); |
---|
532 | terminalGuiElement = |
---|
533 | searchHierarchyForGuiElementWithConsideredType(terminalGuiElement); |
---|
534 | |
---|
535 | if (terminalGuiElement != null) { |
---|
536 | terminalGuiElements.add(terminalGuiElement); |
---|
537 | } |
---|
538 | } |
---|
539 | } |
---|
540 | else { |
---|
541 | for (ITaskTreeNode child : node.getChildren()) { |
---|
542 | getTerminalGuiElements(child, terminalGuiElements); |
---|
543 | } |
---|
544 | } |
---|
545 | } |
---|
546 | |
---|
547 | /** |
---|
548 | * |
---|
549 | */ |
---|
550 | private List<IGUIElement> getGuiElementHierarchy(IGUIElement guiElement) { |
---|
551 | IGUIElement element = guiElement; |
---|
552 | |
---|
553 | if (!guiElementMatchesConsideredTypes(element)) { |
---|
554 | element = searchHierarchyForGuiElementWithConsideredType(element); |
---|
555 | } |
---|
556 | |
---|
557 | List<IGUIElement> hierarchy = new ArrayList<IGUIElement>(); |
---|
558 | |
---|
559 | while (element != null) { |
---|
560 | hierarchy.add(0, element); |
---|
561 | element = searchHierarchyForGuiElementWithConsideredType(element.getParent()); |
---|
562 | } |
---|
563 | |
---|
564 | if (hierarchy.size() > 0) { |
---|
565 | return hierarchy; |
---|
566 | } |
---|
567 | else { |
---|
568 | return null; |
---|
569 | } |
---|
570 | } |
---|
571 | |
---|
572 | /** |
---|
573 | * |
---|
574 | */ |
---|
575 | private IGUIElement searchHierarchyForGuiElementWithConsideredType(IGUIElement guiElement) { |
---|
576 | IGUIElement returnValue = guiElement; |
---|
577 | |
---|
578 | while ((returnValue != null) && !guiElementMatchesConsideredTypes(returnValue)) { |
---|
579 | returnValue = returnValue.getParent(); |
---|
580 | } |
---|
581 | |
---|
582 | return returnValue; |
---|
583 | } |
---|
584 | |
---|
585 | /** |
---|
586 | * |
---|
587 | */ |
---|
588 | private boolean guiElementsEqual(IGUIElement guiElement1, IGUIElement guiElement2) { |
---|
589 | if (guiElement1 == null) { |
---|
590 | return guiElement2 == null; |
---|
591 | } |
---|
592 | else { |
---|
593 | return guiElement1.equals(guiElement2); |
---|
594 | } |
---|
595 | } |
---|
596 | |
---|
597 | /** |
---|
598 | * |
---|
599 | */ |
---|
600 | private boolean isOnGuiElementPath(IGUIElement potentialPathElement, IGUIElement child) { |
---|
601 | IGUIElement guiElement = child; |
---|
602 | |
---|
603 | while (guiElement != null) { |
---|
604 | if (guiElement.equals(potentialPathElement)) { |
---|
605 | return true; |
---|
606 | } |
---|
607 | guiElement = guiElement.getParent(); |
---|
608 | } |
---|
609 | |
---|
610 | return false; |
---|
611 | } |
---|
612 | |
---|
613 | /** |
---|
614 | * |
---|
615 | */ |
---|
616 | private boolean guiElementMatchesConsideredTypes(IGUIElement guiElement) { |
---|
617 | if (guiElementFilter == null) { |
---|
618 | return true; |
---|
619 | } |
---|
620 | else { |
---|
621 | for (Class<? extends IGUIElement> clazz : guiElementFilter) { |
---|
622 | if (clazz.isInstance(guiElement)) { |
---|
623 | return true; |
---|
624 | } |
---|
625 | } |
---|
626 | |
---|
627 | return false; |
---|
628 | } |
---|
629 | } |
---|
630 | |
---|
631 | /** |
---|
632 | * |
---|
633 | */ |
---|
634 | static class ReducableCommonDenominator { |
---|
635 | |
---|
636 | /** the GUI element being the common denominator */ |
---|
637 | IGUIElement commonGuiElement; |
---|
638 | |
---|
639 | /** the number of tasks that match the common denominator */ |
---|
640 | int noOfTasks; |
---|
641 | |
---|
642 | /* (non-Javadoc) |
---|
643 | * @see java.lang.Object#toString() |
---|
644 | */ |
---|
645 | @Override |
---|
646 | public String toString() { |
---|
647 | return noOfTasks + " tasks on " + commonGuiElement; |
---|
648 | } |
---|
649 | |
---|
650 | } |
---|
651 | } |
---|