| /** |
| * Copyright (c) 2012, 2014 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.tests.framework.junit.internal; |
| |
| import java.lang.reflect.Constructor; |
| import java.util.List; |
| |
| import org.eclipse.emf.common.notify.Notifier; |
| import org.eclipse.emf.common.util.BasicMonitor; |
| import org.eclipse.emf.compare.Comparison; |
| 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.IMatchEngine; |
| import org.eclipse.emf.compare.match.eobject.EcoreWeightProvider; |
| import org.eclipse.emf.compare.match.eobject.EditionDistance; |
| import org.eclipse.emf.compare.match.eobject.IEObjectMatcher; |
| import org.eclipse.emf.compare.match.eobject.IdentifierEObjectMatcher; |
| import org.eclipse.emf.compare.match.eobject.ProximityEObjectMatcher; |
| import org.eclipse.emf.compare.scope.DefaultComparisonScope; |
| import org.eclipse.emf.compare.scope.IComparisonScope; |
| import org.eclipse.emf.compare.tests.framework.NotifierTuple; |
| import org.eclipse.emf.compare.tests.framework.junit.annotation.MatchTest; |
| import org.junit.runners.model.FrameworkMethod; |
| import org.junit.runners.model.Statement; |
| |
| /** |
| * This implementation of a {@link Statement} allows us to call methods annotated with {@link MatchTest} on |
| * the result of a Matching process. |
| * |
| * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a> |
| */ |
| public class MatchStatement extends Statement { |
| /** Target of the test. */ |
| private final Object testObject; |
| |
| /** |
| * The statement that should be executed to retrieve the {@link NotifierTuple} we are to match. |
| */ |
| private final ResultStatement<NotifierTuple> tupleStatement; |
| |
| /** The methods to call before the match, if any. */ |
| private final List<FrameworkMethod> beforeTest; |
| |
| /** The actual test method. */ |
| private final FrameworkMethod test; |
| |
| /** |
| * Instantiates our statement given its target object and tuple as well as the befores and test methods. |
| * |
| * @param testObject |
| * Target of the test. |
| * @param tupleStatement |
| * The statement that should be executed to retrieve the {@link NotifierTuple} we are to match. |
| * @param beforeTest |
| * If there were any method to call before launching the match, this will contain them. |
| * @param test |
| * The actual test method. |
| */ |
| public MatchStatement(Object testObject, ResultStatement<NotifierTuple> tupleStatement, |
| List<FrameworkMethod> beforeTest, FrameworkMethod test) { |
| this.testObject = testObject; |
| this.tupleStatement = tupleStatement; |
| this.beforeTest = beforeTest; |
| this.test = test; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.junit.runners.model.Statement#evaluate() |
| */ |
| @Override |
| public void evaluate() throws Throwable { |
| tupleStatement.evaluate(); |
| final NotifierTuple tuple = tupleStatement.getResult(); |
| |
| for (FrameworkMethod before : beforeTest) { |
| before.invokeExplosively(testObject, tuple); |
| } |
| |
| final MatchTest annotation = test.getAnnotation(MatchTest.class); |
| final IMatchEngine engine = createMatchEngine(annotation); |
| final IComparisonScope scope = createComparisonScope(tuple, annotation); |
| final Comparison comparison = engine.match(scope, new BasicMonitor()); |
| |
| test.invokeExplosively(testObject, scope, comparison); |
| } |
| |
| /** |
| * Creates the match engine specified by the given annotation if it has a public no-arg constructor, use |
| * the {@link DefaultMatchEngine default} otherwise. |
| * |
| * @param annotation |
| * The annotation on which is defined the match engine we are to use. |
| * @return An instance of the specified match engine if it has a public no-arg constructor; an instance of |
| * the {@link DefaultMatchEngine} otherwise. |
| */ |
| private static IMatchEngine createMatchEngine(MatchTest annotation) { |
| final Class<? extends IMatchEngine> engineClass = annotation.matchEngine(); |
| |
| IMatchEngine engine = null; |
| try { |
| engine = engineClass.newInstance(); |
| } catch (InstantiationException | IllegalAccessException e) { |
| // Swallow : we'll create a default engine instead. |
| } |
| if (engine == null) { |
| final IEObjectMatcher contentMatcher = new ProximityEObjectMatcher( |
| EditionDistance.builder().weightProvider(new EcoreWeightProvider()).build()); |
| final IEObjectMatcher matcher = new IdentifierEObjectMatcher(contentMatcher); |
| engine = new DefaultMatchEngine(matcher, |
| new DefaultComparisonFactory(new DefaultEqualityHelperFactory())); |
| } |
| return engine; |
| } |
| |
| /** |
| * Creates the comparison scope specified by the given annotation if it has a public constructor taking |
| * three {@link Notifier}s as parameters. We'll return an instance of the {@link DefaultComparisonScope} |
| * otherwise. |
| * |
| * @param tuple |
| * The tuple for which we need a comparison scope. |
| * @param annotation |
| * The annotation on which is specified the desired scope's class. |
| * @return An instance of the specified comparison scope it it has the expected constructor, an instance |
| * of the {@link DefaultComparisonScope} otherwise. |
| */ |
| private static IComparisonScope createComparisonScope(NotifierTuple tuple, MatchTest annotation) { |
| final Class<? extends IComparisonScope> scopeClass = annotation.scope(); |
| |
| IComparisonScope scope = null; |
| try { |
| final Constructor<? extends IComparisonScope> constructor = scopeClass |
| .getConstructor(Notifier.class, Notifier.class, Notifier.class); |
| scope = constructor.newInstance(tuple.getLeft(), tuple.getRight(), tuple.getOrigin()); |
| // CHECKSTYLE:OFF invoking a constructor requires 7 catches. Since |
| // we're swallowing all exceptions, we simply catch everything. |
| } catch (Exception e) { |
| // CHECKSTYLE:ON |
| // Swallow : we'll create a default engine instead. |
| } |
| if (scope == null) { |
| scope = new DefaultComparisonScope(tuple.getLeft(), tuple.getRight(), tuple.getOrigin()); |
| } |
| return scope; |
| } |
| } |