blob: a700d7b7eb7866c588db02bd1110ec1403cb724e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011-2014 EclipseSource Muenchen GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Edgar - initial API and implementation
******************************************************************************/
package org.eclipse.emf.emfstore.client.conflictdetection.test.merging;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.emfstore.client.test.common.cases.ESTest;
import org.eclipse.emf.emfstore.client.test.common.dsl.Create;
import org.eclipse.emf.emfstore.client.util.RunESCommand;
import org.eclipse.emf.emfstore.internal.client.model.exceptions.ChangeConflictException;
import org.eclipse.emf.emfstore.internal.common.model.ModelElementId;
import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.internal.server.conflictDetection.ChangeConflictSet;
import org.eclipse.emf.emfstore.internal.server.conflictDetection.ConflictBucket;
import org.eclipse.emf.emfstore.internal.server.conflictDetection.ConflictDetector;
import org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AttributeOperation;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.CreateDeleteOperation;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.util.OperationUtil;
import org.eclipse.emf.emfstore.server.ESCloseableIterable;
import org.eclipse.emf.emfstore.test.model.TestElement;
import org.junit.Test;
/**
* @author emueller
*
*/
public class MergeResolvedConflictsWithSyntheticOpTest extends ESTest {
private static final String BLUB = "blub"; //$NON-NLS-1$
private static final String DESCRIPTION = "description"; //$NON-NLS-1$
private static final String BAR = "bar"; //$NON-NLS-1$
private static final String BAR2 = "bar2"; //$NON-NLS-1$
private static final String FOO = "foo"; //$NON-NLS-1$
private static final String NAME = "name"; //$NON-NLS-1$
@Test
public void testMerge() throws ChangeConflictException {
final TestElement testElement = Create.testElement();
RunESCommand.run(new Callable<Void>() {
public Void call() throws Exception {
getProject().getModelElements().add(testElement);
return null;
}
});
final ModelElementId modelElementId = getProject().getModelElementId(testElement);
final AbstractChangePackage myChangePackage = Create.changePackage();
final AbstractChangePackage theirChangePackage = Create.changePackage();
final AttributeOperation myAttributeOp = Create.attributeOp();
myAttributeOp.setOldValue(FOO);
myAttributeOp.setNewValue(BAR);
myAttributeOp.setFeatureName(NAME);
myAttributeOp.setModelElementId(ModelUtil.clone(modelElementId));
final AttributeOperation theirAttributeOp = Create.attributeOp();
theirAttributeOp.setOldValue(FOO);
theirAttributeOp.setNewValue(BAR2);
theirAttributeOp.setFeatureName(NAME);
theirAttributeOp.setModelElementId(ModelUtil.clone(modelElementId));
myChangePackage.add(myAttributeOp);
theirChangePackage.add(theirAttributeOp);
final List<AbstractChangePackage> myChangePackages = Arrays.asList(myChangePackage);
final List<AbstractChangePackage> theirChangePackages = Arrays.asList(theirChangePackage);
final ConflictDetector conflictDetector = new ConflictDetector();
final ChangeConflictSet conflictSet = conflictDetector.calculateConflicts(
myChangePackages,
theirChangePackages,
getProject());
final ConflictBucket next = conflictSet.getConflictBuckets().iterator().next();
// fake operation during merge
final AttributeOperation generatedAttributeOp = Create.attributeOp();
generatedAttributeOp.setFeatureName(DESCRIPTION);
generatedAttributeOp.setNewValue(BLUB);
generatedAttributeOp.setModelElementId(ModelUtil.clone(modelElementId));
final Set<AbstractOperation> acceptedLocal = new LinkedHashSet<AbstractOperation>();
final Set<AbstractOperation> rejectedTheirs = new LinkedHashSet<AbstractOperation>();
acceptedLocal.add(myAttributeOp);
acceptedLocal.add(generatedAttributeOp);
rejectedTheirs.add(theirAttributeOp);
next.resolveConflict(acceptedLocal, rejectedTheirs);
// myChangePackage.getOperations().add(generatedAttributeOp);
final AbstractChangePackage mergeResolvedConflicts = getProjectSpace().mergeResolvedConflicts(
conflictSet,
myChangePackages,
theirChangePackages);
assertTrue(containsOperations(mergeResolvedConflicts, generatedAttributeOp));
}
// TODO LCP: duplicate code, see ProjectSpace
private static boolean containsOperations(AbstractChangePackage changePackage, AbstractOperation operation) {
final ESCloseableIterable<AbstractOperation> operations = changePackage.operations();
try {
for (final AbstractOperation op : operations.iterable()) {
if (OperationUtil.isCreateDelete(op) &&
OperationUtil.isCreateDelete(operation)) {
final CreateDeleteOperation createDeleteOperation = CreateDeleteOperation.class
.cast(op);
final CreateDeleteOperation otherCreateDeleteOperation = CreateDeleteOperation.class
.cast(operation);
if (createDeleteOperation.getOperationId().equals(otherCreateDeleteOperation.getOperationId())
&& createDeleteOperation.getModelElementId().equals(
otherCreateDeleteOperation.getModelElementId())) {
return true;
}
} else if (EcoreUtil.equals(op, operation)) {
return true;
}
}
} finally {
operations.close();
}
return false;
}
}