Skip to main content
summaryrefslogtreecommitdiffstats
blob: db03a30b1b451e5c2db78602886a0626e4c145e4 (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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
/*******************************************************************************
 * 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;

import static com.google.common.base.Preconditions.checkNotNull;

import java.util.List;

import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.BasicMonitor;
import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.compare.conflict.DefaultConflictDetector;
import org.eclipse.emf.compare.conflict.IConflictDetector;
import org.eclipse.emf.compare.diff.DefaultDiffEngine;
import org.eclipse.emf.compare.diff.DiffBuilder;
import org.eclipse.emf.compare.diff.IDiffEngine;
import org.eclipse.emf.compare.equi.DefaultEquiEngine;
import org.eclipse.emf.compare.equi.IEquiEngine;
import org.eclipse.emf.compare.extension.IPostProcessor;
import org.eclipse.emf.compare.extension.PostProcessorRegistry;
import org.eclipse.emf.compare.match.DefaultMatchEngine;
import org.eclipse.emf.compare.match.IMatchEngine;
import org.eclipse.emf.compare.req.DefaultReqEngine;
import org.eclipse.emf.compare.req.IReqEngine;
import org.eclipse.emf.compare.scope.DefaultComparisonScope;
import org.eclipse.emf.compare.scope.IComparisonScope;
import org.eclipse.emf.compare.utils.UseIdentifiers;

/**
 * This class serves as the main entry point of a comparison. When all that is wanted is a basic comparison of
 * two or three notifiers, a comparison using all of the default configuration can be launched through
 * <code>EMFCompare.builder().build().compare(EMFCompare.createDefaultScope(left, right, origin))</code>.
 * <p>
 * When in need of a more customized comparison, the API can be used through chained calls. For example, if
 * you need to compare two notifiers ({@code left} and {@code right}) while ignoring their identifiers, with a
 * given progress monitor (call it {@code progress}), you can do so through : <code>
 * EMFCompare.builder().setMatchEngine(DefaultMatchEngine.create(UseIdentifiers.NEVER)).build().compare(EMFCompare.createDefaultScope(left, right), new BasicMonitor())
 * </code>.
 * </p>
 * 
 * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
 */
public class EMFCompare {

	/** The IMatchEngine to use to compute comparison. */
	private final IMatchEngine matchEngine;

	/** The IDiffEngine to use to compute comparison. */
	private final IDiffEngine diffEngine;

	/** The IReqEngine to use to compute comparison. */
	private final IReqEngine reqEngine;

	/** The IEquiEngine to use to compute comparison. */
	private final IEquiEngine equiEngine;

	/** The IConflictDetector to use to compute comparison. */
	private final IConflictDetector conflictDetector;

	/** The PostProcessorRegistry to use to find an IPostProcessor. */
	private final PostProcessorRegistry postProcessorRegistry;

	/**
	 * Creates a new EMFCompare object able to compare Notifier with the help of given engines.
	 * 
	 * @param matchEngine
	 *            IMatchEngine to use to compute comparison
	 * @param diffEngine
	 *            IDiffEngine to use to compute comparison
	 * @param reqEngine
	 *            IReqEngine to use to compute comparison
	 * @param equiEngine
	 *            IEquiEngine to use to compute comparison
	 * @param conflictDetector
	 *            IConflictDetector to use to compute comparison
	 * @param postProcessorRegistry
	 *            PostProcessorRegistry to use to find an IPostProcessor
	 */
	protected EMFCompare(IMatchEngine matchEngine, IDiffEngine diffEngine, IReqEngine reqEngine,
			IEquiEngine equiEngine, IConflictDetector conflictDetector,
			PostProcessorRegistry postProcessorRegistry) {
		this.matchEngine = checkNotNull(matchEngine);
		this.diffEngine = checkNotNull(diffEngine);
		this.reqEngine = checkNotNull(reqEngine);
		this.equiEngine = checkNotNull(equiEngine);
		this.conflictDetector = conflictDetector;
		this.postProcessorRegistry = checkNotNull(postProcessorRegistry);
	}

	/**
	 * Creates a default EMF Compare Configuration.
	 * <p>
	 * This will use a basic monitor doing nothing to report progress.
	 * </p>
	 * 
	 * @return The default EMF Compare Configuration.
	 */
	@Deprecated
	public static EMFCompareConfiguration createDefaultConfiguration() {
		final Monitor monitor = new BasicMonitor();
		return new EMFCompareConfiguration(monitor, null);
	}

	/**
	 * Creates a default comparison scope given its left and right notifiers.
	 * <p>
	 * The default comparison scope covers all proper content of the given notifiers, i.e any element
	 * contained directly under that notifier.
	 * </p>
	 * 
	 * @param left
	 *            The left notifier of this scope.
	 * @param right
	 *            The right notifier of this scope.
	 * @return The newly created scope, as used as default by EMF Compare.
	 * @see DefaultComparisonScope
	 */
	public static IComparisonScope createDefaultScope(Notifier left, Notifier right) {
		return new DefaultComparisonScope(left, right, null);
	}

	/**
	 * Creates the default comparison scope given its left and right notifiers, along with the common ancestor
	 * of both.
	 * <p>
	 * The default comparison scope covers all proper content of the given notifiers, i.e any element
	 * contained directly under that notifier.
	 * </p>
	 * 
	 * @param left
	 *            The left notifier of this scope.
	 * @param right
	 *            The right notifier of this scope.
	 * @param origin
	 *            The common ancestor of {@code left} and {@code right}.
	 * @return The newly created scope, as used as default by EMF Compare.
	 * @see DefaultComparisonScope
	 */
	public static IComparisonScope createDefaultScope(Notifier left, Notifier right, Notifier origin) {
		return new DefaultComparisonScope(left, right, origin);
	}

	/**
	 * Computes and returns a new Comparison object representation the differences between Notifier in the
	 * give {@code scope}.
	 * 
	 * @param scope
	 *            the scope to compare.
	 * @return the result of the comparison.
	 */
	public Comparison compare(IComparisonScope scope) {
		return compare(scope, new BasicMonitor());
	}

	/**
	 * Launches the comparison with the given scope and reporting progress to the given {@code monitor}.
	 * 
	 * @param scope
	 *            the scope to compare.
	 * @param monitor
	 *            the monitor to report progress to.
	 * @return the result of the comparison.
	 */
	public Comparison compare(IComparisonScope scope, final Monitor monitor) {
		checkNotNull(scope);
		checkNotNull(monitor);

		final Comparison comparison = matchEngine.match(scope, monitor);

		List<IPostProcessor> postProcessors = postProcessorRegistry.getPostProcessors(scope);

		for (IPostProcessor iPostProcessor : postProcessors) {
			iPostProcessor.postMatch(comparison, monitor);
		}

		diffEngine.diff(comparison, monitor);

		for (IPostProcessor iPostProcessor : postProcessors) {
			iPostProcessor.postDiff(comparison, monitor);
		}

		reqEngine.computeRequirements(comparison, monitor);

		for (IPostProcessor iPostProcessor : postProcessors) {
			iPostProcessor.postRequirements(comparison, monitor);
		}

		equiEngine.computeEquivalences(comparison, monitor);

		for (IPostProcessor iPostProcessor : postProcessors) {
			iPostProcessor.postEquivalences(comparison, monitor);
		}

		if (comparison.isThreeWay() && conflictDetector != null) {
			conflictDetector.detect(comparison, monitor);

			for (IPostProcessor iPostProcessor : postProcessors) {
				iPostProcessor.postConflicts(comparison, monitor);
			}
		}

		for (IPostProcessor iPostProcessor : postProcessors) {
			iPostProcessor.postComparison(comparison, monitor);
		}

		return comparison;
	}

	/**
	 * Creates a new builder to configure the creation of a new EMFCompare object.
	 * 
	 * @return a new builder.
	 */
	public static Builder builder() {
		return new Builder();
	}

	/**
	 * A Builder pattern to instantiate EMFCompare objects.
	 * 
	 * @author <a href="mailto:mikael.barbero@obeo.fr">Mikael Barbero</a>
	 */
	public static class Builder {

		/** The IMatchEngine to use to compute comparison. */
		protected IMatchEngine matchEngine;

		/** The IReqEngine to use to compute comparison. */
		protected IReqEngine reqEngine;

		/** The IDiffEngine to use to compute comparison. */
		protected IDiffEngine diffEngine;

		/** The IEquiEngine to use to compute comparison. */
		protected IEquiEngine equiEngine;

		/** The IConflictDetector to use to compute conflicts. */
		protected IConflictDetector conflictDetector;

		/** The PostProcessorRegistry to use to find an IPostProcessor. */
		protected PostProcessorRegistry registry;

		/**
		 * Creates a new builder object.
		 */
		protected Builder() {
		}

		/**
		 * Sets the IMatchEngine to be used to compute Match.
		 * 
		 * @param me
		 *            the IMatchEngine to be used to compute comparison.
		 * @return this same builder to allow chained call.
		 */
		public Builder setMatchEngine(IMatchEngine me) {
			this.matchEngine = checkNotNull(me);
			return this;
		}

		/**
		 * Sets the IDiffEngine to be used to compute Diff.
		 * 
		 * @param de
		 *            the IDiffEngine to be used to compute Diff.
		 * @return this same builder to allow chained call.
		 */
		public Builder setDiffEngine(IDiffEngine de) {
			this.diffEngine = checkNotNull(de);
			return this;
		}

		/**
		 * Sets the IReqEngine to be used to compute dependencies between Diff.
		 * 
		 * @param re
		 *            the IReqEngine to be used to compute dependencies between Diff.
		 * @return this same builder to allow chained call.
		 */
		public Builder setRequirementEngine(IReqEngine re) {
			this.reqEngine = checkNotNull(re);
			return this;
		}

		/**
		 * Sets the IEquiEngine to be used to compute equivalences between Diff.
		 * 
		 * @param ee
		 *            the IEquiEngine to be used to compute equivalences between Diff
		 * @return this same builder to allow chained call.
		 */
		public Builder setEquivalenceEngine(IEquiEngine ee) {
			this.equiEngine = checkNotNull(ee);
			return this;
		}

		/**
		 * Sets the IEquiEngine to be used to compute conflicts between Diff.
		 * 
		 * @param cd
		 *            the IEquiEngine to be used to compute conflicts between Diff.
		 * @return this same builder to allow chained call.
		 */
		public Builder setConflictDetector(IConflictDetector cd) {
			this.conflictDetector = checkNotNull(cd);
			return this;
		}

		/**
		 * Sets the PostProcessor to be used to find the post processor of each comparison steps.
		 * 
		 * @param r
		 *            the PostProcessor to be used to find the post processor of each comparison steps.
		 * @return this same builder to allow chained call.
		 */
		public Builder setPostProcessorRegistry(PostProcessorRegistry r) {
			this.registry = checkNotNull(r);
			return this;
		}

		/**
		 * Instantiates and return an EMFCompare object configured with the previously given engines.
		 * 
		 * @return an EMFCompare object configured with the previously given engines
		 */
		public EMFCompare build() {
			if (matchEngine == null) {
				matchEngine = DefaultMatchEngine.create(UseIdentifiers.WHEN_AVAILABLE);
			}
			if (diffEngine == null) {
				diffEngine = new DefaultDiffEngine(new DiffBuilder());
			}
			if (reqEngine == null) {
				reqEngine = new DefaultReqEngine();
			}
			if (equiEngine == null) {
				equiEngine = new DefaultEquiEngine();
			}
			if (registry == null) {
				registry = new PostProcessorRegistry();
			}
			if (conflictDetector == null) {
				conflictDetector = new DefaultConflictDetector();
			}
			return new EMFCompare(this.matchEngine, this.diffEngine, this.reqEngine, this.equiEngine,
					this.conflictDetector, this.registry);
		}
	}

}

Back to the top