Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Langer2015-03-10 19:28:06 +0000
committerPhilip Langer2015-03-10 19:28:06 +0000
commitf4420f85337d0fbc7acc1c1210ccae4087b97a15 (patch)
tree6f2d5093bbf7a1349ea7d6918d33cf4f7abea76c
parent92029f6241a7a1a0e7e6584690ec43a746938fd6 (diff)
downloadorg.eclipse.emf.compare-f4420f85337d0fbc7acc1c1210ccae4087b97a15.tar.gz
org.eclipse.emf.compare-f4420f85337d0fbc7acc1c1210ccae4087b97a15.tar.xz
org.eclipse.emf.compare-f4420f85337d0fbc7acc1c1210ccae4087b97a15.zip
[458147] Three-way merging for rejecting opaque element body changes
Bug: 458147 Change-Id: I5462f6f514efddf5e5a9f12982e015a84fe95743 Signed-off-by: Philip Langer <planger@eclipsesource.com>
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/opaque/OpaqueElementBodyChangeMergeTest.java32
-rw-r--r--plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/OpaqueElementBodyChangeMerger.java186
2 files changed, 180 insertions, 38 deletions
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/opaque/OpaqueElementBodyChangeMergeTest.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/opaque/OpaqueElementBodyChangeMergeTest.java
index 78c576dc1..5ba901019 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/opaque/OpaqueElementBodyChangeMergeTest.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/opaque/OpaqueElementBodyChangeMergeTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 EclipseSource Muenchen GmbH and others.
+ * Copyright (c) 2014, 2015 EclipseSource Muenchen GmbH and others.
* 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
@@ -185,6 +185,36 @@ public class OpaqueElementBodyChangeMergeTest extends AbstractUMLTest {
}
@Test
+ public void testA1UseCase_ApplyLeftRevertRightChangeThreeWay() throws IOException {
+ Resource origin = input.getA1Origin();
+ Resource left = input.getA1Left();
+ Resource right = input.getA1Right();
+
+ OpaqueAction leftAction = (OpaqueAction)left.getEObject(OPAQUE_ACTION1_ID);
+ String leftBody = leftAction.getBodies().get(0);
+
+ Comparison comparison = compare(left, right, origin);
+ applyLeftOpaqueElementBodyChangesToRight(comparison);
+ revertRightOpaqueElementBodyChanges(comparison);
+ assertOneBodyWithContents(right, leftBody);
+ }
+
+ @Test
+ public void testA1UseCase_ApplyRightRevertLeftChangeThreeWay() throws IOException {
+ Resource origin = input.getA1Origin();
+ Resource left = input.getA1Left();
+ Resource right = input.getA1Right();
+
+ OpaqueAction rightAction = (OpaqueAction)right.getEObject(OPAQUE_ACTION1_ID);
+ String rightBody = rightAction.getBodies().get(0);
+
+ Comparison comparison = compare(left, right, origin);
+ applyRightOpaqueElementBodyChangesToLeft(comparison);
+ revertLeftOpaqueElementBodyChanges(comparison);
+ assertOneBodyWithContents(left, rightBody);
+ }
+
+ @Test
public void testA2UseCase() throws IOException {
Resource origin = input.getA2Origin();
Resource left = input.getA2Left();
diff --git a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/OpaqueElementBodyChangeMerger.java b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/OpaqueElementBodyChangeMerger.java
index b8ddc79af..3d9defefd 100644
--- a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/OpaqueElementBodyChangeMerger.java
+++ b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/OpaqueElementBodyChangeMerger.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 EclipseSource Muenchen GmbH and others.
+ * Copyright (c) 2014, 2015 EclipseSource Muenchen GmbH and others.
* 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
@@ -238,39 +238,74 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger {
* The direction of merging.
*/
private void changeElement(OpaqueElementBodyChange bodyChange, boolean rightToLeft) {
- final Match match = bodyChange.getMatch();
- final Comparison comparison = match.getComparison();
- final String language = bodyChange.getLanguage();
+ final EObject targetContainer = getTargetContainer(bodyChange.getMatch(), rightToLeft);
+ final String targetValue = getTargetBodyValue(bodyChange, rightToLeft);
- final EObject leftContainer = match.getLeft();
- final EObject rightContainer = match.getRight();
+ setBody(targetContainer, targetValue, bodyChange.getLanguage());
+
+ // we merge the body change as a whole, so set all refining to merged too
+ setRefiningDiffsMerged(bodyChange);
+ }
- final String leftBody = UMLCompareUtil.getOpaqueElementBody(leftContainer, language);
- final String rightBody = UMLCompareUtil.getOpaqueElementBody(rightContainer, language);
+ /**
+ * Sets {@code newBody} as the contents of the body for the given {@code language} in the given
+ * {@code container}.
+ *
+ * @param container
+ * The {@link EObject} to set the body.
+ * @param newBody
+ * The content of the body to set.
+ * @param language
+ * The language at which the body shall be set.
+ */
+ private void setBody(EObject container, String newBody, String language) {
+ final List<String> languages = UMLCompareUtil.getOpaqueElementLanguages(container);
+ final List<String> bodies = UMLCompareUtil.getOpaqueElementBodies(container);
+ final int index = languages.indexOf(language);
+ bodies.set(index, newBody);
+ }
+ /**
+ * Returns the target value, that is, the value to be set when merging the given {@code bodyChange} in the
+ * direction indicated by {@code rightToLeft}.
+ *
+ * @param bodyChange
+ * The bodyChange we are currently merging.
+ * @param rightToLeft
+ * Direction of the merge.
+ * @return The target value to be set when merging.
+ */
+ private String getTargetBodyValue(OpaqueElementBodyChange bodyChange, boolean rightToLeft) {
final String newBody;
- if (comparison.isThreeWay()) {
- final EObject originContainer = match.getOrigin();
- final String originBody = UMLCompareUtil.getOpaqueElementBody(originContainer, language);
- if (isAcceptingChange(bodyChange, rightToLeft)) {
- newBody = performThreeWayTextMerge(leftBody, rightBody, originBody);
- } else {
- newBody = originBody;
- }
+ if (bodyChange.getMatch().getComparison().isThreeWay()) {
+ newBody = performThreeWayTextMerge(bodyChange, rightToLeft);
} else if (rightToLeft) {
- newBody = rightBody;
+ newBody = getRightBodyValue(bodyChange);
} else {
- newBody = leftBody;
+ newBody = getLeftBodyValue(bodyChange);
}
+ return newBody;
+ }
- if (rightToLeft) {
- setBody(leftContainer, newBody, language);
+ /**
+ * Performs a three-way text merge for the given {@code bodyChange} and returns the merged text.
+ * <p>
+ * Depending on whether the given {@code bodyChange} is an accept or reject in the context of the merge
+ * direction indicated by {@code rightToLeft}, this method will perform different strategies of merging.
+ * </p>
+ *
+ * @param bodyChange
+ * The bodyChange for which a three-way text diff is to be performed.
+ * @param rightToLeft
+ * The direction of applying the {@code diff}.
+ * @return The merged text.
+ */
+ private String performThreeWayTextMerge(OpaqueElementBodyChange bodyChange, boolean rightToLeft) {
+ if (isAcceptingChange(bodyChange, rightToLeft)) {
+ return performAcceptingThreeWayTextMerge(bodyChange);
} else {
- setBody(rightContainer, newBody, language);
+ return performRejectingThreeWayTextMerge(bodyChange);
}
-
- // we merged the body change as a whole, so set all refining to merged too
- setRefiningDiffsMerged(bodyChange);
}
/**
@@ -289,21 +324,98 @@ public class OpaqueElementBodyChangeMerger extends AttributeChangeMerger {
}
/**
- * Sets {@code newBody} as the contents of the body for the given {@code language} in the given
- * {@code container}.
+ * Performs a three-way text merge accepting the given {@code bodyChange} and returns the merged text.
*
- * @param container
- * The {@link EObject} to set the body.
- * @param newBody
- * The content of the body to set.
- * @param language
- * The language at which the body shall be set.
+ * @param bodyChange
+ * The bodyChange for which a three-way text diff is to be performed.
+ * @return The merged text.
*/
- private void setBody(EObject container, String newBody, String language) {
- final List<String> languages = UMLCompareUtil.getOpaqueElementLanguages(container);
- final List<String> bodies = UMLCompareUtil.getOpaqueElementBodies(container);
- final int index = languages.indexOf(language);
- bodies.set(index, newBody);
+ private String performAcceptingThreeWayTextMerge(OpaqueElementBodyChange bodyChange) {
+ final String leftBodyValue = getLeftBodyValue(bodyChange);
+ final String rightBodyValue = getRightBodyValue(bodyChange);
+ final String originBodyValue = getOriginBodyValue(bodyChange);
+ return performThreeWayTextMerge(leftBodyValue, rightBodyValue, originBodyValue);
+ }
+
+ /**
+ * Performs a three-way text merge rejecting the given {@code bodyChange} and returns the merged text.
+ * <p>
+ * The implementation of rejecting a body value change is based on a three-way diff corresponding to
+ * {@link AttributeChangeMerger#performRejectingThreeWayTextMerge(AttributeChange, boolean)}.
+ * </p>
+ *
+ * @param bodyChange
+ * The bodyChange for which a three-way text diff is to be performed.
+ * @param rightToLeft
+ * The direction of applying the {@code bodyChange}.
+ * @return The merged text.
+ */
+ private String performRejectingThreeWayTextMerge(OpaqueElementBodyChange bodyChange) {
+ final String originBodyValue = getOriginBodyValue(bodyChange);
+ final AttributeChange bodyValueAddition = getBodyValueAddition(bodyChange).get();
+ final String changedValueFromDiff = (String)bodyValueAddition.getValue();
+
+ final String changedValueFromModel;
+ if (DifferenceSource.LEFT.equals(bodyValueAddition.getSource())) {
+ changedValueFromModel = getLeftBodyValue(bodyChange);
+ } else {
+ changedValueFromModel = getRightBodyValue(bodyChange);
+ }
+
+ return performThreeWayTextMerge(changedValueFromModel, originBodyValue, changedValueFromDiff);
+ }
+
+ /**
+ * Returns the attribute change that adds a body value from the refining differences of the given
+ * {@code bodyChange}.
+ *
+ * @param bodyChange
+ * The body change to get the body value addition from.
+ * @return The attribute change adding a body value.
+ */
+ private Optional<AttributeChange> getBodyValueAddition(OpaqueElementBodyChange bodyChange) {
+ for (Diff diff : bodyChange.getRefinedBy()) {
+ if (isChangeOfOpaqueElementBodyAttribute(diff) && DifferenceKind.ADD.equals(diff.getKind())) {
+ return Optional.of((AttributeChange)diff);
+ }
+ }
+ return Optional.absent();
+ }
+
+ /**
+ * Returns the body value of the left-hand side that is affected by the given {@code bodyChange}.
+ *
+ * @param bodyChange
+ * The body change to get the left-hand side body value for.
+ * @return The left-hand side body value.
+ */
+ private String getLeftBodyValue(OpaqueElementBodyChange bodyChange) {
+ final EObject leftContainer = bodyChange.getMatch().getLeft();
+ return UMLCompareUtil.getOpaqueElementBody(leftContainer, bodyChange.getLanguage());
+ }
+
+ /**
+ * Returns the body value of the right-hand side that is affected by the given {@code bodyChange}.
+ *
+ * @param bodyChange
+ * The body change to get the right-hand side body value for.
+ * @return The right-hand side body value.
+ */
+ private String getRightBodyValue(OpaqueElementBodyChange bodyChange) {
+ final EObject rightContainer = bodyChange.getMatch().getRight();
+ return UMLCompareUtil.getOpaqueElementBody(rightContainer, bodyChange.getLanguage());
+ }
+
+ /**
+ * Returns the body value of the origin that is affected by the given {@code bodyChange}.
+ *
+ * @param bodyChange
+ * The body change to get the origin body value for.
+ * @return The origin body value.
+ */
+ private String getOriginBodyValue(OpaqueElementBodyChange bodyChange) {
+ final EObject originContainer = bodyChange.getMatch().getOrigin();
+ return UMLCompareUtil.getOpaqueElementBody(originContainer, bodyChange.getLanguage());
}
/**

Back to the top