/*******************************************************************************
* Copyright (c) 2015 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.diagram.papyrus.internal;
import java.util.Set;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.merge.ResourceChangeAdapter;
import org.eclipse.emf.compare.merge.ResourceChangeAdapter.IResourceChangeParticipant;
import org.eclipse.emf.ecore.util.EcoreUtil;
/**
* This class materializes the post-comparison treatment. This treatment manages relations between notation
* changes and UML semantic changes when such changes should be linked. For instance, when the target of a
* connector is changed in the representation, it is also changed in the UML model. This treatment also
* installs a {@link IResourceChangeParticipant} on the comparison to make sure Papyrus resources are
* created/deleted together.
*
* @author <a href="mailto:laurent.delaigue@obeo.fr">Laurent Delaigue</a>
*/
public class PapyrusDiagramPostComparison implements Runnable {
/** The comparison. */
private final Comparison comparison;
/** The indexer. */
private final DiffIndexer indexer;
/**
* Constructor.
*
* @param comparison
* The comparison
*/
public PapyrusDiagramPostComparison(Comparison comparison) {
this.comparison = comparison;
indexer = new DiffIndexer();
}
/**
* Executes the treatment.
* <p>
* In a first step, a participant is registered on the comparison to deal with resources to delete.
* </p>
* <p>
* In a second step, implications are created. The algorithm takes 2 passes:
* <ol>
* <li>Index all {@link Diff}s that may be related with another {@link Diff}, using specific keys</li>
* <li>for each key in the index, create bi-directional implication links between the concerned diffs</li>
* </ol>
* This algorithm is linear, indexing in the first pass prevents fancy searches in the comparison model
* which may impede scalability.
* </p>
*/
public void run() {
registerResourceChangeParticipant();
IDiffHandler handler = getHandler();
for (Diff diff : comparison.getDifferences()) {
handler.handle(diff);
}
linkEquivalentDiffsWithRequiresRelations();
}
/**
* Register a {@link IResourceChangeParticipant} on the comparison for Papyrus resources.
*/
protected void registerResourceChangeParticipant() {
final Adapter adapter = EcoreUtil.getAdapter(comparison.eAdapters(), ResourceChangeAdapter.class);
if (adapter instanceof ResourceChangeAdapter) {
((ResourceChangeAdapter)adapter)
.addParticipant(new PapyrusResourceChangeParticipant((ResourceChangeAdapter)adapter));
}
}
/**
* Once all related differences are indexed, walk through the index and create the implication links
* between all concerned {@link Diff}s. The indexing of {@link Diff}s must have been done before calling
* this method.
*/
private void linkEquivalentDiffsWithRequiresRelations() {
for (Object key : indexer.getEquivalentDiffsKeySet()) {
Set<Diff> diffs = indexer.getEquivalentDiffs(key);
if (diffs.size() > 1) {
for (Diff diff : diffs) {
for (Diff other : diffs) {
if (other != diff && other.getSource() == diff.getSource()) {
diff.getRequires().add(other);
}
}
}
}
}
}
/**
* Provide the {@link IDiffHandler} for the comparison used by this instance.
*
* @return An indexer that manages 3-way comparisons if the comparison is 3-way, or an indexer that
* manages 2-way comparisons otherwise.
*/
protected IDiffHandler getHandler() {
if (comparison.isThreeWay()) {
return new PapyrusDiagram3WayDiffHandler(indexer);
} else {
return new PapyrusDiagram2WayDiffHandler(indexer);
}
}
}