Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/internal/CachingDistance.java137
1 files changed, 137 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/internal/CachingDistance.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/internal/CachingDistance.java
new file mode 100644
index 000000000..5774c5f6b
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/match/eobject/internal/CachingDistance.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Obeo.
+ * 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.internal;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.match.eobject.ProximityEObjectMatcher.DistanceFunction;
+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>
+ */
+public class CachingDistance implements DistanceFunction {
+ /**
+ * The maximum number of entries kept in the cache.
+ */
+ private static final int MAX_CACHE_SIZE = 100000;
+
+ /**
+ * The wrapped function.
+ */
+ private DistanceFunction wrapped;
+
+ /**
+ * The cache keeping the previous results.
+ */
+ private Cache<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 = CacheBuilder.newBuilder().maximumSize(MAX_CACHE_SIZE).build();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public double distance(Comparison inProgress, EObject a, EObject b) {
+ Pair key = new Pair(a, b);
+ Double previousResult = distanceCache.getIfPresent(key);
+ if (previousResult == null) {
+ double dist = wrapped.distance(inProgress, a, b);
+ distanceCache.put(key, 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
+
+}

Back to the top