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

Last change on this file since 1887 was 1887, checked in by pharms, 9 years ago
  • extended and corrected task comparison
  • Property svn:executable set to *
File size: 17.2 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.ArrayList;
18import java.util.List;
19
20import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
21import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
22
23/**
24 * <p>
25 * The task equality rule manager is capable of comparing tasks and task instances based on its
26 * internal list of comparison rules. These rules are asked for comparing the two provided tasks or
27 * task instance. If a rule returns a task equality other than null, this equality is returned.
28 * Otherwise the next rule is asked.
29 * </p>
30 *
31 * @author Patrick Harms
32 */
33public class TaskEqualityRuleManager {
34   
35    /**
36     * <p>
37     * the singleton instance of this class
38     * </p>
39     */
40    private static final TaskEqualityRuleManager instance = new TaskEqualityRuleManager();
41
42    /**
43     * <p>
44     * the rules that can be used for comparing tasks
45     * </p>
46     */
47    private List<TaskComparisonRule> mRuleIndex = null;
48
49    /**
50     * <p>
51     * initializes the task equality rule manager by filling the internal list of comparison rules.
52     * </p>
53     */
54    private TaskEqualityRuleManager() {
55        mRuleIndex = new ArrayList<TaskComparisonRule>();
56        mRuleIndex.add(new TaskIdentityRule());
57        mRuleIndex.add(new GUIEventTaskComparisonRule());
58        mRuleIndex.add(new EventTaskComparisonRule());
59        mRuleIndex.add(new IterationComparisonRule());
60        mRuleIndex.add(new OptionalComparisonRule());
61        mRuleIndex.add(new SequenceComparisonRule());
62        mRuleIndex.add(new SelectionComparisonRule());
63        mRuleIndex.add(new TaskAndIterationComparisonRule());
64        mRuleIndex.add(new TaskAndOptionalComparisonRule());
65        mRuleIndex.add(new TaskAndSelectionComparisonRule());
66    }
67
68
69    /**
70     * <p>
71     * returns the singleton instance of this class
72     * </p>
73     *
74     * @return as described
75     */
76    public static TaskEqualityRuleManager getInstance() {
77        return instance;
78    }
79
80    /**
81     * <p>
82     * this method performs a comparison of the two provided tasks. It iterates its internal
83     * comparison rules. If the first rule returns a task equality other than null,
84     * this equality is returned. Otherwise the next rule is tried. If no rule returns an equality
85     * <code>NodeEquality.UNEQUAL</code> is returned.
86     * </p>
87     *
88     * @param task1 the first task to be compared
89     * @param task2 the second task to be compared
90     *
91     * @return as described
92     *
93     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
94     *                               manager before a call to this method.
95     */
96    public TaskEquality compare(ITask task1, ITask task2)
97        throws IllegalStateException
98    {
99        if (mRuleIndex == null) {
100            throw new IllegalStateException("not initialized");
101        }
102       
103        // LOG.info("checking for equality of " + task1 + " and " + task2);
104        TaskEquality taskEquality = null;
105
106        for (TaskComparisonRule rule : mRuleIndex) {
107            if (rule.isApplicable(task1, task2)) {
108                taskEquality = rule.compare(task1, task2);
109                if (taskEquality != null) {
110                    // LOG.warning("used rule " + rule + " for equality check");
111                    return taskEquality;
112                }
113            }
114        }
115
116        // LOG.warning("no rule could be applied --> handling tasks as unequal");
117
118        return TaskEquality.UNEQUAL;
119    }
120
121    /**
122     * <p>
123     * this method two tasks with respect to the fiven equality level and returns true, if this
124     * level is given.
125     * </p>
126     *
127     * @param task1         the first task to be compared
128     * @param task2         the second task to be compared
129     * @param equalityLevel the level of equality to be checked for
130     *
131     * @return as described
132     *
133     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
134     *                               manager before a call to this method.
135     */
136    public boolean areAtLeastEqual(ITask task1, ITask task2, TaskEquality equalityLevel) {
137        if (equalityLevel == null) {
138            throw new IllegalArgumentException("required equality level must not be null");
139        }
140       
141        switch (equalityLevel) {
142            case IDENTICAL:
143                return areIdentical(task1, task2);
144            case LEXICALLY_EQUAL:
145                return areLexicallyEqual(task1, task2);
146            case SYNTACTICALLY_EQUAL:
147                return areSyntacticallyEqual(task1, task2);
148            case SEMANTICALLY_EQUAL:
149                return areSemanticallyEqual(task1, task2);
150            case UNEQUAL:
151                return !areSemanticallyEqual(task1, task2);
152            default:
153                throw new IllegalArgumentException("unknown required equality: " + equalityLevel);
154        }
155    }
156
157    /**
158     * <p>
159     * this method checks if the two given tasks are identical. For this, it iterates its internal
160     * comparison rules. If the first rule returns true, than this method returns true as well.
161     * If no rule returns true, this method returns false.
162     * </p>
163     *
164     * @param task1 the first task to be compared
165     * @param task2 the second task to be compared
166     *
167     * @return as described
168     *
169     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
170     *                               manager before a call to this method.
171     */
172    public boolean areIdentical(ITask task1, ITask task2) {
173        if (mRuleIndex == null) {
174            throw new IllegalStateException("not initialized");
175        }
176       
177        for (TaskComparisonRule rule : mRuleIndex) {
178            if (rule.isApplicable(task1, task2) && rule.areLexicallyEqual(task1, task2)) {
179                 return true;
180            }
181        }
182
183        return false;
184    }
185
186    /**
187     * <p>
188     * this method checks if the two given tasks are lexically equal. For this, it iterates its
189     * internal comparison rules. If the first rule returns true, than this method returns true
190     * as well. If no rule returns true, this method returns false.
191     * </p>
192     *
193     * @param task1 the first task to be compared
194     * @param task2 the second task to be compared
195     *
196     * @return as described
197     *
198     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
199     *                               manager before a call to this method.
200     */
201    public boolean areLexicallyEqual(ITask task1, ITask task2) {
202        if (mRuleIndex == null) {
203            throw new IllegalStateException("not initialized");
204        }
205       
206        for (TaskComparisonRule rule : mRuleIndex) {
207            if (rule.isApplicable(task1, task2) && rule.areLexicallyEqual(task1, task2)) {
208                 return true;
209            }
210        }
211
212        return false;
213    }
214
215    /**
216     * <p>
217     * this method checks if the two given tasks are syntactically equal. For this, it iterates its
218     * internal comparison rules. If the first rule returns true, than this method returns true
219     * as well. If no rule returns true, this method returns false.
220     * </p>
221     *
222     * @param task1 the first task to be compared
223     * @param task2 the second task to be compared
224     *
225     * @return as described
226     *
227     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
228     *                               manager before a call to this method.
229     */
230    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
231        if (mRuleIndex == null) {
232            throw new IllegalStateException("not initialized");
233        }
234       
235        for (TaskComparisonRule rule : mRuleIndex) {
236            if (rule.isApplicable(task1, task2) && rule.areSyntacticallyEqual(task1, task2)) {
237                 return true;
238            }
239        }
240
241        return false;
242    }
243
244    /**
245     * <p>
246     * this method checks if the two given tasks are semantically equal. For this, it iterates its
247     * internal comparison rules. If the first rule returns true, than this method returns true
248     * as well. If no rule returns true, this method returns false.
249     * </p>
250     *
251     * @param task1 the first task to be compared
252     * @param task2 the second task to be compared
253     *
254     * @return as described
255     *
256     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
257     *                               manager before a call to this method.
258     */
259    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
260        if (mRuleIndex == null) {
261            throw new IllegalStateException("not initialized");
262        }
263       
264        for (TaskComparisonRule rule : mRuleIndex) {
265            if (rule.isApplicable(task1, task2) && rule.areSemanticallyEqual(task1, task2)) {
266                 return true;
267            }
268        }
269
270        return false;
271    }
272
273    /**
274     * <p>
275     * this method performs a comparison of the two provided task instances. It iterates its
276     * internal comparison rules. If the first rule returns a task instance equality other than
277     * null, this equality is returned. Otherwise the next rule is tried. If no rule returns an
278     * equality <code>TaskEquality.UNEQUAL</code> is returned.
279     * </p>
280     *
281     * @param instance1 the first task instance to be compared
282     * @param instance2 the second task instance to be compared
283     *
284     * @return as described
285     *
286     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
287     *                               manager before a call to this method.
288     */
289    public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2)
290        throws IllegalStateException
291    {
292        if (mRuleIndex == null) {
293            throw new IllegalStateException("not initialized");
294        }
295       
296        // LOG.info("checking for equality of " + instance1 + " and " + instance2);
297        TaskEquality instanceEquality = null;
298
299        for (TaskComparisonRule rule : mRuleIndex) {
300            if (rule.isApplicable(instance1, instance2)) {
301                instanceEquality = rule.compare(instance1, instance2);
302                if (instanceEquality != null) {
303                    // LOG.warning("used rule " + rule + " for equality check");
304                    return instanceEquality;
305                }
306            }
307        }
308
309        // LOG.warning("no rule could be applied --> handling tasks as unequal");
310
311        return TaskEquality.UNEQUAL;
312    }
313
314    /**
315     * <p>
316     * this method compares two task instances with respect to the given equality level and returns
317     * true, if this level is given.
318     * </p>
319     *
320     * @param instance1     the first task instance to be compared
321     * @param instance2     the second task instance to be compared
322     * @param equalityLevel the level of equality to be checked for
323     *
324     * @return as described
325     *
326     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
327     *                               manager before a call to this method.
328     */
329    public boolean areAtLeastEqual(ITaskInstance        instance1,
330                                   ITaskInstance        instance2,
331                                   TaskEquality equalityLevel)
332    {
333        if (equalityLevel == null) {
334            throw new IllegalArgumentException("required equality level must not be null");
335        }
336       
337        switch (equalityLevel) {
338            case IDENTICAL:
339                return areIdentical(instance1, instance2);
340            case LEXICALLY_EQUAL:
341                return areLexicallyEqual(instance1, instance2);
342            case SYNTACTICALLY_EQUAL:
343                return areSyntacticallyEqual(instance1, instance2);
344            case SEMANTICALLY_EQUAL:
345                return areSemanticallyEqual(instance1, instance2);
346            case UNEQUAL:
347                return !areSemanticallyEqual(instance1, instance2);
348            default:
349                throw new IllegalArgumentException("unknown required equality: " + equalityLevel);
350        }
351    }
352
353    /**
354     * <p>
355     * this method checks if the two given task instances are identical. For this, it iterates its
356     * internal comparison rules. If the first rule returns true, than this method returns true
357     * as well. If no rule returns true, this method returns false.
358     * </p>
359     *
360     * @param instance1 the first task instance to be compared
361     * @param instance2 the second task instance to be compared
362     *
363     * @return as described
364     *
365     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
366     *                               manager before a call to this method.
367     */
368    public boolean areIdentical(ITaskInstance instance1, ITaskInstance instance2) {
369        if (mRuleIndex == null) {
370            throw new IllegalStateException("not initialized");
371        }
372       
373        for (TaskComparisonRule rule : mRuleIndex) {
374            if (rule.isApplicable(instance1, instance2) &&
375                rule.areLexicallyEqual(instance1, instance2))
376            {
377                return true;
378            }
379        }
380
381        return false;
382    }
383
384    /**
385     * <p>
386     * this method checks if the two given task instances are lexically equal. For this, it
387     * iterates its internal comparison rules. If the first rule returns true, than this method
388     * returns true, as well. If no rule returns true, this method returns false.
389     * </p>
390     *
391     * @param instance1 the first task instance to be compared
392     * @param instance2 the second task instance to be compared
393     *
394     * @return as described
395     *
396     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
397     *                               manager before a call to this method.
398     */
399    public boolean areLexicallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
400        if (mRuleIndex == null) {
401            throw new IllegalStateException("not initialized");
402        }
403       
404        for (TaskComparisonRule rule : mRuleIndex) {
405            if (rule.isApplicable(instance1, instance2) &&
406                rule.areLexicallyEqual(instance1, instance2))
407            {
408                return true;
409            }
410        }
411
412        return false;
413    }
414
415    /**
416     * <p>
417     * this method checks if the two given task instances are syntactically equal. For this, it
418     * iterates its internal comparison rules. If the first rule returns true, than this method
419     * returns true, as well. If no rule returns true, this method returns false.
420     * </p>
421     *
422     * @param instance1 the first task instance to be compared
423     * @param instance2 the second task instance to be compared
424     *
425     * @return as described
426     *
427     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
428     *                               manager before a call to this method.
429     */
430    public boolean areSyntacticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
431        if (mRuleIndex == null) {
432            throw new IllegalStateException("not initialized");
433        }
434       
435        for (TaskComparisonRule rule : mRuleIndex) {
436            if (rule.isApplicable(instance1, instance2) &&
437                rule.areSyntacticallyEqual(instance1, instance2))
438            {
439                return true;
440            }
441        }
442
443        return false;
444    }
445
446    /**
447     * <p>
448     * this method checks if the two given task instances are semantically equal. For this, it
449     * iterates its internal comparison rules. If the first rule returns true, than this method
450     * returns true, as well. If no rule returns true, this method returns false.
451     * </p>
452     *
453     * @param instance1 the first task instance to be compared
454     * @param instance2 the second task instance to be compared
455     *
456     * @return as described
457     *
458     * @throws IllegalStateException in the case, the {@link #init()} method was not called on the
459     *                               manager before a call to this method.
460     */
461    public boolean areSemanticallyEqual(ITaskInstance instance1, ITaskInstance instance2) {
462        if (mRuleIndex == null) {
463            throw new IllegalStateException("not initialized");
464        }
465       
466        for (TaskComparisonRule rule : mRuleIndex) {
467            if (rule.isApplicable(instance1, instance2) &&
468                rule.areSemanticallyEqual(instance1, instance2))
469            {
470                 return true;
471            }
472        }
473
474        return false;
475    }
476
477}
Note: See TracBrowser for help on using the repository browser.