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

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

Added automatically created javadoc, still needs to be commented properly though

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