Changeset 987


Ignore:
Timestamp:
11/15/12 11:31:11 (12 years ago)
Author:
pharms
Message:
  • improvement and documentation of the creation of sub sequences based on the GUI hierarchy
Location:
trunk
Files:
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/autoquest-core-tasktrees-test/src/test/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/DefaultGuiElementSequenceDetectionRuleTest.java

    r927 r987  
    192192        simulateEvent(new DummyInteraction("9", 1), eventTargetG); 
    193193 
    194         new TaskTreeChecker().assertTaskTree 
     194        new TaskTreeChecker(true).assertTaskTree 
    195195            ("Sequence sequence0 {" + 
    196196             "  Sequence sequence1 {" + 
     
    208208             "    }" + 
    209209             "    Sequence sequence6 {" + 
    210              "      Event 5 {}" + 
    211              "      Event 6 {}" + 
    212              "    }" + 
    213              "    Sequence sequence7 {" + 
    214              "      Event 7 {}" + 
    215              "    }" + 
    216              "  }" + 
    217              "  Sequence sequence8 {" + 
    218              "    Event 8 {}" + 
    219              "  }" + 
    220              "  Sequence sequence9 {" + 
    221              "    Event 9 {}" + 
     210             "      Sequence sequence7 {" + 
     211             "        Event 5 {}" + 
     212             "        Event 6 {}" + 
     213             "      }" + 
     214             "    }" + 
     215             "    Sequence sequence8 {" + 
     216             "      Sequence sequence9 {" + 
     217             "        Event 7 {}" + 
     218             "      }" + 
     219             "    }" + 
     220             "  }" + 
     221             "  Sequence sequence10 {" + 
     222             "    Sequence sequence11 {" + 
     223             "      Sequence sequence12 {" + 
     224             "        Event 8 {}" + 
     225             "      }" + 
     226             "    }" + 
     227             "  }" + 
     228             "  Sequence sequence13 {" + 
     229             "    Sequence sequence14 {" + 
     230             "      Sequence sequence15 {" + 
     231             "        Event 9 {}" + 
     232             "      }" + 
     233             "    }" + 
    222234             "  }" + 
    223235             "}", getTaskTree()); 
  • trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/DefaultGuiElementSequenceDetectionRule.java

    r972 r987  
    1212 
    1313/** 
    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 * This rule structures the task tree based on GUI elements of the GUI model. The rule can 
     15 * be provided with a filter for considered GUI elements. It generates sub sequences for any 
     16 * GUI element in the hierarchy matching the filter so that each sequence represents all 
     17 * interactions in a certain GUI element. 
    1818 *  
    1919 * @version $Revision: $ $Date: 18.03.2012$ 
     
    2121 */ 
    2222public class DefaultGuiElementSequenceDetectionRule implements TemporalRelationshipRule { 
     23 
     24    /** 
     25     * <p> 
     26     * the GUI element filter to be applied or null if none is specified. 
     27     * </p> 
     28     */ 
     29    private List<Class<? extends IGUIElement>> guiElementFilter; 
     30 
     31    /** 
     32     * <p> 
     33     * instantiates the rule without a GUI element filter 
     34     * </p> 
     35     */ 
     36    DefaultGuiElementSequenceDetectionRule() { 
     37        this.guiElementFilter = null; 
     38    } 
     39 
     40    /** 
     41     * <p> 
     42     * instantiates the rule with a GUI element filter. Only those types given in the filter will 
     43     * be considered during the rule application. For all other types, no subsequences will be 
     44     * created. 
     45     * </p> 
     46     * 
     47     * @param guiElementFilter the GUI element filter to be applied 
     48     */ 
     49    DefaultGuiElementSequenceDetectionRule(List<Class<? extends IGUIElement>> guiElementFilter) { 
     50        this.guiElementFilter = guiElementFilter; 
     51    } 
    2352 
    2453    /* 
     
    3968 
    4069        RuleApplicationResult result = new RuleApplicationResult(); 
    41          
    42         IGUIElement lastGuiElement = null; 
     70        List<List<IGUIElement>> hierarchies = new ArrayList<List<IGUIElement>>(); 
     71         
     72        // collect information about the GUI hierarchy 
     73        int maxHierarchyDepth = 0; 
     74        IGUIElement guiElement; 
     75        List<IGUIElement> guiElements = new ArrayList<IGUIElement>(); 
     76        List<IGUIElement> hierarchy; 
     77         
     78        for (ITaskTreeNode child : parent.getChildren()) { 
     79            guiElement = getGuiElement(child); 
     80            guiElements.add(guiElement); 
     81            hierarchy = getGuiElementHierarchy(guiElement); 
     82            hierarchies.add(hierarchy); 
     83            if (hierarchy != null) { 
     84                maxHierarchyDepth = Math.max(maxHierarchyDepth, hierarchy.size()); 
     85            } 
     86        } 
     87         
     88        IGUIElement commonDenominator = getCommonDenominator(guiElements); 
     89        hierarchy = getGuiElementHierarchy(commonDenominator); 
     90        int initialHierarchyLevel = hierarchy != null ? hierarchy.size() : 0; 
     91         
     92        // now generate sub sequences for the different GUI elements. Start at the hierarchy 
     93        // level of the children of the common denominator to ensure, that different children are 
     94        // found. If this level is already the maximum hierarchy depth, we do not need to condense 
     95        // anything. 
     96         
     97        RuleApplicationStatus status; 
     98        if (initialHierarchyLevel < maxHierarchyDepth) { 
     99            status = generateSubSequences(parent, hierarchies, initialHierarchyLevel, finalize, 
     100                                          builder, nodeFactory, result); 
     101        } 
     102        else { 
     103            status = RuleApplicationStatus.RULE_NOT_APPLIED; 
     104        } 
     105             
     106        result.setRuleApplicationStatus(status); 
     107         
     108        return result; 
     109    } 
     110 
     111    /** 
     112     * <p> 
     113     * generates subsequences for all groups of children of the provided parent, that operate 
     114     * in different GUI elements at the provided hierarchy level. It will not generate a sub 
     115     * sequence for the last elements, if the rule application shall not finalize. 
     116     * </p> 
     117     * 
     118     * @param parent            the parent node of which the children shall be grouped 
     119     * @param hierarchies       the GUI hierarchies for the children of the parent 
     120     * @param hierarchyLevel    the current hierarchy level to be considered 
     121     * @param maxHierarchyDepth the maximum hierarchy depth that may apply in this application 
     122     * @param finalize          true, if the application shall be finalized, false else 
     123     * @param builder           the builder to use for generating the tree structure 
     124     * @param nodeFactory       the node factory to use for generating the tree structure 
     125     * @param result            the result of the rule application to add newly created parent 
     126     *                          nodes to 
     127     *                           
     128     * @return RULE_APPLICATION_FINISHED, if at least one subsequence was generated, 
     129     *         RULE_APPLICATION_FEASIBLE, if the application shall not be finalized but some 
     130     *         children could be condensed if further data was available, and RULE_NOT_APPLIED, 
     131     *         if no subsequence was created and none is can be created, because no further 
     132     *         data is expected 
     133     */ 
     134    private RuleApplicationStatus generateSubSequences(ITaskTreeNode           parent, 
     135                                                       List<List<IGUIElement>> hierarchies, 
     136                                                       int                     hierarchyLevel, 
     137                                                       boolean                 finalize, 
     138                                                       ITaskTreeBuilder        builder, 
     139                                                       ITaskTreeNodeFactory    nodeFactory, 
     140                                                       RuleApplicationResult   result) 
     141    { 
     142        IGUIElement currentParent = null; 
     143        List<IGUIElement> hierarchy; 
     144        int startingIndex = -1; 
     145         
     146        RuleApplicationStatus status = RuleApplicationStatus.RULE_NOT_APPLIED; 
     147        boolean subsequenceHasStarted = false; 
     148        boolean exceedingGuiHierarchyDepth = false; 
     149        boolean nextGuiElementDiffers = false; 
     150        
     151        currentParent = null; 
     152        startingIndex = -1; 
     153 
    43154        int index = 0; 
    44155        while (index < parent.getChildren().size()) { 
    45             ITaskTreeNode child = parent.getChildren().get(index); 
    46             IGUIElement currentGuiElement = getGUIElement(child); 
    47             if ((index > 0) && (!lastGuiElement.equals(currentGuiElement))) { 
    48                 ReducableCommonDenominator commonDenominator = 
    49                     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                 } 
    72             } 
    73  
    74             lastGuiElement = currentGuiElement; 
     156            hierarchy = hierarchies.get(index); 
     157 
     158            exceedingGuiHierarchyDepth = hierarchyLevel >= hierarchy.size(); 
     159            nextGuiElementDiffers = 
     160                subsequenceHasStarted && 
     161                (exceedingGuiHierarchyDepth || !currentParent.equals(hierarchy.get(hierarchyLevel))); 
     162 
     163 
     164            if (!subsequenceHasStarted && !exceedingGuiHierarchyDepth) { 
     165                currentParent = hierarchy.get(hierarchyLevel); 
     166                startingIndex = index; 
     167                subsequenceHasStarted = true; 
     168            } 
     169            else if (nextGuiElementDiffers) { 
     170                status = condenseSequence(parent, hierarchies, hierarchyLevel, startingIndex, 
     171                                          index - 1, builder, nodeFactory, result); 
     172 
     173                if (status != null) { 
     174                    index = startingIndex + 1; 
     175                } 
     176                 
     177                if (!exceedingGuiHierarchyDepth) { 
     178                    currentParent = hierarchy.get(hierarchyLevel); 
     179                    startingIndex = index; 
     180                    subsequenceHasStarted = true; 
     181                } 
     182                else { 
     183                    currentParent = null; 
     184                    startingIndex = -1; 
     185                    subsequenceHasStarted = false; 
     186                } 
     187            } 
     188             
    75189            index++; 
    76190        } 
    77191 
    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                 condenseTasksToSequence 
    86                     (parent, index, commonDenominator.noOfTasks, builder, nodeFactory, result); 
     192        if (finalize) { 
     193            if (subsequenceHasStarted) { 
     194                status = condenseSequence 
     195                    (parent, hierarchies, hierarchyLevel, startingIndex, 
     196                     parent.getChildren().size() - 1, builder, nodeFactory, result); 
     197            } 
     198            else if (status != RuleApplicationStatus.RULE_APPLICATION_FINISHED) { 
     199                status = RuleApplicationStatus.RULE_NOT_APPLIED; 
     200            } 
     201        } 
     202        else { 
     203            if ((currentParent != null) && 
     204                (status != RuleApplicationStatus.RULE_APPLICATION_FINISHED)) 
     205            { 
     206                status = RuleApplicationStatus.RULE_APPLICATION_FEASIBLE; 
     207            } 
     208        } 
     209 
     210        return status; 
     211    } 
     212 
     213    /** 
     214     * <p> 
     215     * condenses a specified group of children on the provided parent to a subsequences and 
     216     * calls {@link #generateSubSequences(ITaskTreeNode, List, int, boolean, ITaskTreeBuilder, ITaskTreeNodeFactory, RuleApplicationResult)} 
     217     * for the newly created subsequence. The method does not condense subgroups consisting of 
     218     * only one child which is already a sequence. 
     219     * </p> 
     220     * 
     221     * @param parent         the parent task of which children shall be condensed 
     222     * @param hierarchies    the GUI element hierarchies of the children of the parent 
     223     * @param hierarchyLevel the currently considered GUI element hierarchy level 
     224     * @param startIndex     the index of the first child belonging to the subgroup 
     225     * @param endIndex       the index of the last child belonging to the subgroup 
     226     * @param builder        the builder to use for generating the tree structure 
     227     * @param nodeFactory    the node factory to use for generating the tree structure 
     228     * @param result         the result of the rule application to add newly created parent nodes to 
     229     *  
     230     * @return RULE_APPLICATION_FINISHED, if at the subsequence was generated and RULE_NOT_APPLIED, 
     231     *         if no subsequence was created, because only one child belonged to the group which 
     232     *         was already a sequence 
     233     */ 
     234    private RuleApplicationStatus condenseSequence(ITaskTreeNode           parent, 
     235                                                   List<List<IGUIElement>> hierarchies, 
     236                                                   int                     hierarchyLevel, 
     237                                                   int                     startIndex, 
     238                                                   int                     endIndex, 
     239                                                   ITaskTreeBuilder        builder, 
     240                                                   ITaskTreeNodeFactory    nodeFactory, 
     241                                                   RuleApplicationResult   result) 
     242    { 
     243        boolean onlyASingleChildToReduce = (endIndex - startIndex) == 0; 
     244        boolean singleChildIsSequence = onlyASingleChildToReduce && 
     245            parent.getChildren().get(startIndex) instanceof ISequence; 
     246 
     247        if (!onlyASingleChildToReduce || !singleChildIsSequence) { 
     248            ISequence sequence = nodeFactory.createNewSequence(); 
     249             
     250            List<List<IGUIElement>> subHierarchies = new ArrayList<List<IGUIElement>>(); 
     251            List<IGUIElement> newHierarchy = 
     252                hierarchies.get(startIndex).subList(0, hierarchyLevel + 1); 
     253            builder.setDescription(sequence, "interactions on " + 
     254                                   newHierarchy.get(newHierarchy.size() - 1).getStringIdentifier()); 
     255 
     256            for (int i = startIndex; i <= endIndex; i++) { 
     257                builder.addChild(sequence, parent.getChildren().get(startIndex)); 
     258                builder.removeChild((ISequence) parent, startIndex); 
    87259                 
    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         return result; 
    98     } 
    99  
    100     /** 
    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 
    138      */ 
    139     private ReducableCommonDenominator getNextReducableCommonDenominator(ITaskTreeNode parent, 
    140                                                                          int           childIndex) 
    141     { 
    142         ReducableCommonDenominator commonDenominator = null; 
    143          
    144         // a common denominator can only exist for at least two task tree nodes 
    145         if (childIndex > 0) { 
    146             // start with the last one 
    147             int pos = childIndex; 
    148  
    149             commonDenominator = new ReducableCommonDenominator(); 
    150              
    151             // check for further predecessors, if they match the same common denominator 
    152             IGUIElement currentCommonDenominator = null; 
    153             do { 
    154                 if (--pos < 0) { 
    155                     currentCommonDenominator = null; 
    156                 } 
    157                 else { 
    158                     currentCommonDenominator = getCommonDenominator 
    159                         (getGUIElement(parent.getChildren().get(pos)), 
    160                          getGUIElement(parent.getChildren().get(pos + 1))); 
    161                 } 
    162                  
    163                 if (commonDenominator.commonGuiElement == null) { 
    164                     commonDenominator.commonGuiElement = currentCommonDenominator; 
    165                 } 
    166             } 
    167             while ((commonDenominator.commonGuiElement != null) && 
    168                    (commonDenominator.commonGuiElement.equals(currentCommonDenominator))); 
    169              
    170             if (commonDenominator.commonGuiElement != null) { 
    171                 // pos points to the last element, that has not the same common denominator. 
    172                 // This one must be subtracted from the task number as well 
    173                 commonDenominator.noOfTasks = childIndex - pos; 
    174             } 
    175             else { 
    176                 commonDenominator = null; 
    177             } 
    178         } 
    179          
    180         return commonDenominator; 
    181     } 
    182  
    183     /** 
    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 
     260                subHierarchies.add(hierarchies.remove(startIndex)); 
     261            } 
     262 
     263            builder.addChild((ISequence) parent, startIndex, sequence); 
     264             
     265            hierarchies.add(startIndex, newHierarchy); 
     266             
     267            generateSubSequences 
     268                (sequence, subHierarchies, hierarchyLevel + 1, true, builder, nodeFactory, result); 
     269 
     270            result.addNewlyCreatedParentNode(sequence); 
     271 
     272            return RuleApplicationStatus.RULE_APPLICATION_FINISHED; 
     273        } 
     274        else { 
     275            return null; 
     276        } 
     277 
     278    } 
     279 
     280    /** 
     281     * <p> 
     282     * return a common denominator for the provided list of GUI elements, i.e. a GUI element, that 
     283     * is part of the parent GUI hiearchy of all GUI elements in the list. If there is no common 
     284     * denominator, the method returns null. 
     285     * </p> 
    237286     */ 
    238287    private IGUIElement getCommonDenominator(List<IGUIElement> guiElements) { 
     
    245294            IGUIElement guiElement = guiElements.get(0); 
    246295            while (guiElement != null) { 
    247                 commonDenominatorPath.add(0, guiElement); 
     296                if (guiElementMatchesConsideredTypes(guiElement)) { 
     297                    commonDenominatorPath.add(0, guiElement); 
     298                } 
    248299                guiElement = guiElement.getParent(); 
     300            } 
     301             
     302            if (commonDenominatorPath.size() == 0) { 
     303                return null; 
    249304            } 
    250305             
     
    257312                guiElement = guiElements.get(i); 
    258313                while (guiElement != null) { 
    259                     currentPath.add(0, guiElement); 
     314                    if (guiElementMatchesConsideredTypes(guiElement)) { 
     315                        currentPath.add(0, guiElement); 
     316                    } 
    260317                    guiElement = guiElement.getParent(); 
    261318                } 
     
    285342    /** 
    286343     * <p> 
    287      * TODO: comment 
    288      * </p> 
    289      * 
    290      * @param child 
    291      * @return 
    292      */ 
    293     private void getTerminalGUIElements(ITaskTreeNode node, List<IGUIElement> terminalGUIElements) { 
     344     * returns the GUI element on which all interactions of the provided task takes place. If 
     345     * the task is a simple event task its target is returned. If the task is a parent task 
     346     * of several children, the common denominator of the GUI elements of all its children is 
     347     * returned. The method returns null, if there is no common GUI element for all events 
     348     * represented by the provided task. 
     349     * </p> 
     350     */ 
     351    private IGUIElement getGuiElement(ITaskTreeNode node) { 
     352        if (node != null) { 
     353            List<IGUIElement> terminalGuiElements = new ArrayList<IGUIElement>(); 
     354            getTerminalGuiElements(node, terminalGuiElements); 
     355            return getCommonDenominator(terminalGuiElements); 
     356        } 
     357        else { 
     358            return null; 
     359        } 
     360    } 
     361         
     362    /** 
     363     * <p> 
     364     * recursive method calling itself to determine all terminal GUI elements of the provided 
     365     * task. The terminal GUI elements are stored in the provided list. 
     366     * </p> 
     367     */ 
     368    private void getTerminalGuiElements(ITaskTreeNode node, List<IGUIElement> terminalGuiElements) { 
    294369        if (node instanceof IEventTask) { 
    295370            if (((IEventTask) node).getEventTarget() instanceof IGUIElement) { 
    296                 terminalGUIElements.add((IGUIElement) ((IEventTask) node).getEventTarget()); 
     371                IGUIElement terminalGuiElement = (IGUIElement) ((IEventTask) node).getEventTarget(); 
     372                terminalGuiElement = 
     373                    searchHierarchyForGuiElementWithConsideredType(terminalGuiElement); 
     374                 
     375                if (terminalGuiElement != null) { 
     376                    terminalGuiElements.add(terminalGuiElement); 
     377                } 
    297378            } 
    298379        } 
    299380        else { 
    300381            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 
    314      */ 
    315     private boolean isOnGuiElementPath(IGUIElement potentialPathElement, IGUIElement child) { 
    316         IGUIElement guiElement = child; 
    317          
    318         while (guiElement != null) { 
    319             if (guiElement.equals(potentialPathElement)) { 
    320                 return true; 
    321             } 
    322             guiElement = guiElement.getParent(); 
    323         } 
    324          
    325         return false; 
    326     } 
    327  
    328     /** 
    329      *  
    330      */ 
    331     private static class ReducableCommonDenominator { 
    332          
    333         /** the GUI element being the common denominator */ 
    334         private IGUIElement commonGuiElement; 
    335          
    336         /** the number of tasks that match the common denominator */ 
    337         private int noOfTasks; 
    338  
    339         /* (non-Javadoc) 
    340          * @see java.lang.Object#toString() 
    341          */ 
    342         @Override 
    343         public String toString() { 
    344             return noOfTasks + " tasks on " + commonGuiElement; 
    345         } 
    346          
    347     } 
     382                getTerminalGuiElements(child, terminalGuiElements); 
     383            } 
     384        } 
     385    } 
     386 
     387    /** 
     388     * <p> 
     389     * returns a list of GUI elements that represents the whole GUI element hierarchy of the 
     390     * provided GUI element. The method considers the GUI element filter applied by this rule. 
     391     * </p> 
     392     */ 
     393    private List<IGUIElement> getGuiElementHierarchy(IGUIElement guiElement) { 
     394        IGUIElement element = guiElement; 
     395         
     396        if (!guiElementMatchesConsideredTypes(element)) { 
     397            element = searchHierarchyForGuiElementWithConsideredType(element); 
     398        } 
     399         
     400        List<IGUIElement> hierarchy = new ArrayList<IGUIElement>(); 
     401         
     402        while (element != null) { 
     403            hierarchy.add(0, element); 
     404            element = searchHierarchyForGuiElementWithConsideredType(element.getParent()); 
     405        } 
     406         
     407        if (hierarchy.size() > 0) { 
     408            return hierarchy; 
     409        } 
     410        else { 
     411            return null; 
     412        } 
     413    } 
     414 
     415    /** 
     416     * <p> 
     417     * returns for a given GUI element the next GUI element in the upper GUI element hierarchy 
     418     * that matches the GUI element filter of the rule. If the provided GUI element already 
     419     * matches the filter, it is returned directly. 
     420     * </p> 
     421     */ 
     422    private IGUIElement searchHierarchyForGuiElementWithConsideredType(IGUIElement guiElement) { 
     423        IGUIElement returnValue = guiElement; 
     424         
     425        while ((returnValue != null) && !guiElementMatchesConsideredTypes(returnValue)) { 
     426            returnValue = returnValue.getParent(); 
     427        } 
     428         
     429        return returnValue; 
     430    } 
     431 
     432    /** 
     433     * <p> 
     434     * checks if the provided GUI element matches the GUI element filter applied by the rule. 
     435     * </p> 
     436     */ 
     437    private boolean guiElementMatchesConsideredTypes(IGUIElement guiElement) { 
     438        if (guiElementFilter == null) { 
     439            return true; 
     440        } 
     441        else { 
     442            for (Class<? extends IGUIElement> clazz : guiElementFilter) { 
     443                if (clazz.isInstance(guiElement)) { 
     444                    return true; 
     445                } 
     446            } 
     447             
     448            return false; 
     449        } 
     450    } 
     451 
    348452} 
  • trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/DefaultGuiElementSequenceDetectionRuleBad.java

    r972 r987  
    1212 
    1313/** 
    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 
    1815 *  
    1916 * @version $Revision: $ $Date: 18.03.2012$ 
    2017 * @author 2012, last modified by $Author: patrick$ 
    2118 */ 
    22 public class DefaultGuiElementSequenceDetectionRule implements TemporalRelationshipRule { 
     19public 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    } 
    2339 
    2440    /* 
     
    3854        } 
    3955 
     56        List<ITaskTreeNode> children = parent.getChildren(); 
    4057        RuleApplicationResult result = new RuleApplicationResult(); 
    4158         
    4259        IGUIElement lastGuiElement = null; 
    4360        int index = 0; 
    44         while (index < parent.getChildren().size()) { 
    45             ITaskTreeNode child = parent.getChildren().get(index); 
    46             IGUIElement currentGuiElement = getGUIElement(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))) { 
    4865                ReducableCommonDenominator commonDenominator = 
    4966                    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 
    7277            } 
    7378 
     
    7681        } 
    7782 
    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                 condenseTasksToSequence 
    86                     (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  
    9783        return result; 
    9884    } 
    9985 
    10086    /** 
    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     *  
    13888     */ 
    13989    private ReducableCommonDenominator getNextReducableCommonDenominator(ITaskTreeNode parent, 
     
    157107                else { 
    158108                    currentCommonDenominator = getCommonDenominator 
    159                         (getGUIElement(parent.getChildren().get(pos)), 
    160                          getGUIElement(parent.getChildren().get(pos + 1))); 
     109                        (getGuiElement(parent.getChildren().get(pos)), 
     110                         getGuiElement(parent.getChildren().get(pos + 1))); 
    161111                } 
    162112                 
     
    182132 
    183133    /** 
    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     *  
    237265     */ 
    238266    private IGUIElement getCommonDenominator(List<IGUIElement> guiElements) { 
     
    245273            IGUIElement guiElement = guiElements.get(0); 
    246274            while (guiElement != null) { 
    247                 commonDenominatorPath.add(0, guiElement); 
     275                if (guiElementMatchesConsideredTypes(guiElement)) { 
     276                    commonDenominatorPath.add(0, guiElement); 
     277                } 
    248278                guiElement = guiElement.getParent(); 
     279            } 
     280             
     281            if (commonDenominatorPath.size() == 0) { 
     282                return null; 
    249283            } 
    250284             
     
    257291                guiElement = guiElements.get(i); 
    258292                while (guiElement != null) { 
    259                     currentPath.add(0, guiElement); 
     293                    if (guiElementMatchesConsideredTypes(guiElement)) { 
     294                        currentPath.add(0, guiElement); 
     295                    } 
    260296                    guiElement = guiElement.getParent(); 
    261297                } 
     
    284320 
    285321    /** 
     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    /** 
    286451     * <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). 
    288455     * </p> 
    289456     * 
    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) { 
    294529        if (node instanceof IEventTask) { 
    295530            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                } 
    297538            } 
    298539        } 
    299540        else { 
    300541            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     *  
    314599     */ 
    315600    private boolean isOnGuiElementPath(IGUIElement potentialPathElement, IGUIElement child) { 
     
    329614     *  
    330615     */ 
    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 { 
    332635         
    333636        /** the GUI element being the common denominator */ 
    334         private IGUIElement commonGuiElement; 
     637        IGUIElement commonGuiElement; 
    335638         
    336639        /** the number of tasks that match the common denominator */ 
    337         private int noOfTasks; 
     640        int noOfTasks; 
    338641 
    339642        /* (non-Javadoc) 
  • trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/DefaultGuiEventSequenceDetectionRule.java

    r972 r987  
    9898 
    9999                            result.addNewlyCreatedParentNode(sequence); 
     100                             
     101                            builder.setDescription 
     102                                (sequence, "logical sequence started by the first event"); 
     103                             
    100104                            result.setRuleApplicationStatus 
    101105                                (RuleApplicationStatus.RULE_APPLICATION_FINISHED); 
  • trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TemporalRelationshipRuleManager.java

    r922 r987  
    55import java.util.logging.Level; 
    66 
     7import de.ugoe.cs.autoquest.eventcore.guimodel.IDialog; 
     8import de.ugoe.cs.autoquest.eventcore.guimodel.IFrame; 
     9import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 
    710import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEquality; 
    811import de.ugoe.cs.autoquest.tasktrees.nodeequality.NodeEqualityRuleManager; 
     
    100103     */ 
    101104    public void init() { 
     105        List<Class<? extends IGUIElement>> frameFilter = 
     106            new ArrayList<Class<? extends IGUIElement>>(); 
     107        frameFilter.add(IFrame.class); 
     108        frameFilter.add(IDialog.class); 
     109 
     110        rules.add(new DefaultGuiElementSequenceDetectionRule(frameFilter)); 
    102111        rules.add(new DefaultGuiElementSequenceDetectionRule()); 
    103112        rules.add(new DefaultEventTargetSequenceDetectionRule()); 
    104113        rules.add(new TrackBarSelectionDetectionRule(nodeEqualityRuleManager)); 
    105         rules.add(new DefaultGuiEventSequenceDetectionRule()); 
     114        //rules.add(new DefaultGuiEventSequenceDetectionRule()); 
    106115         
    107116        rules.add(new DefaultIterationDetectionRule 
     
    153162     * @param finalize     used to indicate, if the rule application shall break up if a rule would 
    154163     *                     be feasible if further data was available, or not. 
    155      * @param logIndent    simply used for loggin purposes to indent the log messages depending 
     164     * @param logIndent    simply used for logging purposes to indent the log messages depending 
    156165     *                     on the recursion depth of calling this method. 
    157166     */ 
     
    169178            RuleApplicationResult result; 
    170179            do { 
    171                 // LOG.info(logIndent + "trying to apply rule " + rule + " on " + parent); 
     180                Console.traceln(Level.FINER, logIndent + "trying rule " + rule + " on " + parent); 
    172181                result = rule.apply(parent, builder, nodeFactory, finalize); 
    173182 
     
    179188                        (Level.FINE, logIndent + "applied rule " + rule + " on " + parent); 
    180189                    noOfRuleApplications++; 
     190                     
     191                    dumpTask(parent, ""); 
    181192 
    182193                    for (ITaskTreeNode newParent : result.getNewlyCreatedParentNodes()) { 
     
    211222     * 
    212223     */ 
    213     /* 
    214      * private void dumpTask(TaskTreeNode task, String indent) { System.err.print(indent); 
    215      * System.err.print(task); System.err.println(" "); 
    216      *  
    217      * if ((task.getChildren() != null) && (task.getChildren().size() > 0)) { for (TaskTreeNode 
    218      * child : task.getChildren()) { dumpTask(child, indent + "  "); } } } 
    219      */ 
     224    private void dumpTask(ITaskTreeNode task, String indent) { 
     225        StringBuffer message = new StringBuffer(); 
     226        message.append(indent); 
     227        message.append(task); 
     228        if (task.getDescription() != null) { 
     229            message.append('('); 
     230            message.append(task.getDescription()); 
     231            message.append(')'); 
     232        } 
     233         
     234        Console.traceln(Level.FINER, message.toString()); 
     235         
     236        if ((task.getChildren() != null) && (task.getChildren().size() > 0)) { 
     237            for (ITaskTreeNode child : task.getChildren()) { 
     238                dumpTask(child, indent + "  "); 
     239            } 
     240        } 
     241    } 
    220242 
    221243} 
Note: See TracChangeset for help on using the changeset viewer.