/******************************************************************************* * Copyright (c) 2013, 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.internal.factories; import com.google.common.base.Predicate; import java.util.List; import org.eclipse.emf.compare.AttributeChange; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.DifferenceKind; import org.eclipse.emf.compare.Match; import org.eclipse.emf.compare.ReferenceChange; import org.eclipse.emf.compare.diagram.internal.extensions.DiagramDiff; import org.eclipse.emf.compare.internal.postprocessor.factories.AbstractChangeFactory; import org.eclipse.emf.compare.internal.utils.ComparisonUtil; import org.eclipse.emf.compare.util.CompareSwitch; import org.eclipse.emf.compare.utils.MatchUtil; import org.eclipse.emf.compare.utils.ReferenceUtil; import org.eclipse.emf.ecore.EObject; import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.gmf.runtime.notation.View; /** * Factory of diagram difference extensions. * * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a> */ public abstract class AbstractDiagramChangeFactory extends AbstractChangeFactory { /** * {@inheritDoc} * * @see org.eclipse.emf.compare.internal.postprocessor.factories.IChangeFactory#create(org.eclipse.emf.compare.Diff) */ @SuppressWarnings("restriction") @Override public Diff create(Diff input) { Diff ret = super.create(input); if (ret instanceof DiagramDiff) { setView((DiagramDiff)ret, input); ((DiagramDiff)ret).setSemanticDiff(getSemanticDiff(input)); } return ret; } /** * Get the view and set the given extension with it, from the given refining one. * * @param extension * The extension to set. * @param refiningDiff * The difference refining the given extension. * @return The view. */ public EObject setView(DiagramDiff extension, Diff refiningDiff) { CompareSwitch<EObject> getterValue = new CompareSwitch<EObject>() { @Override public EObject caseReferenceChange(ReferenceChange object) { return object.getValue(); } @Override public EObject caseAttributeChange(AttributeChange object) { Comparison comparison = object.getMatch().getComparison(); EObject view = MatchUtil.getContainer(comparison, object); while (view != null && !(view instanceof View)) { view = view.eContainer(); } return view; } @Override public EObject caseResourceAttachmentChange( org.eclipse.emf.compare.ResourceAttachmentChange object) { Comparison comparison = object.getMatch().getComparison(); return MatchUtil.getContainer(comparison, object); } }; EObject view = getterValue.doSwitch(refiningDiff); extension.setView(view); return view; } /** * {@inheritDoc} * * @see org.eclipse.emf.compare.internal.postprocessor.factories.IChangeFactory#getParentMatch(org.eclipse.emf.compare.Diff) */ @Override public Match getParentMatch(Diff input) { return getParentMatch(ComparisonUtil.getComparison(input), input); } /** * Get the match in which the given difference should be added. * * @param comparison * The current comparison. * @param input * The difference to locate. * @return The containing match. */ public static Match getParentMatch(Comparison comparison, Diff input) { if (input.getKind() == DifferenceKind.CHANGE) { return comparison.getMatch(getViewContainer(input)); } else { return input.getMatch(); } } /** * Get the GMF view which represents a semantic element and containing the given difference. * * @param input * The difference. * @return The found view. */ private static View getViewContainer(Diff input) { final Match match = input.getMatch(); return getViewContainer(match); } /** * From the one of the matched objects of the given match, it returns the first found parent GMF view * which represents a semantic element. * * @param match * The given match. * @return The found view. */ private static View getViewContainer(Match match) { EObject result = match.getLeft(); if (result == null) { result = match.getRight(); } if (!(result instanceof View && ReferenceUtil.safeEGet(result, NotationPackage.Literals.VIEW__ELEMENT) != null) && match.eContainer() instanceof Match) { result = getViewContainer((Match)match.eContainer()); } return (View)result; } /** * From a given diagram difference extension, get the related semantic difference. * * @param input * The diagram difference extension. * @return The semantic one. */ private Diff getSemanticDiff(Diff input) { if (input instanceof ReferenceChange && ((ReferenceChange)input).getValue() instanceof View) { final View view = (View)((ReferenceChange)input).getValue(); final Object element = ReferenceUtil.safeEGet(view, NotationPackage.Literals.VIEW__ELEMENT); if (element instanceof EObject) { final List<Diff> diffs = findCrossReferences(ComparisonUtil.getComparison(input), (EObject)element, new Predicate<Diff>() { public boolean apply(Diff diff) { return diff instanceof ReferenceChange && ((ReferenceChange)diff).getReference().isContainment(); } }); if (diffs.size() > 0) { return diffs.get(0); } } } return null; } }