// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.tasktrees.taskequality; import java.util.HashMap; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITask; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskInstance; import de.ugoe.cs.autoquest.usageprofiles.SymbolComparator; import de.ugoe.cs.util.StopWatch; /** *

* this class is a very fast implementation for the {@link SymbolComparator} interface to be * applied on task instances. To be efficient, it caches information about the equality of tasks. * Only, if it does not know a specific equality yet, it call the task equality rule manager * to compare two tasks. Otherwise, it returns the known equality. *

* * TODO improve documentation and remove stop watch stuff. * * @author Patrick Harms */ public class TaskComparator implements SymbolComparator { /** */ private static final long serialVersionUID = 1L; /** *

* the task equality manager needed for comparing tasks with each other *

*/ private TaskEqualityRuleManager taskEqualityRuleManager; /** *

* the minimal task equality two identified sublists need to have to consider them as equal *

*/ private TaskEquality minimalNodeEquality; /** *

* the internally used comparer for tasks. *

*/ private Comparer comparer; /** *

* the internally used comparer for tasks considering only lexical equality. *

*/ private Comparer lexicalComparer; /** */ private StopWatch stopWatch = new StopWatch(); /** */ private HashMap equalityBuffer = new HashMap(); /** */ private HashMap lexicalEqualityBuffer; /** * */ public TaskComparator(TaskEqualityRuleManager taskEqualityRuleManager, TaskEquality minimalNodeEquality) { super(); this.taskEqualityRuleManager = taskEqualityRuleManager; this.minimalNodeEquality = minimalNodeEquality; if (minimalNodeEquality == TaskEquality.LEXICALLY_EQUAL) { comparer = new LexicalComparer(); } else if (minimalNodeEquality == TaskEquality.SYNTACTICALLY_EQUAL) { comparer = new SyntacticalComparer(); } else if (minimalNodeEquality == TaskEquality.SEMANTICALLY_EQUAL) { comparer = new SemanticalComparer(); } else { comparer = new DefaultComparer(); } if (minimalNodeEquality == TaskEquality.LEXICALLY_EQUAL) { lexicalComparer = comparer; lexicalEqualityBuffer = equalityBuffer; } else { lexicalComparer = new LexicalComparer(); lexicalEqualityBuffer = new HashMap(); } } /* (non-Javadoc) * @see de.ugoe.cs.autoquest.tasktrees.temporalrelation.SymbolComparator#equals(java.lang.Object, java.lang.Object) */ @Override public boolean equals(ITaskInstance taskInstance1, ITaskInstance taskInstance2) { return equals(taskInstance1.getTask(), taskInstance2.getTask()); } /** * */ public boolean equals(ITask task1, ITask task2) { //String id = "compare " + taskInstance1.getClass().getSimpleName() + " " + // taskInstance2.getClass().getSimpleName(); //String id = "compare"; //stopWatch.start(id); Boolean result; if (task1 != task2) { long key = ((long) System.identityHashCode(task1)) << 32; key += System.identityHashCode(task2); result = equalityBuffer.get(key); if (result == null) { result = comparer.compare(task1, task2); equalityBuffer.put(key, result); } } else { result = true; } //stopWatch.stop(id); /*boolean result2 = taskEqualityRuleManager.areAtLeastEqual(symbol1, symbol2, minimalNodeEquality); if (result != result2) { throw new IllegalStateException("implementation error"); }*/ return result; } /** * */ public boolean haveLexicallyEqualTasks(ITaskInstance taskInstance1, ITaskInstance taskInstance2) { return areLexicallyEqual(taskInstance1.getTask(), taskInstance2.getTask()); } /** * */ public boolean areLexicallyEqual(ITask task1, ITask task2) { Boolean result; if (task1 != task2) { long key = ((long) System.identityHashCode(task1)) << 32; key += System.identityHashCode(task2); result = lexicalEqualityBuffer.get(key); if (result == null) { result = lexicalComparer.compare(task1, task2); lexicalEqualityBuffer.put(key, result); } } else { result = true; } return result; } /** * */ StopWatch getStopWatch() { return stopWatch; } /** * */ TaskEquality getConsideredNodeEquality() { return minimalNodeEquality; } /** * */ private interface Comparer { /** * */ boolean compare(ITask task1, ITask task2); } /** * */ private class LexicalComparer implements Comparer { /** * */ public boolean compare(ITask task1, ITask task2) { return taskEqualityRuleManager.areLexicallyEqual(task1, task2); } } /** * */ private class SyntacticalComparer implements Comparer { /** * */ public boolean compare(ITask task1, ITask task2) { return taskEqualityRuleManager.areSyntacticallyEqual(task1, task2); } } /** * */ private class SemanticalComparer implements Comparer { /** * */ public boolean compare(ITask task1, ITask task2) { return taskEqualityRuleManager.areSemanticallyEqual(task1, task2); } } /** * */ private class DefaultComparer implements Comparer { /** * */ public boolean compare(ITask task1, ITask task2) { return taskEqualityRuleManager.areAtLeastEqual(task1, task2, minimalNodeEquality); } } }