Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikaël Barbero2013-06-19 15:18:37 +0000
committerMikaël Barbero2013-07-16 09:07:10 +0000
commitaa5c098caf7990c952ab785ec91e4b94b23f35ca (patch)
tree998c3fa4f90f2e736711988cf261c0aa0b61d8ba
parentba590393675ff110a533ebd23eef897b6b23b7e0 (diff)
downloadorg.eclipse.emf.compare-aa5c098caf7990c952ab785ec91e4b94b23f35ca.tar.gz
org.eclipse.emf.compare-aa5c098caf7990c952ab785ec91e4b94b23f35ca.tar.xz
org.eclipse.emf.compare-aa5c098caf7990c952ab785ec91e4b94b23f35ca.zip
Refactoring of the mergers
- pull up related diff merging in AbstractMerger (required diff / implied / equivalent) - Refined differences are now merged by abstract merger Change-Id: I4cab6c3a1b50b7b4b2a6abe9bb0f69c736cc9d00
-rw-r--r--plugins/org.eclipse.emf.compare.diagram/src/org/eclipse/emf/compare/diagram/internal/merge/CompareDiagramMerger.java93
-rw-r--r--plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/UMLMerger.java79
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AbstractMerger.java218
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java164
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java3
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/PseudoConflictMerger.java136
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java248
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java136
8 files changed, 322 insertions, 755 deletions
diff --git a/plugins/org.eclipse.emf.compare.diagram/src/org/eclipse/emf/compare/diagram/internal/merge/CompareDiagramMerger.java b/plugins/org.eclipse.emf.compare.diagram/src/org/eclipse/emf/compare/diagram/internal/merge/CompareDiagramMerger.java
index 83fc0f311..a1a77187a 100644
--- a/plugins/org.eclipse.emf.compare.diagram/src/org/eclipse/emf/compare/diagram/internal/merge/CompareDiagramMerger.java
+++ b/plugins/org.eclipse.emf.compare.diagram/src/org/eclipse/emf/compare/diagram/internal/merge/CompareDiagramMerger.java
@@ -10,10 +10,7 @@
*******************************************************************************/
package org.eclipse.emf.compare.diagram.internal.merge;
-import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.compare.Diff;
-import org.eclipse.emf.compare.DifferenceSource;
-import org.eclipse.emf.compare.DifferenceState;
import org.eclipse.emf.compare.diagram.internal.extensions.DiagramDiff;
import org.eclipse.emf.compare.merge.AbstractMerger;
@@ -31,94 +28,4 @@ public class CompareDiagramMerger extends AbstractMerger {
public boolean isMergerFor(Diff target) {
return target instanceof DiagramDiff;
}
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
- */
- public void copyLeftToRight(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final DiagramDiff diff = (DiagramDiff)target;
-
- setEquivalentDiffAsMerged(diff);
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- // final Diff semanticDiff = diff.getSemanticDiff();
- // if (semanticDiff != null) {
- // for (Diff semanticRefines : semanticDiff.getRefines()) {
- // mergeDiff(semanticRefines, false, monitor);
- // }
- // mergeDiff(semanticDiff, false, monitor);
- // }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "requires" diffs
- mergeRequires(diff, false, monitor);
- } else {
- // merge all "required by" diffs
- mergeRequiredBy(diff, false, monitor);
- }
-
- for (Diff refining : diff.getRefinedBy()) {
- mergeDiff(refining, false, monitor);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.merge.IMerger#copyRightToLeft(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
- */
- public void copyRightToLeft(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final DiagramDiff diff = (DiagramDiff)target;
-
- setEquivalentDiffAsMerged(diff);
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- // final Diff semanticDiff = diff.getSemanticDiff();
- // if (semanticDiff != null) {
- // for (Diff semanticRefines : semanticDiff.getRefines()) {
- // mergeDiff(semanticRefines, true, monitor);
- // }
- // mergeDiff(semanticDiff, true, monitor);
- // }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "required by" diffs
- mergeRequiredBy(diff, true, monitor);
- } else {
- mergeRequires(diff, true, monitor);
- }
-
- for (Diff refining : diff.getRefinedBy()) {
- mergeDiff(refining, true, monitor);
- }
- }
-
- /**
- * Iterates over the differences equivalent to {@code diff} and sets them as
- * {@link DifferenceState#MERGED}.
- *
- * @param diff
- * Diff which equivalences are to be considered merged.
- */
- private void setEquivalentDiffAsMerged(DiagramDiff diff) {
- if (diff.getEquivalence() != null) {
- for (Diff equivalent : diff.getEquivalence().getDifferences()) {
- equivalent.setState(DifferenceState.MERGED);
- }
- }
- }
}
diff --git a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/UMLMerger.java b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/UMLMerger.java
index 5f98288d5..d3191368c 100644
--- a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/UMLMerger.java
+++ b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/merge/UMLMerger.java
@@ -10,10 +10,7 @@
*******************************************************************************/
package org.eclipse.emf.compare.uml2.internal.merge;
-import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.compare.Diff;
-import org.eclipse.emf.compare.DifferenceSource;
-import org.eclipse.emf.compare.DifferenceState;
import org.eclipse.emf.compare.merge.AbstractMerger;
import org.eclipse.emf.compare.uml2.internal.UMLDiff;
@@ -31,80 +28,4 @@ public class UMLMerger extends AbstractMerger {
public boolean isMergerFor(Diff target) {
return target instanceof UMLDiff;
}
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
- */
- public void copyLeftToRight(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final UMLDiff diff = (UMLDiff)target;
-
- setEquivalentDiffAsMerged(diff);
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- // for (Diff refining : diff.getRefinedBy()) {
- // mergeDiff(refining, false, monitor);
- // }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "requires" diffs
- mergeRequires(diff, false, monitor);
- } else {
- // merge all "required by" diffs
- mergeRequiredBy(diff, false, monitor);
- }
-
- for (Diff refining : diff.getRefinedBy()) {
- mergeDiff(refining, false, monitor);
- }
- }
-
- public void copyRightToLeft(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final UMLDiff diff = (UMLDiff)target;
-
- setEquivalentDiffAsMerged(diff);
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- // for (Diff refining : diff.getRefinedBy()) {
- // mergeDiff(refining, true, monitor);
- // }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "required by" diffs
- mergeRequiredBy(diff, true, monitor);
- } else {
- mergeRequires(diff, true, monitor);
- }
-
- for (Diff refining : diff.getRefinedBy()) {
- mergeDiff(refining, true, monitor);
- }
- }
-
- /**
- * Iterates over the differences equivalent to {@code diff} and sets them as
- * {@link DifferenceState#MERGED}.
- *
- * @param diff
- * Diff which equivalences are to be considered merged.
- */
- private void setEquivalentDiffAsMerged(UMLDiff diff) {
- if (diff.getEquivalence() != null) {
- for (Diff equivalent : diff.getEquivalence().getDifferences()) {
- equivalent.setState(DifferenceState.MERGED);
- }
- }
- }
}
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AbstractMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AbstractMerger.java
index 93460f792..3d6e4cd1c 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AbstractMerger.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AbstractMerger.java
@@ -10,12 +10,19 @@
*******************************************************************************/
package org.eclipse.emf.compare.merge;
+import static com.google.common.base.Predicates.in;
+import static com.google.common.collect.Iterables.any;
+
import java.util.List;
import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.DifferenceSource;
+import org.eclipse.emf.compare.DifferenceState;
+import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.utils.EMFCompareCopier;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.InternalEList;
@@ -73,6 +80,116 @@ public abstract class AbstractMerger implements IMerger {
}
/**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff,
+ * org.eclipse.emf.common.util.Monitor)
+ */
+ public void copyLeftToRight(Diff target, Monitor monitor) {
+ // Don't merge an already merged (or discarded) diff
+ if (target.getState() != DifferenceState.UNRESOLVED) {
+ return;
+ }
+
+ // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
+ target.setState(DifferenceState.MERGED);
+
+ if (target.getSource() == DifferenceSource.LEFT) {
+ // merge all "requires" diffs
+ mergeRequires(target, false, monitor);
+ handleImplies(target, false, monitor);
+ } else {
+ // merge all "required by" diffs
+ mergeRequiredBy(target, false, monitor);
+ handleImpliedBy(target, false, monitor);
+ }
+
+ for (Diff refining : target.getRefinedBy()) {
+ mergeDiff(refining, false, monitor);
+ }
+
+ boolean hasToBeMerged = true;
+ if (target.getEquivalence() != null) {
+ hasToBeMerged = handleEquivalences(target, false, monitor);
+ }
+
+ if (hasToBeMerged) {
+ if (target.getSource() == DifferenceSource.LEFT) {
+ accept(target, false);
+ } else {
+ reject(target, false);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.merge.IMerger#copyRightToLeft(org.eclipse.emf.compare.Diff,
+ * org.eclipse.emf.common.util.Monitor)
+ */
+ public void copyRightToLeft(Diff target, Monitor monitor) {
+ // Don't merge an already merged (or discarded) diff
+ if (target.getState() != DifferenceState.UNRESOLVED) {
+ return;
+ }
+
+ // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
+ target.setState(DifferenceState.MERGED);
+
+ if (target.getSource() == DifferenceSource.LEFT) {
+ // merge all "required by" diffs
+ mergeRequiredBy(target, true, monitor);
+ handleImpliedBy(target, true, monitor);
+ } else {
+ // merge all "requires" diffs
+ mergeRequires(target, true, monitor);
+ handleImplies(target, true, monitor);
+ }
+
+ for (Diff refining : target.getRefinedBy()) {
+ mergeDiff(refining, true, monitor);
+ }
+
+ boolean hasToBeMerged = true;
+ if (target.getEquivalence() != null) {
+ hasToBeMerged = handleEquivalences(target, true, monitor);
+ }
+
+ if (hasToBeMerged) {
+ if (target.getSource() == DifferenceSource.LEFT) {
+ reject(target, true);
+ } else {
+ accept(target, true);
+ }
+ }
+ }
+
+ /**
+ * Accept the given difference. This may be overridden by clients.
+ *
+ * @param diff
+ * the difference to merge
+ * @param rightToLeft
+ * the direction of the merge
+ */
+ protected void accept(final Diff diff, boolean rightToLeft) {
+
+ }
+
+ /**
+ * Reject the given difference. This may be overridden by clients.
+ *
+ * @param diff
+ * the difference to merge
+ * @param rightToLeft
+ * the direction of the merge
+ */
+ protected void reject(final Diff diff, boolean rightToLeft) {
+
+ }
+
+ /**
* This will merge all {@link Diff#getRequiredBy() differences that require} {@code diff} in the given
* direction.
*
@@ -93,6 +210,42 @@ public abstract class AbstractMerger implements IMerger {
}
/**
+ * Mark as {@link DifferenceState#MERGED merged} all the implied differences recursively from the given
+ * one.
+ *
+ * @param diff
+ * The difference from which the implications have to be marked.
+ * @param rightToLeft
+ * The direction of the merge.
+ * @param monitor
+ * Monitor.
+ */
+ protected void handleImplies(Diff diff, boolean rightToLeft, Monitor monitor) {
+ for (Diff implied : diff.getImplies()) {
+ implied.setState(DifferenceState.MERGED);
+ handleImplies(implied, rightToLeft, monitor);
+ }
+ }
+
+ /**
+ * Mark as {@link DifferenceState#MERGED merged} all the implying differences recursively from the given
+ * one.
+ *
+ * @param diff
+ * The difference from which the implications have to be marked.
+ * @param rightToLeft
+ * The direction of the merge.
+ * @param monitor
+ * Monitor.
+ */
+ protected void handleImpliedBy(Diff diff, boolean rightToLeft, Monitor monitor) {
+ for (Diff impliedBy : diff.getImpliedBy()) {
+ impliedBy.setState(DifferenceState.MERGED);
+ handleImpliedBy(impliedBy, rightToLeft, monitor);
+ }
+ }
+
+ /**
* This will merge all {@link Diff#getRequires() differences required by} {@code diff} in the given
* direction.
*
@@ -134,6 +287,71 @@ public abstract class AbstractMerger implements IMerger {
}
/**
+ * Handles the equivalences of this difference.
+ * <p>
+ * Note that in certain cases, we'll merge our opposite instead of merging this diff. Specifically, we'll
+ * do that for one-to-many eOpposites : we'll merge the 'many' side instead of the 'unique' one. This
+ * allows us not to worry about the order of the references on that 'many' side.
+ * </p>
+ * <p>
+ * This is called before the merge of <code>this</code>. In short, if this returns <code>false</code>, we
+ * won't carry on merging <code>this</code> after returning.
+ * </p>
+ *
+ * @param diff
+ * The diff we are currently merging.
+ * @param rightToLeft
+ * Direction of the merge.
+ * @param monitor
+ * The monitor to use in order to report progress information.
+ * @return <code>true</code> if the current difference should still be merged after handling its
+ * equivalences, <code>false</code> if it should be considered "already merged".
+ */
+ protected boolean handleEquivalences(Diff diff, boolean rightToLeft, Monitor monitor) {
+ boolean continueMerge = true;
+ for (Diff equivalent : diff.getEquivalence().getDifferences()) {
+ // For 1..*, merge diff on many-valued to preserve ordering
+ if (diff instanceof ReferenceChange && equivalent instanceof ReferenceChange) {
+ final EReference reference = ((ReferenceChange)diff).getReference();
+ final EReference equivalentReference = ((ReferenceChange)equivalent).getReference();
+
+ if (reference.getEOpposite() == equivalentReference
+ && equivalent.getState() == DifferenceState.UNRESOLVED) {
+ // This equivalence is on our eOpposite. Should we merge it instead of 'this'?
+ final boolean mergeEquivalence = !reference.isMany()
+ && ((ReferenceChange)equivalent).getReference().isMany();
+ if (mergeEquivalence) {
+ mergeDiff(equivalent, rightToLeft, monitor);
+ continueMerge = false;
+ }
+ }
+ }
+
+ /*
+ * If one of the equivalent differences is implied or implying (depending on the merge direction)
+ * a merged diff, then we have a dependency loop : the "current" difference has already been
+ * merged because of this implication. This will allow us to break out of that loop.
+ */
+ if (rightToLeft) {
+ if (diff.getSource() == DifferenceSource.LEFT) {
+ continueMerge = continueMerge && !any(equivalent.getImplies(), in(diff.getRequiredBy()));
+ } else {
+ continueMerge = continueMerge && !any(equivalent.getImpliedBy(), in(diff.getRequires()));
+ }
+ } else {
+ if (diff.getSource() == DifferenceSource.LEFT) {
+ continueMerge = continueMerge && !any(equivalent.getImpliedBy(), in(diff.getRequires()));
+ } else {
+ continueMerge = continueMerge && !any(equivalent.getImplies(), in(diff.getRequiredBy()));
+ }
+ }
+
+ equivalent.setState(DifferenceState.MERGED);
+ }
+ return continueMerge;
+ }
+
+ /**
* This will create a copy of the given EObject that can be used as the target of an addition (or the
* reverting of a deletion).
* <p>
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java
index 0a165b5f9..a20e69890 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/AttributeChangeMerger.java
@@ -16,12 +16,10 @@ import static org.eclipse.emf.compare.utils.ReferenceUtil.safeEIsSet;
import java.util.List;
import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.compare.AttributeChange;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceSource;
-import org.eclipse.emf.compare.DifferenceState;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.ecore.EObject;
@@ -45,134 +43,56 @@ public class AttributeChangeMerger extends AbstractMerger {
/**
* {@inheritDoc}
*
- * @see org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
+ * @see org.eclipse.emf.compare.merge.AbstractMerger#accept(org.eclipse.emf.compare.Diff, boolean)
*/
- public void copyLeftToRight(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final AttributeChange diff = (AttributeChange)target;
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- if (diff.getEquivalence() != null) {
- for (Diff equivalent : diff.getEquivalence().getDifferences()) {
- equivalent.setState(DifferenceState.MERGED);
- }
- }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "requires" diffs
- mergeRequires(diff, false, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- // Create the same element in right
- addInTarget(diff, false);
- break;
- case DELETE:
- // Delete that same element from right
- removeFromTarget(diff, false);
- break;
- case MOVE:
- moveElement(diff, false);
- break;
- case CHANGE:
- changeValue(diff, false);
- break;
- default:
- break;
- }
- } else {
- // merge all "required by" diffs
- mergeRequiredBy(diff, false, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- // We have a ADD on right. we need to revert this addition
- removeFromTarget(diff, false);
- break;
- case DELETE:
- // DELETE in the right. We need to re-create this element
- addInTarget(diff, false);
- break;
- case MOVE:
- moveElement(diff, false);
- break;
- case CHANGE:
- changeValue(diff, false);
- break;
- default:
- break;
- }
+ @Override
+ protected void accept(final Diff diff, boolean rightToLeft) {
+ AttributeChange attributeChange = (AttributeChange)diff;
+ switch (diff.getKind()) {
+ case ADD:
+ // Create the same element in right
+ addInTarget(attributeChange, rightToLeft);
+ break;
+ case DELETE:
+ // Delete that same element from right
+ removeFromTarget(attributeChange, rightToLeft);
+ break;
+ case MOVE:
+ moveElement(attributeChange, rightToLeft);
+ break;
+ case CHANGE:
+ changeValue(attributeChange, rightToLeft);
+ break;
+ default:
+ break;
}
}
/**
* {@inheritDoc}
*
- * @see org.eclipse.emf.compare.merge.IMerger#copyRightToLeft(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
+ * @see org.eclipse.emf.compare.merge.AbstractMerger#reject(org.eclipse.emf.compare.Diff, boolean)
*/
- public void copyRightToLeft(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final AttributeChange diff = (AttributeChange)target;
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- if (diff.getEquivalence() != null) {
- for (Diff equivalent : diff.getEquivalence().getDifferences()) {
- equivalent.setState(DifferenceState.MERGED);
- }
- }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "required by" diffs
- mergeRequiredBy(diff, true, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- // We have a ADD on left, thus nothing in right. We need to revert the addition
- removeFromTarget(diff, true);
- break;
- case DELETE:
- // DELETE in the left, thus an element in right. We need to re-create that element
- addInTarget(diff, true);
- break;
- case MOVE:
- moveElement(diff, true);
- break;
- case CHANGE:
- changeValue(diff, true);
- break;
- default:
- break;
- }
- } else {
- // merge all "requires" diffs
- mergeRequires(diff, true, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- addInTarget(diff, true);
- break;
- case DELETE:
- removeFromTarget(diff, true);
- break;
- case MOVE:
- moveElement(diff, true);
- break;
- case CHANGE:
- changeValue(diff, true);
- break;
- default:
- break;
- }
+ @Override
+ protected void reject(Diff diff, boolean rightToLeft) {
+ AttributeChange attributeChange = (AttributeChange)diff;
+ switch (diff.getKind()) {
+ case ADD:
+ // We have a ADD on right. we need to revert this addition
+ removeFromTarget(attributeChange, rightToLeft);
+ break;
+ case DELETE:
+ // DELETE in the right. We need to re-create this element
+ addInTarget(attributeChange, rightToLeft);
+ break;
+ case MOVE:
+ moveElement(attributeChange, rightToLeft);
+ break;
+ case CHANGE:
+ changeValue(attributeChange, rightToLeft);
+ break;
+ default:
+ break;
}
}
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java
index fbfe3d76d..5f0453f6a 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/IMerger.java
@@ -31,7 +31,8 @@ import org.eclipse.emf.compare.EMFCompareMessages;
* default mergers are provided by EMF Compare, but they can be sub-classed and extended by clients through
* the extension point "org.eclipse.emf.compare.ide.mergerExtension".
* <p>
- * Clients can either implement the whole merger contract or extend {@link AbstractMerger} instead.
+ * Clients are encouraged to subclass AbstractMerger instead of implementing IMerger so that they can benefit
+ * from a maximum of the common procedures.
* </p>
*
* @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/PseudoConflictMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/PseudoConflictMerger.java
index dbbceea0f..2bc42cf9f 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/PseudoConflictMerger.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/PseudoConflictMerger.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 Obeo.
+ * Copyright (c) 2012, 2013 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
@@ -10,13 +10,8 @@
*******************************************************************************/
package org.eclipse.emf.compare.merge;
-import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.compare.ConflictKind;
import org.eclipse.emf.compare.Diff;
-import org.eclipse.emf.compare.DifferenceSource;
-import org.eclipse.emf.compare.DifferenceState;
-import org.eclipse.emf.compare.ReferenceChange;
-import org.eclipse.emf.ecore.EReference;
/**
* A simple merger for pseudo conflict. It only mark the differences as merged without doing anything except
@@ -34,133 +29,4 @@ public class PseudoConflictMerger extends AbstractMerger {
public boolean isMergerFor(Diff target) {
return target.getConflict() != null && target.getConflict().getKind() == ConflictKind.PSEUDO;
}
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
- */
- public void copyLeftToRight(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final ReferenceChange diff = (ReferenceChange)target;
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- if (diff.getEquivalence() != null) {
- boolean continueMerge = handleEquivalences(diff, false, monitor);
- if (!continueMerge) {
- return;
- }
- }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "requires" diffs
- mergeRequires(diff, false, monitor);
- } else {
- // merge all "required by" diffs
- mergeRequiredBy(diff, false, monitor);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.merge.IMerger#copyRightToLeft(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
- */
- public void copyRightToLeft(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final ReferenceChange diff = (ReferenceChange)target;
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- if (diff.getEquivalence() != null) {
- boolean continueMerge = handleEquivalences(diff, true, monitor);
- if (!continueMerge) {
- return;
- }
- }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "required by" diffs
- mergeRequiredBy(diff, true, monitor);
- } else {
- // merge all "requires" diffs
- mergeRequires(diff, true, monitor);
- }
- }
-
- /**
- * Handles the equivalences of this difference.
- * <p>
- * Note that in certain cases, we'll merge our opposite instead of merging this diff. Specifically, we'll
- * do that for one-to-many eOpposites : we'll merge the 'many' side instead of the 'unique' one. This
- * allows us not to worry about the order of the references on that 'many' side.
- * </p>
- * <p>
- * This is called before the merge of <code>this</code>. In short, if this returns <code>false</code>, we
- * won't carry on merging <code>this</code> after returning.
- * </p>
- *
- * @param diff
- * The diff we are currently merging.
- * @param rightToLeft
- * Direction of the merge.
- * @param monitor
- * The monitor to use in order to report progress information.
- * @return <code>true</code> if the current difference should still be merged after handling its
- * equivalences, <code>false</code> if it should be considered "already merged".
- */
- protected boolean handleEquivalences(ReferenceChange diff, boolean rightToLeft, Monitor monitor) {
- final EReference reference = diff.getReference();
- boolean continueMerge = true;
- for (Diff equivalent : diff.getEquivalence().getDifferences()) {
- if (equivalent instanceof ReferenceChange
- && reference.getEOpposite() == ((ReferenceChange)equivalent).getReference()
- && equivalent.getState() == DifferenceState.UNRESOLVED) {
- // This equivalence is on our eOpposite. Should we merge it instead of 'this'?
- final boolean mergeEquivalence = !reference.isMany()
- && ((ReferenceChange)equivalent).getReference().isMany();
- if (mergeEquivalence) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
- }
- } else if (diff.getSource() == DifferenceSource.LEFT) {
- // This can happen when merging subset/supersets... see AddInterfaceTest#testA50UseCase
- /*
- * This should be removed (or we should make sure that we can never be here) when bug 398402
- * is fixed.
- */
- if (rightToLeft && diff.getRequiredBy().contains(equivalent)) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
- } else if (!rightToLeft && diff.getRequires().contains(equivalent)) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
- }
- } else if (diff.getSource() == DifferenceSource.RIGHT) {
- // This can happen when merging subset/supersets... see AddInterfaceTest#testA50UseCase
- /*
- * This should be removed (or we should make sure that we can never be here) when bug 398402
- * is fixed.
- */
- if (rightToLeft && diff.getRequires().contains(equivalent)) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
- } else if (!rightToLeft && diff.getRequiredBy().contains(equivalent)) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
- }
- }
- equivalent.setState(DifferenceState.MERGED);
- }
- return continueMerge;
- }
}
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java
index cbb74564c..7d5132e90 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ReferenceChangeMerger.java
@@ -13,15 +13,12 @@ package org.eclipse.emf.compare.merge;
import static com.google.common.collect.Iterators.filter;
import static org.eclipse.emf.compare.utils.ReferenceUtil.safeEIsSet;
-import com.google.common.base.Predicates;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.util.EList;
-import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceKind;
@@ -29,7 +26,7 @@ import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.DifferenceState;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
-import org.eclipse.emf.compare.internal.utils.DiffUtil;
+import org.eclipse.emf.compare.utils.DiffUtil;
import org.eclipse.emf.compare.utils.IEqualityHelper;
import org.eclipse.emf.compare.utils.ReferenceUtil;
import org.eclipse.emf.ecore.EObject;
@@ -55,86 +52,6 @@ public class ReferenceChangeMerger extends AbstractMerger {
}
/**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
- */
- public void copyLeftToRight(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final ReferenceChange diff = (ReferenceChange)target;
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "requires" diffs
- mergeRequires(diff, false, monitor);
- handleImplies(diff, false, monitor);
- } else {
- // merge all "required by" diffs
- mergeRequiredBy(diff, false, monitor);
- handleImpliedBy(diff, false, monitor);
- }
-
- boolean hasToBeMerged = true;
- if (diff.getEquivalence() != null) {
- hasToBeMerged = handleEquivalences(diff, false, monitor);
- }
-
- if (hasToBeMerged) {
- if (diff.getSource() == DifferenceSource.LEFT) {
- accept(diff, false);
- } else {
- reject(diff, false);
- }
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.eclipse.emf.compare.merge.IMerger#copyRightToLeft(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
- */
- public void copyRightToLeft(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final ReferenceChange diff = (ReferenceChange)target;
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "required by" diffs
- mergeRequiredBy(diff, true, monitor);
- handleImpliedBy(diff, true, monitor);
- } else {
- // merge all "requires" diffs
- mergeRequires(diff, true, monitor);
- handleImplies(diff, true, monitor);
- }
-
- boolean hasToBeMerged = true;
- if (diff.getEquivalence() != null) {
- hasToBeMerged = handleEquivalences(diff, true, monitor);
- }
-
- if (hasToBeMerged) {
- if (diff.getSource() == DifferenceSource.LEFT) {
- reject(diff, true);
- } else {
- accept(diff, true);
- }
- }
- }
-
- /**
* Merge the given difference rejecting it.
*
* @param diff
@@ -142,42 +59,44 @@ public class ReferenceChangeMerger extends AbstractMerger {
* @param rightToLeft
* The direction of the merge.
*/
- private void reject(final ReferenceChange diff, boolean rightToLeft) {
- DifferenceSource source = diff.getSource();
- switch (diff.getKind()) {
+ @Override
+ protected void reject(final Diff diff, boolean rightToLeft) {
+ ReferenceChange referenceChange = (ReferenceChange)diff;
+ DifferenceSource source = referenceChange.getSource();
+ switch (referenceChange.getKind()) {
case ADD:
// We have a ADD on left, thus nothing in right. We need to revert the addition
- removeFromTarget(diff, rightToLeft);
+ removeFromTarget(referenceChange, rightToLeft);
break;
case DELETE:
// DELETE in the left, thus an element in right. We need to re-create that element
- addInTarget(diff, rightToLeft);
+ addInTarget(referenceChange, rightToLeft);
break;
case MOVE:
- moveElement(diff, rightToLeft);
+ moveElement(referenceChange, rightToLeft);
break;
case CHANGE:
EObject container = null;
if (source == DifferenceSource.LEFT) {
- container = diff.getMatch().getLeft();
+ container = referenceChange.getMatch().getLeft();
} else {
- container = diff.getMatch().getRight();
+ container = referenceChange.getMatch().getRight();
}
// Is it an unset?
if (container != null) {
- final EObject leftValue = (EObject)container.eGet(diff.getReference(), false);
+ final EObject leftValue = (EObject)container.eGet(referenceChange.getReference(), false);
if (leftValue == null) {
// Value has been unset in the right, and we are merging towards right.
// We need to re-add this element
- addInTarget(diff, rightToLeft);
+ addInTarget(referenceChange, rightToLeft);
} else {
// We'll actually need to "reset" this reference to its original value
- resetInTarget(diff, rightToLeft);
+ resetInTarget(referenceChange, rightToLeft);
}
} else {
// we have no left, and the source is on the left. Can only be an unset
- addInTarget(diff, rightToLeft);
+ addInTarget(referenceChange, rightToLeft);
}
break;
default:
@@ -193,38 +112,40 @@ public class ReferenceChangeMerger extends AbstractMerger {
* @param rightToLeft
* The direction of the merge.
*/
- private void accept(final ReferenceChange diff, boolean rightToLeft) {
+ @Override
+ protected void accept(final Diff diff, boolean rightToLeft) {
+ ReferenceChange referenceChange = (ReferenceChange)diff;
DifferenceSource source = diff.getSource();
switch (diff.getKind()) {
case ADD:
// Create the same element in right
- addInTarget(diff, rightToLeft);
+ addInTarget(referenceChange, rightToLeft);
break;
case DELETE:
// Delete that same element from right
- removeFromTarget(diff, rightToLeft);
+ removeFromTarget(referenceChange, rightToLeft);
break;
case MOVE:
- moveElement(diff, rightToLeft);
+ moveElement(referenceChange, rightToLeft);
break;
case CHANGE:
EObject container = null;
if (source == DifferenceSource.LEFT) {
- container = diff.getMatch().getLeft();
+ container = referenceChange.getMatch().getLeft();
} else {
- container = diff.getMatch().getRight();
+ container = referenceChange.getMatch().getRight();
}
// Is it an unset?
if (container != null) {
- final EObject leftValue = (EObject)container.eGet(diff.getReference(), false);
+ final EObject leftValue = (EObject)container.eGet(referenceChange.getReference(), false);
if (leftValue == null) {
- removeFromTarget(diff, rightToLeft);
+ removeFromTarget(referenceChange, rightToLeft);
} else {
- addInTarget(diff, rightToLeft);
+ addInTarget(referenceChange, rightToLeft);
}
} else {
// we have no left, and the source is on the left. Can only be an unset
- removeFromTarget(diff, rightToLeft);
+ removeFromTarget(referenceChange, rightToLeft);
}
break;
default:
@@ -233,40 +154,6 @@ public class ReferenceChangeMerger extends AbstractMerger {
}
/**
- * Mark as MERGED all the implied differences recursively from the given one.
- *
- * @param diff
- * The difference from which the implications have to be marked.
- * @param rightToLeft
- * The direction of the merge.
- * @param monitor
- * Monitor.
- */
- private void handleImplies(Diff diff, boolean rightToLeft, Monitor monitor) {
- for (Diff implied : diff.getImplies()) {
- implied.setState(DifferenceState.MERGED);
- handleImplies(implied, rightToLeft, monitor);
- }
- }
-
- /**
- * Mark as MERGED all the implying differences recursively from the given one.
- *
- * @param diff
- * The difference from which the implications have to be marked.
- * @param rightToLeft
- * The direction of the merge.
- * @param monitor
- * Monitor.
- */
- private void handleImpliedBy(Diff diff, boolean rightToLeft, Monitor monitor) {
- for (Diff impliedBy : diff.getImpliedBy()) {
- impliedBy.setState(DifferenceState.MERGED);
- handleImpliedBy(impliedBy, rightToLeft, monitor);
- }
- }
-
- /**
* This will be called when trying to copy a "MOVE" diff.
*
* @param diff
@@ -629,72 +516,6 @@ public class ReferenceChangeMerger extends AbstractMerger {
}
/**
- * Handles the equivalences of this difference.
- * <p>
- * Note that in certain cases, we'll merge our opposite instead of merging this diff. Specifically, we'll
- * do that for one-to-many eOpposites : we'll merge the 'many' side instead of the 'unique' one. This
- * allows us not to worry about the order of the references on that 'many' side.
- * </p>
- * <p>
- * This is called before the merge of <code>this</code>. In short, if this returns <code>false</code>, we
- * won't carry on merging <code>this</code> after returning.
- * </p>
- *
- * @param diff
- * The diff we are currently merging.
- * @param rightToLeft
- * Direction of the merge.
- * @param monitor
- * The monitor to use in order to report progress information.
- * @return <code>true</code> if the current difference should still be merged after handling its
- * equivalences, <code>false</code> if it should be considered "already merged".
- */
- protected boolean handleEquivalences(ReferenceChange diff, boolean rightToLeft, Monitor monitor) {
- final EReference reference = diff.getReference();
- boolean continueMerge = true;
- for (Diff equivalent : diff.getEquivalence().getDifferences()) {
- // For 1..*, merge diff on many-valued to preserve ordering
- if (equivalent instanceof ReferenceChange
- && reference.getEOpposite() == ((ReferenceChange)equivalent).getReference()
- && equivalent.getState() == DifferenceState.UNRESOLVED) {
- // This equivalence is on our eOpposite. Should we merge it instead of 'this'?
- final boolean mergeEquivalence = !reference.isMany()
- && ((ReferenceChange)equivalent).getReference().isMany();
- if (mergeEquivalence) {
- mergeDiff(equivalent, rightToLeft, monitor);
- continueMerge = false;
- }
- }
-
- /*
- * If one of the equivalent differences is implied or implying (depending on the merge direction)
- * a merged diff, then we have a dependency loop : the "current" difference has already been
- * merged because of this implication. This will allow us to break out of that loop.
- */
- if (rightToLeft) {
- if (diff.getSource() == DifferenceSource.LEFT) {
- continueMerge = continueMerge
- && !containsAny(diff.getRequiredBy(), equivalent.getImplies());
- } else {
- continueMerge = continueMerge
- && !containsAny(diff.getRequires(), equivalent.getImpliedBy());
- }
- } else {
- if (diff.getSource() == DifferenceSource.LEFT) {
- continueMerge = continueMerge
- && !containsAny(diff.getRequires(), equivalent.getImpliedBy());
- } else {
- continueMerge = continueMerge
- && !containsAny(diff.getRequiredBy(), equivalent.getImplies());
- }
- }
-
- equivalent.setState(DifferenceState.MERGED);
- }
- return continueMerge;
- }
-
- /**
* In the case of many-to-many eOpposite references, EMF will simply report the difference made on one
* side of the equivalence to the other, without considering ordering in any way. In such cases, we'll
* iterate over our equivalences after the merge, and double-check the ordering ourselves, fixing it as
@@ -808,21 +629,6 @@ public class ReferenceChangeMerger extends AbstractMerger {
}
/**
- * Utility method to check that the first sequence contains one of the elements of the second sequence at
- * least.
- *
- * @param sequence1
- * The first sequence.
- * @param sequence2
- * The second sequence.
- * @return True if the given first sequence contains one of the elements of the second sequence at least.
- * false otherwise.
- */
- private boolean containsAny(List<? extends EObject> sequence1, List<? extends EObject> sequence2) {
- return Iterables.any(sequence2, Predicates.in(sequence1));
- }
-
- /**
* Seeks a match of the given {@code element} in the given list, using the equality helper to find it.
* This is only used when moving or deleting proxies for now.
*
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java
index 8b742a253..a14620abe 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/merge/ResourceAttachmentChangeMerger.java
@@ -13,11 +13,9 @@ package org.eclipse.emf.compare.merge;
import java.util.Collections;
import java.util.List;
-import org.eclipse.emf.common.util.Monitor;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
-import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.DifferenceState;
import org.eclipse.emf.compare.EMFCompareMessages;
import org.eclipse.emf.compare.Match;
@@ -48,116 +46,46 @@ public class ResourceAttachmentChangeMerger extends AbstractMerger {
/**
* {@inheritDoc}
*
- * @see org.eclipse.emf.compare.merge.IMerger#copyLeftToRight(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
+ * @see org.eclipse.emf.compare.merge.AbstractMerger#accept(org.eclipse.emf.compare.Diff, boolean)
*/
- public void copyLeftToRight(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final ResourceAttachmentChange diff = (ResourceAttachmentChange)target;
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- if (diff.getEquivalence() != null) {
- for (Diff equivalent : diff.getEquivalence().getDifferences()) {
- equivalent.setState(DifferenceState.MERGED);
- }
- }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "requires" diffs
- mergeRequires(diff, false, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- // Create the same root in right
- addInTarget(diff, false);
- break;
- case DELETE:
- // Delete that same root from right
- removeFromTarget(diff, false);
- break;
- default:
- // other cases are unknown at the time of writing
- break;
- }
- } else {
- // merge all "required by" diffs
- mergeRequiredBy(diff, false, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- // Revert the addition of this root
- removeFromTarget(diff, false);
- break;
- case DELETE:
- // re-create this element
- addInTarget(diff, false);
- break;
- default:
- // other cases are unknown at the time of writing
- break;
- }
+ @Override
+ protected void accept(Diff diff, boolean rightToLeft) {
+ ResourceAttachmentChange resourceAttachmentChange = (ResourceAttachmentChange)diff;
+ switch (diff.getKind()) {
+ case ADD:
+ // Create the same root in right
+ addInTarget(resourceAttachmentChange, rightToLeft);
+ break;
+ case DELETE:
+ // Delete that same root from right
+ removeFromTarget(resourceAttachmentChange, rightToLeft);
+ break;
+ default:
+ // other cases are unknown at the time of writing
+ break;
}
}
/**
* {@inheritDoc}
*
- * @see org.eclipse.emf.compare.merge.IMerger#copyRightToLeft(org.eclipse.emf.compare.Diff,
- * org.eclipse.emf.common.util.Monitor)
+ * @see org.eclipse.emf.compare.merge.AbstractMerger#reject(org.eclipse.emf.compare.Diff, boolean)
*/
- public void copyRightToLeft(Diff target, Monitor monitor) {
- // Don't merge an already merged (or discarded) diff
- if (target.getState() != DifferenceState.UNRESOLVED) {
- return;
- }
- final ResourceAttachmentChange diff = (ResourceAttachmentChange)target;
-
- // Change the diff's state before we actually merge it : this allows us to avoid requirement cycles.
- diff.setState(DifferenceState.MERGED);
- if (diff.getEquivalence() != null) {
- for (Diff equivalent : diff.getEquivalence().getDifferences()) {
- equivalent.setState(DifferenceState.MERGED);
- }
- }
-
- if (diff.getSource() == DifferenceSource.LEFT) {
- // merge all "required by" diffs
- mergeRequiredBy(diff, true, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- // Revert the addition of this root
- removeFromTarget(diff, true);
- break;
- case DELETE:
- // re-create this element
- addInTarget(diff, true);
- break;
- default:
- // other cases are unknown at the time of writing
- break;
- }
- } else {
- // merge all "requires" diffs
- mergeRequires(diff, true, monitor);
-
- switch (diff.getKind()) {
- case ADD:
- // Create the same root in left
- addInTarget(diff, true);
- break;
- case DELETE:
- // Delete that same root from left
- removeFromTarget(diff, true);
- break;
- default:
- // other cases are unknown at the time of writing
- break;
- }
+ @Override
+ protected void reject(Diff diff, boolean rightToLeft) {
+ ResourceAttachmentChange resourceAttachmentChange = (ResourceAttachmentChange)diff;
+ switch (diff.getKind()) {
+ case ADD:
+ // Revert the addition of this root
+ removeFromTarget(resourceAttachmentChange, rightToLeft);
+ break;
+ case DELETE:
+ // re-create this element
+ addInTarget(resourceAttachmentChange, rightToLeft);
+ break;
+ default:
+ // other cases are unknown at the time of writing
+ break;
}
}

Back to the top