/******************************************************************************* * 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.mylyn.docs.intent.compare.utils; import com.google.common.base.Predicates; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.EMFCompare; import org.eclipse.emf.compare.EMFCompare.Builder; import org.eclipse.emf.compare.diff.DefaultDiffEngine; import org.eclipse.emf.compare.diff.DiffBuilder; import org.eclipse.emf.compare.diff.FeatureFilter; import org.eclipse.emf.compare.match.DefaultComparisonFactory; import org.eclipse.emf.compare.match.DefaultEqualityHelperFactory; import org.eclipse.emf.compare.match.DefaultMatchEngine; import org.eclipse.emf.compare.match.IComparisonFactory; import org.eclipse.emf.compare.match.IMatchEngine; import org.eclipse.emf.compare.match.IMatchEngine.Factory.Registry; import org.eclipse.emf.compare.match.eobject.IEObjectMatcher; import org.eclipse.emf.compare.match.eobject.ProximityEObjectMatcher; import org.eclipse.emf.compare.match.impl.MatchEngineFactoryImpl; import org.eclipse.emf.compare.match.impl.MatchEngineFactoryRegistryImpl; import org.eclipse.emf.compare.scope.IComparisonScope; import org.eclipse.emf.compare.utils.UseIdentifiers; import org.eclipse.mylyn.docs.intent.compare.match.EditionDistance; import org.eclipse.mylyn.docs.intent.compare.scope.IntentComparisonScope; import org.eclipse.mylyn.docs.intent.core.compiler.CompilationStatus; import org.eclipse.mylyn.docs.intent.core.compiler.SynchronizerCompilationStatus; /** * Utilities for EMF Compare use. * * @author <a href="mailto:william.piers@obeo.fr">William Piers</a> */ public final class EMFCompareUtils { /** * A {@link Registry} always returning a Match engine ignoring identifiers. */ private static Registry neverUsingIdentifiersMatchEngine; /** * Prevents instantiation. */ private EMFCompareUtils() { } /** * Returns the differences between the left element and the right element. Comparison customization: * <ul> * <li>Ignore XMI Ids</li> * <li>Resolve proxies</li> * </ul> * * @param left * the left element * @param right * the right element * @return the differences between the left element and the right element */ public static Comparison compare(Notifier left, Notifier right) { IntentComparisonScope scope = new IntentComparisonScope(left, right); Builder builder = EMFCompare.builder(); builder.setMatchEngineFactoryRegistry(getMatchEngineNeverUsingIdentifiers()); return builder.build().compare(scope); } /** * Returns the differences between the left element and the right element. Comparison customization: * <ul> * <li>Ignore XMI Ids</li> * <li>Resolve proxies</li> * <li>Intent specific match engine</li> * </ul> * * @param left * the left element * @param right * the right element * @return the differences between the left element and the right element */ public static Comparison compareDocuments(Notifier left, Notifier right) { // Step 1: create comparison scope IntentComparisonScope scope = new IntentComparisonScope(left, right); scope.setEObjectContentFilter(Predicates.not(Predicates.or( Predicates.instanceOf(CompilationStatus.class), Predicates.instanceOf(SynchronizerCompilationStatus.class)))); // Step 2: initialize match & diff engine Registry matchEngine = getIntentDocumentMatchEngine(left, right); DefaultDiffEngine diffEngine = new DefaultDiffEngine(new DiffBuilder()) { @Override protected FeatureFilter createFeatureFilter() { return new IntentFeatureFilter(); } }; // Step 3: launch comparison Builder builder = EMFCompare.builder(); builder.setDiffEngine(diffEngine); builder.setMatchEngineFactoryRegistry(matchEngine); return builder.build().compare(scope); } /** * Returns a {@link Registry} always returning a Match engine ignoring identifiers. * * @return a {@link Registry} always returning a Match engine ignoring identifiers */ public static Registry getMatchEngineNeverUsingIdentifiers() { if (neverUsingIdentifiersMatchEngine == null) { IMatchEngine matchEngine = DefaultMatchEngine.create(UseIdentifiers.NEVER); neverUsingIdentifiersMatchEngine = createMatchEngineRegistryFromMatchEngine(matchEngine); } return neverUsingIdentifiersMatchEngine; } /** * Returns a {@link Registry} always returning a Match engine allowing to compare 2 intent documents with * the given left and right roots. * * @param left * the left root of the Intent element (parsed from current editor) * @param right * the right root of the Intent element (from Intent repository) * @return a {@link Registry} always returning a Match engine allowing to compare 2 intent documents with * the given left and right roots */ private static Registry getIntentDocumentMatchEngine(Notifier left, Notifier right) { IEObjectMatcher matcher = new ProximityEObjectMatcher(EditionDistance.builder(left, right).build()); final IComparisonFactory comparisonFactory = new DefaultComparisonFactory( new DefaultEqualityHelperFactory()); IMatchEngine matchEngine = new DefaultMatchEngine(matcher, comparisonFactory); return createMatchEngineRegistryFromMatchEngine(matchEngine); } /** * Returns a {@link Registry} always returning the given {@link IMatchEngine}. * * @param matchEngineToUse * the {@link IMatchEngine} to return * @return a {@link Registry} always returning the given {@link IMatchEngine} */ private static Registry createMatchEngineRegistryFromMatchEngine(final IMatchEngine matchEngineToUse) { Registry matchEngineFactoryRegistry = new MatchEngineFactoryRegistryImpl(); MatchEngineFactoryImpl matchEngineFactory = new MatchEngineFactoryImpl() { @Override public IMatchEngine getMatchEngine() { return matchEngineToUse; } @Override public boolean isMatchEngineFactoryFor(IComparisonScope scope) { return true; } }; matchEngineFactoryRegistry.add(matchEngineFactory); return matchEngineFactoryRegistry; } }