diff options
author | Jan-Philipp Steghöfer | 2021-02-02 15:20:48 +0000 |
---|---|---|
committer | Jan-Philipp Steghöfer | 2021-02-16 13:29:57 +0000 |
commit | 997b5d84fdc66fb41f9c4cc971ea33f3894f5ef3 (patch) | |
tree | fed920561500f3e9526230ceb74c395d6c198380 | |
parent | e0c003fdfa1080f1193c44928aabaa600633707f (diff) | |
download | org.eclipse.capra-997b5d84fdc66fb41f9c4cc971ea33f3894f5ef3.tar.gz org.eclipse.capra-997b5d84fdc66fb41f9c4cc971ea33f3894f5ef3.tar.xz org.eclipse.capra-997b5d84fdc66fb41f9c4cc971ea33f3894f5ef3.zip |
Trace models now differentiate origin and target
Eclipse Capra so far did not provide the ability
to create unidirectional links, i.e., links that
have a defined origin and target. Instead, all
links were implicitly bidirectional. This was
enforced by only allowing to access the "items"
of a link type, i.e., all artifacts that were
connected by a trace links were accessed via one
collection.
This behaviour was problematic since it
a) did not allow to implement directed link,
i.e., links with a clearly defined origin and
target; and
b) did not allow typisation of links that connect
artifacts of different types.
The latter meant that a common super-class
(usually EObject) needed to be used and type
correctness of the trace model could not be
enforced.
With this commit, the TraceMetaModelAdapter
interface introduces a distinction of origin and
target for trace links. This means that trace
links can now connect an arbitrary number of
origin artifacts of the same type with an
arbitrary number of target artifacts of the same
type. If a TIM wants to restrict multiplicities,
it needs to do so via its TraceMetaModelAdapter
implementation.
It is worth noting that this commit changes
Capra's behaviour with the default TIM as well:
while it used to be bidirectional, it now
distinguishes origin and target as well. This is
reflected in changes in the tests. In particular
the traceability matrices now look different and
isThereATraceBetween() is also sensitive to the
order in which artifacts are provided (origin
first, target second).
This change will be followed up by others that
clean up the API, provide clearer Javadoc, in
particular for methods of TraceMetaModelAdapter,
and update the UI to be able to differentiate
sources and targets when creating links.
Change-Id: I5f2c14ec68a141bda57789c8b0fc6ef22cc9ffb8
31 files changed, 519 insertions, 357 deletions
diff --git a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/AbstractMetaModelAdapter.java b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/AbstractMetaModelAdapter.java index f4d00b08..647a13b1 100644 --- a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/AbstractMetaModelAdapter.java +++ b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/AbstractMetaModelAdapter.java @@ -89,11 +89,7 @@ public abstract class AbstractMetaModelAdapter implements TraceMetaModelAdapter List<Integer> hashCodes = new ArrayList<>(); for (Connection conn : existingTraces) { - int connectionHash = conn.getOrigin().hashCode() + conn.getTlink().hashCode(); - for (EObject targ : conn.getTargets()) { - connectionHash += targ.hashCode(); - } - hashCodes.add(connectionHash); + hashCodes.add(conn.hashCode()); } ResourceSet resourceSet = EditingDomainHelper.getResourceSet(); @@ -101,18 +97,16 @@ public abstract class AbstractMetaModelAdapter implements TraceMetaModelAdapter EObject artifactModel = persistenceAdapter.getArtifactWrappers(resourceSet); ArtifactHelper artifactHelper = new ArtifactHelper(artifactModel); for (Connection conn : directElements) { - int connectionHash = conn.getOrigin().hashCode() + conn.getTlink().hashCode(); - for (EObject targ : conn.getTargets()) { - connectionHash += targ.hashCode(); - } - if (!hashCodes.contains(connectionHash)) { + if (!hashCodes.contains(conn.hashCode())) { allElements.add(conn); } // get internal links from source - Object origin = artifactHelper.unwrapWrapper(conn.getOrigin()); - IArtifactHandler<?> originHandler = artifactHelper.getHandler(origin).orElseThrow(); - if (originHandler != null) { - allElements.addAll(originHandler.addInternalLinks(conn.getOrigin(), selectedRelationshipTypes)); + for (EObject o : conn.getOrigins()) { + Object origin = artifactHelper.unwrapWrapper(o); + IArtifactHandler<?> originHandler = artifactHelper.getHandler(origin).get(); + if (originHandler != null) { + allElements.addAll(originHandler.addInternalLinks(o, selectedRelationshipTypes)); + } } // get internal links from targets for (EObject o : conn.getTargets()) { diff --git a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/Connection.java b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/Connection.java index 304821d6..7c3dd5b7 100644 --- a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/Connection.java +++ b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/Connection.java @@ -28,18 +28,18 @@ import org.eclipse.emf.ecore.EObject; * @author Anthony Anjorin, Salome Maro */ public class Connection { - private EObject origin; + private List<EObject> origins; private List<EObject> targets; private EObject tlink; - public Connection(EObject origin, List<EObject> targets, EObject tlink) { - this.origin = origin; + public Connection(List<EObject> origins, List<EObject> targets, EObject tlink) { + this.origins = origins; this.targets = targets; this.tlink = tlink; } - public EObject getOrigin() { - return origin; + public List<EObject> getOrigins() { + return origins; } public List<EObject> getTargets() { @@ -64,10 +64,10 @@ public class Connection { Connection connection = (Connection) object; List<EObject> allFirstElements = new ArrayList<>(this.getTargets()); - allFirstElements.add(this.getOrigin()); + allFirstElements.addAll(this.getOrigins()); List<EObject> allSecondElements = new ArrayList<>(connection.getTargets()); - allSecondElements.add(connection.getOrigin()); + allSecondElements.addAll(connection.getOrigins()); String firstTraceType = EMFHelper.getIdentifier(this.getTlink().eClass()); String secondTracetype = EMFHelper.getIdentifier(connection.getTlink().eClass()); @@ -86,7 +86,8 @@ public class Connection { public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((origin == null) ? 0 : EMFHelper.getIdentifier(origin).hashCode()); + result = prime * result + + ((origins == null) ? 0 : origins.stream().mapToInt(e -> EMFHelper.getIdentifier(e).hashCode()).sum()); result = prime * result + ((targets == null) ? 0 : targets.stream().mapToInt(e -> EMFHelper.getIdentifier(e).hashCode()).sum()); result = prime * result + ((tlink == null) ? 0 : tlink.hashCode()); diff --git a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/TraceMetaModelAdapter.java b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/TraceMetaModelAdapter.java index 0e2c08a2..b91a0c56 100644 --- a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/TraceMetaModelAdapter.java +++ b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/adapters/TraceMetaModelAdapter.java @@ -28,7 +28,7 @@ import org.eclipse.emf.ecore.EObject; * */ public interface TraceMetaModelAdapter { - + /** * Create a new model for the trace links. * @@ -38,114 +38,100 @@ public interface TraceMetaModelAdapter { EObject createModel(); /** - * Used to retrieve a set of types of traces that can be created for the - * given selection of objects in the Eclipse workspace + * Used to retrieve a set of types of traces that can be created for the given + * selection of objects in the Eclipse workspace * - * @param selection - * The selection of objects the user has made and wants to create - * a trace for in the Eclipse workspace - * @return A collection of possible types of traces that can be created for - * the given selection + * @param selection The selection of objects the user has made and wants to + * create a trace for in the Eclipse workspace + * @return A collection of possible types of traces that can be created for the + * given selection */ Collection<EClass> getAvailableTraceTypes(List<EObject> selection); /** * Used to create a trace of the given type * - * @param traceType - * The type of the trace to be created - * @param traceModel - * The root of the trace model that should contain the trace - * type. If this is empty, then a new root is to be created and - * returned. - * @param selection - * Objects to create the trace for + * @param traceType The type of the trace to be created + * @param traceModel The root of the trace model that should contain the trace + * type. If this is empty, then a new root is to be created + * and returned. + * @param selection Objects to create the trace for * @return the trace link that has just been created */ - EObject createTrace(EClass traceType, EObject traceModel, List<EObject> selection); - - /** Decide if two objects are connected according to the given trace model - * - * @param first - * First object - * @param second - * Second object - * @param traceModel - * Trace model to base decision on - * @return <code>true</code> if object are connected, <code>false</code> - * otherwise - */ + EObject createTrace(EClass traceType, EObject traceModel, List<EObject> origins, List<EObject> targets); + + /** + * Decide if two objects are connected according to the given trace model + * + * @param first First object + * @param second Second object + * @param traceModel Trace model to base decision on + * @return <code>true</code> if object are connected, <code>false</code> + * otherwise + */ boolean isThereATraceBetween(EObject first, EObject second, EObject traceModel); /** - * Determine a list of all objects connected to element according to the - * given trace model + * Determine a list of all objects connected to element according to the given + * trace model * - * @param element - * The element used to determine the list of connected objects. - * Note that this element could be a trace in the trace model - * @param traceModel - * Trace model to base calculation on - * @return A Map with the following structure: [Trace object t -> {list of - * all objects connected to element via t}] + * @param element The element used to determine the list of connected + * objects. Note that this element could be a trace in the + * trace model + * @param traceModel Trace model to base calculation on + * @return A Map with the following structure: [Trace object t -> {list of all + * objects connected to element via t}] */ List<Connection> getConnectedElements(EObject element, EObject traceModel); - + /** - * Determine a list of all objects connected to element according to the - * given trace model + * Determine a list of all objects connected to element according to the given + * trace model * - * @param element - * The element used to determine the list of connected objects. - * Note that this element could be a trace in the trace model - * @param traceModel - * Trace model to base calculation on - * @param selectedRelationshipTypes - * List of selected relationship types from the context menu of - * plantuml - * @return A Map with the following structure: [Trace object t -> {list of - * all objects connected to element via t}] + * @param element The element used to determine the list of + * connected objects. Note that this element + * could be a trace in the trace model + * @param traceModel Trace model to base calculation on + * @param selectedRelationshipTypes List of selected relationship types from the + * context menu of plantuml + * @return A Map with the following structure: [Trace object t -> {list of all + * objects connected to element via t}] */ List<Connection> getConnectedElements(EObject element, EObject traceModel, List<String> selectedRelationshipTypes); /** - * Determine a list of all objects connected to element according to the - * given trace model + * Determine a list of all objects connected to element according to the given + * trace model * - * @param element - * The element used to determine the list of connected objects. - * Note that this element could be a trace in the trace model - * @param traceModel - * Trace model to base calculation on - * @param transitivityDepth - * The maximum depth the user wants to go down transitively. 0 - * indicates no limit. - * @return A Map with the following structure: [Trace object t -> {list of - * all objects connected to element via t}] + * @param element The element used to determine the list of connected + * objects. Note that this element could be a trace in + * the trace model + * @param traceModel Trace model to base calculation on + * @param transitivityDepth The maximum depth the user wants to go down + * transitively. 0 indicates no limit. + * @return A Map with the following structure: [Trace object t -> {list of all + * objects connected to element via t}] */ List<Connection> getTransitivelyConnectedElements(EObject element, EObject traceModel, int transitivityDepth); /** - * Determine a list of all objects connected to element according to the - * given trace model + * Determine a list of all objects connected to element according to the given + * trace model * - * @param element - * The element used to determine the list of connected objects. - * Note that this element could be a trace in the trace model - * @param traceModel - * Trace model to base calculation on - * @param selectedRelationshipTypes - * List of selected relationship types from the context menu of - * plantuml - * @param transitivityDepth - * The maximum depth the user wants to go down transitively. 0 - * indicates no limit. - * @return A Map with the following structure: [Trace object t -> {list of - * all objects connected to element via t}] + * @param element The element used to determine the list of + * connected objects. Note that this element + * could be a trace in the trace model + * @param traceModel Trace model to base calculation on + * @param selectedRelationshipTypes List of selected relationship types from the + * context menu of plantuml + * @param transitivityDepth The maximum depth the user wants to go down + * transitively. 0 indicates no limit. + * @return A Map with the following structure: [Trace object t -> {list of all + * objects connected to element via t}] */ List<Connection> getTransitivelyConnectedElements(EObject element, EObject traceModel, List<String> selectedRelationshipTypes, int transitivityDepth); - + /** * Given a trace model, this method returns a list of all trace links in the * model @@ -161,33 +147,26 @@ public interface TraceMetaModelAdapter { * example when you want to delete links based on a quick fix from the * notification feature * - * @param toDelete - * a list of links to be deleted - * @param traceModel - * the trace model to delete the links from + * @param toDelete a list of links to be deleted + * @param traceModel the trace model to delete the links from */ void deleteTrace(List<Connection> toDelete, EObject traceModel); - + /** - * Determine a list of all objects internally connected to element (e.g. - * UML) + * Determine a list of all objects internally connected to element (e.g. UML) * - * @param element - * The element used to determine the list of connected objects. - * Note that this element could be a trace in the trace model - * @param traceModel - * Trace model to base calculation on - * @param selectedRelationshipTypes - * List of selected relationship types from the context menu of - * plantuml - * @param traceLinksTransitive - * Used to determine if tracelink elements should be received - * transitively - * @param transitivityDepth - * Used to in case tracelinks are received transivitely in order - * to set the depth - * @return A Map with the following structure: [Trace object t -> {list of - * all objects connected to element via t}] + * @param element The element used to determine the list of + * connected objects. Note that this element + * could be a trace in the trace model + * @param traceModel Trace model to base calculation on + * @param selectedRelationshipTypes List of selected relationship types from the + * context menu of plantuml + * @param traceLinksTransitive Used to determine if tracelink elements + * should be received transitively + * @param transitivityDepth Used to in case tracelinks are received + * transivitely in order to set the depth + * @return A Map with the following structure: [Trace object t -> {list of all + * objects connected to element via t}] */ List<Connection> getInternalElements(EObject element, EObject traceModel, List<String> selectedRelationshipTypes, boolean traceLinksTransitive, int transitivityDepth, List<Connection> existingTraces); @@ -196,31 +175,27 @@ public interface TraceMetaModelAdapter { * Determine a list of elements internally connected to the selected one * transitively * - * @param element - * The element used to determine the list of connected objects. - * Note that this element could be a trace in the trace model - * @param traceModel - * Trace model to base calculation on - * @param transitivityDepth - * The maximum depth the user wants to go down transitively. 0 - * indicates no limit. - * @return A Map with the following structure: [Trace object t -> {list of - * all objects connected to element via t}] + * @param element The element used to determine the list of connected + * objects. Note that this element could be a trace in + * the trace model + * @param traceModel Trace model to base calculation on + * @param transitivityDepth The maximum depth the user wants to go down + * transitively. 0 indicates no limit. + * @return A Map with the following structure: [Trace object t -> {list of all + * objects connected to element via t}] */ List<Connection> getInternalElementsTransitive(EObject element, EObject traceModel, List<String> selectedRelationshipTypes, int transitivityDepth, List<Connection> existingTraces); - + /** * Decide if two objects are connected internally by passing the selected - * objects down to the artifact handlers and returns a String with the Type - * of connection for the trace matrix (empty String if no connection exists) - * This is implemented in the {@link AbstractMetaModelAdapter} and does not - * need to be overwritten but can be used like it is. + * objects down to the artifact handlers and returns a String with the Type of + * connection for the trace matrix (empty String if no connection exists) This + * is implemented in the {@link AbstractMetaModelAdapter} and does not need to + * be overwritten but can be used like it is. * - * @param first - * First object - * @param second - * Second object + * @param first First object + * @param second Second object * @return <code>true</code> if object are connected, <code>false</code> * otherwise */ diff --git a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/TraceHelper.java b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/TraceHelper.java index b4f908bf..93635e23 100644 --- a/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/TraceHelper.java +++ b/bundles/org.eclipse.capra.core/src/org/eclipse/capra/core/helpers/TraceHelper.java @@ -14,6 +14,7 @@ package org.eclipse.capra.core.helpers; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -50,12 +51,13 @@ public class TraceHelper { /** * Create a trace of the given traceType * - * @param wrappers + * @param origins + * @param targets * @param traceType * @return the trace link that has been created */ - public EObject createTrace(List<EObject> wrappers, EClass traceType) { - return traceAdapter.createTrace(traceType, traceModel, wrappers); + public EObject createTrace(List<EObject> origins, List<EObject> targets, EClass traceType) { + return traceAdapter.createTrace(traceType, traceModel, origins, targets); } /** @@ -119,8 +121,10 @@ public class TraceHelper { */ public List<EObject> getTracedElements(Connection connection) { List<EObject> tracedElements = new ArrayList<>(); - if (!tracedElements.contains(connection.getOrigin())) { - tracedElements.add(connection.getOrigin()); + for (EObject origin : connection.getOrigins()) { + if (!tracedElements.contains(origin)) { + tracedElements.add(origin); + } } for (EObject target : connection.getTargets()) { if (!tracedElements.contains(target)) { @@ -137,32 +141,67 @@ public class TraceHelper { * @param selection the selected elements * @param traceType the type of trace link * @return true if the link exists + * @deprecated As of 0.8.2. Please use {@link #traceExists(List, List, EClass)} + * instead */ + @Deprecated public boolean traceExists(List<EObject> selection, EClass traceType) { return !getTraces(selection, traceType).isEmpty(); } /** + * Checks if a trace link of a certain type with the provided origins and + * targets already exists in the trace model for the instance of this class. + * + * @param origins the origins of the trace link + * @param targets the targets of the trace link + * @param traceType the type of trace link + * @return true if the link exists + * + */ + public boolean traceExists(List<EObject> origins, List<EObject> targets, EClass traceType) { + return !getTraces(origins, targets, traceType).isEmpty(); + } + + /** * Returns all trace links of the given type containing the given selection that * exist in the trace model set in the instance of this class. * + * This version of the method implicitly treats the first element in the + * provided list as the source and the rest as the targets of the link. + * * @param selection the selected elements * @param traceType the type of trace link * @return a list of trace links that fit the criteria + * @deprecated As of 0.8.2. Please use {@link #getTraces(List, List, EClass)} + * instead. */ + @Deprecated public List<Connection> getTraces(List<EObject> selection, EClass traceType) { - // create a connection - List<EObject> allElements = new ArrayList<>(selection); - EObject source = allElements.get(0); - allElements.remove(0); - List<EObject> targets = allElements; + List<EObject> targets = new ArrayList<>(selection); + EObject origin = targets.get(0); + targets.remove(0); + return getTraces(Arrays.asList(origin), targets, traceType); + } + + /** + * Returns all trace links of the given type containing the given origins and + * targets that exist in the trace model set in the instance of this class. + * + * @param origins the origins of the trace links that should be retrieved + * @param targets the targets of the trace links that should be retrieved + * @param traceType the type of trace link + * @return a list of trace links that fit the criteria + */ + public List<Connection> getTraces(List<EObject> origins, List<EObject> targets, EClass traceType) { // create temporary trace model with a temporary trace link EObject tempTraceModel = ExtensionPointHelper.getTracePersistenceAdapter().orElseThrow() .getTraceModel(new ResourceSetImpl()); - EObject tempTlink = traceAdapter.createTrace(traceType, tempTraceModel, selection); + EObject tempTlink = traceAdapter.createTrace(traceType, tempTraceModel, origins, targets); - Connection connection = new Connection(source, targets, tempTlink); + // create a connection + Connection connection = new Connection(origins, targets, tempTlink); return traceAdapter.getAllTraceLinks(this.traceModel).stream().filter(c -> c.equals(connection)) .collect(Collectors.toCollection(ArrayList::new)); @@ -175,7 +214,6 @@ public class TraceHelper { * @param artifact the artifact to look for * @return true if the artifact exists, false otherwise */ - public boolean isArtifactInTraceModel(EObject artifact) { List<EObject> artifacts = new ArrayList<>(); List<Connection> connections = traceAdapter.getAllTraceLinks(traceModel); @@ -231,11 +269,8 @@ public class TraceHelper { public static Set<EObject> getTracedElements(Collection<Connection> traces) { Set<EObject> inserted = new HashSet<>(); for (Connection trace : traces) { - inserted.add(trace.getOrigin()); - List<EObject> targets = trace.getTargets(); - for (EObject target : targets) { - inserted.add(target); - } + inserted.addAll(trace.getOrigins()); + inserted.addAll(trace.getTargets()); } return inserted; } diff --git a/bundles/org.eclipse.capra.generic.tracemodel/model/generictrace.xcore b/bundles/org.eclipse.capra.generic.tracemodel/model/generictrace.xcore index 9731c71d..1ad1289b 100644 --- a/bundles/org.eclipse.capra.generic.tracemodel/model/generictrace.xcore +++ b/bundles/org.eclipse.capra.generic.tracemodel/model/generictrace.xcore @@ -11,5 +11,6 @@ class RelatedTo { EcoreUtil.generateUUID(); } String name - refers EObject [0..*] item + refers EObject [1] origin + refers EObject [1..*] targets }
\ No newline at end of file diff --git a/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/RelatedTo.java b/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/RelatedTo.java index 65d4cb98..ff4e57aa 100644 --- a/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/RelatedTo.java +++ b/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/RelatedTo.java @@ -17,7 +17,8 @@ import org.eclipse.emf.ecore.EObject; * <ul> * <li>{@link org.eclipse.capra.generic.tracemodel.RelatedTo#getID <em>ID</em>}</li> * <li>{@link org.eclipse.capra.generic.tracemodel.RelatedTo#getName <em>Name</em>}</li> - * <li>{@link org.eclipse.capra.generic.tracemodel.RelatedTo#getItem <em>Item</em>}</li> + * <li>{@link org.eclipse.capra.generic.tracemodel.RelatedTo#getOrigin <em>Origin</em>}</li> + * <li>{@link org.eclipse.capra.generic.tracemodel.RelatedTo#getTargets <em>Targets</em>}</li> * </ul> * * @see org.eclipse.capra.generic.tracemodel.TracemodelPackage#getRelatedTo() @@ -59,15 +60,37 @@ public interface RelatedTo extends EObject { void setName(String value); /** - * Returns the value of the '<em><b>Item</b></em>' reference list. + * Returns the value of the '<em><b>Origin</b></em>' reference. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @return the value of the '<em>Origin</em>' reference. + * @see #setOrigin(EObject) + * @see org.eclipse.capra.generic.tracemodel.TracemodelPackage#getRelatedTo_Origin() + * @model required="true" + * @generated + */ + EObject getOrigin(); + + /** + * Sets the value of the '{@link org.eclipse.capra.generic.tracemodel.RelatedTo#getOrigin <em>Origin</em>}' reference. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @param value the new value of the '<em>Origin</em>' reference. + * @see #getOrigin() + * @generated + */ + void setOrigin(EObject value); + + /** + * Returns the value of the '<em><b>Targets</b></em>' reference list. * The list contents are of type {@link org.eclipse.emf.ecore.EObject}. * <!-- begin-user-doc --> * <!-- end-user-doc --> - * @return the value of the '<em>Item</em>' reference list. - * @see org.eclipse.capra.generic.tracemodel.TracemodelPackage#getRelatedTo_Item() - * @model + * @return the value of the '<em>Targets</em>' reference list. + * @see org.eclipse.capra.generic.tracemodel.TracemodelPackage#getRelatedTo_Targets() + * @model required="true" * @generated */ - EList<EObject> getItem(); + EList<EObject> getTargets(); } // RelatedTo diff --git a/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/TracemodelPackage.java b/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/TracemodelPackage.java index eef4c100..75aa50dd 100644 --- a/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/TracemodelPackage.java +++ b/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/TracemodelPackage.java @@ -122,13 +122,22 @@ public interface TracemodelPackage extends EPackage { int RELATED_TO__NAME = 1; /** - * The feature id for the '<em><b>Item</b></em>' reference list. + * The feature id for the '<em><b>Origin</b></em>' reference. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated * @ordered */ - int RELATED_TO__ITEM = 2; + int RELATED_TO__ORIGIN = 2; + + /** + * The feature id for the '<em><b>Targets</b></em>' reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + int RELATED_TO__TARGETS = 3; /** * The number of structural features of the '<em>Related To</em>' class. @@ -137,7 +146,7 @@ public interface TracemodelPackage extends EPackage { * @generated * @ordered */ - int RELATED_TO_FEATURE_COUNT = 3; + int RELATED_TO_FEATURE_COUNT = 4; /** * The number of operations of the '<em>Related To</em>' class. @@ -203,15 +212,26 @@ public interface TracemodelPackage extends EPackage { EAttribute getRelatedTo_Name(); /** - * Returns the meta object for the reference list '{@link org.eclipse.capra.generic.tracemodel.RelatedTo#getItem <em>Item</em>}'. + * Returns the meta object for the reference '{@link org.eclipse.capra.generic.tracemodel.RelatedTo#getOrigin <em>Origin</em>}'. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @return the meta object for the reference '<em>Origin</em>'. + * @see org.eclipse.capra.generic.tracemodel.RelatedTo#getOrigin() + * @see #getRelatedTo() + * @generated + */ + EReference getRelatedTo_Origin(); + + /** + * Returns the meta object for the reference list '{@link org.eclipse.capra.generic.tracemodel.RelatedTo#getTargets <em>Targets</em>}'. * <!-- begin-user-doc --> * <!-- end-user-doc --> - * @return the meta object for the reference list '<em>Item</em>'. - * @see org.eclipse.capra.generic.tracemodel.RelatedTo#getItem() + * @return the meta object for the reference list '<em>Targets</em>'. + * @see org.eclipse.capra.generic.tracemodel.RelatedTo#getTargets() * @see #getRelatedTo() * @generated */ - EReference getRelatedTo_Item(); + EReference getRelatedTo_Targets(); /** * Returns the factory that creates the instances of the model. @@ -281,12 +301,20 @@ public interface TracemodelPackage extends EPackage { EAttribute RELATED_TO__NAME = eINSTANCE.getRelatedTo_Name(); /** - * The meta object literal for the '<em><b>Item</b></em>' reference list feature. + * The meta object literal for the '<em><b>Origin</b></em>' reference feature. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + EReference RELATED_TO__ORIGIN = eINSTANCE.getRelatedTo_Origin(); + + /** + * The meta object literal for the '<em><b>Targets</b></em>' reference list feature. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ - EReference RELATED_TO__ITEM = eINSTANCE.getRelatedTo_Item(); + EReference RELATED_TO__TARGETS = eINSTANCE.getRelatedTo_Targets(); } diff --git a/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/impl/RelatedToImpl.java b/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/impl/RelatedToImpl.java index 6b04bcef..bd987b6d 100644 --- a/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/impl/RelatedToImpl.java +++ b/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/impl/RelatedToImpl.java @@ -13,6 +13,7 @@ import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.impl.ENotificationImpl; import org.eclipse.emf.ecore.impl.MinimalEObjectImpl; @@ -30,7 +31,8 @@ import org.eclipse.emf.ecore.util.EcoreUtil; * <ul> * <li>{@link org.eclipse.capra.generic.tracemodel.impl.RelatedToImpl#getID <em>ID</em>}</li> * <li>{@link org.eclipse.capra.generic.tracemodel.impl.RelatedToImpl#getName <em>Name</em>}</li> - * <li>{@link org.eclipse.capra.generic.tracemodel.impl.RelatedToImpl#getItem <em>Item</em>}</li> + * <li>{@link org.eclipse.capra.generic.tracemodel.impl.RelatedToImpl#getOrigin <em>Origin</em>}</li> + * <li>{@link org.eclipse.capra.generic.tracemodel.impl.RelatedToImpl#getTargets <em>Targets</em>}</li> * </ul> * * @generated @@ -67,14 +69,24 @@ public class RelatedToImpl extends MinimalEObjectImpl.Container implements Relat protected String name = NAME_EDEFAULT; /** - * The cached value of the '{@link #getItem() <em>Item</em>}' reference list. + * The cached value of the '{@link #getOrigin() <em>Origin</em>}' reference. * <!-- begin-user-doc --> * <!-- end-user-doc --> - * @see #getItem() + * @see #getOrigin() * @generated * @ordered */ - protected EList<EObject> item; + protected EObject origin; + + /** + * The cached value of the '{@link #getTargets() <em>Targets</em>}' reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getTargets() + * @generated + * @ordered + */ + protected EList<EObject> targets; /** * <!-- begin-user-doc --> @@ -130,11 +142,49 @@ public class RelatedToImpl extends MinimalEObjectImpl.Container implements Relat * <!-- end-user-doc --> * @generated */ - public EList<EObject> getItem() { - if (item == null) { - item = new EObjectResolvingEList<EObject>(EObject.class, this, TracemodelPackage.RELATED_TO__ITEM); + public EObject getOrigin() { + if (origin != null && origin.eIsProxy()) { + InternalEObject oldOrigin = (InternalEObject)origin; + origin = eResolveProxy(oldOrigin); + if (origin != oldOrigin) { + if (eNotificationRequired()) + eNotify(new ENotificationImpl(this, Notification.RESOLVE, TracemodelPackage.RELATED_TO__ORIGIN, oldOrigin, origin)); + } + } + return origin; + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public EObject basicGetOrigin() { + return origin; + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void setOrigin(EObject newOrigin) { + EObject oldOrigin = origin; + origin = newOrigin; + if (eNotificationRequired()) + eNotify(new ENotificationImpl(this, Notification.SET, TracemodelPackage.RELATED_TO__ORIGIN, oldOrigin, origin)); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public EList<EObject> getTargets() { + if (targets == null) { + targets = new EObjectResolvingEList<EObject>(EObject.class, this, TracemodelPackage.RELATED_TO__TARGETS); } - return item; + return targets; } /** @@ -149,8 +199,11 @@ public class RelatedToImpl extends MinimalEObjectImpl.Container implements Relat return getID(); case TracemodelPackage.RELATED_TO__NAME: return getName(); - case TracemodelPackage.RELATED_TO__ITEM: - return getItem(); + case TracemodelPackage.RELATED_TO__ORIGIN: + if (resolve) return getOrigin(); + return basicGetOrigin(); + case TracemodelPackage.RELATED_TO__TARGETS: + return getTargets(); } return super.eGet(featureID, resolve, coreType); } @@ -167,9 +220,12 @@ public class RelatedToImpl extends MinimalEObjectImpl.Container implements Relat case TracemodelPackage.RELATED_TO__NAME: setName((String)newValue); return; - case TracemodelPackage.RELATED_TO__ITEM: - getItem().clear(); - getItem().addAll((Collection<? extends EObject>)newValue); + case TracemodelPackage.RELATED_TO__ORIGIN: + setOrigin((EObject)newValue); + return; + case TracemodelPackage.RELATED_TO__TARGETS: + getTargets().clear(); + getTargets().addAll((Collection<? extends EObject>)newValue); return; } super.eSet(featureID, newValue); @@ -186,8 +242,11 @@ public class RelatedToImpl extends MinimalEObjectImpl.Container implements Relat case TracemodelPackage.RELATED_TO__NAME: setName(NAME_EDEFAULT); return; - case TracemodelPackage.RELATED_TO__ITEM: - getItem().clear(); + case TracemodelPackage.RELATED_TO__ORIGIN: + setOrigin((EObject)null); + return; + case TracemodelPackage.RELATED_TO__TARGETS: + getTargets().clear(); return; } super.eUnset(featureID); @@ -205,8 +264,10 @@ public class RelatedToImpl extends MinimalEObjectImpl.Container implements Relat return ID_EDEFAULT == null ? getID() != null : !ID_EDEFAULT.equals(getID()); case TracemodelPackage.RELATED_TO__NAME: return NAME_EDEFAULT == null ? name != null : !NAME_EDEFAULT.equals(name); - case TracemodelPackage.RELATED_TO__ITEM: - return item != null && !item.isEmpty(); + case TracemodelPackage.RELATED_TO__ORIGIN: + return origin != null; + case TracemodelPackage.RELATED_TO__TARGETS: + return targets != null && !targets.isEmpty(); } return super.eIsSet(featureID); } diff --git a/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/impl/TracemodelPackageImpl.java b/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/impl/TracemodelPackageImpl.java index 2d76e8f9..ff718608 100644 --- a/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/impl/TracemodelPackageImpl.java +++ b/bundles/org.eclipse.capra.generic.tracemodel/src-gen/org/eclipse/capra/generic/tracemodel/impl/TracemodelPackageImpl.java @@ -150,7 +150,7 @@ public class TracemodelPackageImpl extends EPackageImpl implements TracemodelPac * <!-- end-user-doc --> * @generated */ - public EReference getRelatedTo_Item() { + public EReference getRelatedTo_Origin() { return (EReference)relatedToEClass.getEStructuralFeatures().get(2); } @@ -159,6 +159,15 @@ public class TracemodelPackageImpl extends EPackageImpl implements TracemodelPac * <!-- end-user-doc --> * @generated */ + public EReference getRelatedTo_Targets() { + return (EReference)relatedToEClass.getEStructuralFeatures().get(3); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ public TracemodelFactory getTracemodelFactory() { return (TracemodelFactory)getEFactoryInstance(); } @@ -188,7 +197,8 @@ public class TracemodelPackageImpl extends EPackageImpl implements TracemodelPac relatedToEClass = createEClass(RELATED_TO); createEAttribute(relatedToEClass, RELATED_TO__ID); createEAttribute(relatedToEClass, RELATED_TO__NAME); - createEReference(relatedToEClass, RELATED_TO__ITEM); + createEReference(relatedToEClass, RELATED_TO__ORIGIN); + createEReference(relatedToEClass, RELATED_TO__TARGETS); } /** @@ -230,7 +240,8 @@ public class TracemodelPackageImpl extends EPackageImpl implements TracemodelPac initEClass(relatedToEClass, RelatedTo.class, "RelatedTo", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); initEAttribute(getRelatedTo_ID(), theEcorePackage.getEString(), "ID", null, 0, 1, RelatedTo.class, IS_TRANSIENT, IS_VOLATILE, !IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, !IS_UNIQUE, IS_DERIVED, IS_ORDERED); initEAttribute(getRelatedTo_Name(), theEcorePackage.getEString(), "name", null, 0, 1, RelatedTo.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, !IS_UNIQUE, !IS_DERIVED, IS_ORDERED); - initEReference(getRelatedTo_Item(), theEcorePackage.getEObject(), null, "item", null, 0, -1, RelatedTo.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + initEReference(getRelatedTo_Origin(), theEcorePackage.getEObject(), null, "origin", null, 1, 1, RelatedTo.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); + initEReference(getRelatedTo_Targets(), theEcorePackage.getEObject(), null, "targets", null, 1, -1, RelatedTo.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); // Create resource createResource(eNS_URI); diff --git a/bundles/org.eclipse.capra.generic.tracemodel/src/org/eclipse/capra/generic/tracemodel/GenericMetaModelAdapter.java b/bundles/org.eclipse.capra.generic.tracemodel/src/org/eclipse/capra/generic/tracemodel/GenericMetaModelAdapter.java index bf9e0549..88a71025 100644 --- a/bundles/org.eclipse.capra.generic.tracemodel/src/org/eclipse/capra/generic/tracemodel/GenericMetaModelAdapter.java +++ b/bundles/org.eclipse.capra.generic.tracemodel/src/org/eclipse/capra/generic/tracemodel/GenericMetaModelAdapter.java @@ -14,6 +14,7 @@ package org.eclipse.capra.generic.tracemodel; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -60,11 +61,12 @@ public class GenericMetaModelAdapter extends AbstractMetaModelAdapter implements } @Override - public EObject createTrace(EClass traceType, EObject traceModel, List<EObject> selection) { + public EObject createTrace(EClass traceType, EObject traceModel, List<EObject> origins, List<EObject> targets) { GenericTraceModel tm = (GenericTraceModel) traceModel; EObject trace = TracemodelFactory.eINSTANCE.create(traceType); RelatedTo relatedToTrace = (RelatedTo) trace; - relatedToTrace.getItem().addAll(selection); + relatedToTrace.setOrigin(origins.get(0)); + relatedToTrace.getTargets().addAll(targets); TracePersistenceAdapter persistenceAdapter = ExtensionPointHelper.getTracePersistenceAdapter().orElseThrow(); EObject artifactModel = persistenceAdapter.getArtifactWrappers(EditingDomainHelper.getResourceSet()); ArtifactHelper artifactHelper = new ArtifactHelper(artifactModel); @@ -73,7 +75,10 @@ public class GenericMetaModelAdapter extends AbstractMetaModelAdapter implements // elements it connects so as to make it easy for a user to visually // differentiate trace links StringBuilder name = new StringBuilder(); - for (Object obj : selection) { + name.append(artifactHelper.getHandler(artifactHelper.unwrapWrapper(origins.get(0))).orElseThrow() + .withCastedHandler(artifactHelper.unwrapWrapper(origins.get(0)), (h, e) -> h.getDisplayName(e)) + .orElseGet(origins.get(0)::toString)); + for (Object obj : targets) { name.append(" ") .append(artifactHelper.getHandler(artifactHelper.unwrapWrapper(obj)).orElseThrow() .withCastedHandler(artifactHelper.unwrapWrapper(obj), (h, e) -> h.getDisplayName(e)) @@ -111,8 +116,8 @@ public class GenericMetaModelAdapter extends AbstractMetaModelAdapter implements List<RelatedTo> allTraces = root.getTraces(); for (RelatedTo trace : allTraces) { - if (!firstElement.equals(secondElement) && EMFHelper.isElementInList(trace.getItem(), firstElement) - && EMFHelper.isElementInList(trace.getItem(), secondElement)) { + if (!firstElement.equals(secondElement) && EMFHelper.hasSameIdentifier(firstElement, trace.getOrigin()) + && EMFHelper.isElementInList(trace.getTargets(), secondElement)) { relevantLinks.add(trace); } } @@ -121,23 +126,7 @@ public class GenericMetaModelAdapter extends AbstractMetaModelAdapter implements @Override public List<Connection> getConnectedElements(EObject element, EObject tracemodel) { - GenericTraceModel root = (GenericTraceModel) tracemodel; - List<Connection> connections = new ArrayList<>(); - List<RelatedTo> traces = root.getTraces(); - - if (element instanceof RelatedTo) { - RelatedTo trace = (RelatedTo) element; - connections.add(new Connection(element, trace.getItem(), trace)); - } else { - for (RelatedTo trace : traces) { - for (EObject item : trace.getItem()) { - if (EcoreUtil.equals(item, element)) { - connections.add(new Connection(element, trace.getItem(), trace)); - } - } - } - } - return connections; + return this.getConnectedElements(element, tracemodel, new ArrayList<String>()); } @Override @@ -151,12 +140,14 @@ public class GenericMetaModelAdapter extends AbstractMetaModelAdapter implements || selectedRelationshipTypes.contains(TracemodelPackage.eINSTANCE.getRelatedTo().getName())) { if (element instanceof RelatedTo) { RelatedTo trace = (RelatedTo) element; - connections.add(new Connection(element, trace.getItem(), trace)); + connections.add(new Connection(Arrays.asList(element), trace.getTargets(), trace)); } else { for (RelatedTo trace : traces) { - for (EObject item : trace.getItem()) { + List<EObject> allItems = new ArrayList<>(trace.getTargets()); + allItems.add(trace.getOrigin()); + for (EObject item : allItems) { if (EcoreUtil.equals(item, element)) { - connections.add(new Connection(element, trace.getItem(), trace)); + connections.add(new Connection(Arrays.asList(element), trace.getTargets(), trace)); } } } @@ -199,11 +190,7 @@ public class GenericMetaModelAdapter extends AbstractMetaModelAdapter implements List<Connection> allLinks = new ArrayList<>(); for (RelatedTo trace : model.getTraces()) { - List<EObject> allItems = new ArrayList<>(); - allItems.addAll(trace.getItem()); - EObject origin = allItems.get(0); - allItems.remove(0); - allLinks.add(new Connection(origin, allItems, trace)); + allLinks.add(new Connection(Arrays.asList(trace.getOrigin()), trace.getTargets(), trace)); } return allLinks; } diff --git a/bundles/org.eclipse.capra.handler.app4mc/src/org/eclipse/capra/handler/app4mc/APP4MCHandler.java b/bundles/org.eclipse.capra.handler.app4mc/src/org/eclipse/capra/handler/app4mc/APP4MCHandler.java index 09e631fe..1c9d1035 100644 --- a/bundles/org.eclipse.capra.handler.app4mc/src/org/eclipse/capra/handler/app4mc/APP4MCHandler.java +++ b/bundles/org.eclipse.capra.handler.app4mc/src/org/eclipse/capra/handler/app4mc/APP4MCHandler.java @@ -74,14 +74,15 @@ public class APP4MCHandler extends AbstractArtifactHandler<INamed> { if (named.eCrossReferences() != null) { List<EObject> refs = named.eCrossReferences(); for (EObject ref : refs) { - if ((selectedRelationshipTypes != null) && (selectedRelationshipTypes.isEmpty() - || selectedRelationshipTypes.contains(ref.eClass().getName()))) { - connections.add(new Connection(investigatedElement, Arrays.asList(ref), ref)); - - } else { - // selectedRelationshipTypes is null and therefore return all cross references + if (selectedRelationshipTypes != null) { + if (selectedRelationshipTypes.size() == 0 + || selectedRelationshipTypes.contains(ref.eClass().getName())) { + connections + .add(new Connection(Arrays.asList(investigatedElement), Arrays.asList(ref), ref)); + } + } else {// selectedRelationshipTypes is null and therefore return all cross references // as internal links - connections.add(new Connection(investigatedElement, Arrays.asList(ref), ref)); + connections.add(new Connection(Arrays.asList(investigatedElement), Arrays.asList(ref), ref)); } } } diff --git a/bundles/org.eclipse.capra.handler.emf/src/org/eclipse/capra/handler/emf/notification/ModelChangeListener.java b/bundles/org.eclipse.capra.handler.emf/src/org/eclipse/capra/handler/emf/notification/ModelChangeListener.java index cf3e1171..2de461ea 100644 --- a/bundles/org.eclipse.capra.handler.emf/src/org/eclipse/capra/handler/emf/notification/ModelChangeListener.java +++ b/bundles/org.eclipse.capra.handler.emf/src/org/eclipse/capra/handler/emf/notification/ModelChangeListener.java @@ -84,7 +84,7 @@ public class ModelChangeListener extends EContentAdapter { if (!connections.isEmpty()) { for (Connection c : connections) { List<EObject> tempList = new ArrayList<>(); - tempList.add(c.getOrigin()); + tempList.addAll(c.getOrigins()); tempList.addAll(c.getTargets()); for (EObject tracedItem : tempList) { diff --git a/bundles/org.eclipse.capra.handler.reqIf/src/org/eclipse/capra/handler/reqif/ReqIfHandler.java b/bundles/org.eclipse.capra.handler.reqIf/src/org/eclipse/capra/handler/reqif/ReqIfHandler.java index 719534b9..93488d90 100644 --- a/bundles/org.eclipse.capra.handler.reqIf/src/org/eclipse/capra/handler/reqif/ReqIfHandler.java +++ b/bundles/org.eclipse.capra.handler.reqIf/src/org/eclipse/capra/handler/reqif/ReqIfHandler.java @@ -14,6 +14,7 @@ package org.eclipse.capra.handler.reqif; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -101,13 +102,12 @@ public class ReqIfHandler extends AbstractArtifactHandler<SpecHierarchy> { } } } - connections.add(new Connection(investigatedElement, targets, r)); + connections.add(new Connection(Arrays.asList(investigatedElement), targets, r)); } } return connections; - } else { + } else return Collections.emptyList(); - } } @Override diff --git a/bundles/org.eclipse.capra.handler.uml/src/org/eclipse/capra/handler/uml/UMLHandler.java b/bundles/org.eclipse.capra.handler.uml/src/org/eclipse/capra/handler/uml/UMLHandler.java index c3fd0396..fabe3236 100644 --- a/bundles/org.eclipse.capra.handler.uml/src/org/eclipse/capra/handler/uml/UMLHandler.java +++ b/bundles/org.eclipse.capra.handler.uml/src/org/eclipse/capra/handler/uml/UMLHandler.java @@ -14,6 +14,7 @@ package org.eclipse.capra.handler.uml; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.eclipse.capra.core.adapters.Connection; @@ -73,7 +74,7 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { connectionHash += element.hashCode(); } if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, rel); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, rel); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -87,7 +88,7 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { relatedElements.add(activityEdge.getSource()); int connectionHash = investigatedElement.hashCode() + activityEdge.hashCode(); if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, activityEdge); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, activityEdge); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -102,7 +103,7 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { int connectionHash = investigatedElement.hashCode() + transition.hashCode() + transition.getTarget().hashCode() + transition.getSource().hashCode(); if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, transition); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, transition); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -121,7 +122,7 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { + msg.getMessageSort().hashCode() + sender.getCovered().hashCode() + receiver.getCovered().hashCode(); if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, msg); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, msg); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -141,7 +142,7 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { connectionHash += el.hashCode(); } if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, port); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, port); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -164,7 +165,7 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { connectionHash += el.hashCode(); } if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, connector); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, connector); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -193,7 +194,8 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { connectionHash += element.hashCode(); } if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, relation); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, + relation); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -210,7 +212,8 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { } int connectionHash = investigatedElement.hashCode() + activityEdge.hashCode(); if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, activityEdge); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, + activityEdge); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -223,7 +226,8 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { int connectionHash = investigatedElement.hashCode() + transition.hashCode() + transition.getTarget().hashCode(); if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, transition); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, + transition); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -232,7 +236,8 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { int connectionHash = investigatedElement.hashCode() + transition.hashCode() + transition.getSource().hashCode(); if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, transition); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, + transition); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -249,7 +254,8 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { int connectionHash = investigatedElement.hashCode() + msg.hashCode() + msg.getMessageSort().hashCode() + sender.getCovered().hashCode(); if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, msg); + Connection conn = new Connection(Arrays.asList(investigatedElement), + relatedElements, msg); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -258,7 +264,8 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { int connectionHash = investigatedElement.hashCode() + msg.hashCode() + msg.getMessageSort().hashCode() + receiver.getCovered().hashCode(); if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, msg); + Connection conn = new Connection(Arrays.asList(investigatedElement), + relatedElements, msg); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -294,7 +301,8 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { connectionHash += el.hashCode(); } if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, port); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, + port); allElements.add(conn); duplicationCheck.add(connectionHash); } @@ -325,7 +333,8 @@ public class UMLHandler extends AbstractArtifactHandler<EModelElement> { connectionHash += el.hashCode(); } if (!duplicationCheck.contains(connectionHash)) { - Connection conn = new Connection(investigatedElement, relatedElements, connector); + Connection conn = new Connection(Arrays.asList(investigatedElement), relatedElements, + connector); allElements.add(conn); duplicationCheck.add(connectionHash); } diff --git a/bundles/org.eclipse.capra.ui.matrix/src/org/eclipse/capra/ui/matrix/TraceabilityMatrixBodyToolTip.java b/bundles/org.eclipse.capra.ui.matrix/src/org/eclipse/capra/ui/matrix/TraceabilityMatrixBodyToolTip.java index 76da0923..8a687e9f 100644 --- a/bundles/org.eclipse.capra.ui.matrix/src/org/eclipse/capra/ui/matrix/TraceabilityMatrixBodyToolTip.java +++ b/bundles/org.eclipse.capra.ui.matrix/src/org/eclipse/capra/ui/matrix/TraceabilityMatrixBodyToolTip.java @@ -84,7 +84,8 @@ public class TraceabilityMatrixBodyToolTip extends NatTableContentTooltip { EObject eClass = connection.getTlink().eClass(); String traceType = (eClass == null ? "" : ((EClass) eClass).getName()); Set<String> artifactNames = new LinkedHashSet<>(); - artifactNames.add(artifactHelper.getArtifactLabel(connection.getOrigin())); + artifactNames.addAll(connection.getOrigins().stream().map(a -> artifactHelper.getArtifactLabel(a)) + .collect(Collectors.toCollection(ArrayList::new))); artifactNames.addAll(connection.getTargets().stream().map(a -> artifactHelper.getArtifactLabel(a)) .collect(Collectors.toCollection(ArrayList::new))); StringBuilder tooltipBuilder = new StringBuilder(); diff --git a/bundles/org.eclipse.capra.ui.notification/src/org/eclipse/capra/ui/notification/DeleteQuickFix.java b/bundles/org.eclipse.capra.ui.notification/src/org/eclipse/capra/ui/notification/DeleteQuickFix.java index a8d52075..ceaf4286 100644 --- a/bundles/org.eclipse.capra.ui.notification/src/org/eclipse/capra/ui/notification/DeleteQuickFix.java +++ b/bundles/org.eclipse.capra.ui.notification/src/org/eclipse/capra/ui/notification/DeleteQuickFix.java @@ -134,7 +134,7 @@ public class DeleteQuickFix implements IMarkerResolution { TraceMetaModelAdapter traceMetaModelAdapter = ExtensionPointHelper.getTraceMetamodelAdapter().orElseThrow(); // create a new trace link with the remaining items for (Connection c : toRecreate) { - traceMetaModelAdapter.createTrace(c.getTlink().eClass(), traceModel, c.getTargets()); + traceMetaModelAdapter.createTrace(c.getTlink().eClass(), traceModel, c.getOrigins(), c.getTargets()); } // delete the existing trace link diff --git a/bundles/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/Connections.java b/bundles/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/Connections.java index 4b501bfb..9ea030be 100644 --- a/bundles/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/Connections.java +++ b/bundles/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/Connections.java @@ -121,11 +121,11 @@ public class Connections { Set<String> arrows = new HashSet<>(); connections.forEach(c -> { - c.getTargets().forEach(trg -> { - if (!trg.equals(c.getOrigin())) { - arrows.add(object2Id.get(c.getOrigin()) + "--" + object2Id.get(trg) + ":" + c.getOrigins().forEach(org -> { + c.getTargets().forEach(trg -> { + arrows.add(object2Id.get(org) + "--" + object2Id.get(trg) + ": " + EMFHelper.getIdentifier(c.getTlink())); - } + }); }); }); diff --git a/bundles/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/DiagramTextProviderHandler.java b/bundles/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/DiagramTextProviderHandler.java index 6243cc27..f413d827 100644 --- a/bundles/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/DiagramTextProviderHandler.java +++ b/bundles/org.eclipse.capra.ui.plantuml/src/org/eclipse/capra/ui/plantuml/DiagramTextProviderHandler.java @@ -158,17 +158,19 @@ public class DiagramTextProviderHandler implements DiagramTextProvider { List<Connection> relevantTraces = new ArrayList<>(); List<EObject> wrappers = new ArrayList<>(); for (Connection connection : traces) { - if (selectedEObjects.contains(connection.getOrigin()) + if (selectedEObjects.containsAll(connection.getOrigins()) && selectedEObjects.stream().anyMatch(connection.getTargets()::contains)) { - Connection newConnection = new Connection(connection.getOrigin(), connection.getTargets().stream() + Connection newConnection = new Connection(connection.getOrigins(), connection.getTargets().stream() .filter(selectedEObjects::contains).collect(Collectors.toList()), connection.getTlink()); relevantTraces.add(newConnection); - IArtifactHandler<Object> originHandler = (IArtifactHandler<Object>) artifactHelper - .getHandler(connection.getOrigin()).orElseThrow(); - wrappers.add(originHandler.createWrapper(connection.getOrigin(), artifactModel)); + connection.getOrigins().stream().filter(selectedEObjects::contains).forEach(o -> { + IArtifactHandler<Object> originHandler = (IArtifactHandler<Object>) artifactHelper.getHandler(o) + .orElseThrow(); + wrappers.add(originHandler.createWrapper(o, artifactModel)); + }); connection.getTargets().stream().filter(selectedEObjects::contains).forEach(t -> { - IArtifactHandler<Object> targetHandler = (IArtifactHandler<Object>) artifactHelper - .getHandler(connection.getOrigin()).orElseThrow(); + IArtifactHandler<Object> targetHandler = (IArtifactHandler<Object>) artifactHelper.getHandler(t) + .orElseThrow(); wrappers.add(targetHandler.createWrapper(t, artifactModel)); }); } diff --git a/bundles/org.eclipse.capra.ui.plantuml/xtend-gen/org/eclipse/capra/ui/plantuml/.VisualizationHelper.xtendbin b/bundles/org.eclipse.capra.ui.plantuml/xtend-gen/org/eclipse/capra/ui/plantuml/.VisualizationHelper.xtendbin Binary files differindex ef17addb..59c2741b 100644 --- a/bundles/org.eclipse.capra.ui.plantuml/xtend-gen/org/eclipse/capra/ui/plantuml/.VisualizationHelper.xtendbin +++ b/bundles/org.eclipse.capra.ui.plantuml/xtend-gen/org/eclipse/capra/ui/plantuml/.VisualizationHelper.xtendbin diff --git a/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ConnectionAdapter.java b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ConnectionAdapter.java index 0fadbe05..cacb196b 100644 --- a/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ConnectionAdapter.java +++ b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/adapters/ConnectionAdapter.java @@ -92,7 +92,8 @@ public class ConnectionAdapter implements IPropertySource { @Override public Object getPropertyValue(Object id) { if (id.equals(DescriptorIDs.ORIGIN)) { - return artifactHelper.getArtifactLabel(connection.getOrigin()); + return connection.getOrigins().stream().map(o -> artifactHelper.getArtifactLabel(o)) + .collect(Collectors.toList()); } else if (id.equals(DescriptorIDs.TARGETS)) { return connection.getTargets().stream().map(artifactHelper::getArtifactLabel).collect(Collectors.toList()); } else if (id.equals(DescriptorIDs.TYPE)) { diff --git a/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/handlers/TraceCreationHandler.java b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/handlers/TraceCreationHandler.java index ed4b0ab0..fc17dc61 100644 --- a/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/handlers/TraceCreationHandler.java +++ b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/handlers/TraceCreationHandler.java @@ -13,6 +13,7 @@ *******************************************************************************/ package org.eclipse.capra.ui.handlers; +import java.util.Arrays; import java.util.Optional; import org.eclipse.capra.ui.operations.CreateTraceOperation; @@ -36,7 +37,8 @@ public class TraceCreationHandler extends AbstractHandler { IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory(); CreateTraceOperation createTraceOperation = new CreateTraceOperation("Create trace link", - SelectionView.getOpenedView().getSelection()); + Arrays.asList(SelectionView.getOpenedView().getSelection().get(0)), SelectionView.getOpenedView() + .getSelection().subList(1, SelectionView.getOpenedView().getSelection().size())); createTraceOperation.addContext(undoContext); if (SelectionView.getOpenedView().getSelectedTraceType() != null) { createTraceOperation diff --git a/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/operations/CreateTraceOperation.java b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/operations/CreateTraceOperation.java index af9d9b62..e125bc6f 100644 --- a/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/operations/CreateTraceOperation.java +++ b/bundles/org.eclipse.capra.ui/src/org/eclipse/capra/ui/operations/CreateTraceOperation.java @@ -13,6 +13,7 @@ *******************************************************************************/ package org.eclipse.capra.ui.operations; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -61,15 +62,18 @@ public class CreateTraceOperation extends AbstractOperation { private static final String TRACE_LINK_SUCCESSFULLY_CREATED = "Trace link has been successfully created"; private static final String DO_NOT_SHOW_DIALOG_AGAIN = "Do not show this dialog again"; private static final String SELECT_TRACE_LINK_TYPE = "Select the trace type you want to create"; - private static final String SELECTION = "Selection"; + private static final String SOURCE = "Source:"; + private static final String TARGET = "Target:"; private Optional<EClass> chosenType; - private List<EObject> wrappers; + private List<EObject> originWrappers; + private List<EObject> targetWrappers; private EObject traceModel; - private List<?> artifacts = null; + private List<?> origins = null; + private List<?> targets = null; - private BiFunction<Collection<EClass>, List<EObject>, Optional<EClass>> chooseTraceType = null; + private BiFunction<Collection<EClass>, TraceableObjects, Optional<EClass>> chooseTraceType = null; /** * Creates a new operation to create links. @@ -79,15 +83,17 @@ public class CreateTraceOperation extends AbstractOperation { * @param artifacts the artifacts on which this operation is performed. Should * never be <code>null</code>. */ - public CreateTraceOperation(String label, List<?> artifacts) { + public CreateTraceOperation(String label, List<?> origins, List<?> targets) { super(label); - Assert.isNotNull(artifacts); - this.artifacts = artifacts; + Assert.isNotNull(origins); + Assert.isNotNull(targets); + this.origins = origins; + this.targets = targets; } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { - if (artifacts == null || artifacts.isEmpty()) { + if (origins == null || targets == null || origins.isEmpty() || targets.isEmpty()) { return Status.CANCEL_STATUS; } Shell shell = info.getAdapter(Shell.class); @@ -106,8 +112,10 @@ public class CreateTraceOperation extends AbstractOperation { @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { TraceHelper traceHelper = new TraceHelper(traceModel); - if (this.wrappers != null && this.chosenType != null && this.traceModel != null) { - List<Connection> connections = traceHelper.getTraces(this.wrappers, this.chosenType.get()); + if (this.originWrappers != null && this.targetWrappers != null && this.chosenType != null + && this.traceModel != null) { + List<Connection> connections = traceHelper.getTraces(this.originWrappers, this.targetWrappers, + this.chosenType.get()); if (!connections.isEmpty()) { traceHelper.deleteTraces(connections); return Status.OK_STATUS; @@ -116,6 +124,11 @@ public class CreateTraceOperation extends AbstractOperation { return Status.CANCEL_STATUS; } + public void createTrace(Shell shell) { + Assert.isNotNull(this.chooseTraceType); + this.createTrace(shell, this.chooseTraceType); + } + /** * Create a trace link after eliciting the trace type via the provided * bi-function. @@ -125,7 +138,7 @@ public class CreateTraceOperation extends AbstractOperation { * type */ public void createTrace(Shell shell, - BiFunction<Collection<EClass>, List<EObject>, Optional<EClass>> chooseTraceType) { + BiFunction<Collection<EClass>, TraceableObjects, Optional<EClass>> chooseTraceType) { TraceMetaModelAdapter traceAdapter = ExtensionPointHelper.getTraceMetamodelAdapter().orElseThrow(); TracePersistenceAdapter persistenceAdapter = ExtensionPointHelper.getTracePersistenceAdapter().orElseThrow(); @@ -139,21 +152,25 @@ public class CreateTraceOperation extends AbstractOperation { TraceHelper traceHelper = new TraceHelper(this.traceModel); // Create the artifact wrappers - this.wrappers = artifactHelper.createWrappers(this.artifacts); + this.originWrappers = artifactHelper.createWrappers(this.origins); + this.targetWrappers = artifactHelper.createWrappers(this.targets); + List<EObject> allWrappers = new ArrayList<EObject>(this.originWrappers); + allWrappers.addAll(this.targetWrappers); // Get the type of trace to be created - Collection<EClass> traceTypes = traceAdapter.getAvailableTraceTypes(this.wrappers); - this.chosenType = chooseTraceType.apply(traceTypes, this.wrappers); + Collection<EClass> traceTypes = traceAdapter.getAvailableTraceTypes(allWrappers); + this.chosenType = chooseTraceType.apply(traceTypes, + new TraceableObjects(this.originWrappers, this.targetWrappers)); // Create trace if (this.chosenType.isPresent()) { // check if the connection already exists - if (traceHelper.traceExists(this.wrappers, this.chosenType.get())) { + if (traceHelper.traceExists(this.originWrappers, this.targetWrappers, this.chosenType.get())) { MessageDialog.openInformation(shell, CAPRA_INFORMATION, TRACE_LINK_EXISTS); } else { - traceHelper.createTrace(this.wrappers, this.chosenType.get()); + traceHelper.createTrace(originWrappers, targetWrappers, this.chosenType.get()); persistenceAdapter.saveTracesAndArtifacts(traceModel, artifactModel); - traceHelper.annotateTrace(this.wrappers); + traceHelper.annotateTrace(allWrappers); // check from preferences if user wants to see the "trace // successfully created dialog" @@ -173,11 +190,12 @@ public class CreateTraceOperation extends AbstractOperation { * @param chooseTraceType the bi-function to use to select a suitable trace link * type */ - public void setChooseTraceType(BiFunction<Collection<EClass>, List<EObject>, Optional<EClass>> chooseTraceType) { + public void setChooseTraceType(BiFunction<Collection<EClass>, TraceableObjects, Optional<EClass>> chooseTraceType) { this.chooseTraceType = chooseTraceType; } - private Optional<EClass> getTraceTypeToCreate(Shell shell, Collection<EClass> traceTypes, List<EObject> wrappers) { + private Optional<EClass> getTraceTypeToCreate(Shell shell, Collection<EClass> traceTypes, + TraceableObjects traceableObjects) { ElementListSelectionDialog dialog = new ElementListSelectionDialog(shell, new LabelProvider() { @Override public String getText(Object element) { @@ -188,8 +206,10 @@ public class CreateTraceOperation extends AbstractOperation { dialog.setTitle(SELECT_TRACE_LINK_TYPE); dialog.setElements(traceTypes.toArray()); - dialog.setMessage( - SELECTION + " : " + wrappers.stream().map(this::getSelectionDisplayName).collect(Collectors.toList())); + dialog.setMessage(SOURCE + ": " + + traceableObjects.getOrigins().stream().map(this::getSelectionDisplayName).collect(Collectors.toList()) + + "\n" + TARGET + ": " + traceableObjects.getTargets().stream().map(this::getSelectionDisplayName) + .collect(Collectors.toList())); if (dialog.open() == Window.OK) { return Optional.of((EClass) dialog.getFirstResult()); @@ -209,4 +229,24 @@ public class CreateTraceOperation extends AbstractOperation { } + public class TraceableObjects { + + public TraceableObjects(List<EObject> origins, List<EObject> targets) { + this.origins = origins; + this.targets = targets; + } + + private List<EObject> origins; + private List<EObject> targets; + + public List<EObject> getOrigins() { + return origins; + } + + public List<EObject> getTargets() { + return targets; + } + + } + } diff --git a/tests/org.eclipse.capra.handler.featureide.tests/src/org/eclipse/capra/handler/featureide/tests/TestFeatureIDETraces.java b/tests/org.eclipse.capra.handler.featureide.tests/src/org/eclipse/capra/handler/featureide/tests/TestFeatureIDETraces.java index e5a0fee0..9509d4a7 100644 --- a/tests/org.eclipse.capra.handler.featureide.tests/src/org/eclipse/capra/handler/featureide/tests/TestFeatureIDETraces.java +++ b/tests/org.eclipse.capra.handler.featureide.tests/src/org/eclipse/capra/handler/featureide/tests/TestFeatureIDETraces.java @@ -93,7 +93,7 @@ public class TestFeatureIDETraces { // Create a trace via the selection view TestHelper.createTraceForCurrentSelectionOfType(TracemodelPackage.eINSTANCE.getRelatedTo()); - assertTrue(TestHelper.thereIsATraceBetween(dummyFile, feature)); + assertTrue(TestHelper.thereIsATraceBetween(feature, dummyFile)); // Clear selection view SelectionView.getOpenedView().clearSelection(); diff --git a/tests/org.eclipse.capra.handler.uml.tests/src/org/eclipse/capra/handler/uml/tests/TestUMLInternalLinks.java b/tests/org.eclipse.capra.handler.uml.tests/src/org/eclipse/capra/handler/uml/tests/TestUMLInternalLinks.java index 04e4c0d3..63cda986 100644 --- a/tests/org.eclipse.capra.handler.uml.tests/src/org/eclipse/capra/handler/uml/tests/TestUMLInternalLinks.java +++ b/tests/org.eclipse.capra.handler.uml.tests/src/org/eclipse/capra/handler/uml/tests/TestUMLInternalLinks.java @@ -56,7 +56,7 @@ public class TestUMLInternalLinks { private static final String EXPECTED_TEXT_FOR_INTERNAL_LINKS = "@startuml\n" + "object \"A : Class\" as o0 #pink\n" + "object \"B : Class\" as o1\n" + "object \"C : Class\" as o2\n" - + "o0--o1: A : Class B : Class : RelatedTo\n" + "o1--o2:true : Generalization\n" + "@enduml\n"; + + "o0--o1: A : Class B : Class : RelatedTo\n" + "o1--o2: true : Generalization\n" + "@enduml\n"; @Before public void init() throws CoreException { diff --git a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestCreateTraceOperation.java b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestCreateTraceOperation.java index 51745b72..d08b0cf0 100644 --- a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestCreateTraceOperation.java +++ b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestCreateTraceOperation.java @@ -31,7 +31,6 @@ import static org.junit.Assert.fail; import java.io.IOException; import java.util.Arrays; import java.util.List; -import java.util.Optional; import org.eclipse.capra.core.adapters.TracePersistenceAdapter; import org.eclipse.capra.core.helpers.ArtifactHelper; @@ -117,15 +116,8 @@ public class TestCreateTraceOperation { IWorkbench workbench = PlatformUI.getWorkbench(); IOperationHistory operationHistory = workbench.getOperationSupport().getOperationHistory(); - CreateTraceOperation createTraceOperation = new CreateTraceOperation("Create trace link", - SelectionView.getOpenedView().getSelection()); - createTraceOperation.setChooseTraceType((traceTypes, selection) -> { - if (traceTypes.contains(traceType)) { - return Optional.of(traceType); - } else { - return Optional.empty(); - } - }); + CreateTraceOperation createTraceOperation = TestHelper + .prepareCreateTraceOperationForCurrentSelectionOfType(traceType); try { assertEquals(operationHistory.execute(createTraceOperation, null, adapter), Status.OK_STATUS); } catch (ExecutionException e) { @@ -152,15 +144,8 @@ public class TestCreateTraceOperation { SelectionView.getOpenedView().dropToSelection(_A); SelectionView.getOpenedView().dropToSelection(_C); - CreateTraceOperation createTraceOperation2 = new CreateTraceOperation("Create trace link", - SelectionView.getOpenedView().getSelection()); - createTraceOperation2.setChooseTraceType((traceTypes, sel) -> { - if (traceTypes.contains(traceType)) { - return Optional.of(traceType); - } else { - return Optional.empty(); - } - }); + CreateTraceOperation createTraceOperation2 = TestHelper + .prepareCreateTraceOperationForCurrentSelectionOfType(traceType); try { assertEquals(operationHistory.execute(createTraceOperation2, null, adapter), Status.OK_STATUS); } catch (ExecutionException e) { diff --git a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestDuplicateLinks.java b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestDuplicateLinks.java index bab73ca6..06b26a1b 100644 --- a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestDuplicateLinks.java +++ b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestDuplicateLinks.java @@ -30,7 +30,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import java.io.IOException; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.eclipse.capra.core.adapters.Connection; @@ -114,38 +114,34 @@ public class TestDuplicateLinks { EClass tlinkA = (EClass) _tm.getEClassifier(T_LINK_NAME_A); - List<EObject> targets = new ArrayList<EObject>(); - targets.add(classB); + List<EObject> origins = Arrays.asList(classA); + List<EObject> targets = Arrays.asList(classB); // create a connection - Connection con1 = new Connection(classA, targets, tlinkA); + Connection con1 = new Connection(origins, targets, tlinkA); // create a second connection with the same content - Connection con2 = new Connection(classA, targets, tlinkA); + Connection con2 = new Connection(origins, targets, tlinkA); // check if the connections are equal assertTrue(con1.equals(con2)); assertEquals(con1.hashCode(), con2.hashCode()); // change the order of artifacts - List<EObject> newTarget = new ArrayList<>(); - newTarget.add(classA); - - // create the connections again - Connection con3 = new Connection(classB, newTarget, tlinkA); + Connection con3 = new Connection(targets, origins, tlinkA); // check if the connections are equal assertTrue(con1.equals(con2) && con1.equals(con3) && con2.equals(con3)); // create a new connection with the second trace type - Connection con4 = new Connection(classB, newTarget, tlinkB); + Connection con4 = new Connection(targets, origins, tlinkB); // check that the connections are not equal assertFalse(con3.equals(con4)); assertNotEquals(con3.hashCode(), con4.hashCode()); // create a connection with differesnt artifact - Connection con5 = new Connection(classC, targets, tlinkA); + Connection con5 = new Connection(Arrays.asList(classC), targets, tlinkA); // check that the conenctions are not equal assertFalse(con5.equals(con1)); diff --git a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestHelper.java b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestHelper.java index 4277c1e4..b666afd8 100644 --- a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestHelper.java +++ b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestHelper.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -263,22 +264,29 @@ public class TestHelper { return (EPackage) rs.getResource(path, true).getContents().get(0); } - /** - * Creates a trace between the objects that are in the Selection view. - * - * @param traceType the type of the trace that is to connect the objects - */ - public static void createTraceForCurrentSelectionOfType(EClass traceType) { - Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + public static CreateTraceOperation prepareCreateTraceOperationForCurrentSelectionOfType(EClass traceType) { CreateTraceOperation operation = new CreateTraceOperation("Create trace link", - SelectionView.getOpenedView().getSelection()); - operation.createTrace(shell, (traceTypes, selection) -> { + Arrays.asList(SelectionView.getOpenedView().getSelection().get(0)), SelectionView.getOpenedView() + .getSelection().subList(1, SelectionView.getOpenedView().getSelection().size())); + operation.setChooseTraceType((traceTypes, selection) -> { if (traceTypes.contains(traceType)) { return Optional.of(traceType); } else { return Optional.empty(); } }); + return operation; + } + + /** + * Creates a trace between the objects that are in the Selection view. + * + * @param traceType the type of the trace that is to connect the objects + */ + public static void createTraceForCurrentSelectionOfType(EClass traceType) { + CreateTraceOperation operation = prepareCreateTraceOperationForCurrentSelectionOfType(traceType); + Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); + operation.createTrace(shell); } /** diff --git a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceHelper.java b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceHelper.java index 45bbee93..921af801 100644 --- a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceHelper.java +++ b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceHelper.java @@ -117,7 +117,7 @@ public class TestTraceHelper { // check that only one link is returned assertTrue(traceLinks.size() == 1); // check that the trace link returned is between file A and file B - assertTrue(traceLinks.get(0).getOrigin().equals(A_B_wrappers.get(0))); + assertTrue(traceLinks.get(0).getOrigins().get(0).equals(A_B_wrappers.get(0))); assertTrue(traceLinks.get(0).getTargets().get(0).equals(A_B_wrappers.get(1))); // create a list with wrappers of file A, B and C @@ -131,10 +131,10 @@ public class TestTraceHelper { // check that only two links are returned assertTrue(traceLinksA_B_C.size() == 2); // check that the first link is between file A and B - assertTrue(traceLinksA_B_C.get(0).getOrigin().equals(A_B_wrappers.get(0))); + assertTrue(traceLinksA_B_C.get(0).getOrigins().get(0).equals(A_B_wrappers.get(0))); assertTrue(traceLinksA_B_C.get(0).getTargets().get(0).equals(A_B_wrappers.get(1))); // check that the second link is between file B and C - assertTrue(traceLinksA_B_C.get(1).getOrigin().equals(A_B_Cwrappers.get(1))); + assertTrue(traceLinksA_B_C.get(1).getOrigins().get(0).equals(A_B_Cwrappers.get(1))); assertTrue(traceLinksA_B_C.get(1).getTargets().get(0).equals(A_B_Cwrappers.get(2))); // Testing edge cases diff --git a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceabiltyMatrix.java b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceabiltyMatrix.java index 92aec13c..c834ac58 100644 --- a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceabiltyMatrix.java +++ b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestTraceabiltyMatrix.java @@ -71,21 +71,21 @@ public class TestTraceabiltyMatrix { private static final String EXPECTED_TEXT_FOR_SELECTED_PACKAGES_DIRECT = "@startuml" + LINE_SEPARATOR + "salt" + LINE_SEPARATOR + "{#" + LINE_SEPARATOR + ".|modelA : EPackage|modelB : EPackage" + LINE_SEPARATOR - + "modelA : EPackage |. |X" + LINE_SEPARATOR + "modelB : EPackage |X |." + LINE_SEPARATOR + "}" + + "modelA : EPackage |. |X" + LINE_SEPARATOR + "modelB : EPackage |. |." + LINE_SEPARATOR + "}" + LINE_SEPARATOR + LINE_SEPARATOR + "@enduml" + LINE_SEPARATOR; private static final String EXPECTED_TEXT_FOR_SELECTED_PACKAGES_TRANSITIVE = "@startuml" + LINE_SEPARATOR + "salt" + LINE_SEPARATOR + "{#" + LINE_SEPARATOR + ".|modelA : EPackage|A : EClass|AA : EClass|modelB : EPackage|B : EClass|BB : EClass" + LINE_SEPARATOR + "modelA : EPackage |. |. |. |X |. |." + LINE_SEPARATOR + "A : EClass |. |. |. |. |X |." + LINE_SEPARATOR - + "AA : EClass |. |. |. |. |. |X" + LINE_SEPARATOR + "modelB : EPackage |X |. |. |. |. |." + LINE_SEPARATOR - + "B : EClass |. |X |. |. |. |." + LINE_SEPARATOR + "BB : EClass |. |. |X |. |. |." + LINE_SEPARATOR + "}" + + "AA : EClass |. |. |. |. |. |X" + LINE_SEPARATOR + "modelB : EPackage |. |. |. |. |. |." + LINE_SEPARATOR + + "B : EClass |. |. |. |. |. |." + LINE_SEPARATOR + "BB : EClass |. |. |. |. |. |." + LINE_SEPARATOR + "}" + LINE_SEPARATOR + LINE_SEPARATOR + "@enduml" + LINE_SEPARATOR; private static final String EXPECTED_TEXT_FOR_SELECTED_CLASSES = "@startuml" + LINE_SEPARATOR + "salt" + LINE_SEPARATOR + "{#" + LINE_SEPARATOR + ".|A : EClass|B : EClass|AA : EClass|BB : EClass" - + LINE_SEPARATOR + "A : EClass |. |X |. |." + LINE_SEPARATOR + "B : EClass |X |. |. |." + LINE_SEPARATOR - + "AA : EClass |. |. |. |X" + LINE_SEPARATOR + "BB : EClass |. |. |X |." + LINE_SEPARATOR + "}" + + LINE_SEPARATOR + "A : EClass |. |X |. |." + LINE_SEPARATOR + "B : EClass |. |. |. |." + LINE_SEPARATOR + + "AA : EClass |. |. |. |X" + LINE_SEPARATOR + "BB : EClass |. |. |. |." + LINE_SEPARATOR + "}" + LINE_SEPARATOR + LINE_SEPARATOR + "@enduml" + LINE_SEPARATOR; @Before diff --git a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestUnitCoreAdaptersConnection.java b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestUnitCoreAdaptersConnection.java index fa3f085e..7385e7a8 100644 --- a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestUnitCoreAdaptersConnection.java +++ b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/TestUnitCoreAdaptersConnection.java @@ -16,6 +16,7 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.eclipse.capra.core.adapters.Connection; @@ -110,22 +111,22 @@ public class TestUnitCoreAdaptersConnection { targetsAll.add(classC); // create a connection - Connection con1 = new Connection(classA, targets, tlinkB); + Connection con1 = new Connection(Arrays.asList(classA), targets, tlinkB); // create a connection - Connection con2 = new Connection(classA, targets, tlinkB); + Connection con2 = new Connection(Arrays.asList(classA), targets, tlinkB); // create a connection - Connection con3 = new Connection(classA, targets, tlinkB); + Connection con3 = new Connection(Arrays.asList(classA), targets, tlinkB); // create a connection - Connection con4 = new Connection(classA, targets, tlinkA); + Connection con4 = new Connection(Arrays.asList(classA), targets, tlinkA); // create a connection - Connection con5 = new Connection(classB, targets, tlinkB); + Connection con5 = new Connection(Arrays.asList(classB), targets, tlinkB); // create a connection - Connection con8 = new Connection(classC, targets, tlinkB); + Connection con8 = new Connection(Arrays.asList(classC), targets, tlinkB); // create a connection - Connection con6 = new Connection(classA, targetsAll, tlinkB); + Connection con6 = new Connection(Arrays.asList(classA), targetsAll, tlinkB); // check if the connections equals not null assertFalse("expected: " + con1 + " equals: " + null, con1.equals(null)); @@ -163,7 +164,7 @@ public class TestUnitCoreAdaptersConnection { targets.remove(0); // create a connection - Connection con7 = new Connection(classA, targets, tlinkB); + Connection con7 = new Connection(Arrays.asList(classA), targets, tlinkB); // check if con is consistent when target is being modified assertTrue(con1.equals(con7)); targetsAll.removeAll(targetsAll.subList(0, 2)); @@ -220,13 +221,13 @@ public class TestUnitCoreAdaptersConnection { targets.add(classC); // create a connection - Connection con1 = new Connection(classA, targets, tlinkA); + Connection con1 = new Connection(Arrays.asList(classA), targets, tlinkA); // create a connection - Connection con2 = new Connection(classA, targets, tlinkA); + Connection con2 = new Connection(Arrays.asList(classA), targets, tlinkA); // create a connection - Connection con3 = new Connection(classA, targetsC, tlinkA); + Connection con3 = new Connection(Arrays.asList(classA), targetsC, tlinkA); // create an empty origin connection Connection emptyOrigin1 = new Connection(null, targets, tlinkA); @@ -236,18 +237,18 @@ public class TestUnitCoreAdaptersConnection { Connection emptyOrigin3 = new Connection(null, targetsC, tlinkA); // create an empty target connection - Connection emptyTargetCon1 = new Connection(classA, null, tlinkA); + Connection emptyTargetCon1 = new Connection(Arrays.asList(classA), null, tlinkA); // create an empty target connection - Connection emptyTargetCon2 = new Connection(classA, null, tlinkA); + Connection emptyTargetCon2 = new Connection(Arrays.asList(classA), null, tlinkA); // create an empty target connection - Connection emptyTargetCon3 = new Connection(classB, null, tlinkA); + Connection emptyTargetCon3 = new Connection(Arrays.asList(classB), null, tlinkA); // create an empty link connection - Connection emptyTLinkCon1 = new Connection(classA, targets, null); + Connection emptyTLinkCon1 = new Connection(Arrays.asList(classA), targets, null); // create an empty link connection - Connection emptyTLinkCon2 = new Connection(classA, targets, null); + Connection emptyTLinkCon2 = new Connection(Arrays.asList(classA), targets, null); // create an empty link connection - Connection emptyTLinkCon3 = new Connection(classB, targets, null); + Connection emptyTLinkCon3 = new Connection(Arrays.asList(classB), targets, null); // check if the hashcode returns the same when invoked on the same object assertEquals(con1.hashCode(), con1.hashCode()); diff --git a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/notification/TestNotificationCMethod.java b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/notification/TestNotificationCMethod.java index b81538b5..f30ade3d 100644 --- a/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/notification/TestNotificationCMethod.java +++ b/tests/org.eclipse.capra.testsuite/src/org/eclipse/capra/testsuite/notification/TestNotificationCMethod.java @@ -109,9 +109,9 @@ public class TestNotificationCMethod { assertTrue(SelectionView.getOpenedView().getSelection().isEmpty()); SelectionView.getOpenedView().dropToSelection(method); SelectionView.getOpenedView().dropToSelection(A); - assertFalse(thereIsATraceBetween(A, method)); + assertFalse(thereIsATraceBetween(method, A)); createTraceForCurrentSelectionOfType(TracemodelPackage.eINSTANCE.getRelatedTo()); - assertTrue(thereIsATraceBetween(A, method)); + assertTrue(thereIsATraceBetween(method, A)); // Get current number of markers IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); |