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
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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} 
Note: See TracChangeset for help on using the changeset viewer.