Changeset 2042 for trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UnusedGUIElementsRule.java
- Timestamp:
- 10/20/15 10:11:04 (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/autoquest-core-usability/src/main/java/de/ugoe/cs/autoquest/usability/UnusedGUIElementsRule.java
r1918 r2042 15 15 package de.ugoe.cs.autoquest.usability; 16 16 17 import java.util.ArrayList; 17 18 import java.util.HashMap; 18 19 import java.util.HashSet; … … 28 29 import de.ugoe.cs.autoquest.eventcore.guimodel.IComboBox; 29 30 import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIElement; 31 import de.ugoe.cs.autoquest.eventcore.guimodel.IGUIView; 30 32 import de.ugoe.cs.autoquest.eventcore.guimodel.IListBox; 31 33 import de.ugoe.cs.autoquest.eventcore.guimodel.IMenuButton; 32 34 import de.ugoe.cs.autoquest.eventcore.guimodel.ITextArea; 33 35 import de.ugoe.cs.autoquest.eventcore.guimodel.ITextField; 36 import de.ugoe.cs.autoquest.tasktrees.treeifc.DefaultTaskInstanceTraversingVisitor; 34 37 import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; 35 38 import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance; … … 37 40 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; 38 41 import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskModel; 42 import de.ugoe.cs.autoquest.tasktrees.treeifc.IUserSession; 39 43 40 44 /** … … 54 58 public UsabilityEvaluationResult evaluate(ITaskModel taskModel) { 55 59 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 } 62 70 63 71 return results; … … 65 73 66 74 /** 67 * <p> 68 * TODO: comment 69 * </p> 75 * @param results 70 76 * 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) 77 82 { 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 /** 99 139 * 100 * @param taskModel101 * @return102 */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 104 144 for (ITask task : taskModel.getTasks()) { 105 145 if (task instanceof IEventTask) { … … 107 147 Event event = ((IEventTaskInstance) instance).getEvent(); 108 148 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()); 111 162 } 112 163 } … … 114 165 } 115 166 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; 136 189 } 137 190 } 138 191 } 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); 171 245 } 172 246 } 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 /** 189 260 * 190 * @param taskModel191 */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) 194 265 { 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 /** 211 291 * 212 * @param currentGUIElement213 * @param usedGUIElements214 * @return215 */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 elements224 // 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: comment243 * </p>244 *245 * @param currentGUIElement246 * @return247 292 */ 248 293 private boolean isRelevant(IGUIElement currentGUIElement) {
Note: See TracChangeset
for help on using the changeset viewer.