// 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 {
/**
*
* 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);
}
}
}