source: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/taskequality/IterationComparisonRule.java @ 1733

Last change on this file since 1733 was 1733, checked in by rkrimmel, 10 years ago

Used Eclipse code cleanup

  • Property svn:executable set to *
File size: 13.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 de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
18import de.ugoe.cs.autoquest.tasktrees.treeifc.IIterationInstance;
19import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
20import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
21import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
22
23/**
24 * <p>
25 * This class is capable of comparing Iterations. Iterations equal at distinct
26 * levels in distinct situations. The following table shows the results of the
27 * comparison for the specific situations (the parameters are commutative). In
28 * any other situation, the comparison returns <code>NodeEquality.UNEQUAL</code>
29 * :
30 * </p>
31 *
32 * <table border="1">
33 * <tr>
34 * <th>iteration 1</th>
35 * <th>iteration 2</th>
36 * <th>comparison result</th>
37 * </tr>
38 * <tr>
39 * <td>any iteration</td>
40 * <td>any iteration with a child that is lexically equal to the child of
41 * iteration 1</td>
42 * <td><code>NodeEquality.LEXICALLY_EQUAL</code></td>
43 * </tr>
44 * <tr>
45 * <td>any iteration</td>
46 * <td>any iteration with a child that is syntactically equal to the child of
47 * iteration 1</td>
48 * <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td>
49 * </tr>
50 * <tr>
51 * <td>any iteration</td>
52 * <td>any iteration with a child that is semantically equal to the child of
53 * iteration 1</td>
54 * <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td>
55 * </tr>
56 * <tr>
57 * <td>an iteration with a selection of syntactically equal children</td>
58 * <td>an iteration with a child that is syntactically equal to the children of
59 * the child selection of iteration 1</td>
60 * <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td>
61 * </tr>
62 * <tr>
63 * <td>an iteration with a selection of syntactically equal children</td>
64 * <td>an iteration with a selection of syntactically equal children that are
65 * all syntactically equal to the selection of children of iteration 1</td>
66 * <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td>
67 * </tr>
68 * <tr>
69 * <td>an iteration with a selection of semantically equal children</td>
70 * <td>an iteration with a child that is semantically equal to the children of
71 * the child selection of iteration 1</td>
72 * <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td>
73 * </tr>
74 * <tr>
75 * <td>an iteration with a selection of semantically equal children</td>
76 * <td>an iteration with a selection of semantically equal children that are all
77 * semantically equal to the selection of children of iteration 1</td>
78 * <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td>
79 * </tr>
80 * </table>
81 *
82 * @version $Revision: $ $Date: 19.02.2012$
83 * @author 2012, last modified by $Author: patrick$
84 */
85public class IterationComparisonRule implements TaskComparisonRule {
86
87        /*
88         * (non-Javadoc)
89         *
90         * @see TaskComparisonRule#areLexicallyEqual(ITask, ITask)
91         */
92        @Override
93        public boolean areLexicallyEqual(ITask task1, ITask task2) {
94                final ITask child1 = ((IIteration) task1).getMarkedTask();
95                final ITask child2 = ((IIteration) task2).getMarkedTask();
96
97                if (child1 != null) {
98                        if (child2 == null) {
99                                return false;
100                        } else {
101                                // iterations may have 3 different structures.
102                                // 1. they have one child, which is the iterated one
103                                // 2. they have a sequence of children, which is iterated
104                                // 3. they have a selection of different iterated variants
105                                // (usually the variants
106                                // are semantically equal)
107                                // ignore the type of the children but check them for equality.
108
109                                return getNodeEquality(child1, child2).isAtLeast(
110                                                TaskEquality.LEXICALLY_EQUAL);
111                        }
112                } else if (child2 == null) {
113                        return true;
114                }
115
116                return false;
117        }
118
119        /*
120         * (non-Javadoc)
121         *
122         * @see TaskComparisonRule#areLexicallyEqual(ITaskInstance, ITaskInstance)
123         */
124        @Override
125        public boolean areLexicallyEqual(ITaskInstance instance1,
126                        ITaskInstance instance2) {
127                final IIterationInstance iteration1 = (IIterationInstance) instance1;
128                final IIterationInstance iteration2 = (IIterationInstance) instance2;
129
130                // if both sequences do not have children, they are equal although this
131                // doesn't make sense
132                if ((iteration1.size() == 0) && (iteration2.size() == 0)) {
133                        return true;
134                }
135
136                if (iteration1.size() != iteration2.size()) {
137                        return false;
138                }
139
140                for (int i = 0; i < iteration1.size(); i++) {
141                        final ITaskInstance child1 = iteration1.get(i);
142                        final ITaskInstance child2 = iteration2.get(i);
143
144                        final TaskEquality taskEquality = callRuleManager(child1, child2,
145                                        TaskEquality.LEXICALLY_EQUAL);
146
147                        if ((taskEquality == null)
148                                        || (taskEquality == TaskEquality.UNEQUAL)) {
149                                return false;
150                        }
151                }
152
153                return true;
154        }
155
156        /*
157         * (non-Javadoc)
158         *
159         * @see TaskComparisonRule#areSemanticallyEqual(ITask, ITask)
160         */
161        @Override
162        public boolean areSemanticallyEqual(ITask task1, ITask task2) {
163                return compare(task1, task2).isAtLeast(TaskEquality.SEMANTICALLY_EQUAL);
164        }
165
166        /*
167         * (non-Javadoc)
168         *
169         * @see TaskComparisonRule#areSemanticallyEqual(ITaskInstance,
170         * ITaskInstance)
171         */
172        @Override
173        public boolean areSemanticallyEqual(ITaskInstance instance1,
174                        ITaskInstance instance2) {
175                return areLexicallyEqual(instance1, instance2);
176        }
177
178        /*
179         * (non-Javadoc)
180         *
181         * @see TaskComparisonRule#areSyntacticallyEqual(ITask, ITask)
182         */
183        @Override
184        public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
185                return areLexicallyEqual(task1, task2);
186        }
187
188        /*
189         * (non-Javadoc)
190         *
191         * @see TaskComparisonRule#areSyntacticallyEqual(ITaskInstance,
192         * ITaskInstance)
193         */
194        @Override
195        public boolean areSyntacticallyEqual(ITaskInstance instance1,
196                        ITaskInstance instance2) {
197                return areLexicallyEqual(instance1, instance2);
198        }
199
200        /**
201         * <p>
202         * used to to call the task equality rule manager for the comparison of the
203         * two provided children. If no required equality level is provided, than
204         * the most concrete equality is returned. Otherwise, the required equality
205         * is returned as long as the children are equal on that level.
206         * </p>
207         *
208         * @param child1
209         *            the first task to be compared
210         * @param child2
211         *            the second task to be compared
212         * @param requiredEqualityLevel
213         *            the equality level to be checked for
214         *
215         * @return the determined equality
216         */
217        private TaskEquality callRuleManager(ITask child1, ITask child2,
218                        TaskEquality requiredEqualityLevel) {
219                if (requiredEqualityLevel == null) {
220                        return TaskEqualityRuleManager.getInstance()
221                                        .compare(child1, child2);
222                } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual(
223                                child1, child2, requiredEqualityLevel)) {
224                        return requiredEqualityLevel;
225                } else {
226                        return TaskEquality.UNEQUAL;
227                }
228        }
229
230        /**
231         * <p>
232         * used to to call the task equality rule manager for the comparison of the
233         * two provided children. If no required equality level is provided, than
234         * the most concrete equality is returned. Otherwise, the required equality
235         * is returned as long as the children are equal on that level.
236         * </p>
237         *
238         * @param taskInstance1
239         *            the first task instance to be compared
240         * @param taskInstance2
241         *            the second task instance to be compared
242         * @param requiredEqualityLevel
243         *            the equality level to be checked for
244         *
245         * @return the determined equality
246         */
247        private TaskEquality callRuleManager(ITaskInstance taskInstance1,
248                        ITaskInstance taskInstance2, TaskEquality requiredEqualityLevel) {
249                if (requiredEqualityLevel == null) {
250                        return TaskEqualityRuleManager.getInstance().compare(taskInstance1,
251                                        taskInstance2);
252                } else if (TaskEqualityRuleManager.getInstance().areAtLeastEqual(
253                                taskInstance1, taskInstance2, requiredEqualityLevel)) {
254                        return requiredEqualityLevel;
255                } else {
256                        return TaskEquality.UNEQUAL;
257                }
258        }
259
260        /*
261         * (non-Javadoc)
262         *
263         * @see TaskComparisonRule#compare(ITask, ITask)
264         */
265        @Override
266        public TaskEquality compare(ITask task1, ITask task2) {
267                final ITask child1 = ((IIteration) task1).getMarkedTask();
268                final ITask child2 = ((IIteration) task2).getMarkedTask();
269
270                // if both iterations do not have children, they are equal although this
271                // doesn't make sense
272                if ((child1 == null) && (child2 == null)) {
273                        return TaskEquality.LEXICALLY_EQUAL;
274                } else if ((child1 == null) || (child2 == null)) {
275                        return TaskEquality.UNEQUAL;
276                }
277
278                // iterations may have 3 different structures.
279                // 1. they have one child, which is the iterated one
280                // 2. they have a sequence of children, which is iterated
281                // 3. they have a selection of different iterated variants (usually the
282                // variants are
283                // semantically equal)
284                //
285                // the permutations of the three variants in combination must be checked
286
287                // check if both tasks are the same variants of iterations and if their
288                // children are equal.
289                // This condition matches, if both iterations are the same variants of
290                // iteration. I.e. three
291                // combinations of the permutation are handled herewith.
292                final TaskEquality taskEquality = getNodeEquality(child1, child2);
293
294                if (taskEquality != null) {
295                        return taskEquality;
296                }
297
298                // compare one iteration with a single task as a child and another one
299                // with a selection of
300                // semantically equal tasks
301                return selectionChildrenSemanticallyEqualNode(child1, child2);
302
303                // all other combinations (i.e. sequence with single child and sequence
304                // with selection)
305                // can not match
306        }
307
308        /*
309         * (non-Javadoc)
310         *
311         * @see TaskComparisonRule#compare(ITaskInstance, ITaskInstance)
312         */
313        @Override
314        public TaskEquality compare(ITaskInstance instance1, ITaskInstance instance2) {
315                if (areLexicallyEqual(instance1, instance2)) {
316                        return TaskEquality.LEXICALLY_EQUAL;
317                } else {
318                        return TaskEquality.UNEQUAL;
319                }
320        }
321
322        /**
323         * <p>
324         * compares two tasks with each other by calling the rule manager. If the
325         * rule manager returns identity, then the returned equality is set to
326         * lexically equal. The reason is, that the children of the iterations are
327         * compared and that therefore the distinct iterations can be at most
328         * lexically equal.
329         * </p>
330         *
331         * @param child1
332         *            the first task to be compared
333         * @param child2
334         *            the second task to be compared
335         *
336         * @return the determined equality being at most lexical equality.
337         */
338        private TaskEquality getNodeEquality(ITask child1, ITask child2) {
339                final TaskEquality taskEquality = callRuleManager(child1, child2, null);
340
341                if (taskEquality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL)) {
342                        // prevent, that identical is returned, because the iterations
343                        // itself are not identical
344                        // although the iterated tasks are
345                        if (taskEquality == TaskEquality.IDENTICAL) {
346                                return TaskEquality.LEXICALLY_EQUAL;
347                        } else {
348                                return taskEquality;
349                        }
350                }
351
352                return TaskEquality.UNEQUAL;
353        }
354
355        /*
356         * (non-Javadoc)
357         *
358         * @see TaskComparisonRule#isApplicable(ITask, ITask)
359         */
360        @Override
361        public boolean isApplicable(ITask task1, ITask task2) {
362                return (task1 instanceof IIteration) && (task2 instanceof IIteration);
363        }
364
365        /*
366         * (non-Javadoc)
367         *
368         * @see TaskComparisonRule#isApplicable(ITaskInstance, ITaskInstance)
369         */
370        @Override
371        public boolean isApplicable(ITaskInstance instance1, ITaskInstance instance2) {
372                return isApplicable(instance1.getTask(), instance2.getTask());
373        }
374
375        /**
376         * <p>
377         * compares two tasks. One of them must be a selection, the other one can be
378         * any task. The method returns a task equality that is not
379         * <code>NodeEquality.UNEQUAL</code> if the other task is at least
380         * semantically equal to the children of the selection. It returns more
381         * concrete equalities, if the equality between the other task and the
382         * children of the selection is more concrete.
383         * </p>
384         *
385         * @param task1
386         *            the first task to compare
387         * @param task2
388         *            the second task to compare
389         *
390         * @return as described
391         */
392        private TaskEquality selectionChildrenSemanticallyEqualNode(ITask task1,
393                        ITask task2) {
394                ISelection selection = null;
395                ITask task = null;
396                if (task1 instanceof ISelection) {
397                        selection = (ISelection) task1;
398                        task = task2;
399                } else if (task2 instanceof ISelection) {
400                        selection = (ISelection) task2;
401                        task = task1;
402                } else {
403                        return TaskEquality.UNEQUAL;
404                }
405
406                // Iterations, where one has a selection and the other one not can at
407                // most be syntactically
408                // equal but not identical
409                TaskEquality commonDenominatorForAllComparisons = TaskEquality.SYNTACTICALLY_EQUAL;
410
411                for (final ITask child : selection.getChildren()) {
412                        final TaskEquality taskEquality = callRuleManager(task, child,
413                                        commonDenominatorForAllComparisons);
414
415                        if ((taskEquality == null)
416                                        || (taskEquality == TaskEquality.UNEQUAL)) {
417                                return TaskEquality.UNEQUAL;
418                        }
419
420                        commonDenominatorForAllComparisons = commonDenominatorForAllComparisons
421                                        .getCommonDenominator(taskEquality);
422                }
423
424                return commonDenominatorForAllComparisons;
425        }
426}
Note: See TracBrowser for help on using the repository browser.