Skip to main content
summaryrefslogtreecommitdiffstats
blob: c1772b4eca1ddceceba8d2b54078dd67e6b553bd (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/**
 * 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 e) {
			// Swallow : we'll create a default engine instead.
		} catch (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;
	}
}

Back to the top