/*****************************************************************************
* 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 leftToRight
.
*
* Will notify the list of its merge listeners before, and after the operation. *
* * @param element * {@link DiffElement} containing the information to merge. * @param leftToRight *True
if the changes must be applied from the left to the right model, False
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 leftToRight
.
* * Will notify the list of its merge listeners before, and after the merge. *
* * @param element * {@link DiffElement} containing the information to merge. * @param leftToRight *True
if the changes must be applied from the left to the right model, False
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 leftToRight
.
// * // * Will notify the list of its merge listeners before, and after the operation. // *
// * // * @param elements // * {@link DiffElement}s containing the information to merge. // * @param leftToRight // *True
if the changes must be applied from the left to the right model, False
when they have to be applied the
// * other way around.
// */
// public static void merge(final List