Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvlorenzo2012-05-03 05:01:59 -0400
committervlorenzo2012-05-03 05:01:59 -0400
commit204bafd806c8828a2e914c7d9c2ea67888f639e4 (patch)
treeae0cde8411c09018e600487b32b346a0eb28a118 /sandbox/UMLCompareMergerExample
parent7174ae797f528be78da12c60c2f7427853eb4375 (diff)
downloadorg.eclipse.papyrus-204bafd806c8828a2e914c7d9c2ea67888f639e4.tar.gz
org.eclipse.papyrus-204bafd806c8828a2e914c7d9c2ea67888f639e4.tar.xz
org.eclipse.papyrus-204bafd806c8828a2e914c7d9c2ea67888f639e4.zip
342163: [Usability] Papyrus merge should use the service edit of Papyrus
https://bugs.eclipse.org/bugs/show_bug.cgi?id=342163 A save of my work
Diffstat (limited to 'sandbox/UMLCompareMergerExample')
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/AbstractFireMergeCommand.java76
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeDiffEndCommand.java43
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeDiffStartCommand.java43
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeOperationEndCommand.java52
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeOperationStartCommand.java52
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeChangeLeftTargetMerger.java157
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeChangeRightTargetMerger.java158
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeOrderChangeMerger.java271
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDefaultExtensionMerger.java21
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDiffExtensionMerger.java21
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDiffGroupMerger.java122
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CModelElementChangeLeftTargetMerger.java206
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CModelElementChangeRightTargetMerger.java203
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CMoveModelElementMerger.java214
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceChangeLeftTargetMerger.java227
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceChangeRightTargetMerger.java224
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceOrderChangeMerger.java161
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CUpdateAttributeMerger.java146
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CUpdateReferenceMerger.java178
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/EObjectComparator.java68
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MergerUtils.java62
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MoveWithIndexCommand.java136
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MoveWithIndexRequest.java56
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusCompareEObjectCopier.java299
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusEFactory.java301
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusMap.java104
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PositionAdapter.java48
-rw-r--r--sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/TransactionalMergeService.java311
28 files changed, 3960 insertions, 0 deletions
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/AbstractFireMergeCommand.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/AbstractFireMergeCommand.java
new file mode 100644
index 00000000000..d6891b822c2
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/AbstractFireMergeCommand.java
@@ -0,0 +1,76 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.commands;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.emf.common.command.AbstractCommand;
+import org.eclipse.emf.compare.diff.merge.IMergeListener;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+
+
+public abstract class AbstractFireMergeCommand extends AbstractCommand {
+
+ /**
+ * the list of the listeners
+ */
+ private final List<IMergeListener> listeners;
+
+ /**
+ * a list of the diff element
+ */
+ private final List<DiffElement> diffs;
+
+ private final DiffElement diffElement;
+
+ public AbstractFireMergeCommand(final DiffElement diffElement, final List<IMergeListener> listeners) {
+ this.diffElement = diffElement;
+ this.diffs = Collections.emptyList();
+ this.listeners = new ArrayList<IMergeListener>(listeners);
+ }
+
+ public AbstractFireMergeCommand(final List<DiffElement> diffs, final List<IMergeListener> listeners) {
+ this.diffElement = null;
+ this.diffs = new ArrayList<DiffElement>(diffs);
+ this.listeners = new ArrayList<IMergeListener>(listeners);
+ }
+
+ public boolean canRedo() {
+ return canExecute();
+ }
+
+ public List<IMergeListener> getMergeListeners() {
+ return Collections.unmodifiableList(listeners);
+ }
+
+ public List<DiffElement> getDiffElementsList() {
+ return Collections.unmodifiableList(this.diffs);
+ }
+
+ public DiffElement getDiffElement() {
+ return this.diffElement;
+ }
+
+ @Override
+ protected boolean prepare() {
+ return true;
+ }
+
+ public void redo() {
+ execute();
+
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeDiffEndCommand.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeDiffEndCommand.java
new file mode 100644
index 00000000000..ed68eb4a088
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeDiffEndCommand.java
@@ -0,0 +1,43 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.commands;
+
+import java.util.List;
+
+import org.eclipse.emf.compare.diff.merge.IMergeListener;
+import org.eclipse.emf.compare.diff.merge.MergeEvent;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+
+
+public class FireMergeDiffEndCommand extends AbstractFireMergeCommand {
+
+ public FireMergeDiffEndCommand(final DiffElement diffElement, final List<IMergeListener> listeners) {
+ super(diffElement, listeners);
+ }
+
+ public void execute() {
+ List<IMergeListener> listeners = getMergeListeners();
+ if(getDiffElement() != null) {
+ for(IMergeListener current : listeners) {
+ current.mergeDiffStart(new MergeEvent(getDiffElement()));
+ }
+
+ }
+ }
+
+ @Override
+ public void undo() {
+ //TODO?
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeDiffStartCommand.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeDiffStartCommand.java
new file mode 100644
index 00000000000..dc0f23f2cf5
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeDiffStartCommand.java
@@ -0,0 +1,43 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.commands;
+
+import java.util.List;
+
+import org.eclipse.emf.compare.diff.merge.IMergeListener;
+import org.eclipse.emf.compare.diff.merge.MergeEvent;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+
+
+public class FireMergeDiffStartCommand extends AbstractFireMergeCommand {
+
+ public FireMergeDiffStartCommand(final DiffElement diffElement, final List<IMergeListener> listeners) {
+ super(diffElement, listeners);
+ }
+
+ public void execute() {
+ List<IMergeListener> listeners = getMergeListeners();
+ if(getDiffElement() != null) {
+ for(IMergeListener current : listeners) {
+ current.mergeDiffEnd(new MergeEvent(getDiffElement()));
+ }
+
+ }
+ }
+
+ @Override
+ public void undo() {
+ //TODO?
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeOperationEndCommand.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeOperationEndCommand.java
new file mode 100644
index 00000000000..d8afd27e6f2
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeOperationEndCommand.java
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.commands;
+
+import java.util.List;
+
+import org.eclipse.emf.compare.diff.merge.IMergeListener;
+import org.eclipse.emf.compare.diff.merge.MergeEvent;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+
+
+public class FireMergeOperationEndCommand extends AbstractFireMergeCommand {
+
+ public FireMergeOperationEndCommand(final DiffElement diffElement, final List<IMergeListener> listeners) {
+ super(diffElement, listeners);
+ }
+
+ public FireMergeOperationEndCommand(final List<DiffElement> diffs, final List<IMergeListener> listeners) {
+ super(diffs, listeners);
+ }
+
+ public void execute() {
+ List<IMergeListener> listeners = getMergeListeners();
+ if(!getDiffElementsList().isEmpty()) {
+ for(IMergeListener current : listeners) {
+ current.mergeOperationEnd(new MergeEvent(getDiffElementsList()));
+ }
+ }
+ if(getDiffElement() != null) {
+ for(IMergeListener current : listeners) {
+ current.mergeOperationEnd(new MergeEvent(getDiffElement()));
+ }
+
+ }
+ }
+
+ @Override
+ public void undo() {
+ //TODO?
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeOperationStartCommand.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeOperationStartCommand.java
new file mode 100644
index 00000000000..59c39d98ca7
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/commands/FireMergeOperationStartCommand.java
@@ -0,0 +1,52 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.commands;
+
+import java.util.List;
+
+import org.eclipse.emf.compare.diff.merge.IMergeListener;
+import org.eclipse.emf.compare.diff.merge.MergeEvent;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+
+
+public class FireMergeOperationStartCommand extends AbstractFireMergeCommand {
+
+ public FireMergeOperationStartCommand(final DiffElement diffElement, final List<IMergeListener> listeners) {
+ super(diffElement, listeners);
+ }
+
+ public FireMergeOperationStartCommand(final List<DiffElement> diffs, final List<IMergeListener> listeners) {
+ super(diffs, listeners);
+ }
+
+ public void execute() {
+ List<IMergeListener> listeners = getMergeListeners();
+ if(!getDiffElementsList().isEmpty()) {
+ for(IMergeListener current : listeners) {
+ current.mergeOperationStart(new MergeEvent(getDiffElementsList()));
+ }
+ }
+ if(getDiffElement() != null) {
+ for(IMergeListener current : listeners) {
+ current.mergeOperationStart(new MergeEvent(getDiffElement()));
+ }
+
+ }
+ }
+
+ @Override
+ public void undo() {
+ //TODO?
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeChangeLeftTargetMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeChangeLeftTargetMerger.java
new file mode 100644
index 00000000000..5e1ad0f971e
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeChangeLeftTargetMerger.java
@@ -0,0 +1,157 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import java.util.List;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.EMFComparePlugin;
+import org.eclipse.emf.compare.FactoryException;
+import org.eclipse.emf.compare.diff.internal.merge.impl.AttributeChangeLeftTargetMerger;
+import org.eclipse.emf.compare.diff.metamodel.AttributeChangeLeftTarget;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusEFactory;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+
+
+public class CAttributeChangeLeftTargetMerger extends AttributeChangeLeftTargetMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for AttributeChangeLeftTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for AttributeChangeLeftTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final AttributeChangeLeftTarget theDiff = (AttributeChangeLeftTarget)this.diff;
+ final EObject origin = theDiff.getLeftElement();
+ final Object value = theDiff.getLeftTarget();
+ final EAttribute attr = theDiff.getAttribute();
+ try {
+ cmd = PapyrusEFactory.getERemoveCommand(domain, origin, attr.getName(), value);
+ } catch (FactoryException e) {
+ EMFComparePlugin.log(e, true);
+ }
+ return cmd;
+ }
+
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final AttributeChangeLeftTarget theDiff = (AttributeChangeLeftTarget)this.diff;
+ final EObject target = theDiff.getRightElement();
+ final Object value = theDiff.getLeftTarget();
+ final EAttribute attr = theDiff.getAttribute();
+ try {
+ int valueIndex = -1;
+ if(attr.isMany()) {
+ final EObject leftElement = theDiff.getLeftElement();
+ final Object leftValues = leftElement.eGet(attr);
+ if(leftValues instanceof List) {
+ final List<?> leftValuesList = (List<?>)leftValues;
+ valueIndex = leftValuesList.indexOf(value);
+ }
+ }
+ cmd = PapyrusEFactory.getEAddCommand(domain, target, attr.getName(), value, valueIndex);
+ } catch (FactoryException e) {
+ Activator.log.error(e);
+ }
+ return cmd;
+
+ }
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CAttributeChangeLeftTargetMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CAttributeChangeLeftTargetMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeChangeRightTargetMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeChangeRightTargetMerger.java
new file mode 100644
index 00000000000..31ad88c9084
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeChangeRightTargetMerger.java
@@ -0,0 +1,158 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import java.util.List;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.FactoryException;
+import org.eclipse.emf.compare.diff.internal.merge.impl.AttributeChangeRightTargetMerger;
+import org.eclipse.emf.compare.diff.metamodel.AttributeChangeRightTarget;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusEFactory;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+
+
+public class CAttributeChangeRightTargetMerger extends AttributeChangeRightTargetMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.emf.compare.diff.merge.DefaultMerger#undoInTarget()
+ *
+ */
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for AttributeChangeRightTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for AttributeChangeRightTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final AttributeChangeRightTarget theDiff = (AttributeChangeRightTarget)this.diff;
+ final EObject origin = theDiff.getLeftElement();
+ final Object value = theDiff.getRightTarget();
+ final EAttribute attr = theDiff.getAttribute();
+ try {
+ int valueIndex = -1;
+ if (attr.isMany()) {
+ final EObject rightElement = theDiff.getRightElement();
+ final Object rightValues = rightElement.eGet(attr);
+ if (rightValues instanceof List) {
+ final List<?> rightValuesList = (List<?>)rightValues;
+ valueIndex = rightValuesList.indexOf(value);
+ }
+ }
+ cmd = PapyrusEFactory.getEAddCommand(domain, origin, attr.getName(), value, valueIndex);
+ } catch (FactoryException e) {
+ Activator.log.error(e);
+ }
+ return cmd;
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final AttributeChangeRightTarget theDiff = (AttributeChangeRightTarget)this.diff;
+ final EObject target = theDiff.getRightElement();
+ final Object value = theDiff.getRightTarget();
+ final EAttribute attr = theDiff.getAttribute();
+ try {
+ cmd = PapyrusEFactory.getERemoveCommand(domain, target, attr.getName(), value);
+ } catch (FactoryException e) {
+ Activator.log.error(e);
+ }
+ return cmd;
+ }
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CAttributeChangeRightTargetMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CAttributeChangeRightTargetMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeOrderChangeMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeOrderChangeMerger.java
new file mode 100644
index 00000000000..10c81924340
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CAttributeOrderChangeMerger.java
@@ -0,0 +1,271 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.diff.internal.merge.impl.AttributeOrderChangeMerger;
+import org.eclipse.emf.compare.diff.metamodel.AttributeOrderChange;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.infra.tools.util.ReflectHelper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+import org.eclipse.papyrus.uml.merger.internal.provider.PapyrusMergeCommandProvider;
+
+
+public class CAttributeOrderChangeMerger extends AttributeOrderChangeMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.emf.compare.diff.merge.DefaultMerger#undoInTarget()
+ *
+ */
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for AttributeOrderChangeMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for AttributeOrderChangeMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ final AttributeOrderChange theDiff = (AttributeOrderChange)this.diff;
+ final EAttribute attribute = theDiff.getAttribute();
+ final EObject leftElement = theDiff.getLeftElement();
+ final EObject rightElement = theDiff.getRightElement();
+
+ final List<Object> leftList = (List<Object>)leftElement.eGet(attribute);
+ final List<Object> rightList = (List<Object>)rightElement.eGet(attribute);
+
+ /*
+ * We need to transform the "left" list into the "right" list, modulo missing values. In practical
+ * terms, this means that we'll simply leave untouched any element that has no match in the "right"
+ * list (elements that were deleted) while reordering the others in the order they have in the "right"
+ * list.
+ */
+ final List<Object> leftCopy = new ArrayList<Object>(leftList);
+ final List<Object> result = new ArrayList<Object>(leftList.size());
+ // Add all unmatched values in the result list
+ for(int i = 0; i < leftList.size(); i++) {
+ final Object left = leftList.get(i);
+
+ boolean hasMatch = false;
+ for(int j = 0; !hasMatch && j < rightList.size(); j++) {
+ hasMatch = !areDistinctValues(left, rightList.get(j));
+ }
+
+ if(!hasMatch) {
+ leftCopy.remove(left);
+ result.add(left);
+ }
+ }
+ // Then reorder according to the right list's order
+ for(int i = 0; i < rightList.size(); i++) {
+ final Object right = rightList.get(i);
+
+ Object leftMatch = null;
+ for(int j = 0; leftMatch == null && j < leftCopy.size(); j++) {
+ if(!areDistinctValues(right, leftCopy.get(j))) {
+ leftMatch = leftCopy.get(j);
+ }
+ }
+
+ if(leftMatch != null) {
+ leftCopy.remove(leftMatch);
+ result.add(leftMatch);
+ }
+ }
+ // Finally, set the value of our attribute to this new list
+ // leftElement.eSet(attribute, result);
+ return PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, leftElement, attribute, result);
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ final AttributeOrderChange theDiff = (AttributeOrderChange)this.diff;
+ final EAttribute attribute = theDiff.getAttribute();
+ final EObject leftElement = theDiff.getLeftElement();
+ final EObject rightElement = theDiff.getRightElement();
+
+ final List<Object> leftList = (List<Object>)leftElement.eGet(attribute);
+ final List<Object> rightList = (List<Object>)rightElement.eGet(attribute);
+
+ /*
+ * We need to transform the "right" list into the "left" list, modulo missing values. In practical
+ * terms, this means that we'll simply leave untouched any element that has no match in the "left"
+ * list (elements that were added) while reordering the others in the order they have in the "left"
+ * list.
+ */
+ final List<Object> rightCopy = new ArrayList<Object>(rightList);
+ final List<Object> result = new ArrayList<Object>(rightList.size());
+ // Add all unmatched values in the result list
+ for(int i = 0; i < rightList.size(); i++) {
+ final Object right = rightList.get(i);
+
+ boolean hasMatch = false;
+ for(int j = 0; !hasMatch && j < leftList.size(); j++) {
+ hasMatch = !areDistinctValues(right, leftList.get(j));
+ }
+
+ if(!hasMatch) {
+ rightCopy.remove(right);
+ result.add(right);
+ }
+ }
+ // Then reorder according to the left list's order
+ for(int i = 0; i < leftList.size(); i++) {
+ final Object left = leftList.get(i);
+
+ Object rightMatch = null;
+ for(int j = 0; rightMatch == null && j < rightCopy.size(); j++) {
+ if(!areDistinctValues(left, rightCopy.get(j))) {
+ rightMatch = rightCopy.get(j);
+ }
+ }
+
+ if(rightMatch != null) {
+ rightCopy.remove(rightMatch);
+ result.add(rightMatch);
+ }
+ }
+ // Finally, set the value of our attribute to this new list
+ // rightElement.eSet(attribute, result);
+ return PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, rightElement, attribute, result);
+ }
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CAttributeOrderChangeMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CAttributeOrderChangeMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+
+ /**
+ * This method uses the reflexive way to call the static method of the super class
+ *
+ * @param left
+ * the left object
+ * @param right
+ * the right object
+ * @return
+ * <code>true</code> if the 2 objects are dictinct.
+ */
+ //TODO write a JUnit test to be sure that this methods is always accessible
+ protected boolean areDistinctValues(final Object left, final Object right) {
+
+ final Class<?>[] parameterTypes = new Class[2];
+ parameterTypes[0] = java.lang.Object.class;
+ parameterTypes[1] = java.lang.Object.class;
+ Method m = null;
+ try {
+ m = ReflectHelper.getMethod(AttributeOrderChangeMerger.class, "areDistinctValues", parameterTypes);
+ } catch (SecurityException e) {
+ Activator.log.error(e);
+ } catch (NoSuchMethodException e) {
+ Activator.log.error(e);
+ }
+
+ Object[] parameters = new Object[2];
+ parameters[0] = left;
+ parameters[1] = right;
+
+ Object result = null;
+ try {
+ result = m.invoke(AttributeOrderChangeMerger.class, parameters);
+ } catch (IllegalArgumentException e) {
+ Activator.log.error(e);
+ } catch (IllegalAccessException e) {
+ Activator.log.error(e);
+ } catch (InvocationTargetException e) {
+ Activator.log.error(e);
+ }
+ assert (result instanceof Boolean);
+ return ((Boolean)result).booleanValue();
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDefaultExtensionMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDefaultExtensionMerger.java
new file mode 100644
index 00000000000..b2044bab3dc
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDefaultExtensionMerger.java
@@ -0,0 +1,21 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import org.eclipse.emf.compare.diff.merge.DefaultExtensionMerger;
+
+
+public class CDefaultExtensionMerger extends DefaultExtensionMerger {
+ //TODO
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDiffExtensionMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDiffExtensionMerger.java
new file mode 100644
index 00000000000..d320bb4ae01
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDiffExtensionMerger.java
@@ -0,0 +1,21 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import org.eclipse.emf.compare.diff.internal.merge.impl.DiffExtensionMerger;
+
+
+public class CDiffExtensionMerger extends DiffExtensionMerger {
+ //TODO ?
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDiffGroupMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDiffGroupMerger.java
new file mode 100644
index 00000000000..bf0b3c89490
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CDiffGroupMerger.java
@@ -0,0 +1,122 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.diff.internal.merge.impl.DiffGroupMerger;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+
+
+public class CDiffGroupMerger extends DiffGroupMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.emf.compare.diff.merge.DefaultMerger#undoInTarget()
+ *
+ */
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for CDiffGroupMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CDiffGroupMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ throw new UnsupportedOperationException("Not yet supported");
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ throw new UnsupportedOperationException("Not yet supported");
+ }
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CDiffGroupMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CDiffGroupMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CModelElementChangeLeftTargetMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CModelElementChangeLeftTargetMerger.java
new file mode 100644
index 00000000000..9156457a311
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CModelElementChangeLeftTargetMerger.java
@@ -0,0 +1,206 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.FactoryException;
+import org.eclipse.emf.compare.diff.internal.merge.impl.ModelElementChangeLeftTargetMerger;
+import org.eclipse.emf.compare.diff.metamodel.ModelElementChangeLeftTarget;
+import org.eclipse.emf.compare.diff.metamodel.ReferenceChangeLeftTarget;
+import org.eclipse.emf.compare.diff.metamodel.ReferenceOrderChange;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusEFactory;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+import org.eclipse.papyrus.uml.merger.internal.provider.PapyrusMergeCommandProvider;
+
+public class CModelElementChangeLeftTargetMerger extends ModelElementChangeLeftTargetMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.emf.compare.diff.merge.DefaultMerger#undoInTarget()
+ *
+ */
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for CModelElementChangeLeftTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CModelElementChangeLeftTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ final ModelElementChangeLeftTarget theDiff = (ModelElementChangeLeftTarget)this.diff;
+ final EObject element = theDiff.getLeftElement();
+ return PapyrusMergeCommandProvider.INSTANCE.getDestroyCommand(domain, element);
+ //removeDanglingReferences(parent); not used
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ CompoundCommand cmd = new CompoundCommand("Command CModelElementChangeLeftTargetMerger#getDoUndoInTargetCommand");
+ final ModelElementChangeLeftTarget theDiff = (ModelElementChangeLeftTarget)this.diff;
+ // we should copy the element to the Origin one.
+ final EObject origin = theDiff.getRightParent();
+ final EObject element = theDiff.getLeftElement();
+ final EObject newOne = copy(element);
+ final EReference ref = element.eContainmentFeature();
+ if(ref != null) {
+ try {
+ int elementIndex = -1;
+ if(ref.isMany()) {
+ final Object containmentRefVal = element.eContainer().eGet(ref);
+ if(containmentRefVal instanceof List<?>) {
+ @SuppressWarnings("unchecked")
+ final List<EObject> listVal = (List<EObject>)containmentRefVal;
+ elementIndex = listVal.indexOf(element);
+ }
+ }
+ // EFactory.eAdd(origin, ref.getName(), newOne, elementIndex, true);
+ // setXMIID(newOne, getXMIID(element));
+ cmd.append(PapyrusEFactory.getEAddCommand(domain, origin, ref.getName(), newOne, elementIndex, true));
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getSetXMIIDCommand(domain, element, newOne));
+ } catch (final FactoryException e) {
+ Activator.log.error(e);
+ }
+ } else if(origin == null && getDiffModel().getRightRoots().size() > 0) {
+ // getDiffModel().getRightRoots().get(0).eResource().getContents().add(newOne);
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getAddToResourceCommand(domain, getDiffModel().getRightRoots().get(0).eResource(), newOne));
+ } else if(origin != null) {
+ // origin.eResource().getContents().add(newOne);
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getAddToResourceCommand(domain, origin.eResource(), newOne));
+ } else {
+ // FIXME throw exception : couldn't merge this
+ }
+ cmd.append(new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ // we should now have a look for RemovedReferencesLinks needing elements to apply
+ final Iterator<EObject> siblings = getDiffModel().eAllContents();
+ while(siblings.hasNext()) {
+ final Object op = siblings.next();
+ if(op instanceof ReferenceChangeLeftTarget) {
+ final ReferenceChangeLeftTarget link = (ReferenceChangeLeftTarget)op;
+ // now if I'm in the target References I should put my copy in the origin
+ if(link.getRightTarget() != null && link.getRightTarget() == element) {
+ link.setLeftTarget(newOne);
+ }
+ } else if(op instanceof ReferenceOrderChange) {
+ final ReferenceOrderChange link = (ReferenceOrderChange)op;
+ if(link.getRightElement() == origin && link.getReference() == ref) {
+ final ListIterator<EObject> targetIterator = link.getRightTarget().listIterator();
+ boolean replaced = false;
+ while(!replaced && targetIterator.hasNext()) {
+ final EObject target = targetIterator.next();
+ if(target.eIsProxy() && equalProxyURIs(((InternalEObject)target).eProxyURI(), EcoreUtil.getURI(element))) {
+ targetIterator.set(newOne);
+ replaced = true;
+ }
+ }
+ }
+ }
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ }));
+
+ return cmd;
+ }
+
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CModelElementChangeLeftTargetMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CModelElementChangeLeftTargetMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CModelElementChangeRightTargetMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CModelElementChangeRightTargetMerger.java
new file mode 100644
index 00000000000..91c15527776
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CModelElementChangeRightTargetMerger.java
@@ -0,0 +1,203 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.FactoryException;
+import org.eclipse.emf.compare.diff.internal.merge.impl.ModelElementChangeRightTargetMerger;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+import org.eclipse.emf.compare.diff.metamodel.ModelElementChangeRightTarget;
+import org.eclipse.emf.compare.diff.metamodel.ReferenceChangeRightTarget;
+import org.eclipse.emf.compare.diff.metamodel.ReferenceOrderChange;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusEFactory;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+import org.eclipse.papyrus.uml.merger.internal.provider.PapyrusMergeCommandProvider;
+
+
+public class CModelElementChangeRightTargetMerger extends ModelElementChangeRightTargetMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.emf.compare.diff.merge.DefaultMerger#undoInTarget()
+ *
+ */
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for CModelElementChangeRightTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CModelElementChangeRightTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ final CompoundCommand cmd = new CompoundCommand("Command CModelElementChangeRightTargetMerger#getDoApplyInOriginCommand");
+ final ModelElementChangeRightTarget theDiff = (ModelElementChangeRightTarget)this.diff;
+ final EObject origin = theDiff.getLeftParent();
+ final EObject element = theDiff.getRightElement();
+ final EObject newOne = copy(element);
+ final EReference ref = element.eContainmentFeature();
+ if(ref != null) {
+ try {
+ int expectedIndex = -1;
+ if(ref.isMany()) {
+ final Object containmentRefVal = element.eContainer().eGet(ref);
+ if(containmentRefVal instanceof List<?>) {
+ @SuppressWarnings("unchecked")
+ final List<EObject> listVal = (List<EObject>)containmentRefVal;
+ expectedIndex = listVal.indexOf(element);
+ }
+ }
+ // EFactory.eAdd(origin, ref.getName(), newOne, expectedIndex, true);
+ // setXMIID(newOne, getXMIID(element));
+ cmd.append(PapyrusEFactory.getEAddCommand(domain, origin, ref.getName(), newOne, expectedIndex, true));
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getSetXMIIDCommand(domain, element, newOne));
+ } catch (final FactoryException e) {
+ Activator.log.error(e);
+ }
+ } else if(origin == null && getDiffModel().getLeftRoots().size() > 0) {
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getAddToResourceCommand(domain, getDiffModel().getLeftRoots().get(0).eResource(), newOne));
+ } else if(origin != null) {
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getAddToResourceCommand(domain, origin.eResource(), newOne));
+ } else {
+ // FIXME Throw exception : couldn't merge this
+ }
+ cmd.append(new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, null, null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ // we should now have a look for AddReferencesLinks needing this object
+ final Iterator<EObject> siblings = getDiffModel().eAllContents();
+ while(siblings.hasNext()) {
+ final DiffElement op = (DiffElement)siblings.next();
+ if(op instanceof ReferenceChangeRightTarget) {
+ final ReferenceChangeRightTarget link = (ReferenceChangeRightTarget)op;
+ // now if I'm in the target References I should put my copy in the origin
+ if(link.getLeftTarget() != null && link.getLeftTarget() == element) {
+ link.setRightTarget(newOne);
+ }
+ } else if(op instanceof ReferenceOrderChange) {
+ final ReferenceOrderChange link = (ReferenceOrderChange)op;
+ if(link.getLeftElement() == origin && link.getReference() == ref) {
+ final ListIterator<EObject> targetIterator = link.getLeftTarget().listIterator();
+ boolean replaced = false;
+ while(!replaced && targetIterator.hasNext()) {
+ final EObject target = targetIterator.next();
+ if(target.eIsProxy() && equalProxyURIs(((InternalEObject)target).eProxyURI(), EcoreUtil.getURI(element))) {
+ targetIterator.set(newOne);
+ replaced = true;
+ }
+ }
+ }
+ }
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ }));
+ return cmd;
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ final ModelElementChangeRightTarget theDiff = (ModelElementChangeRightTarget)this.diff;
+ final EObject element = theDiff.getRightElement();
+ return PapyrusMergeCommandProvider.INSTANCE.getDestroyCommand(domain, element);
+ }
+
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CModelElementChangeRightTargetMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CModelElementChangeRightTargetMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CMoveModelElementMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CMoveModelElementMerger.java
new file mode 100644
index 00000000000..87c82eec240
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CMoveModelElementMerger.java
@@ -0,0 +1,214 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import java.util.List;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.common.command.UnexecutableCommand;
+import org.eclipse.emf.compare.diff.internal.merge.impl.MoveModelElementMerger;
+import org.eclipse.emf.compare.diff.metamodel.MoveModelElement;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.xmi.XMIResource;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+import org.eclipse.papyrus.uml.merger.internal.provider.PapyrusMergeCommandProvider;
+
+/**
+ *
+ * Created for EMF-Compare, for MoveModelElementMerger
+ *
+ */
+public class CMoveModelElementMerger extends MoveModelElementMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.emf.compare.diff.merge.DefaultMerger#undoInTarget()
+ *
+ */
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for CMoveModelElementMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CMoveModelElementMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ final CompoundCommand cmd = new CompoundCommand("CMoveModelElementMerger#getDoApplyInOriginCommand");
+ final MoveModelElement theDiff = (MoveModelElement)this.diff;
+ final EObject leftTarget = theDiff.getLeftTarget();
+ final EObject leftElement = theDiff.getLeftElement();
+ final EReference ref = theDiff.getRightElement().eContainmentFeature();
+ if(ref != null) {
+ // ordering handling:
+ int index = -1;
+ final EObject rightElementParent = theDiff.getRightElement().eContainer();
+ final Object rightRefValue = rightElementParent.eGet(ref);
+ if(rightRefValue instanceof List) {
+ final List<Object> refRightValueList = (List<Object>)rightRefValue;
+ index = refRightValueList.indexOf(theDiff.getRightElement());
+ }
+
+
+ // We'll store the element's ID because moving an element deletes its XMI ID
+ final String elementID = getXMIID(leftElement);
+
+ if(rightRefValue instanceof List<?>) {
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getMoveWithIndexCommand(domain, leftTarget, leftTarget, ref, leftElement, index, true));
+ } else {
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getMoveCommand(domain, leftTarget, leftTarget, ref, leftElement));
+ }
+ cmd.append(getPreserveXMIIDCommand(domain, leftElement, elementID));
+
+ } else {
+ // shouldn't be here
+ cmd.append(UnexecutableCommand.INSTANCE);
+ }
+ return cmd;
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ final CompoundCommand cmd = new CompoundCommand("CMoveModelElementMerger#getDoUndoInTargetCommand");
+ final MoveModelElement theDiff = (MoveModelElement)this.diff;
+ final EObject rightTarget = theDiff.getRightTarget();
+ final EObject rightElement = theDiff.getRightElement();
+ final EReference ref = theDiff.getLeftElement().eContainmentFeature();
+ if(ref != null) {
+ // ordering handling:
+ int index = -1;
+ final EObject leftElementParent = theDiff.getLeftElement().eContainer();
+ final Object leftRefValue = leftElementParent.eGet(ref);
+ if(leftRefValue instanceof List) {
+ final List<Object> refLeftValueList = (List<Object>)leftRefValue;
+ index = refLeftValueList.indexOf(theDiff.getLeftElement());
+ }
+ if(leftRefValue instanceof List<?>) {
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getMoveWithIndexCommand(domain, rightTarget, rightTarget, ref, rightElement, index, true));
+ } else {
+ cmd.append(PapyrusMergeCommandProvider.INSTANCE.getMoveCommand(domain, rightTarget, rightTarget, ref, rightElement));
+ }
+ final String elementID = getXMIID(rightElement);
+ cmd.append(getPreserveXMIIDCommand(domain, rightElement, elementID));
+ } else {
+ // shouldn't be here
+ cmd.append(UnexecutableCommand.INSTANCE);
+ }
+ return cmd;
+ }
+
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CMoveModelElementMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CMoveModelElementMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+
+ /**
+ * This command is not the the class PapyrusUMLMergeProvider because it only should be used to preserve the xmi_id after a move,
+ * but not to change the id
+ *
+ * @param domain
+ * @param element
+ * @param id
+ * @return
+ * the command to set the ID
+ */
+ private Command getPreserveXMIIDCommand(final TransactionalEditingDomain domain, final EObject element, final String id) {
+ //TODO change for an EMFCommand
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Set XMI Command", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ if(element != null && element.eResource() instanceof XMIResource) {
+ ((XMIResource)element.eResource()).setID(element, id);
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ });
+
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceChangeLeftTargetMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceChangeLeftTargetMerger.java
new file mode 100644
index 00000000000..4cfdd659124
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceChangeLeftTargetMerger.java
@@ -0,0 +1,227 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.FactoryException;
+import org.eclipse.emf.compare.diff.internal.merge.impl.ReferenceChangeLeftTargetMerger;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+import org.eclipse.emf.compare.diff.metamodel.ReferenceChangeLeftTarget;
+import org.eclipse.emf.compare.diff.metamodel.ReferenceOrderChange;
+import org.eclipse.emf.compare.diff.metamodel.ResourceDependencyChange;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusCompareEObjectCopier;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusEFactory;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+
+
+public class CReferenceChangeLeftTargetMerger extends ReferenceChangeLeftTargetMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ /**
+ *
+ * @see org.eclipse.emf.compare.diff.merge.DefaultMerger#undoInTarget()
+ *
+ */
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for CReferenceChangeLeftTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CReferenceChangeLeftTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ final CompoundCommand cmd = new CompoundCommand("CReferenceChangeLeftTargetMerger#getDoApplyInOriginCommand");
+ final ReferenceChangeLeftTarget theDiff = (ReferenceChangeLeftTarget)this.diff;
+ final EObject element = theDiff.getLeftElement();
+ final EObject leftTarget = theDiff.getLeftTarget();
+ try {
+ cmd.append(PapyrusEFactory.getERemoveCommand(domain, element, theDiff.getReference().getName(), leftTarget));
+ } catch (final FactoryException e) {
+ Activator.log.error(e);
+ }
+ cmd.append(new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, null, null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ // we should now have a look for AddReferencesLinks needing this object
+ final Iterator<EObject> siblings = getDiffModel().eAllContents();
+ while(siblings.hasNext()) {
+ final DiffElement op = (DiffElement)siblings.next();
+ if(op instanceof ReferenceChangeLeftTarget) {
+ final ReferenceChangeLeftTarget link = (ReferenceChangeLeftTarget)op;
+ // now if I'm in the target References I should put my copy in the origin
+ if(link.getReference().equals(theDiff.getReference().getEOpposite()) && link.getLeftTarget().equals(element)) {
+ removeFromContainer(link);
+ }
+ } else if(op instanceof ResourceDependencyChange) {
+ final ResourceDependencyChange link = (ResourceDependencyChange)op;
+ final Resource res = link.getRoots().get(0).eResource();
+ if(res == leftTarget.eResource()) {
+ EcoreUtil.remove(link);
+ res.unload();
+ }
+ }
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ }));
+ return cmd;
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ final CompoundCommand cmd = new CompoundCommand();
+ final ReferenceChangeLeftTarget theDiff = (ReferenceChangeLeftTarget)this.diff;
+ final EReference reference = theDiff.getReference();
+ final EObject element = theDiff.getRightElement();
+ final EObject leftTarget = theDiff.getLeftTarget();
+ final EObject rightTarget = theDiff.getRightTarget();
+
+ int index = -1;
+ if(reference.isMany()) {
+ final EObject leftElement = theDiff.getLeftElement();
+ final Object leftRefValue = leftElement.eGet(reference);
+ if(leftRefValue instanceof List) {
+ final List<?> refLeftValueList = (List<?>)leftRefValue;
+ index = refLeftValueList.indexOf(leftTarget);
+ }
+ }
+ final PapyrusCompareEObjectCopier copier = new PapyrusCompareEObjectCopier(diff);
+ Command copierCommand = copier.getCopyReferenceValueCommand(domain, reference, element, leftTarget, rightTarget, index);
+ cmd.append(copierCommand);
+ final AbstractTransactionalCommand updateDiffModelCommand = new AbstractTransactionalCommand(domain, "Update Diff Model", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ final EObject copiedValue = copier.getCopiedValue(leftTarget);
+ final Iterator<EObject> siblings = getDiffModel().eAllContents();
+ while(siblings.hasNext()) {
+ final DiffElement op = (DiffElement)siblings.next();
+ if(op instanceof ReferenceChangeLeftTarget) {
+ final ReferenceChangeLeftTarget link = (ReferenceChangeLeftTarget)op;
+ // now if I'm in the target References I should put my copy in the origin
+ if(link.getReference().equals(reference.getEOpposite()) && link.getLeftTarget().equals(element)) {
+ removeFromContainer(link);
+ }
+ } else if(op instanceof ReferenceOrderChange) {
+ final ReferenceOrderChange link = (ReferenceOrderChange)op;
+ if(link.getLeftElement() == element && link.getReference() == reference) {
+ final ListIterator<EObject> targetIterator = link.getLeftTarget().listIterator();
+ boolean replaced = false;
+ while(!replaced && targetIterator.hasNext()) {
+ final EObject target = targetIterator.next();
+ if(target.eIsProxy() && equalProxyURIs(((InternalEObject)target).eProxyURI(), EcoreUtil.getURI(leftTarget))) {
+ targetIterator.set(copiedValue);
+ replaced = true;
+ }
+ }
+ }
+ }
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ };
+ cmd.append(new GMFtoEMFCommandWrapper(updateDiffModelCommand));
+ return cmd;
+ }
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CReferenceChangeLeftTargetMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CReferenceChangeLeftTargetMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+
+
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceChangeRightTargetMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceChangeRightTargetMerger.java
new file mode 100644
index 00000000000..2675d56e3fd
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceChangeRightTargetMerger.java
@@ -0,0 +1,224 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.FactoryException;
+import org.eclipse.emf.compare.diff.internal.merge.impl.ReferenceChangeRightTargetMerger;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+import org.eclipse.emf.compare.diff.metamodel.ReferenceChangeRightTarget;
+import org.eclipse.emf.compare.diff.metamodel.ReferenceOrderChange;
+import org.eclipse.emf.compare.diff.metamodel.ResourceDependencyChange;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusCompareEObjectCopier;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusEFactory;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+
+
+public class CReferenceChangeRightTargetMerger extends ReferenceChangeRightTargetMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for CReferenceChangeRightTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CReferenceChangeRightTargetMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CReferenceChangeRightTargetMerger#getDoApplyInOriginCommand");
+ final ReferenceChangeRightTarget theDiff = (ReferenceChangeRightTarget)this.diff;
+ final EReference reference = theDiff.getReference();
+ final EObject element = theDiff.getLeftElement();
+ final EObject rightTarget = theDiff.getRightTarget();
+ final EObject leftTarget = theDiff.getLeftTarget();
+
+ // ordering handling:
+ int index = -1;
+ if(reference.isMany()) {
+ final EObject rightElement = theDiff.getRightElement();
+ final Object rightRefValue = rightElement.eGet(reference);
+ if(rightRefValue instanceof List) {
+ final List<?> refRightValueList = (List<?>)rightRefValue;
+ index = refRightValueList.indexOf(rightTarget);
+ }
+ }
+ final PapyrusCompareEObjectCopier copier = new PapyrusCompareEObjectCopier(diff);
+ cmd.append(copier.getCopyReferenceValueCommand(domain, reference, element, rightTarget, leftTarget, index));
+
+ cmd.append(new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ final EObject copiedValue = copier.getCopiedValue(rightTarget);
+ // We'll now look through this reference's eOpposite as they are already taken care of
+ final Iterator<EObject> related = getDiffModel().eAllContents();
+ while(related.hasNext()) {
+ final DiffElement op = (DiffElement)related.next();
+ if(op instanceof ReferenceChangeRightTarget) {
+ final ReferenceChangeRightTarget link = (ReferenceChangeRightTarget)op;
+ // If this is my eOpposite, delete it from the DiffModel (merged along with this one)
+ if(link.getReference().equals(theDiff.getReference().getEOpposite()) && link.getRightTarget().equals(element)) {
+ removeFromContainer(link);
+ }
+ } else if(op instanceof ReferenceOrderChange) {
+ final ReferenceOrderChange link = (ReferenceOrderChange)op;
+ if(link.getLeftElement() == element && link.getReference() == reference) {
+ final ListIterator<EObject> targetIterator = link.getLeftTarget().listIterator();
+ boolean replaced = false;
+ while(!replaced && targetIterator.hasNext()) {
+ final EObject target = targetIterator.next();
+ if(target.eIsProxy() && equalProxyURIs(((InternalEObject)target).eProxyURI(), EcoreUtil.getURI(rightTarget))) {
+ targetIterator.set(copiedValue);
+ replaced = true;
+ }
+ }
+ }
+ }
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ }));
+
+ return cmd;
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CReferenceChangeRightTargetMerger#getDoUndoInTargetCommand");
+ final ReferenceChangeRightTarget theDiff = (ReferenceChangeRightTarget)this.diff;
+ final EObject element = theDiff.getRightElement();
+ final EObject rightTarget = theDiff.getRightTarget();
+ try {
+ cmd.append(PapyrusEFactory.getERemoveCommand(domain, element, theDiff.getReference().getName(), rightTarget));
+ } catch (final FactoryException e) {
+ Activator.log.error(e);
+ }
+ cmd.append(new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, null, null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ // we should now have a look for AddReferencesLinks needing this object
+ final Iterator<EObject> related = getDiffModel().eAllContents();
+ while(related.hasNext()) {
+ final DiffElement op = (DiffElement)related.next();
+ if(op instanceof ReferenceChangeRightTarget) {
+ final ReferenceChangeRightTarget link = (ReferenceChangeRightTarget)op;
+ // now if I'm in the target References I should put my copy in the origin
+ if(link.getReference().equals(theDiff.getReference().getEOpposite()) && link.getRightTarget().equals(element)) {
+ removeFromContainer(link);
+ }
+ } else if(op instanceof ResourceDependencyChange) {
+ final ResourceDependencyChange link = (ResourceDependencyChange)op;
+ final Resource res = link.getRoots().get(0).eResource();
+ if(res == rightTarget.eResource()) {
+ EcoreUtil.remove(link);
+ res.unload();
+ }
+ }
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ }));
+
+ return cmd;
+ }
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CReferenceChangeRightTargetMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CReferenceChangeRightTargetMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceOrderChangeMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceOrderChangeMerger.java
new file mode 100644
index 00000000000..42c4bef8dd9
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CReferenceOrderChangeMerger.java
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import java.util.Collection;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.FactoryException;
+import org.eclipse.emf.compare.diff.internal.merge.impl.ReferenceOrderChangeMerger;
+import org.eclipse.emf.compare.diff.merge.DefaultMerger;
+import org.eclipse.emf.compare.diff.metamodel.ReferenceOrderChange;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusEFactory;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+
+public class CReferenceOrderChangeMerger extends ReferenceOrderChangeMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for CReferenceOrderChangeMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CReferenceOrderChangeMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final ReferenceOrderChange theDiff = (ReferenceOrderChange)this.diff;
+ final EObject leftElement = theDiff.getLeftElement();
+
+ final Collection<EObject> target = Lists.newArrayList(Collections2.filter(theDiff.getLeftTarget(), new Predicate<EObject>() {
+
+ public boolean apply(final EObject input) {
+ return !input.eIsProxy() || !DefaultMerger.isEMFCompareProxy(((InternalEObject)input).eProxyURI());
+ }
+ }));
+
+ try {
+ cmd = PapyrusEFactory.getESetCommand(domain, leftElement, theDiff.getReference().getName(), target);
+ } catch (final FactoryException e) {
+ Activator.log.error(e);
+ }
+ return cmd;
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final ReferenceOrderChange theDiff = (ReferenceOrderChange)this.diff;
+ final EObject rightElement = theDiff.getRightElement();
+
+ final Collection<EObject> target = Lists.newArrayList(Collections2.filter(theDiff.getRightTarget(), new Predicate<EObject>() {
+
+ public boolean apply(final EObject input) {
+ return !input.eIsProxy() || !DefaultMerger.isEMFCompareProxy(((InternalEObject)input).eProxyURI());
+ }
+ }));
+
+ try {
+ cmd = PapyrusEFactory.getESetCommand(domain, rightElement, theDiff.getReference().getName(), target);
+ } catch (final FactoryException e) {
+ Activator.log.error(e);
+ }
+ return cmd;
+ }
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CReferenceOrderChangeMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CReferenceOrderChangeMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CUpdateAttributeMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CUpdateAttributeMerger.java
new file mode 100644
index 00000000000..b40ed6d83ab
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CUpdateAttributeMerger.java
@@ -0,0 +1,146 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.FactoryException;
+import org.eclipse.emf.compare.diff.internal.merge.impl.UpdateAttributeMerger;
+import org.eclipse.emf.compare.diff.metamodel.UpdateAttribute;
+import org.eclipse.emf.compare.util.EFactory;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusEFactory;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+
+
+public class CUpdateAttributeMerger extends UpdateAttributeMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for CUpdateAttributeMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CUpdateAttributeMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final UpdateAttribute theDiff = (UpdateAttribute)this.diff;
+ final EObject element = theDiff.getRightElement();
+ final EObject origin = theDiff.getLeftElement();
+ final EAttribute attr = theDiff.getAttribute();
+ try {
+ cmd = PapyrusEFactory.getESetCommand(domain, origin, attr.getName(), EFactory.eGet(element, attr.getName()));
+ } catch (FactoryException e) {
+ Activator.log.error(e);
+ }
+ return cmd;
+ }
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final UpdateAttribute theDiff = (UpdateAttribute)this.diff;
+ final EObject element = theDiff.getRightElement();
+ final EObject origin = theDiff.getLeftElement();
+ final EAttribute attr = theDiff.getAttribute();
+ try {
+ cmd = PapyrusEFactory.getESetCommand(domain, element, attr.getName(), EFactory.eGet(origin, attr.getName()));
+ } catch (FactoryException e) {
+ Activator.log.error(e);
+ }
+ return cmd;
+ }
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CUpdateAttributeMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CUpdateAttributeMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CUpdateReferenceMerger.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CUpdateReferenceMerger.java
new file mode 100644
index 00000000000..6bcb0bc98e2
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/merger/CUpdateReferenceMerger.java
@@ -0,0 +1,178 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.merger;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.diff.internal.merge.impl.UpdateReferenceMerger;
+import org.eclipse.emf.compare.diff.metamodel.UpdateReference;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.MergerUtils;
+import org.eclipse.papyrus.uml.compare.merger.internal.utils.PapyrusCompareEObjectCopier;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+import org.eclipse.papyrus.uml.merger.internal.provider.PapyrusMergeCommandProvider;
+
+
+public class CUpdateReferenceMerger extends UpdateReferenceMerger implements ITransactionalMerger {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.eclipse.emf.compare.diff.merge.IMerger#applyInOrigin()
+ */
+ @Override
+ public void applyInOrigin() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getApplyInOriginCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.applyInOrigin();
+ }
+ }
+
+ @Override
+ public void undoInTarget() {
+ if(MergerUtils.usePapyrusMerger()) {
+ final TransactionalEditingDomain domain = MergerUtils.getEditingDomain();
+ final Command cmd = getUndoInTargetCommand(domain);
+ if(cmd.canExecute()) {
+ domain.getCommandStack().execute(cmd);
+ }
+ } else {
+ super.undoInTarget();
+ }
+ }
+
+
+ public Command getApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(true);
+ // doApplyInOrigin();
+ // postProcess();
+ CompoundCommand cmd = new CompoundCommand("Apply in Origin Command for CUpdateReferenceMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, true));
+ cmd.append(getDoApplyInOriginCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+ public Command getUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ // mergeRequiredDifferences(false);
+ // doUndoInTarget();
+ // postProcess();
+
+ CompoundCommand cmd = new CompoundCommand("Undo In Target Command for CUpdateReferenceMerger");
+ cmd.append(getMergeRequiredDifferencesCommand(domain, false));
+ cmd.append(getDoUndoInTargetCommand(domain));
+ cmd.append(getPostProcessCommand(domain));
+ return cmd;
+ }
+
+
+ public Command getDoApplyInOriginCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final UpdateReference theDiff = (UpdateReference)this.diff;
+ final EReference reference = theDiff.getReference();
+ final EObject element = theDiff.getLeftElement();
+ final EObject leftTarget = (EObject)theDiff.getRightElement().eGet(reference);
+ final EObject matchedLeftTarget = theDiff.getLeftTarget();
+
+ if(leftTarget == null) {
+ if(FeatureMapUtil.isMany(element, reference)) {
+ //TODO : I didn't find an example to test this case.
+ throw new UnsupportedOperationException("Not Yet Supported");
+ } else {
+ final Object value = theDiff.getLeftElement().eGet(reference);
+ if(value instanceof EObject) {
+ cmd = PapyrusMergeCommandProvider.INSTANCE.getDestroyReferenceCommand(domain, element, reference, (EObject)value, false);
+ } else {
+ //TODO : we don't use the ServiceEdit
+ //TODO : not tested
+ // element.eUnset(reference);
+ cmd = new SetCommand(domain, element, reference, null);
+ }
+ }
+ } else {
+ final PapyrusCompareEObjectCopier copier = new PapyrusCompareEObjectCopier(diff);
+ cmd = copier.getCopyReferenceValueCommand(domain, reference, element, leftTarget, matchedLeftTarget, -1);
+ }
+ return cmd;
+ }
+
+
+ public Command getDoUndoInTargetCommand(final TransactionalEditingDomain domain) {
+ Command cmd = null;
+ final UpdateReference theDiff = (UpdateReference)this.diff;
+ final EReference reference = theDiff.getReference();
+ final EObject element = theDiff.getRightElement();
+ final EObject rightTarget = (EObject)theDiff.getLeftElement().eGet(reference);
+ final EObject matchedRightTarget = theDiff.getRightTarget();
+
+ if(rightTarget == null) {
+ if(FeatureMapUtil.isMany(element, reference)) {
+ //TODO : I didn't find an example to test this case.
+ throw new UnsupportedOperationException("Not Yet Supported");
+ } else {
+ final Object value = theDiff.getRightElement().eGet(reference);
+ if(value instanceof EObject) {
+ cmd = PapyrusMergeCommandProvider.INSTANCE.getDestroyReferenceCommand(domain, element, reference, (EObject)value, false);
+ } else {
+ //TODO : we don't use the ServiceEdit
+ //TODO : not tested
+ // element.eUnset(reference);
+ cmd = new SetCommand(domain, element, reference, null);
+ }
+ }
+ } else {
+ final PapyrusCompareEObjectCopier copier = new PapyrusCompareEObjectCopier(diff);
+ cmd = copier.getCopyReferenceValueCommand(domain, reference, element, rightTarget, matchedRightTarget, -1);
+ }
+ return cmd;
+ }
+
+ public Command getMergeRequiredDifferencesCommand(final TransactionalEditingDomain domain, final boolean applyInOrigin) {
+ // TODO the super method mergeRequiredDifferences should be rewritten to use cmd too
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CUpdateReferenceMerger.this.mergeRequiredDifferences(applyInOrigin);
+ return null;
+ }
+ });
+ }
+
+ public Command getPostProcessCommand(final TransactionalEditingDomain domain) {
+ return new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "Merge Required Differences", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ CUpdateReferenceMerger.this.postProcess();
+ return null;
+ }
+ });
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/EObjectComparator.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/EObjectComparator.java
new file mode 100644
index 00000000000..090cfd8cb0b
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/EObjectComparator.java
@@ -0,0 +1,68 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.utils;
+
+import java.util.Comparator;
+import java.util.Iterator;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.ecore.EObject;
+
+/**
+ *
+ * This class allows to compare EObject using the PositionAdapter.
+ *
+ *
+ */
+public class EObjectComparator<T> implements Comparator<T> {
+
+ /**
+ *
+ * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+ *
+ * @param o1
+ * @param o2
+ * @return
+ */
+ public int compare(final T o1, final T o2) {
+ if(o1 instanceof EObject && o2 instanceof EObject) {
+ final int position1 = getWantedPosition((EObject)o1);
+ final int position2 = getWantedPosition((EObject)o2);
+ if(position1 != -1 && position2 != -1) {
+ return position1 - position2;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ *
+ * @param obj1
+ * an EObject
+ * @return
+ * the wanted position for this object
+ */
+ private int getWantedPosition(final EObject obj1) {
+ final Iterator<Adapter> adapters = obj1.eAdapters().iterator();
+ int expectedIndex = -1;
+ while(expectedIndex == -1 && adapters.hasNext()) {
+ final Adapter adapter = adapters.next();
+ if(adapter instanceof PositionAdapter) {
+ expectedIndex = ((PositionAdapter)adapter).getExpectedIndex();
+ }
+ }
+ return expectedIndex;
+ }
+
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MergerUtils.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MergerUtils.java
new file mode 100644
index 00000000000..76aa0ee33d8
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MergerUtils.java
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.utils;
+
+import org.eclipse.emf.edit.domain.IEditingDomainProvider;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.papyrus.infra.core.sasheditor.editor.IMultiPageEditorPart;
+import org.eclipse.papyrus.infra.tools.util.EditorHelper;
+import org.eclipse.ui.IEditorPart;
+
+/**
+ *
+ * This class provides useful method for the mergers
+ *
+ */
+public final class MergerUtils {
+
+ /**
+ *
+ * Constructor.
+ *
+ */
+ private MergerUtils() {
+ //nothing to do
+ }
+
+ /**
+ *
+ * @return
+ * <code>true</code> if we can use the Papyrus Mergers
+ */
+ public static boolean usePapyrusMerger() {
+ return getEditingDomain() != null;
+ }
+
+ /**
+ *
+ * @return
+ * the {@link TransactionalEditingDomain} to use for the merge action, or <code>null</code> if not found
+ */
+ public static TransactionalEditingDomain getEditingDomain() {
+ IEditorPart editor = EditorHelper.getCurrentEditor();
+ if(editor instanceof IMultiPageEditorPart) {
+ editor = ((IMultiPageEditorPart)editor).getActiveEditor();
+ }
+ if(editor instanceof IEditingDomainProvider) {
+ return (TransactionalEditingDomain)((IEditingDomainProvider)editor).getEditingDomain();
+ }
+ return null;
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MoveWithIndexCommand.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MoveWithIndexCommand.java
new file mode 100644
index 00000000000..358de8f604c
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MoveWithIndexCommand.java
@@ -0,0 +1,136 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.utils;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.type.core.commands.MoveElementsCommand;
+import org.eclipse.gmf.runtime.emf.type.core.internal.l10n.EMFTypeCoreMessages;
+import org.eclipse.gmf.runtime.emf.type.core.requests.IEditCommandRequest;
+import org.eclipse.gmf.runtime.emf.type.core.requests.MoveRequest;
+
+//TODO move this class and create it in the service edit
+//TODO : breaks this class into 2 classes : 1 for the move and another one for the reorder?
+public class MoveWithIndexCommand extends MoveElementsCommand {
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param request
+ */
+ public MoveWithIndexCommand(final MoveRequest request) {
+ super(request);
+ }
+
+ /**
+ *
+ * @see org.eclipse.gmf.runtime.emf.type.core.commands.MoveElementsCommand#doExecuteWithResult(org.eclipse.core.runtime.IProgressMonitor,
+ * org.eclipse.core.runtime.IAdaptable)
+ *
+ * @param monitor
+ * @param info
+ * @return
+ * @throws ExecutionException
+ */
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ final int index = getIndex();
+ if(index != -1) {
+ for(Iterator<?> i = getElementsToMove().keySet().iterator(); i.hasNext();) {
+ final EObject element = (EObject)i.next();
+ final EReference feature = getTargetFeature(element);
+ if(feature != null) {
+ if(FeatureMapUtil.isMany(getTargetContainer(), feature)) {
+ if(shouldReorder()) {
+ //we attach the real position to the object
+ PapyrusEFactory.attachRealPositionEAdapter(element, index);
+ }
+ final Object value = getTargetContainer().eGet(feature);
+ if(value instanceof List<?>) {
+ final List<?> listValue = (List<?>)value;
+ final int indexMax = listValue.size() - 1;
+ if(indexMax < index) {
+ //we add the element at the end of the list
+ final List values = ((List<?>)getTargetContainer().eGet(feature));
+ values.add(element);
+ if(shouldReorder()) {
+ PapyrusEFactory.reorderList(values);
+ }
+ } else {
+ ((List)value).add(index, element);
+ if(shouldReorder()) {
+ PapyrusEFactory.reorderList((List)value);
+ }
+ }
+
+ } else {
+ ((Collection)getTargetContainer().eGet(feature)).add(element);
+ if(shouldReorder()) {
+ PapyrusEFactory.reorderList((List)((Collection)getTargetContainer().eGet(feature)));
+ }
+ }
+ } else {
+ getTargetContainer().eSet(feature, element);
+ }
+ } else {
+ return CommandResult.newErrorCommandResult(EMFTypeCoreMessages.moveElementsCommand_noTargetFeature);
+ }
+ }
+ return CommandResult.newOKCommandResult();
+ }
+ return super.doExecuteWithResult(monitor, info);
+ }
+
+ @Override
+ public boolean canExecute() {
+ super.canExecute();
+ return true;
+ }
+ /**
+ *
+ * @return
+ * the index for the move command
+ */
+ protected int getIndex() {
+ IEditCommandRequest req = getRequest();
+ if(req instanceof MoveWithIndexRequest) {
+ return ((MoveWithIndexRequest)req).getIndex();
+ }
+ return -1;
+ }
+
+ /**
+ *
+ * @return
+ * <code>true</code> when the list should be reorderded
+ */
+ protected boolean shouldReorder() {
+ final IEditCommandRequest req = getRequest();
+ boolean shouldReoder = false;
+ if(req instanceof MoveWithIndexRequest) {
+ shouldReoder = ((MoveWithIndexRequest)req).shouldReoder();
+ }
+ return shouldReoder;
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MoveWithIndexRequest.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MoveWithIndexRequest.java
new file mode 100644
index 00000000000..47a8a1373b4
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/MoveWithIndexRequest.java
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.utils;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.emf.type.core.requests.MoveRequest;
+
+//TODO : move this class
+/**
+ *
+ * Created for EMF-Compare, for MoveModelElementMerger
+ *
+ *
+ */
+public class MoveWithIndexRequest extends MoveRequest {
+
+ /**
+ * the wanted index for the moved element
+ */
+ private final int index;
+
+ /**
+ * indicates if the list should be reordered after the move
+ */
+ private final boolean reorder;
+
+ //TODO : and the other constructor?
+ public MoveWithIndexRequest(final TransactionalEditingDomain editingDomain, final EObject targetContainer, final EReference targetFeature, final EObject elementToMove, final int index, final boolean reorder) {
+ super(editingDomain, targetContainer, targetFeature, elementToMove);
+ this.index = index;
+ this.reorder = reorder;
+ }
+
+
+ public int getIndex() {
+ return this.index;
+ }
+
+ public boolean shouldReoder() {
+ return this.reorder;
+ }
+
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusCompareEObjectCopier.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusCompareEObjectCopier.java
new file mode 100644
index 00000000000..da303966162
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusCompareEObjectCopier.java
@@ -0,0 +1,299 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.utils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.compare.diff.merge.EMFCompareEObjectCopier;
+import org.eclipse.emf.compare.diff.merge.service.MergeService;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.gmf.runtime.common.core.command.CommandResult;
+import org.eclipse.gmf.runtime.emf.commands.core.command.AbstractTransactionalCommand;
+import org.eclipse.papyrus.commands.wrappers.GMFtoEMFCommandWrapper;
+import org.eclipse.papyrus.uml.merger.internal.provider.PapyrusMergeCommandProvider;
+
+/**
+ *
+ * This class copies the code of {@link EMFCompareEObjectCopier}, to do the actions with EMFCommands
+ *
+ */
+public class PapyrusCompareEObjectCopier {
+
+ /**
+ * we encapsulate the "standard" implementation of {@link EMFCompareEObjectCopier}
+ */
+ private EMFCompareEObjectCopier copier = null;
+
+ /**
+ *
+ * Constructor.
+ *
+ * @param diff
+ * a diff element
+ */
+ public PapyrusCompareEObjectCopier(final DiffElement diff) {
+ copier = MergeService.getCopier(diff);
+ }
+
+ /**
+ * Adapted from copyReferenceValue(EReference targetReference, EObject target, EObject value,
+ * EObject matchedValue, int index)
+ *
+ * @param targetReference
+ * @param target
+ * @param value
+ * @param matchedValue
+ * @param index
+ * @return
+ */
+ public Command getCopyReferenceValueCommand(final TransactionalEditingDomain domain, final EReference targetReference, final EObject target, final EObject value, final EObject matchedValue, final int index) {
+ EObject actualValue = value;
+ if(value == null && matchedValue != null) {
+ // handleLinkedResourceDependencyChange(matchedValue);
+ // actualValue = get(matchedValue);
+ //TODO
+ throw new UnsupportedOperationException("Not yet supported");
+ }
+ if(matchedValue != null) {
+ this.copier.put(actualValue, matchedValue);
+
+ final Object referenceValue = target.eGet(targetReference);
+ if(referenceValue instanceof Collection<?>) {
+ //tested with ReferenceChangeLefttargetExample
+ return getAddAtIndexCommand(domain, target, targetReference, (Collection<EObject>)referenceValue, matchedValue, index);
+
+ } else {
+ //target.eSet(targetReference, matchedValue);
+ //tested with the project UpdateReferenceExample2
+ return PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, target, targetReference, targetReference);
+ }
+ }
+ //tested with ReferenceChangeLefttargetExample2
+ return getCopyValueReferenceCommand(domain, targetReference, target, actualValue, index);
+ }
+
+ private Command getCopyValueReferenceCommand(final TransactionalEditingDomain domain, final EReference targetReference, final EObject target, final EObject value, final int index) {
+ final Command copyValueCommand = new GMFtoEMFCommandWrapper(new AbstractTransactionalCommand(domain, "", null) {
+
+ @Override
+ protected CommandResult doExecuteWithResult(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
+ final EObject copy;
+ final EObject targetValue = PapyrusCompareEObjectCopier.this.copier.get(value);
+ if(targetValue != null) {
+ copy = targetValue;
+ } else {
+ if(value.eResource() == null || value.eResource().getURI().isPlatformPlugin()) {
+ // We can't copy that object
+ copy = value;
+ } else {
+ copy = PapyrusCompareEObjectCopier.this.copier.copy(value);
+ }
+ }
+ Command cmd = null;
+ final Object referenceValue = target.eGet(targetReference);
+ if(referenceValue instanceof List && targetReference.isMany()) {
+ if(copy.eIsProxy() && copy instanceof InternalEObject) {
+ // only add if the element is not already there.
+ final URI proxURI = ((InternalEObject)copy).eProxyURI();
+ boolean found = false;
+ final Iterator<EObject> it = ((List<EObject>)referenceValue).iterator();
+ while(!found && it.hasNext()) {
+ final EObject obj = it.next();
+ if(obj instanceof InternalEObject) {
+ found = proxURI.equals(((InternalEObject)obj).eProxyURI());
+ }
+ }
+ if(!found) {
+ final List<EObject> targetList = (List<EObject>)referenceValue;
+ //addAtIndex(targetList, copy, index);
+ //not tested
+ cmd = getAddAtIndexCommand(domain, target, targetReference, targetList, copy, index);
+ }
+ } else {
+ final List<EObject> targetList = (List<EObject>)referenceValue;
+ final int currentIndex = targetList.indexOf(copy);
+ if(currentIndex == -1) {
+ //addAtIndex(targetList, copy, index);
+ //not tested
+ cmd = getAddAtIndexCommand(domain, target, targetReference, targetList, copy, index);
+ } else {
+ // The order could be wrong in case of eOpposites
+ // movetoIndex(targetList, currentIndex, index);
+ cmd = getMoveAtIndexCommand(domain, target, targetList, targetReference, copy, currentIndex, index);
+ // throw new UnsupportedOperationException("Not yet supported");
+ }
+ }
+ } else {
+ if(copy.eIsProxy() && copy instanceof InternalEObject) {
+ // only change value if the URI changes
+ final URI proxURI = ((InternalEObject)copy).eProxyURI();
+ if(referenceValue instanceof InternalEObject) {
+ if(!proxURI.equals(((InternalEObject)referenceValue).eProxyURI())) {
+ //not tested
+ //target.eSet(targetReference, copy);
+ cmd = PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, target, targetReference, copy);
+ }
+ }
+ } else {
+ //not tested
+ //target.eSet(targetReference, copy);
+ cmd = PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, target, targetReference, copy);
+ }
+ }
+
+ if(cmd != null) {
+ cmd.execute();
+ }
+ return CommandResult.newOKCommandResult();
+ }
+
+ });
+ return copyValueCommand;
+ }
+
+ /**
+ *
+ * @param key
+ * @return
+ * the copied object
+ */
+ public EObject getCopiedValue(final EObject key) {
+ return this.copier.get(key);
+ }
+
+
+ private Command getMoveAtIndexCommand(final TransactionalEditingDomain domain, final EObject target, final List<EObject> targetList, final EReference targetReference, final EObject copy, final int currentIndex, final int expectedIndex) {
+ final List<EObject> newColl = new ArrayList<EObject>(targetList);
+ final int size = targetList.size();
+ if(size <= 1 || currentIndex < 0 || currentIndex >= size) {
+ // return;
+ //do nothing
+ } else if(expectedIndex != -1 && expectedIndex != currentIndex && expectedIndex <= size - 1) {
+ newColl.add(expectedIndex, newColl.remove(currentIndex));
+ }
+
+ return PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, target, targetReference, newColl);
+ }
+
+ /**
+ * Returns the command to set the wanted object at the wanted index
+ *
+ * @param domain
+ * @param editedElement
+ * @param feature
+ * @param collection
+ * @param newValue
+ * @param index
+ * @return
+ */
+ private Command getAddAtIndexCommand(final TransactionalEditingDomain domain, final EObject editedElement, final EStructuralFeature feature, final Collection<EObject> collection, final EObject newValue, final int index) {
+ final List<EObject> newColl = new ArrayList<EObject>(collection);
+ final int listSize = collection.size();
+ if(index > -1 && index < listSize) {
+ newColl.add(index, newValue);
+ } else {
+ newColl.add(newValue);
+ }
+ attachRealPositionEAdapter(newValue, index);
+ reorderList(newColl);
+ return PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, editedElement, feature, newColl);
+ }
+
+ /**
+ * Duplicate code from EFactory
+ * If we could not merge a given object at its expected position in a list, we'll attach an Adapter to it
+ * in order to "remember" that "expected" position. That will allow us to reorder the list later on if
+ * need be.
+ *
+ * @param object
+ * The object on which to attach an Adapter.
+ * @param expectedPosition
+ * The expected position of <code>object</code> in its list.
+ */
+ private void attachRealPositionEAdapter(final Object object, final int expectedPosition) {
+ if(object instanceof EObject) {
+ ((EObject)object).eAdapters().add(new PositionAdapter(expectedPosition));
+ }
+ }
+
+ /**
+ * Duplicate code from EFactory
+ * Reorders the given list if it contains EObjects associated with a PositionAdapter which are not located
+ * at their expected positions.
+ *
+ * @param list
+ * The list that is to be reordered.
+ * @param <T>
+ * type of the list's elements.
+ */
+ private <T> void reorderList(final List<T> list) {
+ final List<T> newList = new ArrayList<T>(list);
+ Collections.sort(newList, new EObjectComparator());
+ for(int i = 0; i < list.size(); i++) {
+ int oldIndex = list.indexOf(newList.get(i));
+ list.add(i, list.remove(oldIndex));
+ }
+ return;
+ }
+
+
+ /**
+ * This class exists in several classes of this plugin. It is not an error : the same obejct can be referenced by different
+ * feature and different position at the same time. So we need to have a class PositionAdapter for each context!
+ * duplicate code from Efactory
+ * This adapter will be used to remember the accurate position of an EObject in its target list.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+ private class PositionAdapter extends AdapterImpl {
+
+ /** The index at which we expect to find this object. */
+ private final int expectedIndex;
+
+ /**
+ * Creates our adapter.
+ *
+ * @param index
+ * The index at which we expect to find this object.
+ */
+ public PositionAdapter(final int index) {
+ this.expectedIndex = index;
+ }
+
+ /**
+ * Returns the index at which we expect to find this object.
+ *
+ * @return The index at which we expect to find this object.
+ */
+ public int getExpectedIndex() {
+ return expectedIndex;
+ }
+ }
+
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusEFactory.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusEFactory.java
new file mode 100644
index 00000000000..76c461af314
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusEFactory.java
@@ -0,0 +1,301 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.utils;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.compare.EMFCompareMessages;
+import org.eclipse.emf.compare.FactoryException;
+import org.eclipse.emf.compare.util.EFactory;
+import org.eclipse.emf.ecore.EEnum;
+import org.eclipse.emf.ecore.EEnumLiteral;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.merger.internal.provider.PapyrusMergeCommandProvider;
+//TODO : merge with thepapyrus table command factory?
+/**
+ *
+ * This class is adapted from {@link EFactory}
+ *
+ */
+public class PapyrusEFactory {
+
+
+ private PapyrusEFactory() {
+ //nothing to do
+ }
+
+ public static final <T> Command getEAddCommand(final TransactionalEditingDomain domain, final EObject object, final String name, final T arg) throws FactoryException {
+ return getEAddCommand(domain, object, name, arg, -1);
+ }
+
+ public static final <T> Command getEAddCommand(final TransactionalEditingDomain domain, final EObject object, final String name, final T arg, final int elementIndex) throws FactoryException {
+ return getEAddCommand(domain, object, name, arg, elementIndex, false);
+ }
+
+ public static final <T> Command getEAddCommand(final TransactionalEditingDomain domain, final EObject object, final String name, final T arg, final int elementIndex, final boolean reorder) throws FactoryException {
+ Command returnedCommand = null;
+ final EStructuralFeature feature = eStructuralFeature(object, name);
+ if(feature.isMany() && arg != null) {
+ final Object manyValue = object.eGet(feature);
+ // if (manyValue instanceof InternalEList<?>) {
+ // final InternalEList<? super T> internalEList = (InternalEList<? super T>)manyValue;
+ // final int listSize = internalEList.size();
+ // if (elementIndex > -1 && elementIndex < listSize) {
+ // internalEList.addUnique(elementIndex, arg);
+ // } else {
+ // internalEList.addUnique(arg);
+ // }
+ // if (reorder) {
+ // attachRealPositionEAdapter(arg, elementIndex);
+ // reorderList(internalEList);
+ // }
+ // } else if (manyValue instanceof List<?>) {
+ // final List<? super T> list = (List<? super T>)manyValue;
+ // final int listSize = list.size();
+ // if (elementIndex > -1 && elementIndex < listSize) {
+ // list.add(elementIndex, arg);
+ // } else {
+ // list.add(arg);
+ // }
+ // if (reorder) {
+ // attachRealPositionEAdapter(arg, elementIndex);
+ // reorderList(list);
+ // }
+ // } else if (manyValue instanceof Collection<?>) {
+ // ((Collection<? super T>)manyValue).add(arg);
+ // }
+
+ if(manyValue instanceof Collection<?>) {
+ List<Object> newValue = new ArrayList<Object>((Collection<?>)manyValue);
+ final int listSize = newValue.size();
+ if(manyValue instanceof List<?>) {
+ if(elementIndex > -1 && elementIndex < listSize) {
+ newValue.add(elementIndex, arg);
+ } else {
+ newValue.add(arg);
+ }
+ if(reorder) {
+ attachRealPositionEAdapter(arg, elementIndex);
+ reorderList((List<?>)newValue);
+ }
+ } else if(manyValue instanceof Collection<?>) {
+ newValue.add(arg);
+ }
+ returnedCommand = PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, object, feature, newValue);
+ }
+ } else if(!feature.isMany()) {
+ // eSet(object, name, arg);
+ returnedCommand = PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, object, feature, arg);
+ }
+ return returnedCommand;
+ }
+
+ //TODO not tested
+ public static final Command getERemoveCommand(final TransactionalEditingDomain domain, final EObject object, final String name, final Object arg) throws FactoryException {
+ // final Object list = object.eGet(eStructuralFeature(object, name));
+ // if (list instanceof List) {
+ // if (arg != null) {
+ // ((List<?>)list).remove(arg);
+ // }
+ // } else {
+ // eSet(object, name, null);
+ // }
+ final Object list = object.eGet(eStructuralFeature(object, name));
+ if(list instanceof List) {
+ if(arg != null) {
+ List<?> newValue = new ArrayList((List<?>)list);
+ ((List<?>)newValue).remove(arg);
+ return getESetCommand(domain, object, name, newValue);
+ }
+ } else {
+ return getESetCommand(domain, object, name, null);
+ }
+ return null;
+ }
+
+ /**
+ *
+ * @param object
+ * @param name
+ * @param arg
+ * @return
+ * @throws FactoryException
+ */
+ public static final Command getESetCommand(final TransactionalEditingDomain domain, final EObject object, final String name, final Object arg) throws FactoryException {
+ Command returnedCommand;
+ final EStructuralFeature feature = eStructuralFeature(object, name);
+ if(!feature.isChangeable())
+ throw new FactoryException(EMFCompareMessages.getString("EFactory.UnSettableFeature", name)); //$NON-NLS-1$
+
+ if(feature.getEType() instanceof EEnum && arg instanceof String) {
+ final EEnumLiteral literal = ((EEnum)feature.getEType()).getEEnumLiteral((String)arg);
+ //object.eSet(feature, literal);
+ returnedCommand = PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, object, feature, literal);
+ } else {
+ if(arg == null && feature.isMany()) {
+ //object.eSet(feature, Collections.EMPTY_LIST);
+ returnedCommand = PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, object, feature, Collections.EMPTY_LIST);
+ } else if(arg == null) {
+ //object.eSet(feature, feature.getDefaultValue());
+ returnedCommand = PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, object, feature, feature.getDefaultValue());
+ } else {
+ //object.eSet(feature, arg);
+ returnedCommand = PapyrusMergeCommandProvider.INSTANCE.getSetCommand(domain, object, feature, arg);
+ }
+ }
+ return returnedCommand;
+ }
+
+
+ public static EStructuralFeature eStructuralFeature(final EObject object, final String name) throws FactoryException {
+ return EFactory.eStructuralFeature(object, name);
+ }
+
+
+
+ // /**
+ // * If we could not merge a given object at its expected position in a list, we'll attach an Adapter to it
+ // * in order to "remember" that "expected" position. That will allow us to reorder the list later on if
+ // * need be.
+ // *
+ // * @param object
+ // * The object on which to attach an Adapter.
+ // * @param expectedPosition
+ // * The expected position of <code>object</code> in its list.
+ // */
+ // public static void attachRealPositionEAdapter(final Object object, final int expectedPosition) {
+ // Class<?> myClass = null;
+ // try {
+ // myClass = Class.forName("org.eclipse.emf.compare.util.EFactory");
+ // } catch (ClassNotFoundException e2) {
+ // // TODO Auto-generated catch block
+ // e2.printStackTrace();
+ // }
+ // Class[] parameterTypes = new Class[2];
+ // parameterTypes[0] = java.lang.Object.class;
+ // parameterTypes[1] = Integer.TYPE;
+ // Method m = null;
+ //
+ // try {
+ // m = myClass.getDeclaredMethod("attachRealPositionEAdapter", parameterTypes);
+ // } catch (SecurityException e1) {
+ // // TODO Auto-generated catch block
+ // e1.printStackTrace();
+ // } catch (NoSuchMethodException e1) {
+ // // TODO Auto-generated catch block
+ // e1.printStackTrace();
+ // }
+ // m.setAccessible(true);
+ // Object[] parameters = new Object[2];
+ // parameters[0] = object;
+ // parameters[1] = expectedPosition;
+ //
+ // Object result = null;
+ // try {
+ // result = m.invoke(myClass, parameters);
+ // } catch (IllegalArgumentException e) {
+ // Activator.log.error(e);
+ // } catch (IllegalAccessException e) {
+ // Activator.log.error(e);
+ // } catch (InvocationTargetException e) {
+ // Activator.log.error(e);
+ // }
+ // }
+
+ /**
+ * Duplicate code from EFactory
+ * If we could not merge a given object at its expected position in a list, we'll attach an Adapter to it
+ * in order to "remember" that "expected" position. That will allow us to reorder the list later on if
+ * need be.
+ *
+ * @param object
+ * The object on which to attach an Adapter.
+ * @param expectedPosition
+ * The expected position of <code>object</code> in its list.
+ */
+ public static void attachRealPositionEAdapter(final Object object, final int expectedPosition) {
+ if(object instanceof EObject) {
+ ((EObject)object).eAdapters().add(new PositionAdapter(expectedPosition));
+ }
+ }
+
+ /**
+ * Reorders the given list if it contains EObjects associated with a PositionAdapter which are not located
+ * at their expected positions.
+ *
+ * @param list
+ * The list that is to be reordered.
+ * @param <T>
+ * type of the list's elements.
+ */
+ public static <T> void reorderList(final List<T> list) {
+ List<T> newList = new ArrayList<T>(list);
+ Collections.sort(newList, new EObjectComparator());
+ for(int i=0;i<list.size();i++){
+ int oldIndex = list.indexOf(newList.get(i));
+ list.add(i, list.remove(oldIndex));
+ }
+ return;
+ }
+
+
+ /**
+ * This method should never been called, except by copyCollection;
+ * This method allows to invoke the clone method on Cloneable object.
+ *
+ * @param cloneable
+ * a cloneable object
+ * @return
+ * a copy of the cloned object
+ * @throws UnsupportedOperationException
+ * used when the object is {@link Cloneable}, but not implemented (like LinkedList...)
+ */
+ private static Object clone(final Cloneable cloneable) throws UnsupportedOperationException {
+ Class<?> cloneableClass = cloneable.getClass();
+ Method cloneMethod = null;
+ Object newValue = null;
+ try {
+ cloneMethod = cloneableClass.getMethod("clone", new Class[0]);
+ } catch (SecurityException e) {
+ Activator.log.error(e);
+ } catch (NoSuchMethodException e) {
+ Activator.log.error(e);
+ }
+ cloneMethod.setAccessible(true);
+ try {
+ newValue = cloneMethod.invoke(cloneable, new Object[0]);
+ } catch (IllegalArgumentException e) {
+ Activator.log.error(e);
+ } catch (IllegalAccessException e) {
+ Activator.log.error(e);
+ } catch (InvocationTargetException e) {
+ Activator.log.error(e);
+ } catch (UnsupportedOperationException e) {
+ Activator.log.error(NLS.bind("I can't clone this object : {0}", cloneableClass), e);
+ throw e;
+ }
+ return newValue;
+ }
+
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusMap.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusMap.java
new file mode 100644
index 00000000000..037d9e822ba
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PapyrusMap.java
@@ -0,0 +1,104 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+
+/**
+ * This map log an error when a wanted element is unknown in the map
+ *
+ * @author VL222926
+ *
+ * @param <K>
+ * @param <V>
+ */
+public class PapyrusMap<K, V> extends HashMap<K, V> {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs an empty <tt>HashMap</tt> with the specified initial
+ * capacity and load factor.
+ *
+ * @param initialCapacity
+ * The initial capacity.
+ * @param loadFactor
+ * The load factor.
+ * @throws IllegalArgumentException
+ * if the initial capacity is negative
+ * or the load factor is nonpositive.
+ */
+ public PapyrusMap(final int initialCapacity, final float loadFactor) {
+ super(initialCapacity, loadFactor);
+ }
+
+ /**
+ * Constructs an empty <tt>HashMap</tt> with the specified initial
+ * capacity and the default load factor (0.75).
+ *
+ * @param initialCapacity
+ * the initial capacity.
+ * @throws IllegalArgumentException
+ * if the initial capacity is negative.
+ */
+ public PapyrusMap(final int initialCapacity) {
+ super(initialCapacity);
+ }
+
+ /**
+ * Constructs an empty <tt>HashMap</tt> with the default initial capacity
+ * (16) and the default load factor (0.75).
+ */
+ public PapyrusMap() {
+ super();
+ }
+
+ /**
+ * Constructs a new <tt>HashMap</tt> with the same mappings as the
+ * specified <tt>Map</tt>. The <tt>HashMap</tt> is created with
+ * default load factor (0.75) and an initial capacity sufficient to
+ * hold the mappings in the specified <tt>Map</tt>.
+ *
+ * @param m
+ * the map whose mappings are to be placed in this map.
+ * @throws NullPointerException
+ * if the specified map is null.
+ */
+ public PapyrusMap(final Map<? extends K, ? extends V> m) {
+ super(m);
+ }
+
+ /**
+ * We display an error when a wanted element is not included in the Map
+ *
+ * @see java.util.HashMap#get(java.lang.Object)
+ *
+ * @param key
+ * @return
+ */
+ @Override
+ public V get(final Object key) {
+ V obj = super.get(key);
+ if(obj == null) {
+ Activator.log.error("The following element is unknown in the map : " + key, new NullPointerException());
+ }
+ return obj;
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PositionAdapter.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PositionAdapter.java
new file mode 100644
index 00000000000..74dc5fdf07f
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/PositionAdapter.java
@@ -0,0 +1,48 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.utils;
+
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+
+
+ /**
+ * duplicate code from Efactory
+ * This adapter will be used to remember the accurate position of an EObject in its target list.
+ *
+ * @author <a href="mailto:laurent.goubet@obeo.fr">Laurent Goubet</a>
+ */
+public class PositionAdapter extends AdapterImpl {
+
+ /** The index at which we expect to find this object. */
+ private final int expectedIndex;
+
+ /**
+ * Creates our adapter.
+ *
+ * @param index
+ * The index at which we expect to find this object.
+ */
+ public PositionAdapter(final int index) {
+ this.expectedIndex = index;
+ }
+
+ /**
+ * Returns the index at which we expect to find this object.
+ *
+ * @return The index at which we expect to find this object.
+ */
+ public int getExpectedIndex() {
+ return expectedIndex;
+ }
+}
diff --git a/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/TransactionalMergeService.java b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/TransactionalMergeService.java
new file mode 100644
index 00000000000..b1bc5a649da
--- /dev/null
+++ b/sandbox/UMLCompareMergerExample/org.eclipse.papyrus.uml.compare.merger/src/org/eclipse/papyrus/uml/compare/merger/internal/utils/TransactionalMergeService.java
@@ -0,0 +1,311 @@
+/*****************************************************************************
+ * Copyright (c) 2012 CEA LIST.
+ *
+ *
+ * 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:
+ * Vincent Lorenzo (CEA LIST) Vincent.Lorenzo@cea.fr - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.uml.compare.merger.internal.utils;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
+import org.eclipse.emf.compare.diff.merge.IMergeListener;
+import org.eclipse.emf.compare.diff.merge.IMerger;
+import org.eclipse.emf.compare.diff.merge.service.MergeFactory;
+import org.eclipse.emf.compare.diff.merge.service.MergeService;
+import org.eclipse.emf.compare.diff.metamodel.ConflictingDiffElement;
+import org.eclipse.emf.compare.diff.metamodel.DiffElement;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.papyrus.infra.tools.util.ReflectHelper;
+import org.eclipse.papyrus.uml.compare.merger.Activator;
+import org.eclipse.papyrus.uml.compare.merger.internal.commands.FireMergeDiffEndCommand;
+import org.eclipse.papyrus.uml.compare.merger.internal.commands.FireMergeDiffStartCommand;
+import org.eclipse.papyrus.uml.compare.merger.internal.commands.FireMergeOperationEndCommand;
+import org.eclipse.papyrus.uml.compare.merger.internal.commands.FireMergeOperationStartCommand;
+import org.eclipse.papyrus.uml.compare.merger.utils.ITransactionalMerger;
+
+/**
+ *
+ * This service should replace the EMF-Compare MergeService
+ *
+ */
+//TODO not used
+public class TransactionalMergeService {
+
+ private static Method addMergeListenerMethod = null;
+
+ private static Method removeMergeListenerMethod = null;
+
+ // /** This copier will be used when merging references. */
+ // private static EMFCompareEObjectCopier copier;
+
+ /**
+ * Default constructor.
+ */
+ private TransactionalMergeService() {
+ // hides default constructor
+ }
+
+ /**
+ * TODO this method should be covered with a JUnit test
+ * Registers a new merge listener for notifications about merge operations. Has no effect if the listener
+ * is already registered.
+ *
+ * @param listener
+ * New Listener to register for notifications.
+ */
+ public static void addMergeListener(final IMergeListener listener) {
+ if(addMergeListenerMethod == null) {
+ Class<?>[] parameterTypes = new Class[1];
+ parameterTypes[0] = IMergeListener.class;
+ try {
+ addMergeListenerMethod = ReflectHelper.getMethod(MergeService.class, "addMergeListener", parameterTypes);
+ } catch (SecurityException e) {
+ Activator.log.error(e);
+ } catch (NoSuchMethodException e) {
+ Activator.log.error(e);
+ }
+ }
+ final Object[] parameters = new Object[1];
+ parameters[0] = listener;
+ try {
+ addMergeListenerMethod.invoke(null, parameters);
+ } catch (IllegalArgumentException e) {
+ Activator.log.error(e);
+ } catch (IllegalAccessException e) {
+ Activator.log.error(e);
+ } catch (InvocationTargetException e) {
+ Activator.log.error(e);
+ }
+ }
+
+
+ // /**
+ // * Returns the copier given the diff it should merge.
+ // *
+ // * @param diff
+ // * The DiffElement for which a copier is needed.
+ // * @return The copier for a given diff.
+ // */
+ // public static EMFCompareEObjectCopier getCopier(final DiffElement diff) {
+ // final DiffModel diffModel = getContainerDiffModel(diff);
+ // if (diffModel == null)
+ // throw new IllegalArgumentException("The diff element should be contained in a DiffModel instance"); //$NON-NLS-1$
+ // if (diffModel.eContainer() instanceof DiffResourceSet) {
+ // if (copier == null) {
+ // copier = new EMFCompareEObjectCopier((DiffResourceSet)diffModel.eContainer());
+ // } else if (copier.getDiffResourceSet() != diffModel.eContainer()) {
+ // copier.clear();
+ // copier = new EMFCompareEObjectCopier((DiffResourceSet)diffModel.eContainer());
+ // }
+ // } else {
+ // if (copier == null) {
+ // copier = new EMFCompareEObjectCopier(diffModel);
+ // } else if (copier.getDiffModel() != diffModel) {
+ // copier.clear();
+ // copier = new EMFCompareEObjectCopier(diffModel);
+ // }
+ // }
+ // return copier;
+ // }
+
+ // /**
+ // * Browse the diff model from the leaf to the top to find the containing {@link DiffModel} instance.
+ // *
+ // * @param diff
+ // * any {@link DiffElement}.
+ // * @return the containing {@link DiffModel} instance, null if not found.
+ // */
+ // private static DiffModel getContainerDiffModel(final DiffElement diff) {
+ // EObject container = diff.eContainer();
+ // while (container != null) {
+ // if (container instanceof DiffModel)
+ // return (DiffModel)container;
+ // container = container.eContainer();
+ // }
+ // return null;
+ // }
+
+ /**
+ * Merges a single DiffElement in the direction specified by <code>leftToRight</code>.
+ * <p>
+ * Will notify the list of its merge listeners before, and after the operation.
+ * </p>
+ *
+ * @param element
+ * {@link DiffElement} containing the information to merge.
+ * @param leftToRight
+ * <code>True</code> if the changes must be applied from the left to the right model, <code>False</code> when they have to be applied the
+ * other way around.
+ */
+ // public static void merge(final DiffElement element, final boolean leftToRight) {
+ // fireMergeOperationStart(element);
+ // doMerge(element, leftToRight);
+ // fireMergeOperationEnd(element);
+ // }
+
+ public static Command getMergeCommand(final TransactionalEditingDomain domain, final DiffElement element, final boolean leftToRight) {
+ CompoundCommand cmd = new CompoundCommand("MergeCommand");
+ cmd.append(new FireMergeOperationStartCommand(element, getMergeListeners()));
+ cmd.append(getDoMergeCommand(domain, element, leftToRight));
+ cmd.append(new FireMergeOperationEndCommand(element, getMergeListeners()));
+ return cmd;
+ }
+
+ /**
+ * Applies the changes implied by a given {@link DiffElement} in the direction specified by <code>leftToRight</code>.
+ * <p>
+ * Will notify the list of its merge listeners before, and after the merge.
+ * </p>
+ *
+ * @param element
+ * {@link DiffElement} containing the information to merge.
+ * @param leftToRight
+ * <code>True</code> if the changes must be applied from the left to the right model, <code>False</code> when they have to be applied the
+ * other way around.
+ */
+ // protected static void doMerge(final DiffElement element, final boolean leftToRight) {
+ // fireMergeDiffStart(element);
+ // final IMerger merger;
+ // if(element instanceof ConflictingDiffElement)
+ // merger = MergeFactory.createMerger(element.getSubDiffElements().get(0));
+ // else
+ // merger = MergeFactory.createMerger(element);
+ // if(leftToRight && merger.canUndoInTarget()) {
+ // merger.undoInTarget();
+ // } else if(!leftToRight && merger.canApplyInOrigin()) {
+ // merger.applyInOrigin();
+ // }
+ // fireMergeDiffEnd(element);
+ // }
+
+ private static Command getDoMergeCommand(final TransactionalEditingDomain domain, final DiffElement element, final boolean leftToRight) {
+ final CompoundCommand cmd = new CompoundCommand("DoMergeCommand");
+ cmd.append(new FireMergeDiffStartCommand(element, getMergeListeners()));
+ final IMerger merger;
+ if(element instanceof ConflictingDiffElement) {
+ merger = MergeFactory.createMerger(element.getSubDiffElements().get(0));
+ } else {
+ merger = MergeFactory.createMerger(element);
+ }
+ if(merger instanceof ITransactionalMerger) {
+ if(leftToRight && merger.canUndoInTarget()) {
+ cmd.append(((ITransactionalMerger)merger).getUndoInTargetCommand(domain));
+ } else if(!leftToRight && merger.canApplyInOrigin()) {
+ cmd.append(((ITransactionalMerger)merger).getApplyInOriginCommand(domain));
+ }
+ } else {
+ throw new UnsupportedOperationException(NLS.bind("I can't found the Papyrus Merger for {0}.", element));
+ }
+
+ cmd.append(new FireMergeDiffEndCommand(element, getMergeListeners()));
+ return cmd;
+ }
+
+
+ // /**
+ // * Merges a list of DiffElements in the direction specified by <code>leftToRight</code>.
+ // * <p>
+ // * Will notify the list of its merge listeners before, and after the operation.
+ // * </p>
+ // *
+ // * @param elements
+ // * {@link DiffElement}s containing the information to merge.
+ // * @param leftToRight
+ // * <code>True</code> if the changes must be applied from the left to the right model, <code>False</code> when they have to be applied the
+ // * other way around.
+ // */
+ // public static void merge(final List<DiffElement> elements, final boolean leftToRight) {
+ // fireMergeOperationStart(elements);
+ // for(DiffElement element : new ArrayList<DiffElement>(elements))
+ // // we might remove the diff from the list before merging it
+ // // (eOpposite reference)
+ // if(element.eContainer() != null)
+ // doMerge(element, leftToRight);
+ // fireMergeOperationEnd(elements);
+ // }
+
+ public static Command getMergeCommand(final TransactionalEditingDomain domain, final List<DiffElement> elements, final boolean leftToRight) {
+ final CompoundCommand cmd = new CompoundCommand("MergeCommand");
+ cmd.append(new FireMergeOperationStartCommand(elements, getMergeListeners()));
+ for(DiffElement element : new ArrayList<DiffElement>(elements)) {
+ // we might remove the diff from the list before merging it
+ // (eOpposite reference)
+ if(element.eContainer() != null) {
+ cmd.append(getDoMergeCommand(domain, element, leftToRight));
+ }
+ }
+ cmd.append(new FireMergeOperationEndCommand(elements, getMergeListeners()));
+ return cmd;
+ }
+
+ /**
+ * removes a merge listener from the list of registered listeners. This will have no effect if the given
+ * listener is not registered for notifications on this service.
+ *
+ * @param listener
+ * New Listener to register for notifications.
+ */
+ public static void removeMergeListener(final IMergeListener listener) {
+ if(removeMergeListenerMethod == null) {
+ Class<?>[] parameterTypes = new Class[1];
+ parameterTypes[0] = IMergeListener.class;
+ try {
+ removeMergeListenerMethod = ReflectHelper.getMethod(MergeService.class, "removeMergeListener", parameterTypes);
+ } catch (SecurityException e) {
+ Activator.log.error(e);
+ } catch (NoSuchMethodException e) {
+ Activator.log.error(e);
+ }
+ }
+ final Object[] parameters = new Object[1];
+ parameters[0] = listener;
+ try {
+ removeMergeListenerMethod.invoke(null, parameters);
+ } catch (IllegalArgumentException e) {
+ Activator.log.error(e);
+ } catch (IllegalAccessException e) {
+ Activator.log.error(e);
+ } catch (InvocationTargetException e) {
+ Activator.log.error(e);
+ }
+ }
+
+
+ @SuppressWarnings("unchecked")
+ //we suppress this warning because the field is always a List of IMergeListener
+ private static List<IMergeListener> getMergeListeners() {
+ List<IMergeListener> listeners = null;
+ Field myField = null;
+ try {
+ myField = MergeService.class.getDeclaredField("MERGE_LISTENERS");
+ } catch (SecurityException e) {
+ Activator.log.error(e);
+ } catch (NoSuchFieldException e) {
+ Activator.log.error(e);
+ }
+ myField.setAccessible(true);
+ try {
+ listeners = (List<IMergeListener>)myField.get(null);
+ } catch (IllegalArgumentException e) {
+ Activator.log.error(e);
+ } catch (IllegalAccessException e) {
+ Activator.log.error(e);
+ }
+ return listeners;
+ }
+
+}

Back to the top