source: trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/GUIEventTaskComparisonRule.java @ 2137

Last change on this file since 2137 was 2137, checked in by pharms, 7 years ago

added a small bug fix

File size: 27.5 KB
Line 
1//   Copyright 2012 Georg-August-Universität Göttingen, Germany
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15package de.ugoe.cs.autoquest.tasktrees.taskequality;
16
17import java.util.Collection;
18
19import de.ugoe.cs.autoquest.eventcore.IEventTarget;
20import de.ugoe.cs.autoquest.eventcore.gui.IInteraction;
21import de.ugoe.cs.autoquest.eventcore.gui.KeyInteraction;
22import de.ugoe.cs.autoquest.eventcore.gui.KeyPressed;
23import de.ugoe.cs.autoquest.eventcore.gui.KeyReleased;
24import de.ugoe.cs.autoquest.eventcore.gui.KeyTyped;
25import de.ugoe.cs.autoquest.eventcore.gui.MouseButtonDown;
26import de.ugoe.cs.autoquest.eventcore.gui.MouseButtonInteraction;
27import de.ugoe.cs.autoquest.eventcore.gui.MouseButtonUp;
28import de.ugoe.cs.autoquest.eventcore.gui.MouseClick;
29import de.ugoe.cs.autoquest.eventcore.gui.MouseDoubleClick;
30import de.ugoe.cs.autoquest.eventcore.gui.MouseDragAndDrop;
31import de.ugoe.cs.autoquest.eventcore.gui.Scroll;
32import de.ugoe.cs.autoquest.eventcore.gui.TextInput;
33import de.ugoe.cs.autoquest.eventcore.gui.ValueSelection;
34import de.ugoe.cs.autoquest.eventcore.guimodel.IButton;
35import de.ugoe.cs.autoquest.eventcore.guimodel.ICheckBox;
36import de.ugoe.cs.autoquest.eventcore.guimodel.IComboBox;
37import de.ugoe.cs.autoquest.eventcore.guimodel.IImage;
38import de.ugoe.cs.autoquest.eventcore.guimodel.IListBox;
39import de.ugoe.cs.autoquest.eventcore.guimodel.IMenu;
40import de.ugoe.cs.autoquest.eventcore.guimodel.IMenuButton;
41import de.ugoe.cs.autoquest.eventcore.guimodel.IRadioButton;
42import de.ugoe.cs.autoquest.eventcore.guimodel.IShape;
43import de.ugoe.cs.autoquest.eventcore.guimodel.IText;
44import de.ugoe.cs.autoquest.eventcore.guimodel.IToolTip;
45import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
46import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTaskInstance;
47import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
48import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
49
50/**
51 * <p>
52 * This rule compares GUI event tasks (i.e. it is more concrete, than the
53 * {@link EventTaskComparisonRule}). Two GUI event tasks are only equal if their event type and
54 * target are equal. The returned equality is even more fine-grained for events whose type is
55 * {@link TextInput} and {@link ValueSelection}. For text inputs, lexical equality is returned if
56 * the same text is entered using the same key interactions. Syntactical equality is returned if
57 * the same text is entered using different key interactions. Semantical equality is returned if
58 * different text is entered, but into the same event target. Value selections are syntactically
59 * equal, if the same value is selected. Otherwise they are semantically equal.
60 * </p>
61 *
62 * @author Patrick Harms
63 */
64public class GUIEventTaskComparisonRule implements TaskComparisonRule {
65   
66    /* (non-Javadoc)
67     * @see TaskComparisonRule#isApplicable(ITask, ITask)
68     */
69    @Override
70    public boolean isApplicable(ITask task1, ITask task2) {
71        if (!(task1 instanceof IEventTask)) {
72            return false;
73        }
74       
75        if (!(task2 instanceof IEventTask)) {
76            return false;
77        }
78       
79        IEventTaskInstance instance1 = (IEventTaskInstance) task1.getInstances().iterator().next();
80       
81        if (!(instance1.getEvent().getType() instanceof IInteraction)) {
82            return false;
83        }
84       
85        IEventTaskInstance instance2 = (IEventTaskInstance) task2.getInstances().iterator().next();
86       
87        if (!(instance2.getEvent().getType() instanceof IInteraction)) {
88            return false;
89        }
90       
91        return true;
92    }
93
94    /* (non-Javadoc)
95     * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
96     */
97    @Override
98    public boolean areLexicallyEqual(ITask task1, ITask task2) {
99        TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL);
100        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
101    }
102
103    /* (non-Javadoc)
104     * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
105     */
106    @Override
107    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
108        TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL);
109        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
110    }
111
112    /* (non-Javadoc)
113     * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
114     */
115    @Override
116    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
117        TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL);
118        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
119    }
120
121    /* (non-Javadoc)
122     * @see TaskComparisonRule#compare(ITask, ITask)
123     */
124    @Override
125    public TaskEquality compare(ITask task1, ITask task2) {
126        return getEquality(task1, task2, null);
127    }
128
129    /* (non-Javadoc)
130     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#isApplicable(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
131     */
132    @Override
133    public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
134        return
135            (instance1 instanceof IEventTaskInstance) &&
136            (instance2 instanceof IEventTaskInstance) &&
137            (((IEventTaskInstance) instance1).getEvent().getType() instanceof IInteraction) &&
138            (((IEventTaskInstance) instance2).getEvent().getType() instanceof IInteraction);
139    }
140
141    /* (non-Javadoc)
142     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#areLexicallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
143     */
144    @Override
145    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
146        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.LEXICALLY_EQUAL);
147        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
148    }
149
150    /* (non-Javadoc)
151     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#areSyntacticallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
152     */
153    @Override
154    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
155        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SYNTACTICALLY_EQUAL);
156        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
157    }
158
159    /* (non-Javadoc)
160     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#areSemanticallyEqual(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
161     */
162    @Override
163    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
164        TaskEquality equality = getEquality(instance1, instance2, TaskEquality.SEMANTICALLY_EQUAL);
165        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
166    }
167
168    /* (non-Javadoc)
169     * @see de.ugoe.cs.autoquest.tasktrees.taskequality.TaskComparisonRule#compare(de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance, de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance)
170     */
171    @Override
172    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
173        return getEquality(instance1, instance2, null);
174    }
175
176    /**
177     *
178     */
179    private TaskEquality getEquality(ITask         task1,
180                                     ITask         task2,
181                                     TaskEquality  requiredEqualityLevel)
182    {
183        Collection<ITaskInstance> taskInstances1 = task1.getInstances();
184        Collection<ITaskInstance> taskInstances2 = task2.getInstances();
185       
186        if (taskInstances1.size() > taskInstances2.size()) {
187            // it may be the case, that all instances of first task match already the first instance
188            // of the second task. In this case, the below for loops would iterate of all instances
189            // of the first task but the internal loop would always break. But if the first task
190            // has many more instances than the second task, performing the comparison the other
191            // way around would result in less comparisons. Hence, we switch the task instance lists
192            // to have fewer comparisons.
193            Collection<ITaskInstance> tmp = taskInstances1;
194            taskInstances1 = taskInstances2;
195            taskInstances2 = tmp;
196        }
197       
198        TaskEquality checkedEquality =
199            requiredEqualityLevel != null ? requiredEqualityLevel : TaskEquality.SEMANTICALLY_EQUAL;
200       
201        TaskEquality commonDenominator = TaskEquality.LEXICALLY_EQUAL;
202       
203        for (ITaskInstance instance1 : taskInstances1) {
204            TaskEquality mostConcreteEquality = null;
205           
206            for (ITaskInstance instance2 : taskInstances2) {
207                TaskEquality equality = getEquality(instance1, instance2, requiredEqualityLevel);
208               
209                if ((equality != null) && ((mostConcreteEquality == null) ||
210                                           (equality.isAtLeast(mostConcreteEquality))))
211                {
212                    mostConcreteEquality = equality;
213                   
214                    if (((requiredEqualityLevel != null) &&
215                         (mostConcreteEquality.isAtLeast(requiredEqualityLevel))) ||
216                        (mostConcreteEquality.isAtLeast(TaskEquality.LEXICALLY_EQUAL)))
217                    {
218                        break;
219                    }
220                }
221            }
222           
223            commonDenominator = commonDenominator.getCommonDenominator(mostConcreteEquality);
224           
225            if (!commonDenominator.isAtLeast(checkedEquality)) {
226                return TaskEquality.UNEQUAL;
227            }
228        }
229       
230        return commonDenominator;
231    }
232
233    /**
234     *
235     */
236    private TaskEquality getEquality(ITaskInstance instance1,
237                                     ITaskInstance instance2,
238                                     TaskEquality  requiredEqualityLevel)
239    {
240        IEventTaskInstance eventTask1 = (IEventTaskInstance) instance1;
241        IEventTaskInstance eventTask2 = (IEventTaskInstance) instance2;
242       
243        if (!eventTask1.getEvent().getTarget().equals(eventTask2.getEvent().getTarget())) {
244            return TaskEquality.UNEQUAL;
245        }
246       
247        IInteraction interaction1 = (IInteraction) eventTask1.getEvent().getType();
248        IInteraction interaction2 = (IInteraction) eventTask2.getEvent().getType();
249       
250        return compareInteractions
251            (interaction1, interaction2, eventTask1.getEvent().getTarget(), requiredEqualityLevel);
252    }
253
254    /**
255     * <p>
256     * compares two interactions. The method delegates to other, more specific compare method, e.g.,
257     * {@link #compareTextInputs(TextInput, TextInput)} and
258     * {@link #compareValueSelections(ValueSelection, ValueSelection)}, if any exist for the
259     * concrete interaction types. Otherwise it uses the equals method of the interactions for
260     * comparison. In this case, if the interactions equals method returns true, this method
261     * returns lexical equality.
262     * </p>
263     * <p>
264     * The provided equality level can be used to restrict the quality check to the given level.
265     * This is done for optimization purposes. The returned equality level can be at most as
266     * concrete as the provided one. If the provided one is null, it is expected to be lexical
267     * equality.
268     * </p>
269     *
270     * @param interaction1  the first interaction to compare
271     * @param interaction2  the second interaction to compare
272     * @param eventTarget   the event target on which the interactions happened (used within
273     *                      special comparisons like mouse clicks on buttons, where the coordinates
274     *                      can be ignored)
275     * @param equalityLevel the equality level to be checked for
276     *
277     * @return as described
278     */
279    private TaskEquality compareInteractions(IInteraction interaction1,
280                                             IInteraction interaction2,
281                                             IEventTarget eventTarget,
282                                             TaskEquality equalityLevel)
283    {
284        TaskEquality level = equalityLevel;
285       
286        if (level == null) {
287            level = TaskEquality.LEXICALLY_EQUAL;
288        }
289       
290        if (interaction1 == interaction2) {
291            return TaskEquality.LEXICALLY_EQUAL;
292        }
293        else if ((interaction1 instanceof KeyInteraction) &&
294                 (interaction2 instanceof KeyInteraction))
295        {
296            return compareKeyInteractions
297                ((KeyInteraction) interaction1, (KeyInteraction) interaction2, level);
298        }
299        else if ((interaction1 instanceof MouseButtonInteraction) &&
300                 (interaction2 instanceof MouseButtonInteraction))
301        {
302            return compareMouseButtonInteractions
303                ((MouseButtonInteraction) interaction1, (MouseButtonInteraction) interaction2,
304                 eventTarget, level);
305        }
306        else if ((interaction1 instanceof Scroll) && (interaction2 instanceof Scroll)) {
307            return compareScrolls((Scroll) interaction1, (Scroll) interaction2, level);
308        }
309        else if ((interaction1 instanceof TextInput) && (interaction2 instanceof TextInput)) {
310            return compareTextInputs
311                ((TextInput) interaction1, (TextInput) interaction2, level);
312        }
313        else if ((interaction1 instanceof ValueSelection) &&
314                 (interaction2 instanceof ValueSelection))
315        {
316            return compareValueSelections
317                ((ValueSelection<?>) interaction1, (ValueSelection<?>) interaction2, level);
318        }
319        else if (interaction1.equals(interaction2)) {
320            return TaskEquality.LEXICALLY_EQUAL;
321        }
322        else {
323            return TaskEquality.UNEQUAL;
324        }
325    }
326
327    /**
328     * <p>
329     * compares two key interactions. If both are of the same type and if both have the
330     * same key, they are lexically equal. If both are only of the same type, they are
331     * semantically equal. Otherwise, they are unequal.
332     * </p>
333     * <p>
334     * The provided equality level can be used to restrict the quality check to the given level.
335     * This is done for optimization purposes. The returned equality level is as concrete as
336     * the provided one. It may be more concrete if there is no difference regarding the
337     * comparison on the levels.
338     * </p>
339     *
340     * @param interaction1  the first key interaction
341     * @param interaction2  the second key interaction
342     * @param equalityLevel the equality level to be checked for
343     *
344     * @return as described
345     */
346    private TaskEquality compareKeyInteractions(KeyInteraction interaction1,
347                                                KeyInteraction interaction2,
348                                                TaskEquality   equalityLevel)
349    {
350        if (((interaction1 instanceof KeyPressed) && (interaction2 instanceof KeyPressed)) ||
351            ((interaction1 instanceof KeyReleased) && (interaction2 instanceof KeyReleased)) ||
352            ((interaction1 instanceof KeyTyped) && (interaction2 instanceof KeyTyped)))
353        {
354            if ((equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) &&
355                (interaction1.getKey() == interaction2.getKey()))
356            {
357                return TaskEquality.LEXICALLY_EQUAL;
358            }
359            else {
360                // pressing a key on the same target, e.g. a text field, usually has the same
361                // semantics
362                return TaskEquality.SEMANTICALLY_EQUAL;
363            }
364        }
365       
366        return TaskEquality.UNEQUAL;
367    }
368   
369    /**
370     * <p>
371     * compares two mouse drag and drops. If both drag and drops have the same start and end
372     * coordinates, they are lexically equal. Otherwise, they are semantically equal.
373     * </p>
374     * <p>
375     * The provided equality level can be used to restrict the quality check to the given level.
376     * This is done for optimization purposes. The returned equality level is as concrete as
377     * the provided one. It may be more concrete if there is no difference regarding the
378     * comparison on the levels.
379     * </p>
380     *
381     * @param interaction1  the first mouse drag and drop to compare
382     * @param interaction2  the second mouse drag and drop to compare
383     * @param equalityLevel the equality level to be checked for
384     *
385     * @return as described
386     */
387    private TaskEquality compareMouseDragAndDrops(MouseDragAndDrop interaction1,
388                                                  MouseDragAndDrop interaction2,
389                                                  TaskEquality     equalityLevel)
390    {
391        if (interaction1.getButton() != interaction2.getButton()) {
392            return TaskEquality.UNEQUAL;
393        }
394       
395        if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) {
396            int x1 = interaction1.getX();
397            int x1Start = interaction1.getXStart();
398            int x2 = interaction2.getX();
399            int x2Start = interaction2.getXStart();
400            int y1 = interaction1.getY();
401            int y1Start = interaction1.getYStart();
402            int y2 = interaction2.getY();
403            int y2Start = interaction2.getYStart();
404       
405            if ((x1Start == x2Start) && (x1 == x2) && (y1Start == y2Start) && (y1 == y2)) {
406                return TaskEquality.LEXICALLY_EQUAL;
407            }
408        }
409       
410        // performing drag and drops on the same target usually have the same semantic meaning,
411        // i.e., the same function is called
412        return TaskEquality.SEMANTICALLY_EQUAL;
413    }
414
415    /**
416     * <p>
417     * compares two mouse button interactions such as clicks, mouse button down, or double clicks.
418     * If both interactions have the same coordinates, they are lexically equal. Otherwise, they
419     * are semantically equal. Mouse clicks for which the coordinates make no lexical difference
420     * (see {@link #clickCoordinatesMakeLexicalDifference(IEventTarget)}) are treated as
421     * lexically equal.
422     * </p>
423     * <p>
424     * The provided equality level can be used to restrict the quality check to the given level.
425     * This is done for optimization purposes. The returned equality level is as concrete as
426     * the provided one. It may be more concrete if there is no difference regarding the
427     * comparison on the levels.
428     * </p>
429     *
430     * @param interaction1  the first mouse button interaction to compare
431     * @param interaction2  the second mouse button interaction to compare
432     * @param eventTarget   the event target on which the interactions happened (used within
433     *                      special comparisons like mouse clicks on buttons, where the coordinates
434     *                      can be ignored)
435     * @param equalityLevel the equality level to be checked for
436     *
437     * @return as described
438     */
439    private TaskEquality compareMouseButtonInteractions(MouseButtonInteraction interaction1,
440                                                        MouseButtonInteraction interaction2,
441                                                        IEventTarget           eventTarget,
442                                                        TaskEquality           equalityLevel)
443    {
444        boolean coordinatesMatch = true;
445       
446        if ((interaction1 instanceof MouseDragAndDrop) &&
447            (interaction2 instanceof MouseDragAndDrop))
448        {
449            return compareMouseDragAndDrops
450                ((MouseDragAndDrop) interaction1, (MouseDragAndDrop) interaction2, equalityLevel);
451        }
452        else if (interaction1.getButton() != interaction2.getButton()) {
453            return TaskEquality.UNEQUAL;
454        }
455        else if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL) &&
456                 clickCoordinatesMakeLexicalDifference(eventTarget))
457        {
458            int x1 = interaction1.getX();
459            int x2 = interaction2.getX();
460            int y1 = interaction1.getY();
461            int y2 = interaction2.getY();
462
463            if ((x1 != x2) || (y1 != y2)) {
464                coordinatesMatch = false;
465            }
466        }
467       
468        // up to now, they can be equal. Now check the types. Do it as last action as these
469        // checks take the most time and should, therefore, only be done latest
470        if (((interaction1 instanceof MouseClick) && (interaction2 instanceof MouseClick)) ||
471            ((interaction1 instanceof MouseDoubleClick) &&
472             (interaction2 instanceof MouseDoubleClick)) ||
473            ((interaction1 instanceof MouseButtonDown) &&
474             (interaction2 instanceof MouseButtonDown)) ||
475            ((interaction1 instanceof MouseButtonUp) &&
476             (interaction2 instanceof MouseButtonUp)))
477        {
478            if (coordinatesMatch) {
479                return TaskEquality.LEXICALLY_EQUAL;
480            }
481            else {
482                // in most situations, the coordinates are not of interest. But if they are, then
483                // the event can be at most semantically equal
484                return TaskEquality.SEMANTICALLY_EQUAL;
485            }
486        }
487       
488        return TaskEquality.UNEQUAL;
489    }
490
491    /**
492     * <p>
493     * compares two scrolls and considers them as lexically equal if they have the same coordinates.
494     * Otherwise, they are syntactically equal as the happen on the same target
495     * </p>
496     *
497     * @param interaction1  the first scroll interaction to compare
498     * @param interaction2  the second scroll interaction to compare
499     * @param equalityLevel the equality level to be checked for
500     *
501     * @return as described
502     */
503    private TaskEquality compareScrolls(Scroll       interaction1,
504                                        Scroll       interaction2,
505                                        TaskEquality equalityLevel)
506    {
507        if (equalityLevel.isAtLeast(TaskEquality.LEXICALLY_EQUAL)) {
508            int x1 = interaction1.getXPosition();
509            int x2 = interaction2.getXPosition();
510            int y1 = interaction1.getYPosition();
511            int y2 = interaction2.getYPosition();
512       
513            if ((x1 == x2) && (y1 == y2)) {
514                return TaskEquality.LEXICALLY_EQUAL;
515            }
516        }
517       
518        return TaskEquality.SYNTACTICALLY_EQUAL;
519    }
520
521    /**
522     * <p>
523     * compares two text inputs. If both text inputs have the same entered text and text input
524     * events, they are lexically equal. If they only have the same entered text, they are
525     * syntactically equal. If they are only both text inputs, they are semantically equal.
526     * (the equality of the event targets is checked beforehand).
527     * </p>
528     * <p>
529     * The provided equality level can be used to restrict the quality check to the given level.
530     * This is done for optimization purposes. The returned equality level is as concrete as
531     * the provided one. It may be more concrete if there is no difference regarding the
532     * comparison on the levels.
533     * </p>
534     *
535     * @param interaction1  the first text input to compare
536     * @param interaction2  the second text input to compare
537     * @param equalityLevel the equality level to be checked for
538     *
539     * @return as described
540     */
541    private TaskEquality compareTextInputs(TextInput    interaction1,
542                                           TextInput    interaction2,
543                                           TaskEquality equalityLevel)
544    {
545        switch (equalityLevel) {
546            case LEXICALLY_EQUAL:
547                if (interaction1.getTextInputEvents().equals(interaction2.getTextInputEvents())) {
548                    return TaskEquality.LEXICALLY_EQUAL;
549                }
550                // fall through
551            case SYNTACTICALLY_EQUAL:
552                if (interaction1.getEnteredText().equals(interaction2.getEnteredText())) {
553                    return TaskEquality.SYNTACTICALLY_EQUAL;
554                }
555                // fall through
556            case SEMANTICALLY_EQUAL:
557                return TaskEquality.SEMANTICALLY_EQUAL;
558            default:
559                return TaskEquality.UNEQUAL;
560        }
561    }
562
563    /**
564     * <p>
565     * compares two value selections. If both value selections have the same selected value, they
566     * are syntactically equal, otherwise they are semantically equal.
567     * (the equality of the event targets is checked beforehand).
568     * </p>
569     * <p>
570     * The provided equality level can be used to restrict the quality check to the given level.
571     * This is done for optimization purposes. The returned equality level is as concrete as
572     * the provided one. It may be more concrete if there is no difference regarding the
573     * comparison on the levels.
574     * </p>
575     *
576     * @param interaction1  the first value selection to compare
577     * @param interaction2  the second value selection to compare
578     * @param equalityLevel the equality level to be checked for
579     *
580     * @return as described
581     */
582    private TaskEquality compareValueSelections(ValueSelection<?> interaction1,
583                                                ValueSelection<?> interaction2,
584                                                TaskEquality      equalityLevel)
585    {
586        if (equalityLevel.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL)) {
587            Object value1 = interaction1.getSelectedValue();
588            Object value2 = interaction2.getSelectedValue();
589       
590            if ((value1 == value2) || ((value1 != null) && (value1.equals(value2)))) {
591                return TaskEquality.LEXICALLY_EQUAL;
592            }
593        }
594       
595        return TaskEquality.SEMANTICALLY_EQUAL;
596    }
597
598    /**
599     * <p>
600     * Checks, if the coordinates of a click or double click on the provided event target makes
601     * a lexical difference. Mouse clicks and double clicks on buttons, check boxes,
602     * combo boxes, images, list boxes, menu buttons, radio buttons, shapes, uneditable text,
603     * and tool tips have no lexical difference as long as they happen on the same event target.
604     * The concrete coordinates are not relevant.
605     * </p>
606     *
607     * @param eventTarget the event target on which the interaction occurred
608     *
609     * @return if the coordinates are important to be considered for clicks and double clicks,
610     *         false else
611     */
612    private boolean clickCoordinatesMakeLexicalDifference(IEventTarget eventTarget) {
613        if ((eventTarget instanceof IButton) ||
614            (eventTarget instanceof ICheckBox) ||
615            (eventTarget instanceof IComboBox) ||
616            (eventTarget instanceof IImage) ||
617            (eventTarget instanceof IListBox) ||
618            (eventTarget instanceof IMenu) ||
619            (eventTarget instanceof IMenuButton) ||
620            (eventTarget instanceof IRadioButton) ||
621            (eventTarget instanceof IShape) ||
622            (eventTarget instanceof IText) ||
623            (eventTarget instanceof IToolTip))
624        {
625            return false;
626        }
627        else {
628            return true;
629        }
630    }
631
632}
Note: See TracBrowser for help on using the repository browser.