From fcf2ff0e2d9f8b8e3f28d7ea64f19a114e026000 Mon Sep 17 00:00:00 2001
From: Sebastian Krings <sebastian@krin.gs>
Date: Tue, 27 Jan 2015 10:47:46 +0100
Subject: [PATCH] try to integrate a custom match engine for eventb

---
 .../eventb/texttools/PersistenceHelper.java   |  19 ++-
 .../texttools/merge/EventBMatchEngine.java    |  20 ++++
 .../merge/EventBResourceMatcher.java          | 109 ++++++++++++++++++
 3 files changed, 144 insertions(+), 4 deletions(-)
 create mode 100644 org.eventb.texttools/src/org/eventb/texttools/merge/EventBMatchEngine.java
 create mode 100644 org.eventb.texttools/src/org/eventb/texttools/merge/EventBResourceMatcher.java

diff --git a/org.eventb.texttools/src/org/eventb/texttools/PersistenceHelper.java b/org.eventb.texttools/src/org/eventb/texttools/PersistenceHelper.java
index 41dc656..2b8cf28 100644
--- a/org.eventb.texttools/src/org/eventb/texttools/PersistenceHelper.java
+++ b/org.eventb.texttools/src/org/eventb/texttools/PersistenceHelper.java
@@ -44,7 +44,7 @@ import org.eventb.emf.core.AttributeType;
 import org.eventb.emf.core.CoreFactory;
 import org.eventb.emf.core.EventBElement;
 import org.eventb.emf.core.EventBNamedCommentedComponentElement;
-//import org.eventb.texttools.merge.ModelMerge;
+import org.eventb.texttools.merge.EventBMatchEngine;
 import org.eventb.texttools.prettyprint.PrettyPrinter;
 
 import de.be4.eventb.core.parser.BException;
@@ -54,6 +54,8 @@ import de.be4.eventb.core.parser.node.AMachineParseUnit;
 import de.be4.eventb.core.parser.node.PParseUnit;
 import de.be4.eventb.core.parser.node.Start;
 
