source: trunk/autoquest-core-tasktrees/src/main/java/de/ugoe/cs/autoquest/tasktrees/nodeequality/IterationComparisonRule.java @ 1125

Last change on this file since 1125 was 1125, checked in by pharms, 11 years ago
  • refactoring of task tree node comparison to be able to optimize the comparisons for the different comparison levels lexically, syntactically, semantically
  • Property svn:executable set to *
File size: 12.6 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.nodeequality;
16
17import java.util.List;
18
19import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask;
20import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration;
21import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection;
22import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence;
23import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode;
24
25/**
26 * <p>
27 * This class is capable of comparing Iterations. Iterations equal at distinct levels
28 * in distinct situations. The following table shows the results of the comparison for the
29 * specific situations (the parameters are commutative). In any other situation, the comparison
30 * returns <code>NodeEquality.UNEQUAL</code>:
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 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 iteration 1</td>
47 *     <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td>
48 *   </tr>
49 *   <tr>
50 *     <td>any iteration</td>
51 *     <td>any iteration with a child that is semantically equal to the child of iteration 1</td>
52 *     <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td>
53 *   </tr>
54 *   <tr>
55 *     <td>an iteration with a selection of syntactically equal children</td>
56 *     <td>an iteration with a child that is syntactically equal to the children of the child
57 *     selection of iteration 1</td>
58 *     <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td>
59 *   </tr>
60 *   <tr>
61 *     <td>an iteration with a selection of syntactically equal children</td>
62 *     <td>an iteration with a selection of syntactically equal children that are all syntactically
63 *     equal to the selection of children of iteration 1</td>
64 *     <td><code>NodeEquality.SYNTACTICALLY_EQUAL</code></td>
65 *   </tr>
66 *   <tr>
67 *     <td>an iteration with a selection of semantically equal children</td>
68 *     <td>an iteration with a child that is semantically equal to the children of the child
69 *     selection of iteration 1</td>
70 *     <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td>
71 *   </tr>
72 *   <tr>
73 *     <td>an iteration with a selection of semantically equal children</td>
74 *     <td>an iteration with a selection of semantically equal children that are all semantically
75 *     equal to the selection of children of iteration 1</td>
76 *     <td><code>NodeEquality.SEMANTICALLY_EQUAL</code></td>
77 *   </tr>
78 * </table>
79 *
80 * @version $Revision: $ $Date: 19.02.2012$
81 * @author 2012, last modified by $Author: patrick$
82 */
83public class IterationComparisonRule implements NodeComparisonRule {
84   
85    /** the rule manager for internally comparing task tree nodes */
86    private NodeEqualityRuleManager mRuleManager;
87
88    /**
89     * <p>
90     * simple constructor to provide the rule with the node equality rule manager to be able
91     * to perform comparisons of the children of provided task tree nodes
92     * </p>
93     *
94     * @param ruleManager the rule manager for comparing task tree nodes
95     */
96    IterationComparisonRule(NodeEqualityRuleManager ruleManager) {
97        super();
98        mRuleManager = ruleManager;
99    }
100
101    /* (non-Javadoc)
102     * @see NodeComparisonRule#isApplicable(ITaskTreeNode, ITaskTreeNode)
103     */
104    @Override
105    public boolean isApplicable(ITaskTreeNode node1, ITaskTreeNode node2) {
106        return (node1 instanceof IIteration) && (node2 instanceof IIteration);
107    }
108
109    /* (non-Javadoc)
110     * @see NodeComparisonRule#areLexicallyEqual(ITaskTreeNode, ITaskTreeNode)
111     */
112    @Override
113    public boolean areLexicallyEqual(ITaskTreeNode node1, ITaskTreeNode node2) {
114        List<ITaskTreeNode> children1 = node1.getChildren();
115        List<ITaskTreeNode> children2 = node2.getChildren();
116       
117        if (children1.size() == children2.size()) {
118            if (children1.size() == 0) {
119                return true;
120            }
121            else {
122                ITaskTreeNode child1 = children1.get(0);
123                ITaskTreeNode child2 = children2.get(0);
124               
125                // iterations may have 3 different structures.
126                // 1. they have one child, which is the iterated one
127                // 2. they have a sequence of children, which is iterated
128                // 3. they have a selection of different iterated variants (usually the variants
129                //    are semantically equal)
130                // check if the type of children match. If not, return false. If they match,
131                // use the equality manager to perform further comparisons
132               
133                if (((child1 instanceof ISelection) && (child2 instanceof ISelection)) ||
134                    ((child1 instanceof ISequence) && (child2 instanceof ISequence)) ||
135                    ((child1 instanceof IEventTask) && (child2 instanceof IEventTask)))
136                {
137                    return getNodeEquality
138                        (child1, child2).isAtLeast(NodeEquality.LEXICALLY_EQUAL);
139                }
140            }
141        }
142       
143        return false;
144    }
145
146    /* (non-Javadoc)
147     * @see NodeComparisonRule#areSyntacticallyEqual(ITaskTreeNode, ITaskTreeNode)
148     */
149    @Override
150    public boolean areSyntacticallyEqual(ITaskTreeNode node1, ITaskTreeNode node2) {
151        List<ITaskTreeNode> children1 = node1.getChildren();
152        List<ITaskTreeNode> children2 = node2.getChildren();
153       
154        if (children1.size() == children2.size()) {
155            if (children1.size() == 0) {
156                return true;
157            }
158            else {
159                ITaskTreeNode child1 = children1.get(0);
160                ITaskTreeNode child2 = children2.get(0);
161               
162                // iterations may have 3 different structures.
163                // 1. they have one child, which is the iterated one
164                // 2. they have a sequence of children, which is iterated
165                // 3. they have a selection of different iterated variants (usually the variants
166                //    are semantically equal)
167                // ignore the type of the children but check them for equality.
168               
169                return getNodeEquality(child1, child2).isAtLeast(NodeEquality.SYNTACTICALLY_EQUAL);
170            }
171        }
172       
173        return false;
174    }
175
176    /* (non-Javadoc)
177     * @see NodeComparisonRule#areSemanticallyEqual(ITaskTreeNode, ITaskTreeNode)
178     */
179    @Override
180    public boolean areSemanticallyEqual(ITaskTreeNode node1, ITaskTreeNode node2) {
181        return compare(node1, node2).isAtLeast(NodeEquality.SEMANTICALLY_EQUAL);
182    }
183
184    /* (non-Javadoc)
185     * @see NodeComparisonRule#compare(ITaskTreeNode, ITaskTreeNode)
186     */
187    @Override
188    public NodeEquality compare(ITaskTreeNode node1, ITaskTreeNode node2) {
189        List<ITaskTreeNode> children1 = node1.getChildren();
190        List<ITaskTreeNode> children2 = node2.getChildren();
191
192        // if both iterations do not have children, they are equal although this doesn't make sense
193        if ((children1.size() == 0) && (children2.size() == 0)) {
194            return NodeEquality.LEXICALLY_EQUAL;
195        }
196        else if ((children1.size() == 0) || (children2.size() == 0)) {
197            return NodeEquality.UNEQUAL;
198        }
199
200        ITaskTreeNode child1 = children1.get(0);
201        ITaskTreeNode child2 = children2.get(0);
202
203        // iterations may have 3 different structures.
204        // 1. they have one child, which is the iterated one
205        // 2. they have a sequence of children, which is iterated
206        // 3. they have a selection of different iterated variants (usually the variants are
207        // semantically equal)
208        //
209        // the permutations of the three variants in combination must be checked
210
211        // check if both nodes are the same variants of iterations and if their children are equal.
212        // This condition matches, if both iterations are the same variants of iteration. I.e. three
213        // combinations of the permutation are handled herewith.
214        NodeEquality nodeEquality = getNodeEquality(child1, child2);
215       
216        if (nodeEquality != null) {
217            return nodeEquality;
218        }
219
220        // compare one iteration with a single node as a child and another one with a selection of
221        // semantically equal nodes
222        return selectionChildrenSemanticallyEqualNode(child1, child2);
223       
224        // all other combinations (i.e. sequence with single child and sequence with selection)
225        // can not match
226    }
227
228    /**
229     * TODO update comment
230     */
231    private NodeEquality getNodeEquality(ITaskTreeNode child1, ITaskTreeNode child2) {
232        NodeEquality nodeEquality = callRuleManager(child1, child2, null);
233
234        if (nodeEquality.isAtLeast(NodeEquality.SEMANTICALLY_EQUAL)) {
235            // prevent, that identical is returned, because the iterations itself are not identical
236            // although the iterated tasks are
237            if (nodeEquality == NodeEquality.IDENTICAL) {
238                return NodeEquality.LEXICALLY_EQUAL;
239            }
240            else {
241                return nodeEquality;
242            }
243        }
244       
245        return NodeEquality.UNEQUAL;
246    }
247
248    /**
249     * <p>
250     * compares two task tree nodes. One of them must be a selection, the other one can be any task
251     * tree node. The method returns a node equality that is not <code>NodeEquality.UNEQUAL</code>
252     * if the other node is at least semantically equal to the children of the selection. It
253     * returns more concrete equalities, if the equality between the other node and the children
254     * of the selection is more concrete.
255     * </p>
256     *
257     * @param taskTreeNode  the first task tree node to compare
258     * @param taskTreeNode2 the second task tree node to compare
259     *
260     * @return as described
261     */
262    private NodeEquality selectionChildrenSemanticallyEqualNode(ITaskTreeNode taskTreeNode,
263                                                                ITaskTreeNode taskTreeNode2)
264    {
265        ISelection selection = null;
266        ITaskTreeNode node = null;
267        if (taskTreeNode instanceof ISelection) {
268            selection = (ISelection) taskTreeNode;
269            node = taskTreeNode2;
270        }
271        else if (taskTreeNode2 instanceof ISelection) {
272            selection = (ISelection) taskTreeNode2;
273            node = taskTreeNode;
274        }
275        else {
276            return NodeEquality.UNEQUAL;
277        }
278
279        // Iterations, where one has a selection and the other one not can at most be syntactically
280        // equal but not identical
281        NodeEquality commonDenominatorForAllComparisons = NodeEquality.SYNTACTICALLY_EQUAL;
282
283        for (ITaskTreeNode child : selection.getChildren()) {
284            NodeEquality nodeEquality =
285                  callRuleManager(node, child, commonDenominatorForAllComparisons);
286
287            if ((nodeEquality == null) || (nodeEquality == NodeEquality.UNEQUAL))
288            {
289                return NodeEquality.UNEQUAL;
290            }
291           
292            commonDenominatorForAllComparisons =
293                commonDenominatorForAllComparisons.getCommonDenominator(nodeEquality);
294        }
295
296        return commonDenominatorForAllComparisons;
297    }
298
299    /**
300     * <p>
301     * TODO: comment
302     * </p>
303     *
304     * @param child1
305     * @param child2
306     * @param requiredEqualityLevel
307     * @return
308     */
309    private NodeEquality callRuleManager(ITaskTreeNode child1,
310                                         ITaskTreeNode child2,
311                                         NodeEquality  requiredEqualityLevel)
312    {
313        if (requiredEqualityLevel == null) {
314            return mRuleManager.compare(child1, child2);
315        }
316        else if (mRuleManager.areAtLeastEqual(child1, child2, requiredEqualityLevel)) {
317            return requiredEqualityLevel;
318        }
319        else {
320            return NodeEquality.UNEQUAL;
321        }
322    }
323}
Note: See TracBrowser for help on using the repository browser.