/**
* <copyright>
*
* Copyright (c) 2006-2017 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.sirius;
import java.util.Arrays;
import java.util.Collection;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.diffmerge.api.IMatch;
import org.eclipse.emf.diffmerge.gmf.GMFDiffPolicy;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.sirius.business.api.resource.ResourceDescriptor;
import org.eclipse.sirius.diagram.DiagramPackage;
import org.eclipse.sirius.diagram.sequence.ordering.OrderingPackage;
import org.eclipse.sirius.viewpoint.ViewpointPackage;
/**
* A diff policy for Sirius models.
*/
public class SiriusDiffPolicy extends GMFDiffPolicy {
/** Separator */
private static final char SEGMENT_SEPARATOR = '/';
/**
* The set of references whose order should be ignored (semantically
* unordered references)
*/
private static final Collection<EReference> SEMANTICALLY_UNORDERED_REFERENCES = Arrays
.asList(DiagramPackage.eINSTANCE.getDDiagram_ActivatedLayers(),
DiagramPackage.eINSTANCE.getDDiagram_OwnedDiagramElements(),
ViewpointPackage.eINSTANCE.getDAnalysis_Models(),
ViewpointPackage.eINSTANCE.getDAnalysis_OwnedViews(),
ViewpointPackage.eINSTANCE
.getDRepresentationElement_SemanticElements(),
DiagramPackage.eINSTANCE.getEdgeTarget_IncomingEdges(),
DiagramPackage.eINSTANCE.getEdgeTarget_OutgoingEdges());
/** The set of references that can be ignored */
private static final Collection<EReference> UNSIGNIFICANT_REFERENCES = Arrays
.asList(ViewpointPackage.eINSTANCE.getDRepresentation_UiState(),
DiagramPackage.eINSTANCE.getDDiagram_HiddenElements());
/** The set of types that can be ignored */
private static final Collection<EClass> UNSIGNIFICANT_TYPES = Arrays
.asList(OrderingPackage.eINSTANCE.getEventEndsOrdering(),
OrderingPackage.eINSTANCE.getInstanceRolesOrdering(),
ViewpointPackage.eINSTANCE.getUIState());
/**
* The set of String attributes for which the empty string value must not be
* distinguished from the null value
*/
private static final Collection<EAttribute> IGNORING_EMPTY_STRING_ATTRIBUTES = Arrays
.asList(DiagramPackage.eINSTANCE.getDDiagramElement_TooltipText());
/**
* @see org.eclipse.emf.diffmerge.gmf.GMFDiffPolicy#considerEqual(java.lang.Object, java.lang.Object, org.eclipse.emf.ecore.EAttribute)
*/
@Override
public boolean considerEqual(Object value1_p, Object value2_p,
EAttribute attribute_p) {
boolean result = super.considerEqual(value1_p, value2_p, attribute_p);
if (!result && ViewpointPackage.eINSTANCE.getDAnalysis_SemanticResources() == attribute_p) {
// Get URI(s)
URI refURI = ((ResourceDescriptor) value1_p).getResourceURI();
URI trgtURI = ((ResourceDescriptor) value2_p).getResourceURI();
// Get the position of project name in URI segments
int positionInRefURI = getProjectPositionInURI(refURI);
int positionInTrgtURI = getProjectPositionInURI(trgtURI);
// Either make it relative or convert to string
String refURIStr = (positionInRefURI != -1)?
makeRelativeToProject(refURI, positionInRefURI):
refURI.toString();
String trgtURIStr = (positionInTrgtURI != -1)?
makeRelativeToProject(trgtURI, positionInTrgtURI):
trgtURI.toString();
return refURIStr.equals(trgtURIStr);
}
return result;
}
/**
* @see org.eclipse.emf.diffmerge.impl.policies.DefaultDiffPolicy#coverFeature(org.eclipse.emf.ecore.EStructuralFeature)
*/
@Override
public boolean coverFeature(EStructuralFeature feature_p) {
return !UNSIGNIFICANT_REFERENCES.contains(feature_p) &&
super.coverFeature(feature_p);
}
/**
* @see org.eclipse.emf.diffmerge.impl.policies.DefaultDiffPolicy#coverMatch(org.eclipse.emf.diffmerge.api.IMatch)
*/
@Override
public boolean coverMatch(IMatch match_p) {
boolean result = super.coverMatch(match_p);
if (result && match_p.isPartial()) {
// Ignore certain transient elements (OK because no cross-ref)
EObject element = match_p
.get(match_p.getUncoveredRole().opposite());
if (element != null)
result = !UNSIGNIFICANT_TYPES.contains(element.eClass());
}
return result;
}
/**
* @see org.eclipse.emf.diffmerge.impl.policies.DefaultDiffPolicy#coverValue(java.lang.Object, org.eclipse.emf.ecore.EAttribute)
*/
@Override
public boolean coverValue(Object value_p, EAttribute attribute_p) {
boolean result;
if (IGNORING_EMPTY_STRING_ATTRIBUTES.contains(attribute_p)
&& ((String) value_p).length() == 0)
result = false;
else
result = super.coverValue(value_p, attribute_p);
return result;
}
/**
* @see org.eclipse.emf.diffmerge.impl.policies.ConfigurableDiffPolicy#doConsiderOrdered(org.eclipse.emf.ecore.EStructuralFeature)
*/
@Override
protected boolean doConsiderOrdered(EStructuralFeature feature_p) {
return super.doConsiderOrdered(feature_p)
&& !SEMANTICALLY_UNORDERED_REFERENCES.contains(feature_p);
}
/**
*
* @return The position of the segment which corresponds to the project name.
*/
protected int getProjectPositionInURI(URI uri_p) {
if(uri_p.isPlatformResource()){
return 2;
}
return -1;
}
/**
*
* @param uri_p The uri to make relative
* @param projectPositionInURI_p The position of the segment which corresponds to the project
* name in the given uri
*
* @return the relative uri as String
*/
protected String makeRelativeToProject(URI uri_p, int projectPositionInURI_p) {
StringBuilder result = new StringBuilder();
for (int i = projectPositionInURI_p; i < uri_p.segments().length; i++) {
result.append(SEGMENT_SEPARATOR);
result.append(uri_p.segment(i));
}
return result.toString();
}
}