blob: e62745b67553769ed27f0ee457822089f0d4d0a3 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2014 Obeo and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.compare.match.eobject;
import java.util.Map;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.match.eobject.ProximityEObjectMatcher.DistanceFunction;
import org.eclipse.emf.compare.match.eobject.internal.AccessBasedLRUCache;
import org.eclipse.emf.ecore.EObject;
/**
* This class wraps a DistanceFunction and cache its result. Any call to distance(a,b) will be cached and the
* same value will be returned to distance(b,a).
*
* @author <a href="mailto:cedric.brun@obeo.fr">Cedric Brun</a>
* @since 3.1
*/
public class CachingDistance implements DistanceFunction {
/**
* The wrapped function.
*/
private DistanceFunction wrapped;
/**
* The cache keeping the previous results.
*/
private Map<Pair, Double> distanceCache;
/**
* Create a new caching distance.
*
* @param wrapped
* actual distance function to cache results from.
*/
public CachingDistance(DistanceFunction wrapped) {
this.wrapped = wrapped;
distanceCache = new AccessBasedLRUCache<Pair, Double>(10000, 1000, .75F);
}
/**
* {@inheritDoc}
*/
public double distance(Comparison inProgress, EObject a, EObject b) {
Pair key = new Pair(a, b);
Double previousResult = distanceCache.get(key);
if (previousResult == null) {
double dist = wrapped.distance(inProgress, a, b);
distanceCache.put(key, Double.valueOf(dist));
// cache it
return dist;
}
return previousResult.doubleValue();
}
/**
* {@inheritDoc}
*/
public boolean areIdentic(Comparison inProgress, EObject a, EObject b) {
return wrapped.areIdentic(inProgress, a, b);
}
/**
* A class used as a key for two EObjects. Pair(a,b) and Pair(b,a) should be equals and have the same
* hashcodes
*/
class Pair {
// CHECKSTYLE:OFF
EObject a;
EObject b;
public Pair(EObject a, EObject b) {
super();
this.a = a;
this.b = b;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
int first = a.hashCode();
int second = b.hashCode();
if (first > second) {
int tmp = first;
first = second;
second = tmp;
}
result = prime * result + first;
result = prime * result + second;
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Pair other = (Pair)obj;
if (!getOuterType().equals(other.getOuterType())) {
return false;
}
return (a == other.a && b == other.b) || (b == other.a && a == other.b);
}
private CachingDistance getOuterType() {
return CachingDistance.this;
}
}
// CHECKSTYLE:ON
}