/** * <copyright> * * Copyright (c) 2010-2016 Thales Global Services S.A.S. * 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: * Thales Global Services S.A.S. - initial API and implementation * * </copyright> */ package org.eclipse.emf.diffmerge.gmf; import java.util.Set; import org.eclipse.emf.diffmerge.api.scopes.IFeaturedModelScope; import org.eclipse.emf.diffmerge.impl.policies.DefaultMergePolicy; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.ECrossReferenceAdapter; import org.eclipse.gmf.runtime.notation.Edge; import org.eclipse.gmf.runtime.notation.Node; import org.eclipse.gmf.runtime.notation.NotationPackage; import org.eclipse.gmf.runtime.notation.View; /** * A merge policy for GMF elements. * @author Olivier Constant */ public class GMFMergePolicy extends DefaultMergePolicy { /** Whether graphical elements must be merged when semantic elements are merged */ private boolean _graphicalFromSemantic; /** * Constructor */ public GMFMergePolicy() { _graphicalFromSemantic = false; } /** * @see org.eclipse.emf.diffmerge.impl.policies.DefaultMergePolicy#isSingleMandatory(org.eclipse.emf.ecore.EReference) */ @Override protected boolean isSingleMandatory(EReference reference_p) { return super.isSingleMandatory(reference_p) || reference_p == NotationPackage.eINSTANCE.getView_Element(); } /** * Extend the given addition group for the given element within the given scope * based on GMF peculiarities * @param group_p a non-null, modifiable collection * @param element_p a non-null element * @param scope_p a non-null scope */ protected void extendGMFAdditionGroup(Set<EObject> group_p, EObject element_p, IFeaturedModelScope scope_p) { // Node -> Node content if (element_p instanceof Node) { Node elementNode = (Node)element_p; EObject representedElement = elementNode.getElement(); for (EObject child : element_p.eContents()) { boolean addChild = true; if (child instanceof View) { View childView = (View)child; EObject childRepresentedElement = childView.getElement(); addChild = childRepresentedElement == null || childRepresentedElement == representedElement; } if (addChild) group_p.add(child); } } // Edge -> Edge content if (element_p instanceof Edge) group_p.addAll(element_p.eContents()); // Semantic element -> Views if (isGraphicalFromSemantic()) extendGMFAdditionGroupSemanticTarget(group_p, element_p, scope_p); } /** * Extend the given addition group for the given element within the given scope * so that GMF elements are bound to their semantic elements * @param group_p a non-null, modifiable collection * @param element_p a non-null element * @param scope_p a non-null scope */ protected void extendGMFAdditionGroupSemanticTarget(Set<EObject> group_p, EObject element_p, IFeaturedModelScope scope_p) { ECrossReferenceAdapter crAdapter = ECrossReferenceAdapter.getCrossReferenceAdapter(element_p); if (crAdapter != null) { for (EStructuralFeature.Setting setting : crAdapter.getNonNavigableInverseReferences(element_p, false)) { if (setting.getEStructuralFeature() == NotationPackage.eINSTANCE.getView_Element()) group_p.add(setting.getEObject()); } } } /** * @see org.eclipse.emf.diffmerge.impl.policies.DefaultMergePolicy#getAdditionGroup(org.eclipse.emf.ecore.EObject, org.eclipse.emf.diffmerge.api.scopes.IFeaturedModelScope) */ @Override public Set<EObject> getAdditionGroup(EObject element_p, IFeaturedModelScope scope_p) { Set<EObject> result = super.getAdditionGroup(element_p, scope_p); extendGMFAdditionGroup(result, element_p, scope_p); return result; } /** * Return whether graphical elements must be merged when semantic elements are merged */ public boolean isGraphicalFromSemantic() { return _graphicalFromSemantic; } /** * Set whether graphical elements must be merged when semantic elements are merged */ public void setGraphicalFromSemantic(boolean graphicalFromSemantic_p) { _graphicalFromSemantic = graphicalFromSemantic_p; } }