Ignore:
Timestamp:
10/20/15 10:11:04 (9 years ago)
Author:
pharms
Message:
  • finalized smell detection for phd thesis
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UnusedGUIElementsRule.java

    r1918 r2042  
    1515package de.ugoe.cs.autoquest.usability; 
    1616 
     17import java.util.ArrayList; 
    1718import java.util.HashMap; 
    1819import java.util.HashSet; 
     
    2829import de.ugoe.cs.autoquest.eventcore.guimodel.IComboBox; 
    2930import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 
     31import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIView; 
    3032import de.ugoe.cs.autoquest.eventcore.guimodel.IListBox; 
    3133import de.ugoe.cs.autoquest.eventcore.guimodel.IMenuButton; 
    3234import de.ugoe.cs.autoquest.eventcore.guimodel.ITextArea; 
    3335import de.ugoe.cs.autoquest.eventcore.guimodel.ITextField; 
     36import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor; 
    3437import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 
    3538import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; 
     
    3740import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 
    3841import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel; 
     42import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; 
    3943 
    4044/** 
     
    5458    public UsabilityEvaluationResult evaluate(ITaskModel taskModel) { 
    5559        UsabilityEvaluationResult results = new UsabilityEvaluationResult(taskModel); 
    56  
    57         GUIModel guiModel = getGUIModel(taskModel); 
    58         Set<IGUIElement> allGUIElements = getAllGUIElements(guiModel); 
    59         Set<IGUIElement> usedGUIElements = getUsedGUIElements(taskModel); 
    60         List<IGUIElement> unusedGUIElements = getUnusedGUIElements(usedGUIElements, allGUIElements); 
    61         handleUnusedGUIElements(unusedGUIElements, allGUIElements, results); 
     60         
     61        Map<IGUIView, List<Set<IGUIElement>>> viewDisplays = 
     62            getViewDisplays(taskModel.getUserSessions()); 
     63         
     64        Map<IGUIView, Set<IGUIElement>> allGUIElements = getAllGUIElements(taskModel); 
     65         
     66        for (Map.Entry<IGUIView, List<Set<IGUIElement>>> viewDisplay : viewDisplays.entrySet()) { 
     67            handleUnusedGUIElements 
     68                (allGUIElements, viewDisplay.getKey(), viewDisplay.getValue(), results); 
     69        } 
    6270 
    6371        return results; 
     
    6573 
    6674    /** 
    67      * <p> 
    68      * TODO: comment 
    69      * </p> 
     75     * @param results  
    7076     * 
    71      * @param unusedGUIElements 
    72      * @param results 
    73      */ 
    74     private void handleUnusedGUIElements(List<IGUIElement>         unusedGUIElements, 
    75                                          Set<IGUIElement>          allGUIElements, 
    76                                          UsabilityEvaluationResult results) 
     77     */ 
     78    private void handleUnusedGUIElements(Map<IGUIView, Set<IGUIElement>> usedGUIElements, 
     79                                         IGUIView                        view, 
     80                                         List<Set<IGUIElement>>          viewUsages, 
     81                                         UsabilityEvaluationResult       results) 
    7782    { 
    78         int ratio = 1000 * unusedGUIElements.size() / allGUIElements.size(); 
    79          
    80         UsabilitySmellIntensity severity = UsabilitySmellIntensity.getIntensity(ratio); 
    81  
    82         if (severity != null) { 
    83             Map<String, Object> parameters = new HashMap<String, Object>(); 
    84  
    85             parameters.put("ratio", ratio / 10); 
    86             parameters.put("noOfUnused", unusedGUIElements.size()); 
    87             parameters.put("noOfAll", allGUIElements.size()); 
    88             parameters.put("unusedGuiElements", unusedGUIElements); 
    89              
    90             results.addSmell 
    91                 (severity, UsabilitySmellDescription.UNUSED_GUI_ELEMENTS, parameters); 
    92         } 
    93      } 
    94  
    95     /** 
    96      * <p> 
    97      * TODO: comment 
    98      * </p> 
     83        Set<IGUIElement> allElementsInView = usedGUIElements.get(view); 
     84         
     85        if (allElementsInView == null) { 
     86            return; 
     87        } 
     88         
     89        Map<Integer, List<IGUIElement>> usageCounters = new HashMap<>(); 
     90         
     91        for (IGUIElement relevantElement : allElementsInView) { 
     92            int usageCounter = 0; 
     93             
     94            for (Set<IGUIElement> viewUsage : viewUsages) { 
     95                if (viewUsage.contains(relevantElement)) { 
     96                    usageCounter++; 
     97                } 
     98            } 
     99             
     100            List<IGUIElement> elementsWithSameUsage = usageCounters.get(usageCounter); 
     101             
     102            if (elementsWithSameUsage == null) { 
     103                elementsWithSameUsage = new LinkedList<>(); 
     104                usageCounters.put(usageCounter, elementsWithSameUsage); 
     105            } 
     106             
     107            elementsWithSameUsage.add(relevantElement); 
     108        } 
     109         
     110        int cumulativeGuiElementUsage = 0; 
     111        for (Set<IGUIElement> viewUsage : viewUsages) { 
     112            cumulativeGuiElementUsage += viewUsage.size(); 
     113        } 
     114         
     115        List<IGUIElement> unusedElements = usageCounters.get(0); 
     116         
     117        if (unusedElements != null) { 
     118            int ratio = 1000 * unusedElements.size() / allElementsInView.size(); 
     119 
     120            UsabilitySmellIntensity severity = UsabilitySmellIntensity.getIntensity 
     121                (ratio, cumulativeGuiElementUsage, -1); 
     122 
     123            if (severity != null) { 
     124                Map<String, Object> parameters = new HashMap<String, Object>(); 
     125 
     126                parameters.put("ratio", ratio / 10); 
     127                parameters.put("allDisplays", viewUsages.size()); 
     128                parameters.put("view", view); 
     129                parameters.put("unusedGuiElements", unusedElements); 
     130                parameters.put("allGuiElements", allElementsInView.size()); 
     131 
     132                results.addSmell 
     133                    (severity, UsabilitySmellDescription.UNUSED_GUI_ELEMENTS, parameters); 
     134            } 
     135        } 
     136    } 
     137 
     138    /** 
    99139     * 
    100      * @param taskModel 
    101      * @return 
    102      */ 
    103     private GUIModel getGUIModel(ITaskModel taskModel) { 
     140     */ 
     141    private Map<IGUIView, Set<IGUIElement>> getAllGUIElements(ITaskModel taskModel) { 
     142        Map<IGUIView, Set<IGUIElement>> result = new HashMap<>(); 
     143         
    104144        for (ITask task : taskModel.getTasks()) { 
    105145            if (task instanceof IEventTask) { 
     
    107147                    Event event = ((IEventTaskInstance) instance).getEvent(); 
    108148                     
    109                     if (event.getTarget() instanceof IGUIElement) { 
    110                         return ((IGUIElement) event.getTarget()).getGUIModel(); 
     149                    if ((event.getTarget() instanceof IGUIElement) && 
     150                        (isRelevant((IGUIElement) event.getTarget()))) 
     151                    { 
     152                        IGUIView view = ((IGUIElement) event.getTarget()).getView(); 
     153                         
     154                        Set<IGUIElement> elements = result.get(view); 
     155                         
     156                        if (elements == null) { 
     157                            elements = new HashSet<>(); 
     158                            result.put(view, elements); 
     159                        } 
     160                         
     161                        elements.add((IGUIElement) event.getTarget()); 
    111162                    } 
    112163                } 
     
    114165        } 
    115166         
    116         return null; 
    117     } 
    118  
    119     /** 
    120      * <p> 
    121      * TODO: comment 
    122      * </p> 
    123      * 
    124      * @param taskModel 
    125      */ 
    126     private Set<IGUIElement> getUsedGUIElements(ITaskModel taskModel) { 
    127         Set<IGUIElement> usedGUIElements = new HashSet<IGUIElement>(); 
    128          
    129         for (ITask task : taskModel.getTasks()) { 
    130             if (task instanceof IEventTask) { 
    131                 for (ITaskInstance instance : task.getInstances()) { 
    132                     Event event = ((IEventTaskInstance) instance).getEvent(); 
    133                      
    134                     if (event.getTarget() instanceof IGUIElement) { 
    135                         usedGUIElements.add((IGUIElement) event.getTarget()); 
     167        // the problem is, that using the GUI model does not allow to find all in a specific view 
     168        // as the GUI model may return a merged element instead. But anyway, we can add those, which 
     169        // are in the GUI model and have the same view. 
     170         
     171        GUIModel model = result.values().iterator().next().iterator().next().getGUIModel(); 
     172         
     173        GUIModel.Traverser traverser = model.getTraverser(); 
     174 
     175        IGUIElement currentGUIElement = null; 
     176        do { 
     177            if (traverser.hasFirstChild()) { 
     178                currentGUIElement = traverser.firstChild(); 
     179            } 
     180            else if (traverser.hasNextSibling()) { 
     181                currentGUIElement = traverser.nextSibling(); 
     182            } 
     183            else { 
     184                while (currentGUIElement != null) { 
     185                    currentGUIElement = traverser.parent(); 
     186                    if (traverser.hasNextSibling()) { 
     187                        currentGUIElement = traverser.nextSibling(); 
     188                        break; 
    136189                    } 
    137190                } 
    138191            } 
    139         } 
    140          
    141         return usedGUIElements; 
    142     } 
    143      
    144     /** 
    145      * <p> 
    146      * TODO: comment 
    147      * </p> 
    148      * 
    149      * @param taskModel 
    150      */ 
    151     private Set<IGUIElement> getAllGUIElements(GUIModel guiModel) { 
    152         Set<IGUIElement> allGUIElements = new HashSet<IGUIElement>(); 
    153          
    154         if (guiModel != null) { 
    155             GUIModel.Traverser traverser = guiModel.getTraverser(); 
    156  
    157             IGUIElement currentGUIElement = null; 
    158             do { 
    159                 if (traverser.hasFirstChild()) { 
    160                     currentGUIElement = traverser.firstChild(); 
    161                 } 
    162                 else if (traverser.hasNextSibling()) { 
    163                     currentGUIElement = traverser.nextSibling(); 
    164                 } 
    165                 else { 
    166                     while (currentGUIElement != null) { 
    167                         currentGUIElement = traverser.parent(); 
    168                         if (traverser.hasNextSibling()) { 
    169                             currentGUIElement = traverser.nextSibling(); 
    170                             break; 
     192 
     193            if (isRelevant(currentGUIElement)) { 
     194                IGUIView view = currentGUIElement.getView(); 
     195                 
     196                Set<IGUIElement> elements = result.get(view); 
     197                 
     198                if (elements == null) { 
     199                    elements = new HashSet<>(); 
     200                    result.put(view, elements); 
     201                } 
     202                 
     203                elements.add(currentGUIElement); 
     204            } 
     205        } 
     206        while (currentGUIElement != null); 
     207         
     208        return result; 
     209    } 
     210 
     211    /** 
     212     *  
     213     */ 
     214    private Map<IGUIView, List<Set<IGUIElement>>> getViewDisplays(List<IUserSession> sessions) { 
     215        final IGUIView[] currentView = new IGUIView[1]; 
     216        final List<IEventTaskInstance> actionInstances = new ArrayList<>(); 
     217        final Map<IGUIView, List<Set<IGUIElement>>> result = new HashMap<>(); 
     218         
     219        for (IUserSession session : sessions) { 
     220            currentView[0] = null; 
     221            actionInstances.clear(); 
     222             
     223            for (final ITaskInstance currentRoot : session) { 
     224                currentRoot.accept(new DefaultTaskInstanceTraversingVisitor() { 
     225                    @Override 
     226                    public void visit(IEventTaskInstance eventTaskInstance) { 
     227                        if (eventTaskInstance.getEvent().getTarget() instanceof IGUIElement) { 
     228                            IGUIView view = 
     229                                ((IGUIElement) eventTaskInstance.getEvent().getTarget()).getView(); 
     230                             
     231                            if ((currentView[0] == null) && (view != null)) { 
     232                                currentView[0] = view; 
     233                                actionInstances.clear(); 
     234                            } 
     235                            else if ((currentView[0] != null) && (!currentView[0].equals(view))) { 
     236                                addRelevantTargets(currentView[0], actionInstances, result); 
     237                                 
     238                                currentView[0] = view; 
     239                                actionInstances.clear(); 
     240                            } 
     241                        } 
     242                         
     243                        if (eventTaskInstance.getEvent().getTarget() instanceof IGUIElement) { 
     244                            actionInstances.add(eventTaskInstance); 
    171245                        } 
    172246                    } 
    173                 } 
    174  
    175                 if (isRelevant(currentGUIElement)) { 
    176                     allGUIElements.add(currentGUIElement); 
    177                 } 
    178             } 
    179             while (currentGUIElement != null); 
    180         } 
    181          
    182         return allGUIElements; 
    183     } 
    184      
    185     /** 
    186      * <p> 
    187      * TODO: comment 
    188      * </p> 
     247                }); 
     248            } 
     249             
     250            // add the used GUI elements of the last shown view in the session 
     251            if (currentView[0] != null) { 
     252                addRelevantTargets(currentView[0], actionInstances, result); 
     253            } 
     254        } 
     255         
     256        return result; 
     257    } 
     258 
     259    /** 
    189260     * 
    190      * @param taskModel 
    191      */ 
    192     private List<IGUIElement> getUnusedGUIElements(Set<IGUIElement> usedGUIElements, 
    193                                                    Set<IGUIElement> allGUIElements) 
     261     */ 
     262    private void addRelevantTargets(IGUIView                              view, 
     263                                    List<IEventTaskInstance>              actionInstances, 
     264                                    Map<IGUIView, List<Set<IGUIElement>>> result) 
    194265    { 
    195         List<IGUIElement> unusedGUIElements = new LinkedList<IGUIElement>(); 
    196         for (IGUIElement currentGUIElement : allGUIElements) { 
    197             if (isRelevant(currentGUIElement) && 
    198                 !belongsToUsedGUIElements(currentGUIElement, usedGUIElements)) 
    199             { 
    200                 unusedGUIElements.add(currentGUIElement); 
    201             } 
    202         } 
    203          
    204         return unusedGUIElements; 
    205     } 
    206  
    207     /** 
    208      * <p> 
    209      * TODO: comment 
    210      * </p> 
     266        List<Set<IGUIElement>> usedGUIElements = result.get(view); 
     267         
     268        if (usedGUIElements == null) { 
     269            usedGUIElements = new LinkedList<>(); 
     270            result.put(view, usedGUIElements); 
     271        } 
     272         
     273        Set<IGUIElement> elementsInViewDisplay = new HashSet<>(); 
     274         
     275        for (IEventTaskInstance actionInstance : actionInstances) { 
     276            IGUIElement element = (IGUIElement) actionInstance.getEvent().getTarget(); 
     277             
     278            while (element != null) { 
     279                if (isRelevant(element)) { 
     280                    elementsInViewDisplay.add(element); 
     281                } 
     282                 
     283                element = element.getParent(); 
     284            } 
     285        } 
     286         
     287        usedGUIElements.add(elementsInViewDisplay); 
     288    } 
     289 
     290    /** 
    211291     * 
    212      * @param currentGUIElement 
    213      * @param usedGUIElements 
    214      * @return 
    215      */ 
    216     private boolean belongsToUsedGUIElements(IGUIElement      relevantGUIElement, 
    217                                              Set<IGUIElement> usedGUIElements) 
    218     { 
    219         if (usedGUIElements.contains(relevantGUIElement)) { 
    220             return true; 
    221         } 
    222         else { 
    223             // in some cases, the events are recorded for the children of the relevant GUI elements 
    224             // therefore, check the children, as well. 
    225             List<IGUIElement> children = 
    226                 relevantGUIElement.getGUIModel().getChildren(relevantGUIElement); 
    227              
    228             if (children != null) { 
    229                 for (IGUIElement child : children) { 
    230                     if (belongsToUsedGUIElements(child, usedGUIElements)) { 
    231                         return true; 
    232                     } 
    233                 } 
    234             } 
    235         } 
    236          
    237         return false; 
    238     } 
    239  
    240     /** 
    241      * <p> 
    242      * TODO: comment 
    243      * </p> 
    244      * 
    245      * @param currentGUIElement 
    246      * @return 
    247292     */ 
    248293    private boolean isRelevant(IGUIElement currentGUIElement) { 
Note: See TracChangeset for help on using the changeset viewer.