+//import org.eventb.texttools.merge.ModelMerge;
+
 public class PersistenceHelper {
 
 	public static final Boolean DEBUG = false;
@@ -160,12 +162,21 @@ public class PersistenceHelper {
 		try {
 			long time0 = System.currentTimeMillis();
 
-			IEObjectMatcher matcher = DefaultMatchEngine
-					.createDefaultEObjectMatcher(UseIdentifiers.NEVER);
 			IComparisonFactory comparisonFactory = new DefaultComparisonFactory(
 					new DefaultEqualityHelperFactory());
-			IMatchEngine.Factory matchEngineFactory = new MatchEngineFactoryImpl(
+
+			IEObjectMatcher matcher = DefaultMatchEngine
+					.createDefaultEObjectMatcher(UseIdentifiers.NEVER);
+
+			final IMatchEngine eventBMatchEngine = new EventBMatchEngine(
 					matcher, comparisonFactory);
+
+			IMatchEngine.Factory matchEngineFactory = new MatchEngineFactoryImpl() {
+				@Override
+				public IMatchEngine getMatchEngine() {
+					return eventBMatchEngine;
+				}
+			};
 			matchEngineFactory.setRanking(20);
 			IMatchEngine.Factory.Registry matchEngineRegistry = new MatchEngineFactoryRegistryImpl();
 			matchEngineRegistry.add(matchEngineFactory);
diff --git a/org.eventb.texttools/src/org/eventb/texttools/merge/EventBMatchEngine.java b/org.eventb.texttools/src/org/eventb/texttools/merge/EventBMatchEngine.java
new file mode 100644
index 0000000..e34ef81
--- /dev/null
+++ b/org.eventb.texttools/src/org/eventb/texttools/merge/EventBMatchEngine.java
@@ -0,0 +1,20 @@
+package org.eventb.texttools.merge;
+
+import org.eclipse.emf.compare.match.DefaultMatchEngine;
+import org.eclipse.emf.compare.match.IComparisonFactory;
+import org.eclipse.emf.compare.match.eobject.IEObjectMatcher;
+import org.eclipse.emf.compare.match.resource.IResourceMatcher;
+
+public class EventBMatchEngine extends DefaultMatchEngine {
+
+	public EventBMatchEngine(IEObjectMatcher matcher,
+			IComparisonFactory comparisonFactory) {
+		super(matcher, comparisonFactory);
+	}
+
+	@Override
+	protected IResourceMatcher createResourceMatcher() {
+		return new EventBResourceMatcher();
+	}
+
+}
diff --git a/org.eventb.texttools/src/org/eventb/texttools/merge/EventBResourceMatcher.java b/org.eventb.texttools/src/org/eventb/texttools/merge/EventBResourceMatcher.java
new file mode 100644
index 0000000..d7467ee
--- /dev/null
+++ b/org.eventb.texttools/src/org/eventb/texttools/merge/EventBResourceMatcher.java
@@ -0,0 +1,109 @@
+package org.eventb.texttools.merge;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.emf.compare.MatchResource;
+import org.eclipse.emf.compare.match.resource.StrategyResourceMatcher;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eventb.emf.core.EventBNamed;
+import org.eventb.emf.core.machine.Event;
+import org.eventb.emf.core.machine.Variant;
+
+import com.google.common.collect.Lists;
+
+public class EventBResourceMatcher extends StrategyResourceMatcher {
+	@Override
+	public Iterable<MatchResource> createMappings(
+			Iterator<? extends Resource> leftResources,
+			Iterator<? extends Resource> rightResources,
+			Iterator<? extends Resource> originResources) {
+		final List<MatchResource> mappings = Lists.newArrayList();
+
+		final List<? extends Resource> leftCopy = Lists
+				.newArrayList(leftResources);
+		final List<? extends Resource> rightCopy = Lists
+				.newArrayList(rightResources);
+		final List<? extends Resource> originCopy = Lists
+				.newArrayList(originResources);
+
+		// only two way merge in camille?!
+		assert (originCopy.isEmpty());
+
+		for (Resource left : leftCopy) {
+			Resource right = findMatch(left, rightCopy);
+			leftCopy.remove(left);
+			rightCopy.remove(right);
+			mappings.add(createMatchResource(left, right, null));
+		}
+
+		// further matches (including the left-only / right-only ones are found
+		// by the default strategies
+		Iterable<MatchResource> superMappings = super.createMappings(
+				leftCopy.iterator(), rightCopy.iterator(),
+				originCopy.iterator());
+
+		for (MatchResource matchResource : superMappings) {
+			mappings.add(matchResource);
+		}
+
+		return mappings;
+	}
+
+	protected Resource findMatch(Resource reference,
+			List<? extends Resource> rightCopy) {
+		for (Resource candidate : rightCopy) {
+			if (matching(reference, candidate)) {
+				rightCopy.remove(candidate);
+				return candidate;
+			}
+		}
+		return null;
+	}
+
+	// this logic was previously found in isSimiliar of EventBMatchEngine
+	private boolean matching(Resource reference, Resource candidate) {
+		/*
+		 * Only one variant may exist in a model, so two variants are a match
+		 */
+		// FIXME: type of reference / resource
+		// if (areVariants(reference, candidate)) {
+		// return true;
+		// }
+
+		/*
+		 * Improve matching for event b named objects with same name
+		 */
+		if (reference instanceof EventBNamed
+				&& candidate instanceof EventBNamed) {
+			Event r = (Event) reference;
+			Event c = (Event) reference;
+
+			if (r.getName().equals(c.getName())) {
+				return true;
+			}
+		}
+
+		// false => the default behaviour of StrategyResourceMatcher will be
+		// tried afterwards
+		return false;
+	}
+
+	private boolean areSameType(final EObject obj1, final EObject obj2) {
+		return obj1 != null && obj2 != null
+				&& obj1.eClass().equals(obj2.eClass());
+	}
+
+	/**
+	 * Test if both given {@link EObject}s are of type {@link Variant}, includes
+	 * <code>null</code> check.
+	 * 
+	 * @param obj1
+	 * @param obj2
+	 * @return
+	 */
+	private boolean areVariants(final EObject obj1, final EObject obj2) {
+		return areSameType(obj1, obj2) && obj2 instanceof Variant;
+	}
+}
-- 
GitLab