source: branches/ralph/src/main/java/de/ugoe/cs/autoquest/tasktrees/temporalrelation/TaskInstanceComparator.java @ 1645

Last change on this file since 1645 was 1401, checked in by pharms, 10 years ago
File size: 9.4 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.temporalrelation;
16
17import java.io.IOException;
18import java.io.ObjectInputStream;
19import java.util.HashMap;
20
21import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEquality;
22import de.ugoe.cs.autoquest.tasktrees.taskequality.TaskEqualityRuleManager;
23import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask;
24import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance;
25import de.ugoe.cs.autoquest.usageprofiles.SymbolComparator;
26
27/**
28 * <p>
29 * implementation of a symbol comparator for task instances. Internally, it uses comparison buffers
30 * to prevent comparing two tasks or task instances several times. It internally instantiates
31 * comparers being the implementation strategy of the comparisons required for a specific level
32 * of task equality. The comparers internally use the {@link TaskEqualityRuleManager} for
33 * performing comparisons.
34 * </p>
35 */
36public class TaskInstanceComparator implements SymbolComparator<ITaskInstance> {
37   
38    /**  */
39    private static final long serialVersionUID = 1L;
40   
41    /**
42     * the maximum size of the internal buffer used for storing comparison results
43     */
44    private static final int MAX_BUFFER_SIZE = 2 * 1024 * 1024;
45
46    /**
47     * the considered level of task equality
48     */
49    private TaskEquality minimalTaskEquality;
50
51    /**
52     * the comparer used internally for comparing two tasks
53     */
54    private transient Comparer comparer;
55
56    /**
57     * the comparer used for comparing two tasks on the lexical level
58     */
59    private transient Comparer lexicalComparer;
60
61    /**
62     * internal buffer used for storing comparison results
63     */
64    private transient HashMap<Long, Boolean> equalityBuffer = new HashMap<Long, Boolean>();
65
66    /**
67     * internal buffer used for storing comparison results only for lexical comparisons
68     */
69    private transient HashMap<Long, Boolean> lexicalEqualityBuffer;
70
71    /**
72     * <p>
73     * initializes the comparator with a considered task equality level
74     * </p>
75     *
76     * @param minimalTaskEquality the considered task equality level
77     */
78    public TaskInstanceComparator(TaskEquality minimalTaskEquality) {
79        this.minimalTaskEquality = minimalTaskEquality;
80        init();
81    }
82
83    /* (non-Javadoc)
84     * @see SymbolComparator#equals(Object, Object)
85     */
86    @Override
87    public boolean equals(ITaskInstance taskInstance1, ITaskInstance taskInstance2) {
88        return equals(taskInstance1.getTask(), taskInstance2.getTask());
89    }       
90
91    /**
92     * <p>
93     * returns true, if this comparator considers the provided tasks as equal, false else
94     * </p>
95     *
96     * @param task1 the first task to compare
97     * @param task2 the second task to compare
98     *
99     * @return as described
100     */
101    public boolean equals(ITask task1, ITask task2) {
102        Boolean result;
103       
104        if (task1 != task2) {
105            //if ((task1 instanceof IEventTask) && (task2 instanceof IEventTask)) {
106                long key = ((long) System.identityHashCode(task1)) << 32;
107                key += System.identityHashCode(task2);
108           
109                result = equalityBuffer.get(key);
110           
111                if (result == null) {
112                    result = comparer.compare(task1, task2);
113                   
114                    if (equalityBuffer.size() < MAX_BUFFER_SIZE) {
115                        equalityBuffer.put(key, result);
116                    }
117                }
118            /*}
119            else {
120                result = false;
121            }*/
122        }
123        else {
124            result = true;
125        }
126       
127        return result;
128    }
129
130    /**
131     * <p>
132     * returns true, if this comparator considers the provided tasks as lexically equal, false else
133     * </p>
134     *
135     * @param task1 the first task to compare
136     * @param task2 the second task to compare
137     *
138     * @return as described
139     */
140    public boolean areLexicallyEqual(ITask task1, ITask task2) {
141        Boolean result;
142       
143        if (task1 != task2) {
144            long key = ((long) System.identityHashCode(task1)) << 32;
145            key += System.identityHashCode(task2);
146           
147            result = lexicalEqualityBuffer.get(key);
148           
149            if (result == null) {
150                result = lexicalComparer.compare(task1, task2);
151                if (equalityBuffer.size() < MAX_BUFFER_SIZE) {
152                    lexicalEqualityBuffer.put(key, result);
153                }
154            }
155        }
156        else {
157            result = true;
158        }
159       
160        return result;
161    }
162   
163    /**
164     * <p>
165     * can be called externally to clear the internal comparison buffers
166     * </p>
167     */
168    public void clearBuffers() {
169        equalityBuffer.clear();
170        init();
171    }
172   
173    /**
174     * <p>
175     * initializes the comparator with comparers depending on the different comparison levels as
176     * well as with the required comparison buffers. Comparers and buffers for lexical comparison
177     * may be reused if the considered equality level is also lexical.
178     * </p>
179     */
180    private void init() {
181        if (minimalTaskEquality == TaskEquality.LEXICALLY_EQUAL) {
182            comparer = new LexicalComparer();
183        }
184        else if (minimalTaskEquality == TaskEquality.SYNTACTICALLY_EQUAL) {
185            comparer = new SyntacticalComparer();
186        }
187        else if (minimalTaskEquality == TaskEquality.SEMANTICALLY_EQUAL) {
188            comparer = new SemanticalComparer();
189        }
190        else {
191            comparer = new DefaultComparer(this.minimalTaskEquality);
192        }
193       
194        if (minimalTaskEquality == TaskEquality.LEXICALLY_EQUAL) {
195            lexicalComparer = comparer;
196            lexicalEqualityBuffer = equalityBuffer;
197        }
198        else {
199            lexicalComparer = new LexicalComparer();
200            lexicalEqualityBuffer = new HashMap<Long, Boolean>();
201        }
202    }
203   
204    /**
205     * <p>
206     * deserialize this object and reinitialize the buffers
207     * </p>
208     */
209    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
210        in.defaultReadObject();
211        init();
212    }
213
214
215    /**
216     * <p>
217     * interface for internally used comparers containing only a compare method
218     * </p>
219     */
220    private static interface Comparer {
221       
222        /**
223         * <p>
224         * returns true, if this comparator considers the provided tasks as equal, false else
225         * </p>
226         *
227         * @param task1 the first task to compare
228         * @param task2 the second task to compare
229         *
230         * @return as described
231         */
232        boolean compare(ITask task1, ITask task2);
233    }
234
235    /**
236     * <p>
237     * comparer that performs comparisons only on the lexical level
238     * </p>
239     */
240    private static class LexicalComparer implements Comparer {
241       
242        /* (non-Javadoc)
243         * @see Comparer#compare(ITask, ITask)
244         */
245        public boolean compare(ITask task1, ITask task2) {
246            return TaskEqualityRuleManager.getInstance().areLexicallyEqual(task1, task2);
247        }
248    }
249
250    /**
251     * <p>
252     * comparer that performs comparisons only on the syntactical level
253     * </p>
254     *
255     */
256    private static class SyntacticalComparer implements Comparer {
257       
258        /* (non-Javadoc)
259         * @see Comparer#compare(ITask, ITask)
260         */
261        public boolean compare(ITask task1, ITask task2) {
262            return TaskEqualityRuleManager.getInstance().areSyntacticallyEqual(task1, task2);
263        }
264    }
265
266    /**
267     * <p>
268     * comparer that performs comparisons only on the semantical level
269     * </p>
270     */
271    private static class SemanticalComparer implements Comparer {
272       
273        /* (non-Javadoc)
274         * @see Comparer#compare(ITask, ITask)
275         */
276        public boolean compare(ITask task1, ITask task2) {
277            return TaskEqualityRuleManager.getInstance().areSemanticallyEqual(task1, task2);
278        }
279    }
280
281    /**
282     * <p>
283     * comparer that performs comparisons only on the provided level
284     * </p>
285     */
286    private static class DefaultComparer implements Comparer {
287       
288        /**
289         * <p>
290         * the minimal task equality considered by this comparer
291         * </p>
292         */
293        private TaskEquality minimalTaskEquality;
294       
295        /**
296         * <p>
297         * initializes this comparer with the task equality to be considered
298         * </p>
299         */
300        public DefaultComparer(TaskEquality minimalTaskEquality) {
301           this.minimalTaskEquality = minimalTaskEquality;
302        }
303       
304        /* (non-Javadoc)
305         * @see Comparer#compare(ITask, ITask)
306         */
307        public boolean compare(ITask task1, ITask task2) {
308            return TaskEqualityRuleManager.getInstance().areAtLeastEqual
309                (task1, task2, minimalTaskEquality);
310        }
311    }
312
313}
Note: See TracBrowser for help on using the repository browser.