Changeset 987 for trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/DefaultGuiElementSequenceDetectionRuleBad.java
- Timestamp:
- 11/15/12 11:31:11 (12 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/DefaultGuiElementSequenceDetectionRuleBad.java
r972 r987 12 12 13 13 /** 14 * This rule generates sequences depending on a GUI model. All actions occurring on the same GUI 15 * element are put together in a sequence. All sequences and actions within a common panel are also 16 * put together to a sequence. Through this, an event sequence gets a logical structure and shows, 17 * which interactions that happen together also happen in the same GUI context. 14 * TODO: comment or delete 18 15 * 19 16 * @version $Revision: $ $Date: 18.03.2012$ 20 17 * @author 2012, last modified by $Author: patrick$ 21 18 */ 22 public class DefaultGuiElementSequenceDetectionRule implements TemporalRelationshipRule { 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 } 23 39 24 40 /* … … 38 54 } 39 55 56 List<ITaskTreeNode> children = parent.getChildren(); 40 57 RuleApplicationResult result = new RuleApplicationResult(); 41 58 42 59 IGUIElement lastGuiElement = null; 43 60 int index = 0; 44 while (index < parent.getChildren().size()) {45 ITaskTreeNode child = parent.getChildren().get(index);46 IGUIElement currentGuiElement = getG UIElement(child);47 if ((index > 0) && (! lastGuiElement.equals(currentGuiElement))) {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))) { 48 65 ReducableCommonDenominator commonDenominator = 49 66 getNextReducableCommonDenominator(parent, index - 1); 50 51 if (commonDenominator != null) { 52 // condense only if not all children would be condensed or if we can be sure, 53 // that there will be no further child that should be included in the condensed 54 // sequence 55 if ((commonDenominator.noOfTasks < parent.getChildren().size()) && 56 (!isOnGuiElementPath(commonDenominator.commonGuiElement, currentGuiElement))) 57 { 58 condenseTasksToSequence(parent, index, commonDenominator.noOfTasks, 59 builder, nodeFactory, result); 60 61 result.setRuleApplicationStatus 62 (RuleApplicationStatus.RULE_APPLICATION_FINISHED); 63 return result; 64 } 65 else { 66 // the common denominator is on the parent path of the next GUI element. 67 // Therefore, the current sequences is not finished yet. So break up. 68 result.setRuleApplicationStatus 69 (RuleApplicationStatus.RULE_APPLICATION_FEASIBLE); 70 } 71 } 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 72 77 } 73 78 … … 76 81 } 77 82 78 ReducableCommonDenominator commonDenominator =79 getNextReducableCommonDenominator(parent, parent.getChildren().size() - 1);80 81 if ((commonDenominator != null) &&82 (commonDenominator.noOfTasks < parent.getChildren().size()))83 {84 if (finalize) {85 condenseTasksToSequence86 (parent, index, commonDenominator.noOfTasks, builder, nodeFactory, result);87 88 result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FINISHED);89 90 return result;91 }92 else {93 result.setRuleApplicationStatus(RuleApplicationStatus.RULE_APPLICATION_FEASIBLE);94 }95 }96 97 83 return result; 98 84 } 99 85 100 86 /** 101 * <p> 102 * TODO: comment 103 * </p> 104 * 105 * @param guiElement 106 * @param detectedTasks 107 * @param parent 108 * @param index 109 * @param builder 110 * @param nodeFactory 111 * @return 112 */ 113 private void condenseTasksToSequence(ITaskTreeNode parent, 114 int parentIndex, 115 int noOfTasks, 116 ITaskTreeBuilder builder, 117 ITaskTreeNodeFactory nodeFactory, 118 RuleApplicationResult result) 119 { 120 ISequence newSequence = nodeFactory.createNewSequence(); 121 for (int i = 0; i < noOfTasks; i++) { 122 builder.addChild(newSequence, parent.getChildren().get(parentIndex - noOfTasks)); 123 // remove exactly the same number of children from the parent. 124 builder.removeChild((ISequence) parent, parentIndex - noOfTasks); 125 } 126 127 builder.addChild((ISequence) parent, parentIndex - noOfTasks, newSequence); 128 result.addNewlyCreatedParentNode(newSequence); 129 } 130 131 /** 132 * <p> 133 * TODO: comment 134 * </p> 135 * 136 * @param detectedTasks 137 * @return 87 * 138 88 */ 139 89 private ReducableCommonDenominator getNextReducableCommonDenominator(ITaskTreeNode parent, … … 157 107 else { 158 108 currentCommonDenominator = getCommonDenominator 159 (getG UIElement(parent.getChildren().get(pos)),160 getG UIElement(parent.getChildren().get(pos + 1)));109 (getGuiElement(parent.getChildren().get(pos)), 110 getGuiElement(parent.getChildren().get(pos + 1))); 161 111 } 162 112 … … 182 132 183 133 /** 184 * <p> 185 * TODO: comment 186 * </p> 187 * 188 * @param child 189 * @return 190 */ 191 private IGUIElement getGUIElement(ITaskTreeNode node) { 192 List<IGUIElement> terminalGUIElements = new ArrayList<IGUIElement>(); 193 getTerminalGUIElements(node, terminalGUIElements); 194 return getCommonDenominator(terminalGUIElements); 195 } 196 197 /** 198 * <p> 199 * TODO: comment 200 * </p> 201 * 202 * @param detectedTaskGroups 203 * @return 204 */ 205 /*private IGUIElement getCommonDenominator(Stack<Task> detectedTasks, int start) { 206 List<IGUIElement> allGUIElements = new ArrayList<IGUIElement>(); 207 208 for (int i = start; i < detectedTasks.size(); i++) { 209 allGUIElements.add(detectedTasks.get(i).commonGuiElement); 210 } 211 212 return getCommonDenominator(allGUIElements); 213 }*/ 214 215 /** 216 * <p> 217 * TODO: comment 218 * </p> 219 * 220 * @param child 221 * @return 222 */ 223 private IGUIElement getCommonDenominator(IGUIElement guiElement1, IGUIElement guiElement2) { 224 List<IGUIElement> allGUIElements = new ArrayList<IGUIElement>(); 225 allGUIElements.add(guiElement1); 226 allGUIElements.add(guiElement2); 227 return getCommonDenominator(allGUIElements); 228 } 229 230 /** 231 * <p> 232 * TODO: comment 233 * </p> 234 * 235 * @param child 236 * @return 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 * 237 265 */ 238 266 private IGUIElement getCommonDenominator(List<IGUIElement> guiElements) { … … 245 273 IGUIElement guiElement = guiElements.get(0); 246 274 while (guiElement != null) { 247 commonDenominatorPath.add(0, guiElement); 275 if (guiElementMatchesConsideredTypes(guiElement)) { 276 commonDenominatorPath.add(0, guiElement); 277 } 248 278 guiElement = guiElement.getParent(); 279 } 280 281 if (commonDenominatorPath.size() == 0) { 282 return null; 249 283 } 250 284 … … 257 291 guiElement = guiElements.get(i); 258 292 while (guiElement != null) { 259 currentPath.add(0, guiElement); 293 if (guiElementMatchesConsideredTypes(guiElement)) { 294 currentPath.add(0, guiElement); 295 } 260 296 guiElement = guiElement.getParent(); 261 297 } … … 284 320 285 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 /** 286 451 * <p> 287 * TODO: comment 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). 288 455 * </p> 289 456 * 290 * @param child 291 * @return 292 */ 293 private void getTerminalGUIElements(ITaskTreeNode node, List<IGUIElement> terminalGUIElements) { 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) { 294 529 if (node instanceof IEventTask) { 295 530 if (((IEventTask) node).getEventTarget() instanceof IGUIElement) { 296 terminalGUIElements.add((IGUIElement) ((IEventTask) node).getEventTarget()); 531 IGUIElement terminalGuiElement = (IGUIElement) ((IEventTask) node).getEventTarget(); 532 terminalGuiElement = 533 searchHierarchyForGuiElementWithConsideredType(terminalGuiElement); 534 535 if (terminalGuiElement != null) { 536 terminalGuiElements.add(terminalGuiElement); 537 } 297 538 } 298 539 } 299 540 else { 300 541 for (ITaskTreeNode child : node.getChildren()) { 301 getTerminalGUIElements(child, terminalGUIElements); 302 } 303 } 304 } 305 306 /** 307 * <p> 308 * TODO: comment 309 * </p> 310 * 311 * @param currentCommonDenominator 312 * @param guiElement 313 * @return 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 * 314 599 */ 315 600 private boolean isOnGuiElementPath(IGUIElement potentialPathElement, IGUIElement child) { … … 329 614 * 330 615 */ 331 private static class ReducableCommonDenominator { 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 { 332 635 333 636 /** the GUI element being the common denominator */ 334 privateIGUIElement commonGuiElement;637 IGUIElement commonGuiElement; 335 638 336 639 /** the number of tasks that match the common denominator */ 337 privateint noOfTasks;640 int noOfTasks; 338 641 339 642 /* (non-Javadoc)
Note: See TracChangeset
for help on using the changeset viewer.