Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui.tests/.classpath2
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui.tests/.settings/org.eclipse.jdt.core.prefs6
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui.tests/META-INF/MANIFEST.MF2
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MirroredMergeActionTest.java6
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MockMergeAction.java14
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/MirrorManager.java7
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java15
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewerContentProvider.java267
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/AbstractMergeContainedAction.java58
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java72
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java21
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedAction.java4
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedConflictingAction.java12
-rw-r--r--plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedNonConflictingAction.java10
-rw-r--r--plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/provider/TreeNodeItemProviderSpec.java3
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/StereotypeApplicationConflictTests.java185
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/StereotypeApplicationConflictInputData.java93
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/left.uml13
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/origin.uml10
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/right.uml13
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/left.uml13
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/origin.uml10
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/right.uml13
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/left.uml13
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/origin.uml10
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/right.uml13
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/left.uml15
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/origin.uml12
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/right.uml15
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/left.uml15
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/origin.uml12
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/right.uml15
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/left.uml10
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/origin.uml16
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/right.uml10
-rw-r--r--plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java7
-rw-r--r--plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/StereotypedElementChangePostProcessor.java224
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/conflict/AbstractConflictSearch.java13
-rw-r--r--plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java17
39 files changed, 1045 insertions, 221 deletions
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/.classpath b/plugins/org.eclipse.emf.compare.ide.ui.tests/.classpath
index 098194ca4..eca7bdba8 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/.classpath
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/.classpath
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.emf.compare.ide.ui.tests/.settings/org.eclipse.jdt.core.prefs
index 79ea86fdb..75adc0ebb 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/.settings/org.eclipse.jdt.core.prefs
@@ -8,9 +8,9 @@ org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nul
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
@@ -101,7 +101,7 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
-org.eclipse.jdt.core.compiler.source=1.7
+org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.compare.ide.ui.tests/META-INF/MANIFEST.MF
index e705f5ab0..5c2704523 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/META-INF/MANIFEST.MF
@@ -4,7 +4,7 @@ Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.emf.compare.ide.ui.tests;singleton:=true
Bundle-Version: 4.4.3.qualifier
Bundle-Vendor: %providerName
-Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime,
org.junit;bundle-version="4.8.0",
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MirroredMergeActionTest.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MirroredMergeActionTest.java
index 050cbfb79..19439103e 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MirroredMergeActionTest.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MirroredMergeActionTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.List;
+import java.util.stream.Collectors;
import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.INavigatable;
@@ -264,9 +265,10 @@ public class MirroredMergeActionTest {
}
@Override
- protected Iterable<Diff> getSelectedDifferences(IStructuredSelection selection) {
+ protected List<Diff> getSelectedDifferences(IStructuredSelection selection) {
List<?> selectedObjects = selection.toList();
- return filter(selectedObjects, Diff.class);
+ return selectedObjects.stream().filter(Diff.class::isInstance).map(Diff.class::cast)
+ .collect(Collectors.toList());
}
}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MockMergeAction.java b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MockMergeAction.java
index 7222b0f08..d67ed702d 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MockMergeAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui.tests/src/org/eclipse/emf/compare/ide/ui/tests/structuremergeviewer/actions/MockMergeAction.java
@@ -8,10 +8,8 @@
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.tests.structuremergeviewer.actions;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-
import java.util.List;
+import java.util.stream.Collectors;
import org.eclipse.compare.INavigatable;
import org.eclipse.emf.compare.Diff;
@@ -19,8 +17,6 @@ import org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions.Merg
import org.eclipse.emf.compare.internal.merge.MergeMode;
import org.eclipse.emf.compare.merge.IMerger.Registry;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration;
-import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroup;
-import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.tree.TreeNode;
import org.eclipse.jface.viewers.IStructuredSelection;
@@ -46,10 +42,10 @@ public class MockMergeAction extends MergeAction {
}
@Override
- protected Iterable<Diff> getSelectedDifferences(IStructuredSelection selection) {
+ protected List<Diff> getSelectedDifferences(IStructuredSelection selection) {
List<?> selectedObjects = selection.toList();
- Iterable<TreeNode> selectedTreeNode = filter(selectedObjects, TreeNode.class);
- Iterable<EObject> selectedEObjects = transform(selectedTreeNode, IDifferenceGroup.TREE_NODE_DATA);
- return filter(selectedEObjects, Diff.class);
+ return selectedObjects.stream().filter(TreeNode.class::isInstance)
+ .map(node -> ((TreeNode)node).getData()).filter(Diff.class::isInstance).map(Diff.class::cast)
+ .collect(Collectors.toList());
}
}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/MirrorManager.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/MirrorManager.java
index 72dddd4ae..978b0b009 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/MirrorManager.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/contentmergeviewer/MirrorManager.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2018 EclipseSource and others.
+ * Copyright (c) 2018, 2019 EclipseSource, Christian W. Damus, 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
@@ -7,6 +7,7 @@
*
* Contributors:
* Philip Langer - initial API and implementation
+ * Christian W. Damus - bug 549463
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.contentmergeviewer;
@@ -136,12 +137,12 @@ public class MirrorManager {
@Override
public void saveRightContent(Object input, byte[] bytes) {
- delegate.saveLeftContent(input, bytes);
+ delegate.saveRightContent(input, bytes);
}
@Override
public void saveLeftContent(Object input, byte[] bytes) {
- delegate.saveRightContent(input, bytes);
+ delegate.saveLeftContent(input, bytes);
}
@Override
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java
index 0f3f2a2e3..611bb84b2 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewer.java
@@ -22,7 +22,6 @@ import static org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.EMFCo
import com.google.common.base.Function;
import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
@@ -43,6 +42,7 @@ import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
+import java.util.function.Predicate;
import org.eclipse.compare.CompareUI;
import org.eclipse.compare.CompareViewerPane;
@@ -662,7 +662,7 @@ public class EMFCompareStructureMergeViewer extends AbstractStructuredViewerWrap
private void addMergeNonConflictingActions(IMenuManager manager, EnumSet<MergeMode> modes,
IMerger.Registry mergerRegistry) {
final Predicate<TreeNode> filterPredicate = new Predicate<TreeNode>() {
- public boolean apply(TreeNode input) {
+ public boolean test(TreeNode input) {
return input != null && JFaceUtil.isFiltered(getViewer(), input, input.getParent());
}
};
@@ -689,7 +689,7 @@ public class EMFCompareStructureMergeViewer extends AbstractStructuredViewerWrap
private void addMergeConflictingActions(IMenuManager manager, EnumSet<MergeMode> modes,
IMerger.Registry mergerRegistry) {
final Predicate<TreeNode> filterPredicate = new Predicate<TreeNode>() {
- public boolean apply(TreeNode input) {
+ public boolean test(TreeNode input) {
return input != null && JFaceUtil.isFiltered(getViewer(), input, input.getParent());
}
};
@@ -715,7 +715,7 @@ public class EMFCompareStructureMergeViewer extends AbstractStructuredViewerWrap
private void addMergeAllActions(IMenuManager manager, EnumSet<MergeMode> modes,
IMerger.Registry mergerRegistry) {
final Predicate<TreeNode> filterPredicate = new Predicate<TreeNode>() {
- public boolean apply(TreeNode input) {
+ public boolean test(TreeNode input) {
return input != null && JFaceUtil.isFiltered(getViewer(), input, input.getParent());
}
};
@@ -767,6 +767,8 @@ public class EMFCompareStructureMergeViewer extends AbstractStructuredViewerWrap
return false;
}
}
+ // all selected objects are differences
+ return true;
}
return false;
}
@@ -2245,11 +2247,12 @@ public class EMFCompareStructureMergeViewer extends AbstractStructuredViewerWrap
public TitleBuilder(EMFCompareConfiguration configuration) {
comparison = configuration.getComparison();
groupProvider = configuration.getStructureMergeViewerGrouper().getProvider();
- filterPredicate = configuration.getStructureMergeViewerFilter().getAggregatedPredicate();
+ filterPredicate = EMFComparePredicates
+ .guavaToJava(configuration.getStructureMergeViewerFilter().getAggregatedPredicate());
}
void visit(TreeNode node, boolean parentApplies) {
- boolean applies = parentApplies && filterPredicate.apply(node);
+ boolean applies = parentApplies && filterPredicate.test(node);
EObject data = node.getData();
if (data instanceof Diff) {
// If we haven't visited it before...
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewerContentProvider.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewerContentProvider.java
index 7cecedc19..8a13dc10b 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewerContentProvider.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/EMFCompareStructureMergeViewerContentProvider.java
@@ -13,10 +13,7 @@
package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer;
import static com.google.common.base.Predicates.instanceOf;
-import static com.google.common.collect.Iterables.toArray;
-import static com.google.common.collect.Iterables.transform;
-import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
@@ -24,6 +21,8 @@ import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -45,7 +44,12 @@ import org.eclipse.emf.compare.ide.ui.internal.treecontentmanager.EMFCompareDefe
import org.eclipse.emf.compare.ide.ui.internal.treecontentmanager.EMFCompareDeferredTreeContentManagerUtil;
import org.eclipse.emf.compare.rcp.ui.internal.util.SWTUtil;
import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroupProvider2;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.FeatureMap;
+import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
+import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.IViewerNotification;
+import org.eclipse.emf.edit.provider.IWrapperItemProvider;
import org.eclipse.emf.edit.provider.ViewerNotification;
import org.eclipse.emf.edit.tree.TreeNode;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
@@ -53,6 +57,12 @@ import org.eclipse.emf.edit.ui.provider.NotifyChangedToViewerRefresh;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.Viewer;
import org.eclipse.ui.progress.DeferredTreeContentManager;
import org.eclipse.ui.progress.IDeferredWorkbenchAdapter;
import org.eclipse.ui.progress.IElementCollector;
@@ -389,6 +399,21 @@ public class EMFCompareStructureMergeViewerContentProvider extends AdapterFactor
*/
@Override
public Object[] getChildren(Object element) {
+ Object[] rawChildren = getRawChildren(element);
+
+ // Adapt all children that are not PendingUpdateAdapters into ICompareInput elements
+ return adaptElementsToCompareInput(rawChildren);
+ }
+
+ /**
+ * Returns the raw list of children for the given element. This array will not be useable by the EMF
+ * Compare viewers without prior going through {@link #adaptElementsToCompareInput(Object[])}.
+ *
+ * @param element
+ * The element which children we need.
+ * @return The children of this element.
+ */
+ protected Object[] getRawChildren(Object element) {
Object[] children;
if (element instanceof CompareInputAdapter) {
children = getCompareInputAdapterChildren((CompareInputAdapter)element);
@@ -398,19 +423,35 @@ public class EMFCompareStructureMergeViewerContentProvider extends AdapterFactor
children = super.getChildren(element);
}
- final Object[] compareInputChildren;
// Avoid NPE.
if (children == null) {
children = new Object[] {};
}
- // Do not adapt if it's a pending updater
- if (!Iterables.all(Arrays.asList(children), Predicates.instanceOf(PendingUpdateAdapter.class))) {
- Iterable<?> compareInputs = adapt(children, getAdapterFactory(), ICompareInput.class);
- compareInputChildren = toArray(compareInputs, Object.class);
- } else {
- compareInputChildren = children;
+ return children;
+ }
+
+ /**
+ * Adapt all of the given elements that are not instances of {@link PendingUpdateAdapter} into
+ * {@link ICompareInput} for the emf compare viewers when possible.
+ *
+ * @param elements
+ * The elements to adapt.
+ * @return The array of adapted elements.
+ */
+ protected Object[] adaptElementsToCompareInput(Object[] elements) {
+ Object[] result = new Object[elements.length];
+ for (int i = 0; i < result.length; i++) {
+ Object child = elements[i];
+ if (child instanceof PendingUpdateAdapter) {
+ result[i] = child;
+ } else {
+ result[i] = adapterFactory.adapt(child, ICompareInput.class);
+ if (result[i] == null) {
+ result[i] = child;
+ }
+ }
}
- return compareInputChildren;
+ return result;
}
/**
@@ -512,26 +553,7 @@ public class EMFCompareStructureMergeViewerContentProvider extends AdapterFactor
&& viewer.getInput() != null) {
if (notification instanceof IViewerNotification) {
if (viewerRefresh == null) {
- viewerRefresh = new ViewerRefresh(viewer) {
- int count = 0;
-
- @Override
- public synchronized boolean addNotification(IViewerNotification notification) {
- if (super.addNotification(notification)) {
- count = 0;
- return true;
- }
-
- // When there are more than 30 notifications, it's probably cheaper to simply
- // refresh the overall view.
- if (count > 30) {
- super.addNotification(new ViewerNotification(notification, null, true, true));
- }
-
- ++count;
- return false;
- }
- };
+ viewerRefresh = new EMFCompareViewerRefresh(viewer);
}
if (viewerRefresh.addNotification((IViewerNotification)notification)) {
@@ -546,53 +568,6 @@ public class EMFCompareStructureMergeViewerContentProvider extends AdapterFactor
}
/**
- * Adapts each elements of the the given <code>iterable</code> to the given <code>type</code> by using the
- * given <code>adapterFactory</code>.
- *
- * @param <T>
- * the type of returned elements.
- * @param iterable
- * the iterable to transform.
- * @param adapterFactory
- * the {@link AdapterFactory} used to adapt elements.
- * @param type
- * the target type of adapted elements.
- * @return an iterable with element of type <code>type</code>.
- */
- private static Iterable<?> adapt(Iterable<?> iterable, final AdapterFactory adapterFactory,
- final Class<?> type) {
- Function<Object, Object> adaptFunction = new Function<Object, Object>() {
- public Object apply(Object input) {
- Object ret = adapterFactory.adapt(input, type);
- if (ret == null) {
- return input;
- }
- return ret;
- }
- };
- return transform(iterable, adaptFunction);
- }
-
- /**
- * Adapts each elements of the the given <code>array</code> to the given <code>type</code> by using the
- * given <code>adapterFactory</code>.
- *
- * @param <T>
- * the type of returned elements.
- * @param iterable
- * the array to transform.
- * @param adapterFactory
- * the {@link AdapterFactory} used to adapt elements.
- * @param type
- * the target type of adapted elements
- * @return an iterable with element of type <code>type</code>.
- */
- private static Iterable<?> adapt(Object[] iterable, final AdapterFactory adapterFactory,
- final Class<?> type) {
- return adapt(Arrays.asList(iterable), adapterFactory, type);
- }
-
- /**
* {@inheritDoc}
*
* @see IJobChangeListener{@link #aboutToRun(IJobChangeEvent)
@@ -687,4 +662,140 @@ public class EMFCompareStructureMergeViewerContentProvider extends AdapterFactor
// Nothing to do
}
+ /**
+ * This custom implementation of a ViewerRefresh intends to suppress the thousands of
+ * NoSuchMethodExceptions thrown by the regular implementation when it calls
+ * {@link AdapterFactoryEditingDomain#isStale(Object)}.
+ */
+ private static class EMFCompareViewerRefresh extends ViewerRefresh {
+ int count = 0;
+
+ final Viewer targetViewer;
+
+ public EMFCompareViewerRefresh(Viewer viewer) {
+ super(viewer);
+ targetViewer = viewer;
+ }
+
+ /**
+ * Copy/paste of the super implementation except for the
+ * {@link AdapterFactoryEditingDomain#isStale(Object)} calls which are replaced with calls to
+ * {@link #isStale(Object)}.
+ */
+ @Override
+ protected void refresh(IViewerNotification notification) {
+ Object element = notification.getElement();
+
+ if (targetViewer instanceof StructuredViewer) {
+ StructuredViewer structuredViewer = (StructuredViewer)targetViewer;
+
+ ISelection selection = structuredViewer.getSelection();
+ boolean isStaleSelection = isStale(selection);
+ if (isStaleSelection) {
+ targetViewer.setSelection(StructuredSelection.EMPTY);
+ }
+
+ AbstractTreeViewer treeViewer = structuredViewer instanceof AbstractTreeViewer
+ ? (AbstractTreeViewer)structuredViewer
+ : null;
+ List<Object> expandedElements = treeViewer == null ? Collections.emptyList()
+ : Arrays.asList(treeViewer.getExpandedElements());
+ boolean isStaleExpandedElements = isStale(expandedElements);
+
+ if (element != null) {
+ if (notification.isContentRefresh()) {
+ structuredViewer.refresh(element, notification.isLabelUpdate());
+ } else if (notification.isLabelUpdate()) {
+ structuredViewer.update(element, null);
+ }
+ } else {
+ structuredViewer.refresh(notification.isLabelUpdate());
+ }
+
+ if (isStaleSelection || isStaleExpandedElements) {
+ Object object = structuredViewer.getInput();
+ EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(object);
+ if (editingDomain == null) {
+ for (Object child : ((IStructuredContentProvider)structuredViewer
+ .getContentProvider()).getElements(object)) {
+ editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(child);
+ if (editingDomain != null) {
+ break;
+ }
+ }
+ }
+ if (editingDomain instanceof AdapterFactoryEditingDomain) {
+ AdapterFactoryEditingDomain adapterFactoryEditingDomain = (AdapterFactoryEditingDomain)editingDomain;
+ if (treeViewer != null && isStaleExpandedElements) {
+ treeViewer.setExpandedElements(
+ adapterFactoryEditingDomain.resolve(expandedElements).toArray());
+ }
+ if (isStaleSelection) {
+ structuredViewer
+ .setSelection(
+ new StructuredSelection(adapterFactoryEditingDomain
+ .resolve(((IStructuredSelection)selection).toList())),
+ true);
+ }
+ }
+ }
+ } else {
+ targetViewer.refresh();
+ }
+ }
+
+ /**
+ * Copy/paste of {@link AdapterFactoryEditingDomain#isStale(Object)} but prevents exceptions from
+ * being thrown.
+ */
+ private boolean isStale(Object object) {
+ if (object instanceof IWrapperItemProvider) {
+ IWrapperItemProvider wrapper = (IWrapperItemProvider)object;
+ return isStale(wrapper.getValue()) || isStale(wrapper.getOwner());
+ } else if (object instanceof Collection<?>) {
+ for (Object item : (Collection<?>)object) {
+ if (isStale(item)) {
+ return true;
+ }
+ }
+ return false;
+ } else if (object instanceof Object[]) {
+ for (Object item : (Object[])object) {
+ if (isStale(item)) {
+ return true;
+ }
+ }
+ return false;
+ } else if (object instanceof EObject) {
+ EObject eObject = (EObject)object;
+ return eObject.eIsProxy() && eObject.eAdapters().isEmpty();
+ } else if (object instanceof FeatureMap.Entry) {
+ return isStale(((FeatureMap.Entry)object).getValue());
+ } else if (object == null) {
+ return false;
+ } else if (object instanceof IStructuredSelection) {
+ return isStale(((IStructuredSelection)object).toArray());
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public synchronized boolean addNotification(IViewerNotification notification) {
+ if (super.addNotification(notification)) {
+ count = 0;
+ return true;
+ }
+
+ // When there are more than 30 notifications, it's probably cheaper to simply
+ // refresh the overall view.
+ if (count > 30) {
+ super.addNotification(new ViewerNotification(notification, null, true, true));
+ }
+
+ ++count;
+ return false;
+ }
+ }
+
}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/AbstractMergeContainedAction.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/AbstractMergeContainedAction.java
index 1d1e9d0cd..1cc16e721 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/AbstractMergeContainedAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/AbstractMergeContainedAction.java
@@ -10,28 +10,20 @@
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
-import static com.google.common.collect.Iterables.concat;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.transform;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
-import com.google.common.collect.Lists;
-
import java.util.List;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.eclipse.compare.INavigatable;
import org.eclipse.emf.common.notify.Adapter;
-import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.internal.merge.MergeMode;
import org.eclipse.emf.compare.merge.IMerger.Registry;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration;
import org.eclipse.emf.compare.rcp.ui.internal.structuremergeviewer.groups.provider.GroupItemProviderAdapter;
-import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroup;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.tree.TreeNode;
import org.eclipse.jface.viewers.IStructuredSelection;
@@ -47,18 +39,17 @@ public abstract class AbstractMergeContainedAction extends MergeAction {
/**
* Function for transforming a tree node into all non-filtered leaf differences.
*/
- private static Function<TreeNode, Iterable<Diff>> treeNodesToLeafDiffs(
+ private static Function<TreeNode, Stream<Diff>> treeNodesToLeafDiffs(
final Predicate<TreeNode> isFiltered) {
- return new Function<TreeNode, Iterable<Diff>>() {
- public Iterable<Diff> apply(TreeNode input) {
+ return new Function<TreeNode, Stream<Diff>>() {
+ public Stream<Diff> apply(TreeNode input) {
final TreeIterator<EObject> allContents = input.eAllContents();
- final Builder<Diff> builder = new ImmutableList.Builder<Diff>();
+ final Stream.Builder<Diff> builder = Stream.builder();
while (allContents.hasNext()) {
final EObject eObject = allContents.next();
- if (eObject instanceof TreeNode) {
- final TreeNode treeNode = (TreeNode)eObject;
- final EObject data = IDifferenceGroup.TREE_NODE_DATA.apply(treeNode);
- if (data instanceof Diff && !isFiltered.apply(treeNode)) {
+ if (eObject instanceof TreeNode && !isFiltered.test((TreeNode)eObject)) {
+ final EObject data = ((TreeNode)eObject).getData();
+ if (data instanceof Diff) {
builder.add((Diff)data);
}
}
@@ -101,22 +92,21 @@ public abstract class AbstractMergeContainedAction extends MergeAction {
}
@Override
- protected Iterable<Diff> getSelectedDifferences(IStructuredSelection selection) {
- final List<?> selectedObjects = selection.toList();
+ protected List<Diff> getSelectedDifferences(IStructuredSelection selection) {
Object firstElement = selection.getFirstElement();
- if (selection.getFirstElement() instanceof GroupItemProviderAdapter) {
- final List<Object> effectiveSelectedObjects = Lists.newArrayList();
- effectiveSelectedObjects
- .addAll(((GroupItemProviderAdapter)firstElement).getChildren(firstElement));
- final Iterable<TreeNode> selectedTreeNodes = filter(effectiveSelectedObjects, TreeNode.class);
- Iterable<Diff> diffs = concat(transform(selectedTreeNodes, treeNodesToLeafDiffs(isFiltered)));
- return filter(getSelectedDifferences(diffs), getDiffPredicate());
+ if (firstElement instanceof GroupItemProviderAdapter) {
+ Stream<Diff> diffs = ((GroupItemProviderAdapter)firstElement).getChildren(firstElement).stream()
+ .filter(TreeNode.class::isInstance).map(TreeNode.class::cast)
+ .flatMap(treeNodesToLeafDiffs(isFiltered));
+ return getSelectedDifferences(diffs).stream().filter(getDiffPredicate())
+ .collect(Collectors.toList());
} else {
- final Iterable<Adapter> selectedAdapters = filter(selectedObjects, Adapter.class);
- final Iterable<Notifier> selectedNotifiers = transform(selectedAdapters, ADAPTER__TARGET);
- final Iterable<TreeNode> selectedTreeNodes = filter(selectedNotifiers, TreeNode.class);
- Iterable<Diff> diffs = concat(transform(selectedTreeNodes, treeNodesToLeafDiffs(isFiltered)));
- return filter(getSelectedDifferences(diffs), getDiffPredicate());
+ final List<?> selectedObjects = selection.toList();
+ Stream<Diff> diffs = selectedObjects.stream().filter(Adapter.class::isInstance)
+ .map(adapter -> ((Adapter)adapter).getTarget()).filter(TreeNode.class::isInstance)
+ .map(TreeNode.class::cast).flatMap(treeNodesToLeafDiffs(isFiltered));
+ return getSelectedDifferences(diffs).stream().filter(getDiffPredicate())
+ .collect(Collectors.toList());
}
}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java
index 9bf5b7b36..f3dd0ab0c 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAction.java
@@ -13,11 +13,6 @@
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
-import static com.google.common.collect.Iterables.addAll;
-import static com.google.common.collect.Iterables.any;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.isEmpty;
-import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static org.eclipse.emf.compare.DifferenceSource.LEFT;
import static org.eclipse.emf.compare.DifferenceSource.RIGHT;
@@ -28,18 +23,17 @@ import static org.eclipse.emf.compare.internal.merge.MergeMode.LEFT_TO_RIGHT;
import static org.eclipse.emf.compare.internal.merge.MergeMode.REJECT;
import static org.eclipse.emf.compare.internal.merge.MergeMode.RIGHT_TO_LEFT;
-import com.google.common.base.Function;
import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -48,7 +42,6 @@ import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.AdapterFactory;
-import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceSource;
import org.eclipse.emf.compare.DifferenceState;
@@ -70,8 +63,6 @@ import org.eclipse.emf.compare.merge.IMerger;
import org.eclipse.emf.compare.merge.IMerger.Registry;
import org.eclipse.emf.compare.provider.ITooltipLabelProvider;
import org.eclipse.emf.compare.rcp.ui.internal.configuration.IEMFCompareConfiguration;
-import org.eclipse.emf.compare.rcp.ui.structuremergeviewer.groups.IDifferenceGroup;
-import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.tree.TreeNode;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
@@ -87,24 +78,6 @@ import org.eclipse.ui.plugin.AbstractUIPlugin;
*/
public class MergeAction extends BaseSelectionListenerAction {
- private static final Predicate<Diff> IS_IN_TERMINAL_STATE = new Predicate<Diff>() {
- public boolean apply(Diff diff) {
- return AbstractMerger.isInTerminalState(diff);
- }
- };
-
- private static final Predicate<Diff> IS_NOT_IN_TERMINAL_STATE = new Predicate<Diff>() {
- public boolean apply(Diff diff) {
- return !AbstractMerger.isInTerminalState(diff);
- }
- };
-
- protected static final Function<? super Adapter, ? extends Notifier> ADAPTER__TARGET = new Function<Adapter, Notifier>() {
- public Notifier apply(Adapter adapter) {
- return adapter.getTarget();
- }
- };
-
protected final Registry mergerRegistry;
protected ICompareEditingDomain editingDomain;
@@ -282,7 +255,8 @@ public class MergeAction extends BaseSelectionListenerAction {
// If selected diffs are still in the terminal state we seem to be unable to process them.
// This should really never happen, but if some command doesn't support undo, it's possible to
// get in this situation.
- if (any(selectedDifferences, IS_IN_TERMINAL_STATE)) {
+
+ if (selectedDifferences.stream().anyMatch(AbstractMerger::isInTerminalState)) {
managedCmdStack.restoreCommandStack();
return;
}
@@ -347,7 +321,7 @@ public class MergeAction extends BaseSelectionListenerAction {
*/
private class ManagedCommandStack {
- private List<Multimap<DifferenceState, Diff>> diffChangesList = Lists.newArrayList();
+ private List<Multimap<DifferenceState, Diff>> diffChangesList = new ArrayList<>();
private Map<Multimap<DifferenceState, Diff>, EditCommand> editCommands = new IdentityHashMap<Multimap<DifferenceState, Diff>, EditCommand>();
@@ -403,7 +377,7 @@ public class MergeAction extends BaseSelectionListenerAction {
}
public void undoUntilDiffsAreInTerminalState(List<Diff> diffs) {
- while (commandStack.canUndo() && any(diffs, IS_IN_TERMINAL_STATE)) {
+ while (commandStack.canUndo() && diffs.stream().anyMatch(AbstractMerger::isInTerminalState)) {
Command undoCommand = commandStack.getUndoCommand();
// Keep track of undone changes
@@ -478,8 +452,8 @@ public class MergeAction extends BaseSelectionListenerAction {
if (!diffsToRestore.values().isEmpty()) {
undoIfNotUndoneYet();
- List<Diff> diffsToMerge = Lists.newArrayList(diffsToRestore.get(MERGED));
- List<Diff> diffsToDiscard = Lists.newArrayList(diffsToRestore.get(DISCARDED));
+ List<Diff> diffsToMerge = new ArrayList<>(diffsToRestore.get(MERGED));
+ List<Diff> diffsToDiscard = new ArrayList<>(diffsToRestore.get(DISCARDED));
if (mode == ACCEPT || mode == REJECT) {
redoDiffs(diffsToMerge, diffsToDiscard, ACCEPT, REJECT);
@@ -567,13 +541,14 @@ public class MergeAction extends BaseSelectionListenerAction {
*/
@Override
protected boolean updateSelection(IStructuredSelection selection) {
- addAll(selectedDifferences, getSelectedDifferences(selection));
+ getSelectedDifferences().addAll(getSelectedDifferences(selection));
if (this.adapterFactory != null) {
contextualizeTooltip();
}
// The action is enabled only if all the elements in the selection are diffs that will change state
// when this action is applied.
- return !selectedDifferences.isEmpty() && selection.toList().size() == selectedDifferences.size();
+ return !getSelectedDifferences().isEmpty()
+ && selection.toList().size() == getSelectedDifferences().size();
}
/**
@@ -586,22 +561,17 @@ public class MergeAction extends BaseSelectionListenerAction {
selectedDifferences.clear();
}
- protected Iterable<Diff> getSelectedDifferences(IStructuredSelection selection) {
+ protected List<Diff> getSelectedDifferences(IStructuredSelection selection) {
List<?> selectedObjects = selection.toList();
- Iterable<Adapter> selectedAdapters = filter(selectedObjects, Adapter.class);
- Iterable<Notifier> selectedNotifiers = transform(selectedAdapters, ADAPTER__TARGET);
- Iterable<TreeNode> selectedTreeNode = filter(selectedNotifiers, TreeNode.class);
- Iterable<EObject> selectedEObjects = transform(selectedTreeNode, IDifferenceGroup.TREE_NODE_DATA);
- Iterable<Diff> diffs = filter(selectedEObjects, Diff.class);
- if (isEmpty(diffs)) {
- diffs = filter(selectedObjects, Diff.class);
- }
- return getSelectedDifferences(diffs);
+ Stream<Diff> selectedDiffs = selectedObjects.stream().filter(Adapter.class::isInstance)
+ .map(adapter -> ((Adapter)adapter).getTarget()).filter(TreeNode.class::isInstance)
+ .map(node -> ((TreeNode)node).getData()).filter(Diff.class::isInstance).map(Diff.class::cast);
+ return getSelectedDifferences(selectedDiffs);
}
protected Predicate<Diff> getStatePredicate() {
return new Predicate<Diff>() {
- public boolean apply(Diff diff) {
+ public boolean test(Diff diff) {
switch (diff.getState()) {
case DISCARDED:
switch (getSelectedMode()) {
@@ -633,18 +603,18 @@ public class MergeAction extends BaseSelectionListenerAction {
};
}
- protected Iterable<Diff> getSelectedDifferences(Iterable<Diff> diffs) {
+ protected List<Diff> getSelectedDifferences(Stream<Diff> diffs) {
ICompareCommandStack commandStack = editingDomain.getCommandStack();
// We can only re-process diffs in the terminal state if we have a command stack that supports
// suspending the delivery of notifications. So filter out diffs that are already in the terminal
// state.
if (!(commandStack instanceof TransactionalDualCompareCommandStack)) {
- return filter(diffs, IS_NOT_IN_TERMINAL_STATE);
+ return diffs.filter(diff -> !AbstractMerger.isInTerminalState(diff)).collect(Collectors.toList());
}
// Filter out diffs whose state would not be changed by this actions's selected mode.
- return filter(diffs, getStatePredicate());
+ return diffs.filter(getStatePredicate()).collect(Collectors.toList());
}
/**
@@ -681,7 +651,7 @@ public class MergeAction extends BaseSelectionListenerAction {
*
* @return The cached selected differences.
*/
- public List<Diff> getSelectedDifferences() {
+ protected List<Diff> getSelectedDifferences() {
return selectedDifferences;
}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java
index 588d1560c..bd80f6c08 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeAllNonConflictingAction.java
@@ -13,14 +13,13 @@
*******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
-import static com.google.common.collect.Iterables.addAll;
-import static com.google.common.collect.Iterables.filter;
import static org.eclipse.emf.compare.ConflictKind.REAL;
-
-import com.google.common.base.Predicate;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.guavaToJava;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
@@ -47,10 +46,6 @@ import org.eclipse.ui.plugin.AbstractUIPlugin;
*/
public class MergeAllNonConflictingAction extends MergeAction {
- @SuppressWarnings("unchecked")
- private static final Predicate<Diff> NON_CONFLICTING_DIFFS = (Predicate<Diff>)EMFComparePredicates
- .hasNoDirectOrIndirectConflict(REAL);
-
private Comparison comparison;
private List<Diff> differences;
@@ -135,15 +130,17 @@ public class MergeAllNonConflictingAction extends MergeAction {
*/
@Override
protected boolean updateSelection(IStructuredSelection selection) {
- addAll(getSelectedDifferences(), getSelectedDifferences(differences));
- // The action is enabled only there are any selected differences that will change state when this
+ getSelectedDifferences().addAll(getSelectedDifferences(differences.stream()));
+ // The action is enabled only if there are any selected differences that will change state when this
// action is applied.
return !getSelectedDifferences().isEmpty();
}
@Override
- protected Iterable<Diff> getSelectedDifferences(Iterable<Diff> diffs) {
- return filter(super.getSelectedDifferences(diffs), NON_CONFLICTING_DIFFS);
+ protected List<Diff> getSelectedDifferences(Stream<Diff> diffs) {
+ return super.getSelectedDifferences(diffs).stream()
+ .filter(guavaToJava(EMFComparePredicates.hasNoDirectOrIndirectConflict(REAL)))
+ .collect(Collectors.toList());
}
}
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedAction.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedAction.java
index d6a2ead64..88b10ed0b 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedAction.java
@@ -15,7 +15,7 @@ import static org.eclipse.emf.compare.DifferenceSource.RIGHT;
import static org.eclipse.emf.compare.internal.merge.MergeMode.ACCEPT;
import static org.eclipse.emf.compare.internal.merge.MergeMode.LEFT_TO_RIGHT;
-import com.google.common.base.Predicate;
+import java.util.function.Predicate;
import org.eclipse.compare.INavigatable;
import org.eclipse.emf.compare.Diff;
@@ -78,7 +78,7 @@ public class MergeContainedAction extends AbstractMergeContainedAction {
@Override
protected Predicate<Diff> getDiffPredicate() {
return new Predicate<Diff>() {
- public boolean apply(Diff input) {
+ public boolean test(Diff input) {
final DifferenceSource sourceSide;
if (LEFT_TO_RIGHT.equals(getSelectedMode()) || ACCEPT.equals(getSelectedMode())) {
sourceSide = LEFT;
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedConflictingAction.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedConflictingAction.java
index a15b808bc..127e3b854 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedConflictingAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedConflictingAction.java
@@ -11,8 +11,9 @@
package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
import static org.eclipse.emf.compare.ConflictKind.REAL;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.guavaToJava;
-import com.google.common.base.Predicate;
+import java.util.function.Predicate;
import org.eclipse.compare.INavigatable;
import org.eclipse.emf.compare.Diff;
@@ -38,10 +39,6 @@ import org.eclipse.ui.plugin.AbstractUIPlugin;
*/
public class MergeContainedConflictingAction extends AbstractMergeContainedAction {
- @SuppressWarnings("unchecked")
- private static final Predicate<Diff> CONFLICTING_DIFFS = (Predicate<Diff>)EMFComparePredicates
- .hasDirectOrIndirectConflict(REAL);
-
/**
* {@inheritDoc}
*
@@ -97,15 +94,16 @@ public class MergeContainedConflictingAction extends AbstractMergeContainedActio
return new MergeConflictingRunnable(isLeftEditable, isRightEditable, mode, relationshipComputer);
}
+ @SuppressWarnings("unchecked")
@Override
protected Predicate<Diff> getDiffPredicate() {
- return CONFLICTING_DIFFS;
+ return (Predicate<Diff>)guavaToJava(EMFComparePredicates.hasDirectOrIndirectConflict(REAL));
}
@Override
protected Predicate<Diff> getStatePredicate() {
return new Predicate<Diff>() {
- public boolean apply(Diff diff) {
+ public boolean test(Diff diff) {
switch (diff.getState()) {
case DISCARDED:
switch (getSelectedMode()) {
diff --git a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedNonConflictingAction.java b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedNonConflictingAction.java
index fcc30700b..2c80e1d94 100644
--- a/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedNonConflictingAction.java
+++ b/plugins/org.eclipse.emf.compare.ide.ui/src/org/eclipse/emf/compare/ide/ui/internal/structuremergeviewer/actions/MergeContainedNonConflictingAction.java
@@ -12,8 +12,9 @@
package org.eclipse.emf.compare.ide.ui.internal.structuremergeviewer.actions;
import static org.eclipse.emf.compare.ConflictKind.REAL;
+import static org.eclipse.emf.compare.utils.EMFComparePredicates.guavaToJava;
-import com.google.common.base.Predicate;
+import java.util.function.Predicate;
import org.eclipse.compare.INavigatable;
import org.eclipse.emf.compare.Diff;
@@ -38,10 +39,6 @@ import org.eclipse.ui.plugin.AbstractUIPlugin;
*/
public class MergeContainedNonConflictingAction extends AbstractMergeContainedAction {
- @SuppressWarnings("unchecked")
- private static final Predicate<Diff> NON_CONFLICTING_DIFFS = (Predicate<Diff>)EMFComparePredicates
- .hasNoDirectOrIndirectConflict(REAL);
-
/**
* {@inheritDoc}
*
@@ -94,8 +91,9 @@ public class MergeContainedNonConflictingAction extends AbstractMergeContainedAc
return new MergeNonConflictingRunnable(isLeftEditable, isRightEditable, mode, relationshipComputer);
}
+ @SuppressWarnings("unchecked")
@Override
protected Predicate<Diff> getDiffPredicate() {
- return NON_CONFLICTING_DIFFS;
+ return (Predicate<Diff>)guavaToJava(EMFComparePredicates.hasNoDirectOrIndirectConflict(REAL));
}
}
diff --git a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/provider/TreeNodeItemProviderSpec.java b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/provider/TreeNodeItemProviderSpec.java
index 3426e7795..74d746f4b 100644
--- a/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/provider/TreeNodeItemProviderSpec.java
+++ b/plugins/org.eclipse.emf.compare.rcp.ui/src/org/eclipse/emf/compare/rcp/ui/internal/structuremergeviewer/groups/provider/TreeNodeItemProviderSpec.java
@@ -114,6 +114,9 @@ public class TreeNodeItemProviderSpec extends TreeNodeItemProvider implements II
if (data instanceof Comparison) {
IDifferenceGroupProvider groupProvider = (IDifferenceGroupProvider)EcoreUtil
.getExistingAdapter(treeNode, IDifferenceGroupProvider.class);
+ if (groupProvider == null) {
+ return ImmutableList.of();
+ }
Comparison comparison = (Comparison)data;
Collection<? extends IDifferenceGroup> groups = groupProvider.getGroups(comparison);
if (groups.isEmpty()) {
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/StereotypeApplicationConflictTests.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/StereotypeApplicationConflictTests.java
new file mode 100644
index 000000000..048772d9f
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/StereotypeApplicationConflictTests.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * Copyright (c) 2014, 2017 Obeo 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Obeo - initial API and implementation
+ * Christian W. Damus - bug 522080
+ *******************************************************************************/
+package org.eclipse.emf.compare.uml2.tests.stereotypes;
+
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.eclipse.emf.common.EMFPlugin;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.compare.Comparison;
+import org.eclipse.emf.compare.ConflictKind;
+import org.eclipse.emf.compare.Diff;
+import org.eclipse.emf.compare.uml2.profile.test.uml2comparetestprofile.UML2CompareTestProfilePackage;
+import org.eclipse.emf.compare.uml2.tests.AbstractUMLInputData;
+import org.eclipse.emf.compare.uml2.tests.stereotypes.data.conflict.StereotypeApplicationConflictInputData;
+import org.eclipse.emf.compare.utils.EMFComparePredicates;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.uml2.uml.UMLPlugin;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Tests add-add scenarios for stereotype applications (same stereotype applied to same element on both
+ * sides).
+ */
+@SuppressWarnings("nls")
+public class StereotypeApplicationConflictTests extends AbstractStereotypedElementChangeTests {
+
+ private StereotypeApplicationConflictInputData input;
+
+ /**
+ * Initializes me.
+ */
+ public StereotypeApplicationConflictTests() {
+ super();
+ }
+
+ /**
+ * Tests add-add conflict for a stereotype that defines no attributes.
+ */
+ @Test
+ public void testApplyApplyPseudoConflictStereotypeNoAttributes() throws IOException {
+ final Comparison comparison = compare(input.getA1Left(), input.getA1Right(), input.getA1Base());
+ EList<Diff> differences = comparison.getDifferences();
+
+ assertThat(differences, hasItem(hasDirectOrIndirectConflict(ConflictKind.PSEUDO)));
+ assertThat(differences, not(hasItem(hasDirectOrIndirectConflict(ConflictKind.REAL))));
+ }
+
+ /**
+ * Tests add-add conflict for a stereotype that defines attributes where all attributes on both sides are
+ * equal.
+ */
+ @Test
+ public void testApplyApplyPseudoConflictStereotypeWithAttributes() throws IOException {
+ final Comparison comparison = compare(input.getA2Left(), input.getA2Right(), input.getA2Base());
+ EList<Diff> differences = comparison.getDifferences();
+
+ assertThat(differences, hasItem(hasDirectOrIndirectConflict(ConflictKind.PSEUDO)));
+ assertThat(differences, not(hasItem(hasDirectOrIndirectConflict(ConflictKind.REAL))));
+ }
+
+ /**
+ * Tests add-add conflict for a stereotype that defines attributes where the two sides have different
+ * attribute values.
+ */
+ @Test
+ public void testApplyApplyConflictStereotypeWithAttributes() throws IOException {
+ final Comparison comparison = compare(input.getA3Left(), input.getA3Right(), input.getA3Base());
+ EList<Diff> differences = comparison.getDifferences();
+
+ assertThat(differences, hasItem(hasDirectOrIndirectConflict(ConflictKind.REAL)));
+ }
+
+ /**
+ * Tests add-add conflict for a stereotype that defines attributes where all attributes on both sides are
+ * equal.
+ */
+ @Test
+ public void testApplyApplyPseudoConflictStereotypeWithReferences() throws IOException {
+ final Comparison comparison = compare(input.getA4Left(), input.getA4Right(), input.getA4Base());
+ EList<Diff> differences = comparison.getDifferences();
+
+ assertThat(differences, hasItem(hasDirectOrIndirectConflict(ConflictKind.PSEUDO)));
+ assertThat(differences, not(hasItem(hasDirectOrIndirectConflict(ConflictKind.REAL))));
+ }
+
+ /**
+ * Tests add-add conflict for a stereotype that defines attributes where the two sides have different
+ * attribute values.
+ */
+ @Test
+ public void testApplyApplyConflictStereotypeWithReferences() throws IOException {
+ final Comparison comparison = compare(input.getA5Left(), input.getA5Right(), input.getA5Base());
+ EList<Diff> differences = comparison.getDifferences();
+
+ assertThat(differences, hasItem(hasDirectOrIndirectConflict(ConflictKind.REAL)));
+ }
+
+ /**
+ * Tests delete-delete pseudoconflict for a stereotype that is unapplied on both sides.
+ */
+ @Test
+ public void testUnpplyUnapplyPseudoconflictStereotypeWithAttributes() throws IOException {
+ final Comparison comparison = compare(input.getA6Left(), input.getA6Right(), input.getA6Base());
+ EList<Diff> differences = comparison.getDifferences();
+
+ assertThat(differences, hasItem(hasDirectOrIndirectConflict(ConflictKind.PSEUDO)));
+ }
+
+ //
+ // Test framework
+ //
+
+ @Override
+ protected AbstractUMLInputData getInput() {
+ return input;
+ }
+
+ @BeforeClass
+ public static void fillRegistriesForStatic() {
+ beforeClass();
+ if (!EMFPlugin.IS_ECLIPSE_RUNNING) {
+ EPackage.Registry.INSTANCE.put(UML2CompareTestProfilePackage.eNS_URI,
+ UML2CompareTestProfilePackage.eINSTANCE);
+
+ // It is required to link the EPackage to the UML package of the UML Profile
+ Map<String, URI> ePackageNsURIToProfileLocationMap = UMLPlugin
+ .getEPackageNsURIToProfileLocationMap();
+ ePackageNsURIToProfileLocationMap.put(UML2CompareTestProfilePackage.eNS_URI, URI.createURI(
+ "pathmap://UML_COMPARE_TESTS_PROFILE/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"));
+ }
+ }
+
+ @AfterClass
+ public static void resetRegistriesForStatic() {
+ if (!EMFPlugin.IS_ECLIPSE_RUNNING) {
+ UMLPlugin.getEPackageNsURIToProfileLocationMap().remove(UML2CompareTestProfilePackage.eNS_URI);
+ EPackage.Registry.INSTANCE.remove(UML2CompareTestProfilePackage.eNS_URI);
+ }
+ afterClass();
+ }
+
+ @Before
+ @Override
+ public void before() {
+ super.before();
+
+ input = new StereotypeApplicationConflictInputData();
+ }
+
+ static Matcher<Diff> hasDirectOrIndirectConflict(final ConflictKind... ofKind) {
+ return new TypeSafeMatcher<Diff>() {
+ public void describeTo(Description description) {
+ description.appendText("has ") //
+ .appendValueList("", " or ", "", ofKind) //
+ .appendText(" conflict");
+ }
+
+ @Override
+ protected boolean matchesSafely(Diff item) {
+ return EMFComparePredicates.hasDirectOrIndirectConflict(ofKind).apply(item);
+ }
+ };
+ }
+}
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/StereotypeApplicationConflictInputData.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/StereotypeApplicationConflictInputData.java
new file mode 100644
index 000000000..c9d451c58
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/StereotypeApplicationConflictInputData.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Christian W. Damus 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
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Christian W. Damus - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.emf.compare.uml2.tests.stereotypes.data.conflict;
+
+import java.io.IOException;
+
+import org.eclipse.emf.compare.uml2.tests.AbstractUMLInputData;
+import org.eclipse.emf.ecore.resource.Resource;
+
+public class StereotypeApplicationConflictInputData extends AbstractUMLInputData {
+
+ public Resource getA1Base() throws IOException {
+ return loadFromClassLoader("a1/origin.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA1Left() throws IOException {
+ return loadFromClassLoader("a1/left.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA1Right() throws IOException {
+ return loadFromClassLoader("a1/right.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA2Base() throws IOException {
+ return loadFromClassLoader("a2/origin.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA2Left() throws IOException {
+ return loadFromClassLoader("a2/left.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA2Right() throws IOException {
+ return loadFromClassLoader("a2/right.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA3Base() throws IOException {
+ return loadFromClassLoader("a3/origin.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA3Left() throws IOException {
+ return loadFromClassLoader("a3/left.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA3Right() throws IOException {
+ return loadFromClassLoader("a3/right.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA4Base() throws IOException {
+ return loadFromClassLoader("a4/origin.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA4Left() throws IOException {
+ return loadFromClassLoader("a4/left.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA4Right() throws IOException {
+ return loadFromClassLoader("a4/right.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA5Base() throws IOException {
+ return loadFromClassLoader("a5/origin.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA5Left() throws IOException {
+ return loadFromClassLoader("a5/left.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA5Right() throws IOException {
+ return loadFromClassLoader("a5/right.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA6Base() throws IOException {
+ return loadFromClassLoader("a6/origin.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA6Left() throws IOException {
+ return loadFromClassLoader("a6/left.uml"); //$NON-NLS-1$
+ }
+
+ public Resource getA6Right() throws IOException {
+ return loadFromClassLoader("a6/right.uml"); //$NON-NLS-1$
+ }
+
+}
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/left.uml
new file mode 100644
index 000000000..540c645e5
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/left.uml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:standard="http://www.eclipse.org/uml2/5.0.0/UML/Profile/Standard" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_12E9QLjyEeeVg_HuOthLOA">
+ <eAnnotations xmi:id="_12E9QbjyEeeVg_HuOthLOA" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/uml2/5.0.0/UML/Profile/Standard#/"/>
+ </eAnnotations>
+ <appliedProfile href="pathmap://UML_PROFILES/Standard.profile.uml#_0"/>
+ </profileApplication>
+ </uml:Model>
+ <standard:Utility xmi:id="_7M_-oLjyEeeVg_HuOthLOA" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/origin.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/origin.uml
new file mode 100644
index 000000000..a236c69d7
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/origin.uml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_12E9QLjyEeeVg_HuOthLOA">
+ <eAnnotations xmi:id="_12E9QbjyEeeVg_HuOthLOA" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/uml2/5.0.0/UML/Profile/Standard#/"/>
+ </eAnnotations>
+ <appliedProfile href="pathmap://UML_PROFILES/Standard.profile.uml#_0"/>
+ </profileApplication>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/right.uml
new file mode 100644
index 000000000..bad67919f
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a1/right.uml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:standard="http://www.eclipse.org/uml2/5.0.0/UML/Profile/Standard" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_12E9QLjyEeeVg_HuOthLOA">
+ <eAnnotations xmi:id="_12E9QbjyEeeVg_HuOthLOA" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/uml2/5.0.0/UML/Profile/Standard#/"/>
+ </eAnnotations>
+ <appliedProfile href="pathmap://UML_PROFILES/Standard.profile.uml#_0"/>
+ </profileApplication>
+ </uml:Model>
+ <standard:Utility xmi:id="_9GhFALjyEeeVg_HuOthLOA" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/left.uml
new file mode 100644
index 000000000..36db0c8e7
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/left.uml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testProfile="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+ </uml:Model>
+ <testProfile:ACliche xmi:id="_lLJboPzmEeGvprorRl_paQ" singleValuedAttribute="bar" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/origin.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/origin.uml
new file mode 100644
index 000000000..9559588c1
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/origin.uml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/right.uml
new file mode 100644
index 000000000..a0f7622c0
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a2/right.uml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testProfile="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+ </uml:Model>
+ <testProfile:ACliche xmi:id="_DgvBULjxEeeVg_HuOthLOA" singleValuedAttribute="bar" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/left.uml
new file mode 100644
index 000000000..9def561c9
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/left.uml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testProfile="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+ </uml:Model>
+ <testProfile:ACliche xmi:id="_lLJboPzmEeGvprorRl_paQ" singleValuedAttribute="baz" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/origin.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/origin.uml
new file mode 100644
index 000000000..9559588c1
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/origin.uml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/right.uml
new file mode 100644
index 000000000..a0f7622c0
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a3/right.uml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testProfile="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+ </uml:Model>
+ <testProfile:ACliche xmi:id="_DgvBULjxEeeVg_HuOthLOA" singleValuedAttribute="bar" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/left.uml
new file mode 100644
index 000000000..c15a0e099
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/left.uml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testProfile="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_bv63ALmSEee3h-90p9bUpQ" name="Bar"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_b4ngALmSEee3h-90p9bUpQ" name="Baz"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+ </uml:Model>
+ <testProfile:ACliche xmi:id="_lLJboPzmEeGvprorRl_paQ" manyValuedReference="_bv63ALmSEee3h-90p9bUpQ _b4ngALmSEee3h-90p9bUpQ" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/origin.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/origin.uml
new file mode 100644
index 000000000..64fde5208
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/origin.uml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_bv63ALmSEee3h-90p9bUpQ" name="Bar"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_b4ngALmSEee3h-90p9bUpQ" name="Baz"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/right.uml
new file mode 100644
index 000000000..337652f5c
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a4/right.uml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testProfile="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_bv63ALmSEee3h-90p9bUpQ" name="Bar"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_b4ngALmSEee3h-90p9bUpQ" name="Baz"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+ </uml:Model>
+ <testProfile:ACliche xmi:id="_DgvBULjxEeeVg_HuOthLOA" manyValuedReference="_bv63ALmSEee3h-90p9bUpQ _b4ngALmSEee3h-90p9bUpQ" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/left.uml
new file mode 100644
index 000000000..ee12fe3c0
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/left.uml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testProfile="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_bv63ALmSEee3h-90p9bUpQ" name="Bar"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_b4ngALmSEee3h-90p9bUpQ" name="Baz"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+ </uml:Model>
+ <testProfile:ACliche xmi:id="_lLJboPzmEeGvprorRl_paQ" manyValuedReference="_b4ngALmSEee3h-90p9bUpQ _bv63ALmSEee3h-90p9bUpQ" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/origin.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/origin.uml
new file mode 100644
index 000000000..64fde5208
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/origin.uml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_bv63ALmSEee3h-90p9bUpQ" name="Bar"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_b4ngALmSEee3h-90p9bUpQ" name="Baz"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/right.uml
new file mode 100644
index 000000000..337652f5c
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a5/right.uml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testProfile="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_bv63ALmSEee3h-90p9bUpQ" name="Bar"/>
+ <packagedElement xmi:type="uml:Class" xmi:id="_b4ngALmSEee3h-90p9bUpQ" name="Baz"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+ </uml:Model>
+ <testProfile:ACliche xmi:id="_DgvBULjxEeeVg_HuOthLOA" manyValuedReference="_bv63ALmSEee3h-90p9bUpQ _b4ngALmSEee3h-90p9bUpQ" base_Class="_MNDVkPr8EeCcXd0vrIzyPg"/>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/left.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/left.uml
new file mode 100644
index 000000000..9559588c1
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/left.uml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/origin.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/origin.uml
new file mode 100644
index 000000000..f3aaf88a2
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/origin.uml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xmi:XMI xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:testProfile="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+ <uml:Model xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+ </uml:Model>
+ <testProfile:ACliche xmi:id="_lLJboPzmEeGvprorRl_paQ" singleValuedAttribute="baz" base_Class="_MNDVkPr8EeCcXd0vrIzyPg">
+ <manyValuedAttribute>foo</manyValuedAttribute>
+ <manyValuedAttribute>bar</manyValuedAttribute>
+ </testProfile:ACliche>
+</xmi:XMI>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/right.uml b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/right.uml
new file mode 100644
index 000000000..9559588c1
--- /dev/null
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/stereotypes/data/conflict/a6/right.uml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Model xmi:version="20131001" xmlns:xmi="http://www.omg.org/spec/XMI/20131001" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML" xmi:id="_GfO3Ifr8EeCcXd0vrIzyPg" name="model">
+ <packagedElement xmi:type="uml:Class" xmi:id="_MNDVkPr8EeCcXd0vrIzyPg" name="Foo"/>
+ <profileApplication xmi:id="_jAMnAPzmEeGvprorRl_paQ">
+ <eAnnotations xmi:id="_jAMnAfzmEeGvprorRl_paQ" source="http://www.eclipse.org/uml2/2.0.0/UML">
+ <references xmi:type="ecore:EPackage" href="http://www.eclipse.org/emf/compare/uml2/1.0.0/testprofile#/"/>
+ </eAnnotations>
+ <appliedProfile href="platform:/plugin/org.eclipse.emf.compare.uml2.tests/model/uml2.compare.testprofile.profile.uml#_hZFTgIwkEeC_FYHMbTTxXw"/>
+ </profileApplication>
+</uml:Model>
diff --git a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java
index 752546d66..8f7e2552f 100644
--- a/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java
+++ b/plugins/org.eclipse.emf.compare.uml2.tests/src/org/eclipse/emf/compare/uml2/tests/suite/AllTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012, 2016 Obeo and others.
+ * Copyright (c) 2012, 2019 Obeo 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
@@ -11,6 +11,7 @@
* Stefan Dirix - addition of PseudoConflictTest
* Martin Fleck - addition of RemoveStereotypeApplicationPseudoConflictTest
* Martin Fleck - addition of AddMessageSubDiffTest
+ * Christian W. Damus - bug 522080
*******************************************************************************/
package org.eclipse.emf.compare.uml2.tests.suite;
@@ -53,6 +54,7 @@ import org.eclipse.emf.compare.uml2.tests.stereotypes.DynamicStereotypeTest;
import org.eclipse.emf.compare.uml2.tests.stereotypes.DynamicStereotypedElementChangeTests;
import org.eclipse.emf.compare.uml2.tests.stereotypes.StaticStereotypeTest;
import org.eclipse.emf.compare.uml2.tests.stereotypes.StaticStereotypedElementChangeTests;
+import org.eclipse.emf.compare.uml2.tests.stereotypes.StereotypeApplicationConflictTests;
import org.eclipse.emf.compare.uml2.tests.timeConstraint.AddTimeConstraintTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -83,7 +85,8 @@ import junit.textui.TestRunner;
OpaqueElementBodyChangeDiffTest.class, OpaqueElementBodyChangeMergeTest.class,
DanglingStereotypeApplicationTest.class, TestNonRegPseudoConflict_484576.class,
RemoveStereotypeApplicationPseudoConflictTest.class, MultiplicityElementChangesTest.class,
- InstanceSpecificationClassifiersMergeTest.class, AddMessageSubDiffTest.class, })
+ InstanceSpecificationClassifiersMergeTest.class, AddMessageSubDiffTest.class,
+ StereotypeApplicationConflictTests.class, })
public class AllTests {
/**
diff --git a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/StereotypedElementChangePostProcessor.java b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/StereotypedElementChangePostProcessor.java
index 43be1311d..fd46f9df1 100644
--- a/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/StereotypedElementChangePostProcessor.java
+++ b/plugins/org.eclipse.emf.compare.uml2/src/org/eclipse/emf/compare/uml2/internal/postprocessor/StereotypedElementChangePostProcessor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2014 Obeo.
+ * Copyright (c) 2014, 2019 Obeo 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
@@ -7,15 +7,30 @@
*
* Contributors:
* Obeo - initial API and implementation
+ * Christian W. Damus - bug 522080
*******************************************************************************/
package org.eclipse.emf.compare.uml2.internal.postprocessor;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
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.ComparisonCanceledException;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.Match;
+import org.eclipse.emf.compare.diff.DefaultDiffEngine;
+import org.eclipse.emf.compare.diff.FeatureFilter;
import org.eclipse.emf.compare.postprocessor.IPostProcessor;
import org.eclipse.emf.compare.uml2.internal.postprocessor.extension.stereotype.UMLStereotypedElementChangeFactory;
+import org.eclipse.emf.compare.uml2.internal.postprocessor.util.UMLCompareUtil;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+import org.eclipse.uml2.uml.Element;
/**
* Post processor that creates the {@link org.eclipse.emf.compare.uml2.internal.StereotypedElementChange} in
@@ -36,6 +51,27 @@ public class StereotypedElementChangePostProcessor implements IPostProcessor {
* @see org.eclipse.emf.compare.postprocessor.IPostProcessor#postMatch(Comparison , Monitor)
*/
public void postMatch(Comparison comparison, Monitor monitor) {
+ // Re-match applications and unapplications of the same stereotypes to/from
+ // the same base elements
+ Map<Match, Map<URI, Match>> leftApplications = new HashMap<>();
+ Map<Match, Map<URI, Match>> rightApplications = new HashMap<>();
+ mapStereotypeApplications(comparison, leftApplications, rightApplications);
+
+ for (Map.Entry<Match, Map<URI, Match>> left : leftApplications.entrySet()) {
+ EObject base = left.getKey();
+ Map<URI, Match> right = rightApplications.get(base);
+ if (right != null) {
+ for (Map.Entry<URI, Match> next : left.getValue().entrySet()) {
+ Match rightMatch = right.get(next.getKey());
+ if (rightMatch != null) {
+ // Complete the left match
+ next.getValue().setRight(rightMatch.getRight());
+ // Drop the right match from the comparison
+ EcoreUtil.remove(rightMatch);
+ }
+ }
+ }
+ }
}
/**
@@ -43,7 +79,21 @@ public class StereotypedElementChangePostProcessor implements IPostProcessor {
*
* @see org.eclipse.emf.compare.postprocessor.IPostProcessor#postDiff(Comparison , Monitor)
*/
- public void postDiff(Comparison comparison, Monitor monitor) {
+ public void postDiff(final Comparison comparison, Monitor monitor) {
+ // We only need to do this for three-way comparisons to check for conflicts
+ // in stereotypes applied to the same elemnt on both sides but with different
+ // values
+ if (comparison.isThreeWay()) {
+ AttributeDiffEngine engine = new AttributeDiffEngine();
+ for (Match next : comparison.getMatches()) {
+ if (next.getOrigin() == null && next.getLeft() != null && next.getRight() != null) {
+ // Is it an add-add of a stereotype application?
+ if (isStereotypeApplication(next.getLeft())) {
+ engine.checkForDifferences(next, monitor);
+ }
+ }
+ }
+ }
}
/**
@@ -90,4 +140,174 @@ public class StereotypedElementChangePostProcessor implements IPostProcessor {
}
}
+ /**
+ * Compute maps of left- and right-side dangling matches of stereotype applications and unapplications.
+ * These map the {@link Match} for a base UML element to mappings of stereotypes (by {@link URI} of the
+ * definition) to matches for the stereotype application, itself.
+ *
+ * @param comparison
+ * the comparison in which to map stereotype application matches
+ * @param leftApplications
+ * the map of left-side matches to populate
+ * @param rightApplications
+ * the map of right-side matches to populate
+ */
+ protected void mapStereotypeApplications(Comparison comparison,
+ Map<Match, Map<URI, Match>> leftApplications, Map<Match, Map<URI, Match>> rightApplications) {
+ for (Match next : comparison.getMatches()) {
+ if (next.getLeft() != null && next.getRight() == null) {
+ // Unmatched left. Is it a stereotype application?
+ Match base = comparison.getMatch(getBaseElement(next.getLeft()));
+ if (base != null) {
+ // Map it
+ put(leftApplications, base, getStereotypeURI(next.getLeft()), next);
+ }
+ } else if (next.getRight() != null && next.getLeft() == null) {
+ // Unmatched right. Is it a stereotype application?
+ Match base = comparison.getMatch(getBaseElement(next.getRight()));
+ if (base != null) {
+ // Map it
+ put(rightApplications, base, getStereotypeURI(next.getRight()), next);
+ }
+ }
+ }
+ }
+
+ /**
+ * Obtains the URI of a stereotype application's type, for comparison independent of resource set context.
+ *
+ * @param stereotypeApplication
+ * a stereotype applicatkion
+ * @return the URI of its defining (stereo)type
+ */
+ private static URI getStereotypeURI(EObject stereotypeApplication) {
+ return EcoreUtil.getURI(stereotypeApplication.eClass());
+ }
+
+ /**
+ * Puts a value into a two-level map of maps.
+ *
+ * @param mapOfMaps
+ * the map
+ * @param key1
+ * the first level key
+ * @param key2
+ * the second level key
+ * @param value
+ * the value
+ * @return the previous value for these keys, if or {@code null} if there was none
+ * @param <K>
+ * the top level key type
+ * @param <L>
+ * the second level key type
+ * @param <V>
+ * the value type
+ */
+ private static <K, L, V> V put(Map<K, Map<L, V>> mapOfMaps, K key1, L key2, V value) {
+ Map<L, V> map = mapOfMaps.get(key1);
+ if (map == null) {
+ map = new HashMap<>();
+ mapOfMaps.put(key1, map);
+ }
+ return map.put(key2, value);
+ }
+
+ /**
+ * Queries whether an {@code object} is a stereotype application.
+ *
+ * @param object
+ * an object
+ * @return {@code true} if it is a stereotype application; {@code false}, otherwise
+ */
+ protected boolean isStereotypeApplication(EObject object) {
+ return getBaseElement(object) != null;
+ }
+
+ /**
+ * Gets the base element of an {@code object} if that a stereotype application.
+ *
+ * @param object
+ * an object
+ * @return its base element if it is a stereotype application; {@code null}, otherwise
+ */
+ protected Element getBaseElement(EObject object) {
+ Element result = null;
+
+ if (object.eContainer() == null) {
+ result = UMLCompareUtil.getBaseElement(object);
+ }
+
+ return result;
+ }
+
+ //
+ // Nested types
+ //
+
+ /**
+ * <p>
+ * Explicit diff engine for attributes of added stereotype applications.
+ * </p>
+ * <p>
+ * The default diff engine doesn't attempt to compare attributes of added elements. However, stereotype
+ * applications are special because they are extensions of other elements that are not added (because they
+ * would not be matched if the base elements were added, which in turn would not have been matched).
+ * </p>
+ */
+ protected class AttributeDiffEngine extends DefaultDiffEngine {
+ /**
+ * Initializes me.
+ */
+ public AttributeDiffEngine() {
+ super();
+ }
+
+ @Override
+ protected void checkForDifferences(Match match, Monitor monitor) {
+ if (monitor.isCanceled()) {
+ throw new ComparisonCanceledException();
+ }
+
+ final FeatureFilter featureFilter = createFeatureFilter();
+ final Iterator<EAttribute> attributes = featureFilter.getAttributesToCheck(match);
+ while (attributes.hasNext()) {
+ final EAttribute attribute = attributes.next();
+ final boolean considerOrdering = featureFilter.checkForOrderingChanges(attribute);
+ computeDifferences(match, attribute, considerOrdering);
+ }
+
+ for (Match submatch : match.getSubmatches()) {
+ checkForDifferences(submatch, monitor);
+ }
+ }
+
+ @Override
+ protected void computeDifferences(Match match, EAttribute attribute, boolean checkOrdering) {
+ // We *do* care about "attribute" changes on added stereotype applications,
+ // but not removed
+ boolean shortcut = match.getLeft() == null || match.getRight() == null;
+
+ // Do not shortcut when manyvalued FeatureMaps are affected to keep their ordering intact
+ if (shortcut && FeatureMapUtil.isFeatureMap(attribute)) {
+ if (FeatureMapUtil.isMany(match.getLeft(), attribute)) {
+ shortcut = false;
+ }
+ }
+
+ if (shortcut) {
+ return;
+ }
+
+ if (attribute.isMany()) {
+ if (match.getComparison().isThreeWay()) {
+ computeMultiValuedFeatureDifferencesThreeWay(match, attribute, checkOrdering);
+ } else {
+ computeMultiValuedFeatureDifferencesTwoWay(match, attribute, checkOrdering);
+ }
+ } else {
+ computeSingleValuedAttributeDifferences(match, attribute);
+ }
+ }
+ }
+
}
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/conflict/AbstractConflictSearch.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/conflict/AbstractConflictSearch.java
index 90592af95..aad205e26 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/conflict/AbstractConflictSearch.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/internal/conflict/AbstractConflictSearch.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016 Obeo.
+ * Copyright (c) 2016, 2017 Obeo 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
@@ -7,6 +7,7 @@
*
* Contributors:
* Obeo - initial API and implementation
+ * Christian W. Damus - bug 522080
*******************************************************************************/
package org.eclipse.emf.compare.internal.conflict;
@@ -186,7 +187,15 @@ public abstract class AbstractConflictSearch<T extends Diff> {
final String changedValue2 = getChangedValue(diff2);
final EObject originalContainer = diff1.getMatch().getOrigin();
final EAttribute changedAttribute = diff1.getAttribute();
- final String originalValue = (String)ReferenceUtil.safeEGet(originalContainer, changedAttribute);
+ final String originalValue;
+
+ if (originalContainer == null) {
+ // Owner is added to both sides
+ originalValue = null;
+ } else {
+ originalValue = (String)ReferenceUtil.safeEGet(originalContainer, changedAttribute);
+ }
+
return isMergeableText(changedValue1, changedValue2, originalValue);
}
diff --git a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java
index 56d266466..b1906dfa2 100644
--- a/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java
+++ b/plugins/org.eclipse.emf.compare/src/org/eclipse/emf/compare/utils/EMFComparePredicates.java
@@ -1280,6 +1280,23 @@ public final class EMFComparePredicates {
}
/**
+ * Guava predicates and functions are only aligned in recent versions of Guava. This is necessary to
+ * maintain compatibility with guava 15 and can be removed as soon as we drop compatibility with older
+ * guava versions.
+ *
+ * @param guava
+ * The guava predicate.
+ * @return The java predicate.
+ */
+ public static <T> java.util.function.Predicate<T> guavaToJava(Predicate<T> guava) {
+ return new java.util.function.Predicate<T>() {
+ public boolean test(T input) {
+ return guava.apply(input);
+ }
+ };
+ }
+
+ /**
* This particular predicate will be used to check that a given Diff corresponds to a ReferenceChange on a
* given reference, with known "original" and "changed" values.
*

Back to the top