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

Last change on this file since 1146 was 1146, checked in by pharms, 11 years ago
  • complete refactoring of task tree model with a separation of task models and task instances
  • appropriate adaptation of task tree generation process
  • appropriate adaptation of commands and task tree visualization
  • Property svn:executable set to *
File size: 9.0 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.List;
18
19import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
20import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
21
22/**
23 * <p>
24 * this task comparison rule is capable of comparing selections. If both selections do not have
25 * children, they are treated as lexically equal. If they have children, each child of both
26 * selections is compared to each child of the respective other selection. The resulting equality
27 * is the most concrete one of all these comparisons. I.e. if all children are at least lexically
28 * equal, then the selections are lexically equal. If all children are at least syntactically
29 * equal, then the selections are syntactically equal. If all children are at least semantically
30 * equal, then the selections are semantically equal. If only one of the selections has children,
31 * then the selections are unequal.
32 * </p>
33 *
34 * @version $Revision: $ $Date: 19.02.2012$
35 * @author 2012, last modified by $Author: patrick$
36 */
37public class SelectionComparisonRule implements TaskComparisonRule {
38
39    /** the rule manager for internally comparing tasks */
40    private TaskEqualityRuleManager mRuleManager;
41
42    /**
43     * <p>
44     * simple constructor to provide the rule with the task equality rule manager to be able
45     * to perform comparisons of the children of provided tasks
46     * </p>
47     *
48     * @param ruleManager the rule manager for comparing tasks
49     */
50    SelectionComparisonRule(TaskEqualityRuleManager ruleManager) {
51        super();
52        mRuleManager = ruleManager;
53    }
54
55    /* (non-Javadoc)
56     * @see NodeComparisonRule#isApplicable(ITask, ITask)
57     */
58    @Override
59    public boolean isApplicable(ITask task1, ITask task2) {
60        return (task1 instanceof ISelection) && (task2 instanceof ISelection);
61    }
62
63    /* (non-Javadoc)
64     * @see NodeComparisonRule#areLexicallyEqual(ITask, ITask)
65     */
66    @Override
67    public boolean areLexicallyEqual(ITask task1, ITask task2) {
68        TaskEquality equality = getEquality(task1, task2, TaskEquality.LEXICALLY_EQUAL);
69        return (equality != null) && (equality.isAtLeast(TaskEquality.LEXICALLY_EQUAL));
70    }
71
72    /* (non-Javadoc)
73     * @see NodeComparisonRule#areSyntacticallyEqual(ITask, ITask)
74     */
75    @Override
76    public boolean areSyntacticallyEqual(ITask task1, ITask task2) {
77        TaskEquality equality = getEquality(task1, task2, TaskEquality.SYNTACTICALLY_EQUAL);
78        return (equality != null) && (equality.isAtLeast(TaskEquality.SYNTACTICALLY_EQUAL));
79    }
80
81    /* (non-Javadoc)
82     * @see NodeComparisonRule#areSemanticallyEqual(ITask, ITask)
83     */
84    @Override
85    public boolean areSemanticallyEqual(ITask task1, ITask task2) {
86        TaskEquality equality = getEquality(task1, task2, TaskEquality.SEMANTICALLY_EQUAL);
87        return (equality != null) && (equality.isAtLeast(TaskEquality.SEMANTICALLY_EQUAL));
88    }
89
90    /* (non-Javadoc)
91     * @see NodeComparisonRule#compare(ITask, ITask)
92     */
93    @Override
94    public TaskEquality compare(ITask task1, ITask task2) {
95        return getEquality(task1, task2, null);
96    }
97
98    /**
99     *
100     */
101    private TaskEquality getEquality(ITask task1, ITask task2, TaskEquality requiredEqualityLevel) {
102        List<ITask> children1 = ((ISelection) task1).getChildren();
103        List<ITask> children2 = ((ISelection) task2).getChildren();
104
105        // if both selections do not have children, they are lexically equal. If only one of them
106        // has children, they are unequal.
107        if ((children1.size() == 0) && (children2.size() == 0)) {
108            return TaskEquality.LEXICALLY_EQUAL;
109        }
110        else if ((children1.size() == 0) || (children2.size() == 0)) {
111            return TaskEquality.UNEQUAL;
112        }
113
114        TaskEquality selectionEquality;
115
116        if (requiredEqualityLevel == null) {
117            // calculate the common equality level for all children of both selections.
118            // do it in both directions to ensure commutative comparison
119            selectionEquality = getCommonEqualityLevel(children1, children2);
120            if (selectionEquality != TaskEquality.UNEQUAL) {
121                return selectionEquality.getCommonDenominator
122                    (getCommonEqualityLevel(children2, children1));
123            }
124            else {
125                return TaskEquality.UNEQUAL;
126            }
127        }
128        else {
129            // we are searching for a specific equality
130            if (checkEqualityLevel(children1, children2, requiredEqualityLevel) &&
131                checkEqualityLevel(children2, children1, requiredEqualityLevel))
132            {
133                return requiredEqualityLevel;
134            }
135            else {
136                return TaskEquality.UNEQUAL;
137            }
138        }
139    }
140
141    /**
142     * <p>
143     * TODO: comment
144     * </p>
145     *
146     * @param children1
147     * @param children2
148     * @param requiredEqualityLevel
149     */
150    private TaskEquality getCommonEqualityLevel(List<ITask> children1, List<ITask> children2) {
151        TaskEquality listEquality = TaskEquality.LEXICALLY_EQUAL;
152       
153        TaskEquality childEquality;
154        TaskEquality currentEquality;
155        for (ITask child1 : children1) {
156            childEquality = null;
157            for (ITask child2 : children2) {
158                currentEquality = callRuleManager(child1, child2, null);
159                if ((currentEquality != null) && (currentEquality != TaskEquality.UNEQUAL)) {
160                    if (childEquality == null) {
161                        childEquality = currentEquality;
162                    }
163                    else {
164                        childEquality = childEquality.getCommonDenominator(currentEquality);
165                    }
166                   
167                    if (childEquality == TaskEquality.SEMANTICALLY_EQUAL) {
168                        // as we calculate only the common denominator, we can break up here for
169                        // the current child. We will not improve the denominator anymore
170                        break;
171                    }
172                }
173            }
174           
175            if (childEquality == null) {
176                // we did not find any child in the second list, that is equal to the searched
177                // child
178                return TaskEquality.UNEQUAL;
179            }
180            else {
181                listEquality = listEquality.getCommonDenominator(childEquality);
182            }
183        }
184
185        return listEquality;
186    }
187
188    /**
189     * <p>
190     * TODO: comment
191     * </p>
192     *
193     * @param children1
194     * @param children2
195     * @param requiredEqualityLevel
196     */
197    private boolean checkEqualityLevel(List<ITask>  children1,
198                                       List<ITask>  children2,
199                                       TaskEquality requiredEqualityLevel)
200    {
201        TaskEquality childEquality;
202        TaskEquality currentEquality;
203        for (ITask child1 : children1) {
204            childEquality = null;
205            for (ITask child2 : children2) {
206                currentEquality = callRuleManager(child1, child2, requiredEqualityLevel);
207                if ((currentEquality != null) && (currentEquality.isAtLeast(requiredEqualityLevel)))
208                {
209                    // we found at least one equal child with sufficient equality in the
210                    // second list. So be can break up for this child.
211                    childEquality = currentEquality;
212                    break;
213                }
214            }
215           
216            if (childEquality == null) {
217                // we did not find any child in the second list, that is equal to the searched
218                // child
219                return false;
220            }
221        }
222
223        // for all children, we found an equality
224        return true;
225    }
226
227    /**
228     * <p>
229     * TODO: comment
230     * </p>
231     *
232     * @param child1
233     * @param child2
234     * @param requiredEqualityLevel
235     * @return
236     */
237    private TaskEquality callRuleManager(ITask        child1,
238                                         ITask        child2,
239                                         TaskEquality requiredEqualityLevel)
240    {
241        if (requiredEqualityLevel == null) {
242            return mRuleManager.compare(child1, child2);
243        }
244        else if (mRuleManager.areAtLeastEqual(child1, child2, requiredEqualityLevel)) {
245            return requiredEqualityLevel;
246        }
247        else {
248            return TaskEquality.UNEQUAL;
249        }
250    }
251
252}
Note: See TracBrowser for help on using the repository browser.