/******************************************************************************* * Copyright (c) 2016 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: * Alexandra Buzila - initial API and implementation * Philip Langer - bug 501864 *******************************************************************************/ package org.eclipse.emf.compare.uml2.tests.multiplicitychanges; import static com.google.common.base.Predicates.and; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.size; import static org.eclipse.emf.compare.DifferenceSource.LEFT; import static org.eclipse.emf.compare.DifferenceSource.RIGHT; import static org.eclipse.emf.compare.utils.EMFComparePredicates.fromSide; import static org.eclipse.emf.compare.utils.EMFComparePredicates.ofKind; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import com.google.common.base.Predicate; import com.google.common.collect.Lists; import java.io.IOException; import java.util.ArrayList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.compare.AttributeChange; import org.eclipse.emf.compare.Comparison; import org.eclipse.emf.compare.Conflict; import org.eclipse.emf.compare.ConflictKind; import org.eclipse.emf.compare.Diff; import org.eclipse.emf.compare.DifferenceKind; import org.eclipse.emf.compare.ReferenceChange; import org.eclipse.emf.compare.ide.ui.tests.framework.ResolutionStrategyID; import org.eclipse.emf.compare.ide.ui.tests.framework.RuntimeTestRunner; import org.eclipse.emf.compare.ide.ui.tests.framework.annotations.Compare; import org.eclipse.emf.compare.ide.ui.tests.framework.annotations.ResolutionStrategies; import org.eclipse.emf.compare.uml2.internal.MultiplicityElementChange; import org.eclipse.emf.compare.utils.MatchUtil; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.uml2.uml.LiteralInteger; import org.eclipse.uml2.uml.LiteralUnlimitedNatural; import org.eclipse.uml2.uml.UMLPackage; import org.junit.runner.RunWith; @RunWith(RuntimeTestRunner.class) @ResolutionStrategies(ResolutionStrategyID.PROJECT) public class MultiplicityElementChangesTest { private static final Predicate<Diff> IS_MULTIPLICITY_CHANGE = new Predicate<Diff>() { public boolean apply(Diff diff) { return diff instanceof MultiplicityElementChange; } }; private static final Predicate<Diff> IS_LOWER_VALUE_REFERENCE_CHANGE = new Predicate<Diff>() { public boolean apply(Diff diff) { if (!(diff instanceof ReferenceChange)) { return false; } ReferenceChange refChange = (ReferenceChange)diff; return refChange.getReference() == UMLPackage.eINSTANCE.getMultiplicityElement_LowerValue(); } }; private static final Predicate<Diff> IS_LOWER_VALUE_ATTRIBUTE_CHANGE = new Predicate<Diff>() { public boolean apply(Diff diff) { if (!(diff instanceof AttributeChange)) { return false; } EObject container = MatchUtil.getContainer(diff.getMatch().getComparison(), diff); if (container instanceof LiteralInteger || container instanceof LiteralUnlimitedNatural) { EStructuralFeature eContainingFeature = container.eContainingFeature(); return eContainingFeature == UMLPackage.eINSTANCE.getMultiplicityElement_LowerValue(); } return false; } }; private static final Predicate<Diff> IS_UPPER_VALUE_REFERENCE_CHANGE = new Predicate<Diff>() { public boolean apply(Diff diff) { if (!(diff instanceof ReferenceChange)) { return false; } ReferenceChange refChange = (ReferenceChange)diff; return refChange.getReference() == UMLPackage.eINSTANCE.getMultiplicityElement_UpperValue(); } }; private static final Predicate<Diff> IS_UPPER_VALUE_ATTRIBUTE_CHANGE = new Predicate<Diff>() { public boolean apply(Diff diff) { if (!(diff instanceof AttributeChange)) { return false; } EObject container = MatchUtil.getContainer(diff.getMatch().getComparison(), diff); if (container instanceof LiteralInteger || container instanceof LiteralUnlimitedNatural) { EStructuralFeature eContainingFeature = container.eContainingFeature(); return eContainingFeature == UMLPackage.eINSTANCE.getMultiplicityElement_UpperValue(); } return false; } }; private static final Predicate<Diff> IS_UPPER_VALUE_CHANGE = new Predicate<Diff>() { public boolean apply(Diff diff) { return IS_UPPER_VALUE_REFERENCE_CHANGE.apply(diff) || IS_UPPER_VALUE_ATTRIBUTE_CHANGE.apply(diff); } }; private static final Predicate<Diff> IS_LOWER_VALUE_CHANGE = new Predicate<Diff>() { public boolean apply(Diff diff) { return IS_LOWER_VALUE_REFERENCE_CHANGE.apply(diff) || IS_LOWER_VALUE_ATTRIBUTE_CHANGE.apply(diff); } }; /** * <b>origin:</b> an activity with an input pin <br> * <b>left:</b> multiplicity lower value is added to the input pin <br> * <b>right:</b> multiplicity upper value is added to the input pin */ @Compare(left = "a1/left.uml", right = "a1/right.uml", ancestor = "a1/origin.uml") public void testNonConflictingAddition(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); Iterable<Diff> leftChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT))); Iterable<Diff> rightChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT))); assertEquals(1, size(leftChanges)); assertEquals(1, size(rightChanges)); MultiplicityElementChange leftChange = (MultiplicityElementChange)leftChanges.iterator().next(); assertEquals(1, leftChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, leftChange.getKind()); MultiplicityElementChange rightChange = (MultiplicityElementChange)rightChanges.iterator().next(); assertEquals(1, rightChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, rightChange.getKind()); assertEquals(0, comparison.getConflicts().size()); } /** * <b>origin:</b> an activity with an input pin <br> * <b>left:</b> multiplicity lower value is added to the input pin <br> * <b>right:</b> multiplicity lower and upper values are added to the input pin, but the lower value is * the same value as in the left change */ @Compare(left = "a2/left.uml", right = "a2/right.uml", ancestor = "a2/origin.uml") public void testAdditionsWithPseudoconflict(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); ArrayList<Diff> leftChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT)))); ArrayList<Diff> rightChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT)))); assertEquals(1, size(leftChanges)); assertEquals(2, size(rightChanges)); MultiplicityElementChange leftChange = (MultiplicityElementChange)leftChanges.get(0); assertEquals(1, leftChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, leftChange.getKind()); MultiplicityElementChange rightChange1 = (MultiplicityElementChange)rightChanges.get(0); assertEquals(1, rightChange1.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange1) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, rightChange1.getKind()); MultiplicityElementChange rightChange2 = (MultiplicityElementChange)rightChanges.get(1); assertEquals(1, rightChange2.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange2) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, rightChange2.getKind()); assertEquals(1, comparison.getConflicts().size()); Conflict conflict = comparison.getConflicts().get(0); assertEquals(ConflictKind.PSEUDO, conflict.getKind()); assertTrue(conflict.getDifferences().contains(getFirstRefiningDiff(leftChange))); if (isLowerValueChange(rightChange1)) { assertEquals(conflict, getRefiningsConflict(rightChange1)); } else { assertTrue(isLowerValueChange(rightChange2)); assertEquals(conflict, getRefiningsConflict(rightChange2)); } } /** * <b>origin:</b> an activity with an input pin <br> * <b>left:</b> multiplicity lower value is added to the input pin <br> * <b>right:</b> multiplicity lower and upper values are added to the input pin, but the lower value is * different than the one in the left change */ @Compare(left = "a3/left.uml", right = "a3/right.uml", ancestor = "a3/origin.uml") public void testAdditionsWithConflict(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); ArrayList<Diff> leftChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT)))); ArrayList<Diff> rightChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT)))); assertEquals(1, size(leftChanges)); assertEquals(2, size(rightChanges)); MultiplicityElementChange leftChange = (MultiplicityElementChange)leftChanges.get(0); assertEquals(1, leftChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, leftChange.getKind()); MultiplicityElementChange rightChange1 = (MultiplicityElementChange)rightChanges.get(0); assertEquals(1, rightChange1.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange1) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, rightChange1.getKind()); MultiplicityElementChange rightChange2 = (MultiplicityElementChange)rightChanges.get(1); assertEquals(1, rightChange2.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange2) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, rightChange2.getKind()); assertEquals(1, comparison.getConflicts().size()); Conflict conflict = comparison.getConflicts().get(0); assertEquals(ConflictKind.REAL, conflict.getKind()); if (isLowerValueChange(rightChange1)) { assertEquals(conflict, getRefiningsConflict(rightChange1)); } else { assertTrue(isLowerValueChange(rightChange2)); assertEquals(conflict, getRefiningsConflict(rightChange2)); } } /** * <b>origin:</b> an activity with an input pin, with a lower and upper value <br> * <b>left:</b> multiplicity lower value is changed to 1 <br> * <b>right:</b> multiplicity lower value is changed to 2 <br> * A real conflict should be produced. */ @Compare(left = "a4/left.uml", right = "a4/right.uml", ancestor = "a4/origin.uml") public void testChangesWithConflict(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); Iterable<Diff> leftChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT))); Iterable<Diff> rightChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT))); assertEquals(1, size(leftChanges)); MultiplicityElementChange leftChange = (MultiplicityElementChange)leftChanges.iterator().next(); assertEquals(1, leftChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange) instanceof AttributeChange); assertEquals(DifferenceKind.CHANGE, leftChange.getKind()); assertEquals(1, size(rightChanges)); MultiplicityElementChange rightChange = (MultiplicityElementChange)rightChanges.iterator().next(); assertEquals(1, rightChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange) instanceof AttributeChange); assertEquals(DifferenceKind.CHANGE, rightChange.getKind()); assertEquals(1, comparison.getConflicts().size()); Conflict conflict = comparison.getConflicts().get(0); assertEquals(ConflictKind.REAL, conflict.getKind()); assertEquals(conflict, getRefiningsConflict(rightChange)); } /** * <b>origin:</b> an activity with an input pin, with a lower and upper value <br> * <b>left:</b> multiplicity lower value is changed to 1 <br> * <b>right:</b> multiplicity lower value is changed to 1 <br> * A pseudo conflict should be produced. */ @Compare(left = "a5/left.uml", right = "a5/right.uml", ancestor = "a5/origin.uml") public void testChangesWithPseudoconflict(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); Iterable<Diff> leftChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT))); Iterable<Diff> rightChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT))); assertEquals(1, size(leftChanges)); Diff leftChange = leftChanges.iterator().next(); assertEquals(1, leftChange.getRefinedBy().size()); assertTrue(leftChange.getRefinedBy().get(0) instanceof AttributeChange); assertEquals(DifferenceKind.CHANGE, leftChange.getKind()); assertEquals(1, size(rightChanges)); Diff rightChange = rightChanges.iterator().next(); assertEquals(1, rightChange.getRefinedBy().size()); assertTrue(rightChange.getRefinedBy().get(0) instanceof AttributeChange); assertEquals(DifferenceKind.CHANGE, rightChange.getKind()); assertEquals(1, comparison.getConflicts().size()); Conflict conflict = comparison.getConflicts().get(0); assertEquals(ConflictKind.PSEUDO, conflict.getKind()); assertEquals(conflict, getRefiningsConflict(rightChange)); } /** * <b>origin:</b> an activity with an input pin, with a lower and upper value <br> * <b>left:</b> multiplicity lower value is changed to 1 <br> * <b>right:</b> multiplicity lower and upper values are removed <br> */ @Compare(left = "a6/left.uml", right = "a6/right.uml", ancestor = "a6/origin.uml") public void testRemoveConflict(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); ArrayList<Diff> leftChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT)))); ArrayList<Diff> rightChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT)))); assertEquals(1, size(leftChanges)); MultiplicityElementChange leftChange = (MultiplicityElementChange)leftChanges.iterator().next(); assertEquals(1, leftChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange) instanceof AttributeChange); assertEquals(DifferenceKind.CHANGE, leftChange.getKind()); assertEquals(2, size(rightChanges)); MultiplicityElementChange rightChange1 = (MultiplicityElementChange)rightChanges.get(0); assertEquals(1, rightChange1.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange1) instanceof ReferenceChange); assertEquals(DifferenceKind.DELETE, rightChange1.getKind()); MultiplicityElementChange rightChange2 = (MultiplicityElementChange)rightChanges.get(1); assertEquals(1, rightChange2.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange2) instanceof ReferenceChange); assertEquals(DifferenceKind.DELETE, rightChange2.getKind()); assertEquals(1, comparison.getConflicts().size()); Conflict conflict = comparison.getConflicts().get(0); assertEquals(ConflictKind.REAL, conflict.getKind()); if (isLowerValueChange(rightChange1)) { assertTrue(isUpperValueChange(rightChange2)); assertEquals(conflict, getRefiningsConflict(rightChange1)); } else { assertTrue(isUpperValueChange(rightChange1)); assertTrue(isLowerValueChange(rightChange2)); assertEquals(conflict, getRefiningsConflict(rightChange2)); } } /** * <b>origin:</b> an activity with an input pin, with a lower and upper value <br> * <b>left:</b> multiplicity upper value is removed <br> * <b>right:</b> multiplicity lower value is changed to 1 <br> */ @Compare(left = "a7/left.uml", right = "a7/right.uml", ancestor = "a7/origin.uml") public void testRemoveNoConflict(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); Iterable<Diff> leftChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT))); Iterable<Diff> rightChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT))); assertEquals(1, size(leftChanges)); MultiplicityElementChange leftChange = (MultiplicityElementChange)leftChanges.iterator().next(); assertEquals(1, leftChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange) instanceof ReferenceChange); assertEquals(DifferenceKind.DELETE, leftChange.getKind()); assertEquals(1, size(rightChanges)); MultiplicityElementChange rightChange = (MultiplicityElementChange)rightChanges.iterator().next(); assertEquals(1, rightChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange) instanceof AttributeChange); assertEquals(DifferenceKind.CHANGE, rightChange.getKind()); assertEquals(0, comparison.getConflicts().size()); } /** * <b>origin:</b> an activity with an input pin, with a lower and upper value <br> * <b>left:</b> multiplicity upper value is removed <br> * <b>right:</b> multiplicity upper value is removed <br> */ @Compare(left = "a8/left.uml", right = "a8/right.uml", ancestor = "a8/origin.uml") public void testRemovePseudoConflict(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); Iterable<Diff> leftChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT))); Iterable<Diff> rightChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT))); assertEquals(1, size(leftChanges)); assertEquals(1, size(rightChanges)); MultiplicityElementChange leftChange = (MultiplicityElementChange)leftChanges.iterator().next(); assertEquals(1, leftChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange) instanceof ReferenceChange); assertEquals(DifferenceKind.DELETE, leftChange.getKind()); MultiplicityElementChange rightChange = (MultiplicityElementChange)rightChanges.iterator().next(); assertEquals(1, rightChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange) instanceof ReferenceChange); assertEquals(DifferenceKind.DELETE, rightChange.getKind()); assertEquals(1, comparison.getConflicts().size()); Conflict conflict = comparison.getConflicts().get(0); assertEquals(ConflictKind.PSEUDO, conflict.getKind()); } /** * <b>origin:</b> an activity with an input pin, with an upper value <br> * <b>left:</b> multiplicity upper value is removed <br> * <b>right:</b> multiplicity lower value is added <br> */ @Compare(left = "a9/left.uml", right = "a9/right.uml", ancestor = "a9/origin.uml") public void testRemoveAndAddNoConflict(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); Iterable<Diff> leftChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT))); Iterable<Diff> rightChanges = filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT))); assertEquals(1, size(leftChanges)); assertEquals(1, size(rightChanges)); MultiplicityElementChange leftChange = (MultiplicityElementChange)leftChanges.iterator().next(); assertEquals(1, leftChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange) instanceof ReferenceChange); assertEquals(DifferenceKind.DELETE, leftChange.getKind()); MultiplicityElementChange rightChange = (MultiplicityElementChange)rightChanges.iterator().next(); assertEquals(1, rightChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, rightChange.getKind()); assertEquals(0, comparison.getConflicts().size()); } /** * <b>origin:</b> an activity with an input pin, with an upper value <br> * <b>left:</b> multiplicity upper (0) and lower (1) value are added<br> * <b>right:</b> multiplicity upper (1) and lower (1) value are added<br> * These changes should produce a real and a pseudo conflict for the same multiplicity change */ @Compare(left = "a10/left.uml", right = "a10/right.uml", ancestor = "a10/origin.uml") public void testRealAndPseudoConflict(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); ArrayList<Diff> leftChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT)))); ArrayList<Diff> rightChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT)))); assertEquals(2, size(leftChanges)); assertEquals(2, size(rightChanges)); MultiplicityElementChange leftChange1 = (MultiplicityElementChange)leftChanges.get(0); assertEquals(1, leftChange1.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange1) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, leftChange1.getKind()); MultiplicityElementChange leftChange2 = (MultiplicityElementChange)leftChanges.get(1); assertEquals(1, leftChange2.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftChange2) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, leftChange2.getKind()); MultiplicityElementChange rightChange1 = (MultiplicityElementChange)rightChanges.get(0); assertEquals(1, rightChange1.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange1) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, rightChange1.getKind()); MultiplicityElementChange rightChange2 = (MultiplicityElementChange)rightChanges.get(1); assertEquals(1, rightChange2.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange2) instanceof ReferenceChange); assertEquals(DifferenceKind.ADD, rightChange2.getKind()); assertEquals(2, comparison.getConflicts().size()); Conflict conflict1 = comparison.getConflicts().get(0); Conflict conflict2 = comparison.getConflicts().get(1); if (conflict1.getKind() == ConflictKind.PSEUDO) { assertEquals(ConflictKind.REAL, conflict2.getKind()); } else { assertEquals(ConflictKind.PSEUDO, conflict2.getKind()); } if (isUpperValueChange(leftChange1)) { assertTrue(isLowerValueChange(leftChange2)); assertNotNull(leftChange1.getConflict()); assertEquals(ConflictKind.REAL, leftChange1.getConflict().getKind()); assertNotNull(leftChange2.getConflict()); assertEquals(ConflictKind.PSEUDO, leftChange2.getConflict().getKind()); } else { assertTrue(isLowerValueChange(leftChange1)); assertTrue(isUpperValueChange(leftChange2)); assertNotNull(getRefiningsConflict(leftChange1)); assertEquals(ConflictKind.PSEUDO, getRefiningsConflict(leftChange1).getKind()); assertNotNull(getRefiningsConflict(leftChange2)); assertEquals(ConflictKind.REAL, getRefiningsConflict(leftChange2).getKind()); } if (isUpperValueChange(rightChange1)) { assertTrue(isLowerValueChange(rightChange2)); assertNotNull(getRefiningsConflict(rightChange1)); assertEquals(ConflictKind.REAL, getRefiningsConflict(rightChange1).getKind()); assertNotNull(getRefiningsConflict(rightChange2)); assertEquals(ConflictKind.PSEUDO, getRefiningsConflict(rightChange2).getKind()); } else { assertTrue(isLowerValueChange(rightChange1)); assertTrue(isUpperValueChange(rightChange2)); assertNotNull(getRefiningsConflict(rightChange1)); assertEquals(ConflictKind.PSEUDO, getRefiningsConflict(rightChange1).getKind()); assertNotNull(getRefiningsConflict(rightChange2)); assertEquals(ConflictKind.REAL, getRefiningsConflict(rightChange2).getKind()); } } private boolean isLowerValueChange(MultiplicityElementChange multiplicityElementChange) { if (multiplicityElementChange.getRefinedBy().size() != 1) { return false; } return IS_LOWER_VALUE_CHANGE.apply(getFirstRefiningDiff(multiplicityElementChange)); } private boolean isUpperValueChange(MultiplicityElementChange multiplicityElementChange) { if (multiplicityElementChange.getRefinedBy().size() != 1) { return false; } return IS_UPPER_VALUE_CHANGE.apply(getFirstRefiningDiff(multiplicityElementChange)); } /** * <b>origin:</b> an activity with an input pin, with a lower value <br> * <b>left:</b> multiplicity lower value is deleted and upper value is added (0)<br> * <b>right:</b> multiplicity upper value is added, with the same value as in the left change and the * lower value is changed to a different value than the one in the left change<br> * These changes should produce a real and a pseudo conflict for the same multiplicity change */ @Compare(left = "a11/left.uml", right = "a11/right.uml", ancestor = "a11/origin.uml") public void testRealAndPseudoConflictWithChangeAndDelete(Comparison comparison) throws IOException { EList<Diff> diffs = comparison.getDifferences(); ArrayList<Diff> leftChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(LEFT)))); ArrayList<Diff> rightChanges = Lists .newArrayList(filter(diffs, and(IS_MULTIPLICITY_CHANGE, fromSide(RIGHT)))); assertEquals(2, size(leftChanges)); assertEquals(2, size(rightChanges)); MultiplicityElementChange leftAddChange = (MultiplicityElementChange)find(leftChanges, ofKind(DifferenceKind.ADD)); MultiplicityElementChange leftDeleteChange = (MultiplicityElementChange)find(leftChanges, ofKind(DifferenceKind.DELETE)); assertEquals(1, leftAddChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftAddChange) instanceof ReferenceChange); assertEquals(1, leftDeleteChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(leftDeleteChange) instanceof ReferenceChange); MultiplicityElementChange rightAddChange = (MultiplicityElementChange)find(leftChanges, ofKind(DifferenceKind.ADD)); MultiplicityElementChange rightChange = (MultiplicityElementChange)find(rightChanges, ofKind(DifferenceKind.CHANGE)); assertEquals(1, rightAddChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightAddChange) instanceof ReferenceChange); assertEquals(1, rightChange.getRefinedBy().size()); assertTrue(getFirstRefiningDiff(rightChange) instanceof AttributeChange); assertEquals(2, comparison.getConflicts().size()); Conflict conflict1 = comparison.getConflicts().get(0); Conflict conflict2 = comparison.getConflicts().get(1); if (conflict1.getKind() == ConflictKind.PSEUDO) { assertEquals(ConflictKind.REAL, conflict2.getKind()); } else { assertEquals(ConflictKind.PSEUDO, conflict2.getKind()); } final Conflict leftChangeConflict = getRefiningsConflict(leftDeleteChange); final Conflict rightChangeConflict = getRefiningsConflict(rightChange); final Conflict leftAddConflict = getRefiningsConflict(leftAddChange); final Conflict rightAddConflict = getRefiningsConflict(rightAddChange); assertEquals(ConflictKind.REAL, leftChangeConflict.getKind()); assertEquals(leftChangeConflict, rightChangeConflict); assertEquals(ConflictKind.PSEUDO, leftAddConflict.getKind()); assertEquals(leftAddConflict, rightAddConflict); } /** * Returns the first refining diff. * <p> * In the context of MultiplicityElementChanges, this is the prime refining, i.e., the attribute or * reference change that essentially performs the multiplicity change. * </p> * * @param change * The multiplicity change. * @return The first refining diff. */ private Diff getFirstRefiningDiff(Diff change) { return change.getRefinedBy().get(0); } /** * Returns the conflict of the {@link #getFirstRefiningDiff(Diff) first refining diff}. * <p> * In the context of MultiplicityElementChanges, this is the conflict in which the * MultiplicityElementChanges is involved. * </p> * * @param change * The multiplicity change. * @return The conflict of the multiplicity change. */ private Conflict getRefiningsConflict(Diff change) { return getFirstRefiningDiff(change).getConflict(); } }