diff options
author | Christian W. Damus | 2015-09-09 15:46:19 +0000 |
---|---|---|
committer | Christian W. Damus | 2015-12-02 20:29:40 +0000 |
commit | 2e9272a03a37cb13b55a9a3f0225a1978b5bf57d (patch) | |
tree | 285e0978f6cd3b8cbbeb975fa532f24c4cce6b4a | |
parent | cbce1cb34ebe49432741c904fcfab952bca1baea (diff) | |
download | org.eclipse.papyrus-2e9272a03a37cb13b55a9a3f0225a1978b5bf57d.tar.gz org.eclipse.papyrus-2e9272a03a37cb13b55a9a3f0225a1978b5bf57d.tar.xz org.eclipse.papyrus-2e9272a03a37cb13b55a9a3f0225a1978b5bf57d.zip |
[AOF] Support composite states in UML state machine mapping example.
10 files changed, 317 insertions, 138 deletions
diff --git a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/META-INF/MANIFEST.MF b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/META-INF/MANIFEST.MF index 3b543e7067f..ae419a52617 100644 --- a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/META-INF/MANIFEST.MF +++ b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/META-INF/MANIFEST.MF @@ -7,7 +7,8 @@ Bundle-Activator: org.eclipse.papyrus.aof.sync.examples.uml.internal.Activator Bundle-Vendor: %Bundle-Vendor Require-Bundle: org.eclipse.core.runtime;bundle-version="3.11.0", org.eclipse.uml2.uml;bundle-version="5.1.0";visibility:=reexport, - org.eclipse.papyrus.aof.sync;bundle-version="0.7.0" + org.eclipse.papyrus.aof.sync;bundle-version="0.7.0", + org.eclipse.papyrus.infra.tools;bundle-version="1.2.0" Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.papyrus.aof.sync.examples.uml.internal;x-friends:="org.eclipse.papyrus.aof.sync.examples.uml.ui", diff --git a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/UMLRTMappingModule.java b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/UMLRTMappingModule.java index 9dbf2da2b67..32f4dd17a2c 100644 --- a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/UMLRTMappingModule.java +++ b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/UMLRTMappingModule.java @@ -13,6 +13,8 @@ package org.eclipse.papyrus.aof.sync.examples.uml.internal; +import java.util.Optional; + import javax.inject.Inject; import org.eclipse.emf.ecore.EObject; @@ -31,6 +33,7 @@ import org.eclipse.uml2.uml.Behavior; import org.eclipse.uml2.uml.BehavioredClassifier; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Region; +import org.eclipse.uml2.uml.State; import org.eclipse.uml2.uml.StateMachine; import org.eclipse.uml2.uml.Transition; import org.eclipse.uml2.uml.Vertex; @@ -80,6 +83,11 @@ public class UMLRTMappingModule extends MappingModule { } @Provides + public ICorrespondenceResolver<Region, State> provideCompositeStateRegionRedefResolver() { + return RedefinitionUtil::getRedefiningCompositeStateRegion; + } + + @Provides public ICorrespondenceResolver<Vertex, Region> provideVertexRedefResolver() { return RedefinitionUtil::getRedefiningVertex; } @@ -89,6 +97,11 @@ public class UMLRTMappingModule extends MappingModule { return RedefinitionUtil::getRedefiningTransition; } + @Provides + public ICorrespondenceResolver<Vertex, Transition> provideTransitionEndRedefResolver() { + return RedefinitionUtil::getRedefiningEnd; + } + public java.lang.Class<? extends ICorrespondenceResolver<EObject, EObject>> getRedefResolverBinding() { return CorrespondenceResolverSwitch.class; } @@ -113,12 +126,18 @@ public class UMLRTMappingModule extends MappingModule { private ICorrespondenceResolver<Region, StateMachine> region; @Inject + private ICorrespondenceResolver<Region, State> compositeStateRegion; + + @Inject private ICorrespondenceResolver<Vertex, Region> vertex; @Inject private ICorrespondenceResolver<Transition, Region> transition; @Inject + private ICorrespondenceResolver<Vertex, Transition> transitionEnd; + + @Inject private ICorrespondenceResolver<Transition, StateMachine> transitionInStateMachine; @Override @@ -140,18 +159,42 @@ public class UMLRTMappingModule extends MappingModule { @Override public EObject caseRegion(Region object) { - StateMachine context = (parentContext instanceof Region) - ? ((Region) parentContext).getStateMachine() - : (StateMachine) parentContext; - return region.getCorrespondent(object, context); + return new UMLSwitch<Optional<Region>>() { + @Override + public Optional<Region> caseStateMachine(StateMachine machine) { + return Optional.ofNullable(region.getCorrespondent(object, machine)); + } + + @Override + public Optional<Region> caseState(State state) { + return Optional.ofNullable(compositeStateRegion.getCorrespondent(object, state)); + } + + @Override + public Optional<Region> caseRegion(Region region) { + return doSwitch(region.eContainer()); + } + }.doSwitch(parentContext).orElse(null); } @Override public EObject caseVertex(Vertex object) { - Region context = (parentContext instanceof Vertex) - ? ((Vertex) parentContext).getContainer() - : (Region) parentContext; - return vertex.getCorrespondent(object, context); + return new UMLSwitch<Optional<Vertex>>() { + @Override + public Optional<Vertex> caseRegion(Region region) { + return Optional.ofNullable(vertex.getCorrespondent(object, region)); + } + + @Override + public Optional<Vertex> caseTransition(Transition transition) { + return Optional.ofNullable(transitionEnd.getCorrespondent(object, transition)); + } + + @Override + public Optional<Vertex> caseVertex(Vertex vertex) { + return doSwitch(vertex.getContainer()); + } + }.doSwitch(parentContext).orElse(null); } @Override diff --git a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/mappings/TransitionMapping.java b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/mappings/TransitionMapping.java index afc99d0a013..7ffc4c4ac8e 100644 --- a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/mappings/TransitionMapping.java +++ b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/mappings/TransitionMapping.java @@ -16,11 +16,9 @@ package org.eclipse.papyrus.aof.sync.examples.uml.internal.mappings; import javax.inject.Inject; import javax.inject.Singleton; -import org.eclipse.papyrus.aof.core.IBox; import org.eclipse.papyrus.aof.core.IFactory; import org.eclipse.papyrus.aof.core.IOne; import org.eclipse.papyrus.aof.sync.ICorrespondenceResolver; -import org.eclipse.uml2.uml.Region; import org.eclipse.uml2.uml.Transition; import org.eclipse.uml2.uml.UMLPackage; import org.eclipse.uml2.uml.Vertex; @@ -31,7 +29,7 @@ import org.eclipse.uml2.uml.Vertex; @Singleton public class TransitionMapping extends NamedElementMapping<Transition> { @Inject - private ICorrespondenceResolver<Vertex, Region> vertexRedef; + private ICorrespondenceResolver<Vertex, Transition> transitionEndRedef; @Inject public TransitionMapping(IFactory factory) { @@ -44,32 +42,7 @@ public class TransitionMapping extends NamedElementMapping<Transition> { bindPropertyValue(parentTransition, childTransition, UMLPackage.Literals.TRANSITION__REDEFINED_TRANSITION); - IBox<Vertex> parentSource = property(parentTransition, UMLPackage.Literals.TRANSITION__SOURCE); - IBox<Vertex> childSource = property(childTransition, UMLPackage.Literals.TRANSITION__SOURCE); - IBox<Vertex> sourceMapping = parentSource.collectTo(v -> getCorrespondingSource(v, childTransition.get())); - childSource.bind(sourceMapping).setAutoDisable(true); - - IBox<Vertex> parentTarget = property(parentTransition, UMLPackage.Literals.TRANSITION__TARGET); - IBox<Vertex> childtarget = property(childTransition, UMLPackage.Literals.TRANSITION__TARGET); - IBox<Vertex> targetMapping = parentTarget.collectTo(v -> getCorrespondingTarget(v, childTransition.get())); - childtarget.bind(targetMapping).setAutoDisable(true); - } - - protected Vertex getCorrespondingSource(Vertex parentVertex, Transition childTransition) { - if (parentVertex == null) { - // This happens when getting the IOne's default value - return null; - } - - return vertexRedef.getCorrespondent(parentVertex, childTransition.getContainer()); - } - - protected Vertex getCorrespondingTarget(Vertex parentVertex, Transition childTransition) { - if (parentVertex == null) { - // This happens when getting the IOne's default value - return null; - } - - return vertexRedef.getCorrespondent(parentVertex, childTransition.getContainer()); + mapCorresponding(parentTransition, childTransition, UMLPackage.Literals.TRANSITION__SOURCE, transitionEndRedef); + mapCorresponding(parentTransition, childTransition, UMLPackage.Literals.TRANSITION__TARGET, transitionEndRedef); } } diff --git a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/mappings/VertexMapping.java b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/mappings/VertexMapping.java index e5327eb9163..89c962c0cdf 100644 --- a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/mappings/VertexMapping.java +++ b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/mappings/VertexMapping.java @@ -18,6 +18,10 @@ import javax.inject.Singleton; import org.eclipse.papyrus.aof.core.IFactory; import org.eclipse.papyrus.aof.core.IOne; +import org.eclipse.papyrus.aof.sync.ICorrespondenceResolver; +import org.eclipse.papyrus.aof.sync.IMapping; +import org.eclipse.uml2.uml.Pseudostate; +import org.eclipse.uml2.uml.Region; import org.eclipse.uml2.uml.State; import org.eclipse.uml2.uml.UMLPackage; import org.eclipse.uml2.uml.Vertex; @@ -28,6 +32,12 @@ import org.eclipse.uml2.uml.Vertex; @Singleton public class VertexMapping extends NamedElementMapping<Vertex> { @Inject + private ICorrespondenceResolver<Region, State> regionRedef; + + @Inject + private IMapping<Region> regions; + + @Inject public VertexMapping(IFactory factory) { super(UMLPackage.Literals.VERTEX, factory); } @@ -37,5 +47,8 @@ public class VertexMapping extends NamedElementMapping<Vertex> { super.mapProperties(parentVertex, childVertex); bindPropertyValue(parentVertex.select(State.class), childVertex.select(State.class), UMLPackage.Literals.STATE, UMLPackage.Literals.STATE__REDEFINED_STATE); + bindProperty(parentVertex.select(Pseudostate.class), childVertex.select(Pseudostate.class), UMLPackage.Literals.PSEUDOSTATE__KIND); + + mapCorresponding(parentVertex.select(State.class).asOne(null), childVertex.select(State.class).asOne(null), UMLPackage.Literals.STATE__REGION, regionRedef, regions); } } diff --git a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/util/RedefinitionUtil.java b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/util/RedefinitionUtil.java index a55dcf78b41..08a784972e0 100644 --- a/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/util/RedefinitionUtil.java +++ b/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml/src/org/eclipse/papyrus/aof/sync/examples/uml/internal/util/RedefinitionUtil.java @@ -14,6 +14,8 @@ package org.eclipse.papyrus.aof.sync.examples.uml.internal.util; import static org.eclipse.papyrus.aof.sync.examples.uml.internal.util.NamedElements.shallowCopy; +import static org.eclipse.papyrus.infra.tools.util.StreamUtil.asStream; +import static org.eclipse.papyrus.infra.tools.util.StreamUtil.select; import java.util.Objects; import java.util.stream.Stream; @@ -67,6 +69,16 @@ public class RedefinitionUtil { } /** + * Finds the region in a given {@code context} that redefines the specified {@code region}, + * or creates a new one if it doesn't yet exist. + */ + public static Region getRedefiningCompositeStateRegion(Region region, State context) { + return getInverseReferencers(region, UMLPackage.Literals.REGION__EXTENDED_REGION, Region.class) + .filter(r -> r.getState() == context) + .findFirst().orElseGet(() -> shallowCopy(region)); + } + + /** * Finds the state in a given {@code context} that redefines the specified {@code state}, * or creates a new one if it doesn't yet exist. */ @@ -120,6 +132,26 @@ public class RedefinitionUtil { } /** + * Finds the end of a given {@code context} that redefines the specified {@code vertex}. + */ + public static <V extends Vertex> V getRedefiningEnd(V vertex, Transition context) { + V result = null; + + // Vertex is null when computing default result of an active operation + if (vertex != null) { + @SuppressWarnings("unchecked") + final Class<V> type = (Class<V>) vertex.getClass(); + + result = select(asStream(context.containingStateMachine().eAllContents()), type) + .filter(v -> redefines(v, vertex)) + .findFirst() + .orElse(null); + } + + return result; + } + + /** * Queries whether two elements are in a redefinition relationship. * * @return whether {@code element} redefines {@code other}, or vice versa diff --git a/extraplugins/aof/sync/org.eclipse.papyrus.aof.sync/src/org/eclipse/papyrus/aof/sync/AbstractMapping.java b/extraplugins/aof/sync/org.eclipse.papyrus.aof.sync/src/org/eclipse/papyrus/aof/sync/AbstractMapping.java index 7e7db1c72bb..d3bd117b279 100644 --- a/extraplugins/aof/sync/org.eclipse.papyrus.aof.sync/src/org/eclipse/papyrus/aof/sync/AbstractMapping.java +++ b/extraplugins/aof/sync/org.eclipse.papyrus.aof.sync/src/org/eclipse/papyrus/aof/sync/AbstractMapping.java @@ -257,8 +257,8 @@ public abstract class AbstractMapping<T> implements IMapping<T> { * * @return a pairing of the the boxed objects that are mapped */ - protected <E> IPair<IBox<E>, IBox<E>> mapCorresponding(IOne<T> fromContext, IOne<T> toContext, Object property, - ICorrespondenceResolver<E, ? super T> resolvedWith) { + protected <E, U extends T> IPair<IBox<E>, IBox<E>> mapCorresponding(IOne<U> fromContext, IOne<U> toContext, Object property, + ICorrespondenceResolver<E, ? super U> resolvedWith) { return mapCorresponding(fromContext, toContext, property, resolvedWith, null); } @@ -282,8 +282,8 @@ public abstract class AbstractMapping<T> implements IMapping<T> { * * @return a pairing of the the boxed objects that are mapped */ - protected <E> IPair<IBox<E>, IBox<E>> mapCorresponding(IOne<T> fromContext, IOne<T> toContext, Object property, - ICorrespondenceResolver<E, ? super T> resolvedWith, IMapping<? super E> mappedWith) { + protected <E, U extends T> IPair<IBox<E>, IBox<E>> mapCorresponding(IOne<U> fromContext, IOne<U> toContext, Object property, + ICorrespondenceResolver<E, ? super U> resolvedWith, IMapping<? super E> mappedWith) { IBox<E> fromElements = property(fromContext, property); IBox<E> toElements = property(toContext, property); @@ -310,8 +310,8 @@ public abstract class AbstractMapping<T> implements IMapping<T> { * * @return a pairing of the the boxed objects that are mapped */ - protected <E> IPair<IBox<E>, IBox<E>> mapCorresponding(IBox<E> fromElements, IBox<E> toElements, - IOne<T> toContext, ICorrespondenceResolver<E, ? super T> resolvedWith, IMapping<? super E> mappedWith) { + protected <E, U extends T> IPair<IBox<E>, IBox<E>> mapCorresponding(IBox<E> fromElements, IBox<E> toElements, + IOne<U> toContext, ICorrespondenceResolver<E, ? super U> resolvedWith, IMapping<? super E> mappedWith) { IBox<E> mapping = fromElements.collectTo( (E e) -> getCorresponding(e, toContext.get(), resolvedWith)); diff --git a/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/AbstractUMLMappingTest.java b/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/AbstractUMLMappingTest.java new file mode 100644 index 00000000000..e1d5427a6cb --- /dev/null +++ b/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/AbstractUMLMappingTest.java @@ -0,0 +1,117 @@ +/***************************************************************************** + * Copyright (c) 2015 Christian W. Damus and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Christian W. Damus - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.aof.sync.examples.uml.tests; + + + +import java.util.function.Consumer; + +import org.eclipse.emf.common.command.Command; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.edit.command.AddCommand; +import org.eclipse.emf.edit.command.SetCommand; +import org.eclipse.papyrus.aof.sync.tests.AbstractBaseMappingTest; +import org.eclipse.papyrus.aof.sync.tests.runners.InjectWith; +import org.eclipse.papyrus.junit.utils.rules.ResourceSetFixture; +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.UMLFactory; +import org.junit.Rule; + +import com.google.inject.Inject; + +/** + * Common structure of UML example mapping tests. + */ +@InjectWith(TestModelModule.class) +public abstract class AbstractUMLMappingTest<T extends EObject> extends AbstractBaseMappingTest<T> { + + @Rule + public final ResourceSetFixture rset = new ResourceSetFixture(); + + @Inject + protected UMLFactory uml; + + public AbstractUMLMappingTest() { + super(); + } + + // + // test framework + // + + protected CommandBuilder exec() { + return new CommandBuilder(); + } + + protected void add(Object owner, Object feature, Object element) { + exec().add(owner, feature, element).execute(); + } + + protected void set(Object owner, Object feature, Object value) { + exec().set(owner, feature, value).execute(); + } + + public <N extends NamedElement> N create(Object owner, EReference feature, java.lang.Class<N> type, String name) { + return create(owner, feature, type, name, null); + } + + public <N extends NamedElement> N create(Object owner, EReference feature, java.lang.Class<N> type, String name, Consumer<? super N> initializer) { + N result = type.cast(uml.create((EClass) uml.getEPackage().getEClassifier(type.getSimpleName()))); + result.setName(name); + + if (initializer != null) { + initializer.accept(result); + } + + add(owner, feature, result); + return result; + } + + // + // Nested types + // + + protected class CommandBuilder { + private Command command = null; + + private CommandBuilder() { + super(); + } + + private CommandBuilder append(Command command) { + if (this.command == null) { + this.command = command; + } else { + this.command = this.command.chain(command); + } + return this; + } + + public CommandBuilder add(Object owner, Object feature, Object element) { + return append(AddCommand.create(rset.getEditingDomain(), owner, feature, element)); + } + + public CommandBuilder set(Object owner, Object feature, Object value) { + return append(SetCommand.create(rset.getEditingDomain(), owner, feature, value)); + } + + public void execute() { + rset.getEditingDomain().getCommandStack().execute(command); + command = null; + } + } + +}
\ No newline at end of file diff --git a/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/CapsuleMappingTest.java b/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/CapsuleMappingTest.java index c69f2fea1ee..32a9bf19ab0 100644 --- a/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/CapsuleMappingTest.java +++ b/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/CapsuleMappingTest.java @@ -21,40 +21,25 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; -import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.papyrus.aof.sync.examples.uml.internal.mappings.CapsuleMapping; -import org.eclipse.papyrus.aof.sync.tests.AbstractBaseMappingTest; -import org.eclipse.papyrus.aof.sync.tests.runners.InjectWith; import org.eclipse.papyrus.junit.utils.rules.JavaResource; -import org.eclipse.papyrus.junit.utils.rules.ResourceSetFixture; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.StateMachine; -import org.eclipse.uml2.uml.UMLFactory; import org.eclipse.uml2.uml.UMLPackage; -import org.junit.Rule; import org.junit.Test; -import com.google.inject.Inject; - /** * Tests the {@link CapsuleMapping} class. */ -@InjectWith(TestModelModule.class) @JavaResource("capsules.uml") -public class CapsuleMappingTest extends AbstractBaseMappingTest<Class> { - @Rule - public final ResourceSetFixture rset = new ResourceSetFixture(); - - @Inject - private UMLFactory uml; - +public class CapsuleMappingTest extends AbstractUMLMappingTest<Class> { @Test public void addStateMachineToParent() { assertThat(getTo().getClassifierBehavior(), nullValue()); StateMachine parent = uml.createStateMachine(); parent.setName("Lifecycle"); - rset.execute(SetCommand.create(rset.getEditingDomain(), getFrom(), UMLPackage.Literals.BEHAVIORED_CLASSIFIER__CLASSIFIER_BEHAVIOR, parent)); + set(getFrom(), UMLPackage.Literals.BEHAVIORED_CLASSIFIER__CLASSIFIER_BEHAVIOR, parent); StateMachine child = as(getTo().getClassifierBehavior(), StateMachine.class); assertThat(child, notNullValue()); diff --git a/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/StateMachineMappingTest.java b/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/StateMachineMappingTest.java index 10cbd82e2cd..5b3d511d94c 100644 --- a/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/StateMachineMappingTest.java +++ b/tests/junit/extraplugins/aof/examples/org.eclipse.papyrus.aof.sync.examples.uml.tests/src/org/eclipse/papyrus/aof/sync/examples/uml/tests/StateMachineMappingTest.java @@ -22,13 +22,8 @@ import static org.hamcrest.CoreMatchers.sameInstance; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assume.assumeThat; -import org.eclipse.emf.edit.command.AddCommand; -import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.papyrus.aof.sync.examples.uml.internal.mappings.CapsuleMapping; -import org.eclipse.papyrus.aof.sync.tests.AbstractBaseMappingTest; -import org.eclipse.papyrus.aof.sync.tests.runners.InjectWith; import org.eclipse.papyrus.junit.utils.rules.JavaResource; -import org.eclipse.papyrus.junit.utils.rules.ResourceSetFixture; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.FinalState; import org.eclipse.uml2.uml.Pseudostate; @@ -37,53 +32,37 @@ import org.eclipse.uml2.uml.Region; import org.eclipse.uml2.uml.State; import org.eclipse.uml2.uml.StateMachine; import org.eclipse.uml2.uml.Transition; -import org.eclipse.uml2.uml.UMLFactory; import org.eclipse.uml2.uml.UMLPackage; import org.eclipse.uml2.uml.Vertex; -import org.junit.Rule; +import org.junit.Before; import org.junit.Test; -import com.google.inject.Inject; - /** * Tests the {@link CapsuleMapping} class. */ -@InjectWith(TestModelModule.class) @JavaResource("capsules-with-machines.uml") -public class StateMachineMappingTest extends AbstractBaseMappingTest<Class> { - @Rule - public final ResourceSetFixture rset = new ResourceSetFixture(); - - @Inject - private UMLFactory uml; +public class StateMachineMappingTest extends AbstractUMLMappingTest<Class> { + private StateMachine parent; + private StateMachine child; + private Region parentRegion; + private Region childRegion; @Test public void synchInitialRegionFromParent() { - StateMachine parent = as(getFrom().getClassifierBehavior(), StateMachine.class); - assumeThat(parent, notNullValue()); - - StateMachine child = as(getTo().getClassifierBehavior(), StateMachine.class); - assumeThat(child, notNullValue()); - assumeThat(child, not(sameInstance(parent))); - - assertThat(child.getRegions().size(), is(1)); - Region region = child.getRegions().get(0); - - final Region parentRegion = parent.getRegions().get(0); - assertThat(region.getName(), is(parentRegion.getName())); - assertThat(region.getExtendedRegion(), is(parentRegion)); - assertThat(region.getSubvertices().size(), is(2)); - assertThat(region.getTransitions().size(), is(1)); + assertThat(childRegion.getName(), is(parentRegion.getName())); + assertThat(childRegion.getExtendedRegion(), is(parentRegion)); + assertThat(childRegion.getSubvertices().size(), is(2)); + assertThat(childRegion.getTransitions().size(), is(1)); - Pseudostate start = as(region.getSubvertex("start"), Pseudostate.class); + Pseudostate start = as(childRegion.getSubvertex("start"), Pseudostate.class); assertThat(start, notNullValue()); assertThat(start.getKind(), is(PseudostateKind.INITIAL_LITERAL)); - State open = as(region.getSubvertex("open"), State.class); + State open = as(childRegion.getSubvertex("open"), State.class); assertThat(open, notNullValue()); assertThat(open.getRedefinedState(), is(parentRegion.getSubvertex("open"))); - Transition attach = region.getTransition("attach"); + Transition attach = childRegion.getTransition("attach"); assertThat(attach, notNullValue()); assertThat(attach.getSource(), is(start)); @@ -92,25 +71,13 @@ public class StateMachineMappingTest extends AbstractBaseMappingTest<Class> { @Test public void addVertexAndTransitionToParent() { - StateMachine parent = as(getFrom().getClassifierBehavior(), StateMachine.class); - assumeThat(parent, notNullValue()); - final Region parentRegion = parent.getRegions().get(0); final State parentOpen = as(parentRegion.getSubvertex("open"), State.class); - assumeThat(parentOpen, notNullValue()); - - StateMachine child = as(getTo().getClassifierBehavior(), StateMachine.class); - assumeThat(child, notNullValue()); - - assumeThat(child.getRegions().size(), is(1)); - Region region = child.getRegions().get(0); - final State open = as(region.getSubvertex("open"), State.class); + final State open = as(childRegion.getSubvertex("open"), State.class); assumeThat(open, notNullValue()); - FinalState parentEnd = uml.createFinalState(); - parentEnd.setName("end"); - rset.execute(AddCommand.create(rset.getEditingDomain(), parentRegion, UMLPackage.Literals.REGION__SUBVERTEX, parentEnd)); + FinalState parentEnd = create(parentRegion, UMLPackage.Literals.REGION__SUBVERTEX, FinalState.class, "end"); - Vertex end = region.getSubvertex("end"); + Vertex end = childRegion.getSubvertex("end"); assertThat(end, instanceOf(FinalState.class)); assertThat(((FinalState) end).getRedefinedState(), is(parentEnd)); @@ -118,12 +85,12 @@ public class StateMachineMappingTest extends AbstractBaseMappingTest<Class> { // and then adding it to its region Transition parentTransition = uml.createTransition(); parentTransition.setName("finish"); - rset.execute( - SetCommand.create(rset.getEditingDomain(), parentTransition, UMLPackage.Literals.TRANSITION__SOURCE, parentOpen).chain( - SetCommand.create(rset.getEditingDomain(), parentTransition, UMLPackage.Literals.TRANSITION__TARGET, parentEnd).chain( - AddCommand.create(rset.getEditingDomain(), parentRegion, UMLPackage.Literals.REGION__TRANSITION, parentTransition)))); + exec().set(parentTransition, UMLPackage.Literals.TRANSITION__SOURCE, parentOpen) + .set(parentTransition, UMLPackage.Literals.TRANSITION__TARGET, parentEnd) + .add(parentRegion, UMLPackage.Literals.REGION__TRANSITION, parentTransition) + .execute(); - Transition transition = region.getTransition("finish"); + Transition transition = childRegion.getTransition("finish"); assertThat(transition, notNullValue()); assertThat(transition.getRedefinedTransition(), is(parentTransition)); assertThat(transition.getSource(), is(open)); @@ -132,25 +99,13 @@ public class StateMachineMappingTest extends AbstractBaseMappingTest<Class> { @Test public void addVertexAndTransitionToParent2() { - StateMachine parent = as(getFrom().getClassifierBehavior(), StateMachine.class); - assumeThat(parent, notNullValue()); - final Region parentRegion = parent.getRegions().get(0); final State parentOpen = as(parentRegion.getSubvertex("open"), State.class); - assumeThat(parentOpen, notNullValue()); - - StateMachine child = as(getTo().getClassifierBehavior(), StateMachine.class); - assumeThat(child, notNullValue()); - - assumeThat(child.getRegions().size(), is(1)); - Region region = child.getRegions().get(0); - final State open = as(region.getSubvertex("open"), State.class); + final State open = as(childRegion.getSubvertex("open"), State.class); assumeThat(open, notNullValue()); - FinalState parentEnd = uml.createFinalState(); - parentEnd.setName("end"); - rset.execute(AddCommand.create(rset.getEditingDomain(), parentRegion, UMLPackage.Literals.REGION__SUBVERTEX, parentEnd)); + FinalState parentEnd = create(parentRegion, UMLPackage.Literals.REGION__SUBVERTEX, FinalState.class, "end"); - Vertex end = region.getSubvertex("end"); + Vertex end = childRegion.getSubvertex("end"); assumeThat(end, instanceOf(FinalState.class)); assumeThat(((FinalState) end).getRedefinedState(), is(parentEnd)); @@ -158,15 +113,75 @@ public class StateMachineMappingTest extends AbstractBaseMappingTest<Class> { // setting its source and target vertices Transition parentTransition = uml.createTransition(); parentTransition.setName("finish"); - rset.execute( - AddCommand.create(rset.getEditingDomain(), parentRegion, UMLPackage.Literals.REGION__TRANSITION, parentTransition).chain( - SetCommand.create(rset.getEditingDomain(), parentTransition, UMLPackage.Literals.TRANSITION__SOURCE, parentOpen).chain( - SetCommand.create(rset.getEditingDomain(), parentTransition, UMLPackage.Literals.TRANSITION__TARGET, parentEnd)))); + exec().add(parentRegion, UMLPackage.Literals.REGION__TRANSITION, parentTransition) + .set(parentTransition, UMLPackage.Literals.TRANSITION__SOURCE, parentOpen) + .set(parentTransition, UMLPackage.Literals.TRANSITION__TARGET, parentEnd) + .execute(); - Transition transition = region.getTransition("finish"); + Transition transition = childRegion.getTransition("finish"); assertThat(transition, notNullValue()); assertThat(transition.getRedefinedTransition(), is(parentTransition)); assertThat(transition.getSource(), is(open)); assertThat(transition.getTarget(), is(end)); } + + @Test + public void compositeState() { + final State parentOpen = as(parentRegion.getSubvertex("open"), State.class); + final State open = as(childRegion.getSubvertex("open"), State.class); + assumeThat(open, notNullValue()); + + // Make the parent 'open' state composite + Region parentComposite = create(parentOpen, UMLPackage.Literals.STATE__REGION, Region.class, "composite"); + Region childComposite = open.getRegion("composite"); + assertThat(childComposite, notNullValue()); + assertThat(childComposite.getExtendedRegion(), is(parentComposite)); + + // Create a nested state + State parentNested = create(parentComposite, UMLPackage.Literals.REGION__SUBVERTEX, State.class, "nested"); + Vertex childNested = childComposite.getSubvertex("nested"); + assertThat(childNested, notNullValue()); + assertThat(childNested, instanceOf(State.class)); + assertThat(((State) childNested).getRedefinedState(), is(parentNested)); + + Pseudostate parentFork = create(parentRegion, UMLPackage.Literals.REGION__SUBVERTEX, Pseudostate.class, "fork", + fork -> fork.setKind(PseudostateKind.FORK_LITERAL)); + Vertex childFork = childRegion.getSubvertex("fork"); + assertThat(childFork, notNullValue()); + assertThat(childFork, instanceOf(Pseudostate.class)); + assertThat(((Pseudostate) childFork).getKind(), is(PseudostateKind.FORK_LITERAL)); + + // And a transition from the nested state out of the composite + Transition parentTransition = uml.createTransition(); + parentTransition.setName("finish"); + exec().add(parentComposite, UMLPackage.Literals.REGION__TRANSITION, parentTransition) + .set(parentTransition, UMLPackage.Literals.TRANSITION__SOURCE, parentNested) + .set(parentTransition, UMLPackage.Literals.TRANSITION__TARGET, parentFork) + .execute(); + + Transition transition = childComposite.getTransition("finish"); + assertThat(transition, notNullValue()); + assertThat(transition.getRedefinedTransition(), is(parentTransition)); + assertThat(transition.getSource(), is(childNested)); + assertThat(transition.getTarget(), is(childFork)); + } + + // + // Test framework + // + + @Before + public void getSignposts() { + parent = as(getFrom().getClassifierBehavior(), StateMachine.class); + assumeThat(parent, notNullValue()); + assumeThat(parent.getRegions().size(), is(1)); + parentRegion = parent.getRegions().get(0); + + child = as(getTo().getClassifierBehavior(), StateMachine.class); + assumeThat(child, notNullValue()); + assumeThat(child, not(sameInstance(parent))); + + assumeThat(child.getRegions().size(), is(1)); + childRegion = child.getRegions().get(0); + } } diff --git a/tests/junit/extraplugins/aof/sync/org.eclipse.papyrus.aof.sync.tests/src/org/eclipse/papyrus/aof/sync/tests/AbstractMappingTest.java b/tests/junit/extraplugins/aof/sync/org.eclipse.papyrus.aof.sync.tests/src/org/eclipse/papyrus/aof/sync/tests/AbstractMappingTest.java index ba3743c8e1d..a82c8a23d37 100644 --- a/tests/junit/extraplugins/aof/sync/org.eclipse.papyrus.aof.sync.tests/src/org/eclipse/papyrus/aof/sync/tests/AbstractMappingTest.java +++ b/tests/junit/extraplugins/aof/sync/org.eclipse.papyrus.aof.sync.tests/src/org/eclipse/papyrus/aof/sync/tests/AbstractMappingTest.java @@ -411,12 +411,12 @@ public class AbstractMappingTest extends AbstractTest { } @Override - protected <E> IPair<IBox<E>, IBox<E>> mapCorresponding(IOne<EObject> parentContext, IOne<EObject> childContext, Object property, ICorrespondenceResolver<E, ? super EObject> resolvedWith) { + protected <E, U extends EObject> IPair<IBox<E>, IBox<E>> mapCorresponding(IOne<U> parentContext, IOne<U> childContext, Object property, ICorrespondenceResolver<E, ? super U> resolvedWith) { return super.mapCorresponding(parentContext, childContext, property, resolvedWith); } @Override - protected <E> IPair<IBox<E>, IBox<E>> mapCorresponding(IOne<EObject> parentContext, IOne<EObject> childContext, Object property, ICorrespondenceResolver<E, ? super EObject> resolvedWith, IMapping<? super E> mappedWith) { + protected <E, U extends EObject> IPair<IBox<E>, IBox<E>> mapCorresponding(IOne<U> parentContext, IOne<U> childContext, Object property, ICorrespondenceResolver<E, ? super U> resolvedWith, IMapping<? super E> mappedWith) { return super.mapCorresponding(parentContext, childContext, property, resolvedWith, mappedWith); } |