diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 3a527d997..c5a803943 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -6,6 +6,10 @@ - Add support for `ViewUsages` and `ViewDefinitions` +=== Architectural decision records + +- Support representation only through `ViewUsage` + === Breaking changes === Dependency update @@ -35,6 +39,9 @@ When end-users click on _New Object_ on a semantic element, and select a `ViewUs === New features - https://github.com/eclipse-syson/syson/issues/1237[#1237] [general-view] Add `ViewUsage` graphical node in the General View diagram. +- https://github.com/eclipse-syson/syson/issues/1270[#1270] [explorer-view] Change explorer to link representation behavior to `ViewUsage`: +* Open associated representation when a `ViewUsage` is selected +* Hide representation in the explorer == v2025.4.0 diff --git a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewToolService.java b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewToolService.java index c717242f4..12674aa0d 100644 --- a/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewToolService.java +++ b/backend/views/syson-diagram-common-view/src/main/java/org/eclipse/syson/diagram/common/view/services/ViewToolService.java @@ -58,6 +58,7 @@ import org.eclipse.sirius.components.view.diagram.DiagramDescription; import org.eclipse.sirius.components.view.diagram.ListLayoutStrategyDescription; import org.eclipse.sirius.components.view.emf.IViewRepresentationDescriptionSearchService; +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationMetadata; import org.eclipse.syson.diagram.common.view.nodes.AbstractActionsCompartmentNodeDescriptionProvider; import org.eclipse.syson.services.DeleteService; import org.eclipse.syson.services.ElementInitializerSwitch; @@ -101,6 +102,7 @@ import org.eclipse.syson.sysml.Usage; import org.eclipse.syson.sysml.UseCaseDefinition; import org.eclipse.syson.sysml.UseCaseUsage; +import org.eclipse.syson.sysml.ViewUsage; import org.eclipse.syson.sysml.helper.EMFUtils; import org.eclipse.syson.util.SysMLMetamodelHelper; import org.slf4j.Logger; @@ -152,17 +154,17 @@ public ViewToolService(IIdentityService identityService, IObjectSearchService ob *

* * @param parentElement - * the {@link Element} to add in the diagram + * the {@link Element} to add in the diagram * @param editingContext - * the editing context + * the editing context * @param diagramContext - * the diagram context + * the diagram context * @param parentViewCreationRequest - * the creation request of the parent element (not yet rendered on the diagram) + * the creation request of the parent element (not yet rendered on the diagram) * @param convertedNodes - * the converted nodes + * the converted nodes * @param recursive - * whether the tool should add elements recursively or not + * whether the tool should add elements recursively or not * @return the created element */ public Element addExistingElements(Element parentElement, IEditingContext editingContext, IDiagramContext diagramContext, ViewCreationRequest parentViewCreationRequest, @@ -257,17 +259,17 @@ public Element addExistingElements(Element parentElement, IEditingContext editin *

* * @param parentElement - * the {@link Element} to add in the diagram + * the {@link Element} to add in the diagram * @param editingContext - * the editing context + * the editing context * @param diagramContext - * the diagram context + * the diagram context * @param selectedNode - * the creation request of the parent element (not yet rendered on the diagram) + * the creation request of the parent element (not yet rendered on the diagram) * @param convertedNodes - * the converted nodes + * the converted nodes * @param recursive - * whether the tool should add elements recursively or not + * whether the tool should add elements recursively or not * @return the created element */ public Element addExistingElements(Element parentElement, IEditingContext editingContext, IDiagramContext diagramContext, Node selectedNode, @@ -342,19 +344,19 @@ public Element addExistingElements(Element parentElement, IEditingContext editin * Called by "Drop tool" from General View diagram. * * @param element - * the {@link Element} to drop to a General View diagram. + * the {@link Element} to drop to a General View diagram. * @param editingContext - * the {@link IEditingContext} of the tool. It corresponds to a variable accessible from the variable - * manager. + * the {@link IEditingContext} of the tool. It corresponds to a variable accessible from the variable + * manager. * @param diagramContext - * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable - * manager. + * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable + * manager. * @param selectedNode - * the selected node on which the element has been dropped (may be null if the tool has been called from - * the diagram). It corresponds to a variable accessible from the variable manager. + * the selected node on which the element has been dropped (may be null if the tool has been called from + * the diagram). It corresponds to a variable accessible from the variable manager. * @param convertedNodes - * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to - * a variable accessible from the variable manager. + * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to + * a variable accessible from the variable manager. * @return the input {@link Element}. */ public Element dropElementFromExplorer(Element element, IEditingContext editingContext, IDiagramContext diagramContext, Node selectedNode, @@ -394,6 +396,16 @@ public Element dropElementFromExplorer(Element element, IEditingContext editingC return element; } + public Element dropElementFromExplorer(RepresentationMetadata representationMetadata, IEditingContext editingContext, IDiagramContext diagramContext, Node selectedNode, + Map convertedNodes) { + + Element element = this.objectSearchService.getObject(editingContext, representationMetadata.getTargetObjectId()).filter(ViewUsage.class::isInstance).map(ViewUsage.class::cast).orElse(null); + if (element == null) { + return null; + } + return this.dropElementFromExplorer(element, editingContext, diagramContext, selectedNode, convertedNodes); + } + /** * Drops the provided {@code sourceElement} from the explorer on the given {@code selectedNode} on the diagram. *

@@ -408,17 +420,17 @@ public Element dropElementFromExplorer(Element element, IEditingContext editingC *

* * @param sourceElement - * the source element to drop + * the source element to drop * @param targetElement - * the target of the drop + * the target of the drop * @param editingContext - * the editing context + * the editing context * @param diagramContext - * the diagram context + * the diagram context * @param selectedNode - * the selected node + * the selected node * @param convertedNodes - * the converted nodes + * the converted nodes */ private void dropElementFromExplorerInTarget(Element sourceElement, Element targetElement, IEditingContext editingContext, IDiagramContext diagramContext, Node selectedNode, Map convertedNodes) { @@ -457,22 +469,22 @@ private void dropElementFromExplorerInTarget(Element sourceElement, Element targ * Called by "Drop Node tool" from General View diagram. * * @param droppedElement - * the dropped {@link Element}. + * the dropped {@link Element}. * @param droppedNode - * the dropped {@link Node}. + * the dropped {@link Node}. * @param targetElement - * the new semantic container. + * the new semantic container. * @param targetElement - * the new graphical container. + * the new graphical container. * @param editingContext - * the {@link IEditingContext} of the tool. It corresponds to a variable accessible from the variable - * manager. + * the {@link IEditingContext} of the tool. It corresponds to a variable accessible from the variable + * manager. * @param diagramContext - * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable - * manager. + * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable + * manager. * @param convertedNodes - * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to - * a variable accessible from the variable manager. + * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to + * a variable accessible from the variable manager. * @return the input {@link Element}. */ public Element dropElementFromDiagram(Element droppedElement, Node droppedNode, Element targetElement, Node targetNode, IEditingContext editingContext, IDiagramContext diagramContext, @@ -498,9 +510,9 @@ public Element dropElementFromDiagram(Element droppedElement, Node droppedNode, *

* * @param parent - * the parent in the hierarchy + * the parent in the hierarchy * @param child - * the child in the hierarchy + * the child in the hierarchy */ private void logAncestorError(Element parent, Element child) { final String errorMessage; @@ -522,13 +534,13 @@ private void logAncestorError(Element parent, Element child) { *

* * @param parentViewCreationRequest - * the creation request for the Node to hide the compartment from + * the creation request for the Node to hide the compartment from * @param editingContext - * the editing context + * the editing context * @param diagramContext - * the diagram context + * the diagram context * @param convertedNodes - * the converted nodes + * the converted nodes */ private void hideCompartments(ViewCreationRequest parentViewCreationRequest, IEditingContext editingContext, IDiagramContext diagramContext, Map convertedNodes) { @@ -567,7 +579,7 @@ private void hideCompartments(ViewCreationRequest parentViewCreationRequest, IEd *

* * @param parentElement - * the parent element + * the parent element * @return the list of contained elements that should be rendered */ private List getChildElementsToRender(Element parentElement) { @@ -610,17 +622,17 @@ private List getChildElementsToRender(Element parentElement) *

* * @param element - * the element to create a view from + * the element to create a view from * @param parentElementId - * the identifier of the parent that should contain the created view + * the identifier of the parent that should contain the created view * @param editingContext - * the editing context + * the editing context * @param diagramContext - * the diagram context + * the diagram context * @param convertedNodes - * the converted nodes + * the converted nodes * @param recursive - * whether the creation is recursive + * whether the creation is recursive * @return the element */ private Element addElementInParent(Element element, String parentElementId, IEditingContext editingContext, IDiagramContext diagramContext, @@ -655,9 +667,9 @@ private Element addElementInParent(Element element, String parentElementId, IEdi * the given {@link Namespace}. * * @param ns - * the given {@link Namespace}. + * the given {@link Namespace}. * @param type - * the given type. + * the given type. * @return true if the tool should be available, false otherwise. */ public boolean toolShouldBeAvailable(Namespace ns, String type) { @@ -801,11 +813,11 @@ public Element dropElementFromDiagramInConstraintCompartment(Element droppedElem *

* * @param self - * the current UseCase or Requirement + * the current UseCase or Requirement * @param newSource - * the new UseCase or Requirement + * the new UseCase or Requirement * @param otherEnd - * the Actor connected to the UseCase or Requirement + * the Actor connected to the UseCase or Requirement * @return the Actor */ public Element reconnectSourceNestedActorEdge(Element self, Element newSource, Element otherEnd) { @@ -875,9 +887,9 @@ public Element reconnnectTargetCompositionEdge(Element self, Element oldTarget, *

* * @param self - * the current annotating element + * the current annotating element * @param newTarget - * the new Annotated element + * the new Annotated element * @return the annotating element */ public Element reconnnectTargetAnnotatedEdge(Element self, Element newTarget) { @@ -891,7 +903,7 @@ public Element reconnnectTargetAnnotatedEdge(Element self, Element newTarget) { * Moves the provided {@code usage} in the closest containing package. * * @param usage - * the usage to move + * the usage to move * @return the moved element */ public Element moveToClosestContainingPackage(Usage usage) { @@ -920,19 +932,19 @@ private Package getClosestContainingPackageFrom(Element element) { * Create a new graphical view for an element inside a compartment given its label. * * @param childElement - * the semantic object for which the view is created. + * the semantic object for which the view is created. * @param compartmentName - * the label of the compartment in which the view should be created. + * the label of the compartment in which the view should be created. * @param selectedNode - * the {@link Node} where the tool was triggered. It can be an element or the compartment itself. + * the {@link Node} where the tool was triggered. It can be an element or the compartment itself. * @param editingContext - * the {@link IEditingContext} of the tool + * the {@link IEditingContext} of the tool * @param diagramContext - * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable - * manager. + * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable + * manager. * @param convertedNodes - * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to - * a variable accessible from the variable manager. + * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to + * a variable accessible from the variable manager. */ public Element createViewInFreeFormCompartment(Element childElement, String compartmentName, Node selectedNode, IEditingContext editingContext, @@ -963,17 +975,17 @@ public Element createViewInFreeFormCompartment(Element childElement, String comp * and target. * * @param sourceUsage - * the {@link Feature} used as a source for the transition + * the {@link Feature} used as a source for the transition * @param targetUsage - * the {@link Feature} used as a target for the transition + * the {@link Feature} used as a target for the transition * @param source - * the node of the source + * the node of the source * @param target - * the node of the target + * the node of the target * @param diagramService - * service used to navigate inside the diagram + * service used to navigate inside the diagram * @param editingContext - * the current editing context + * the current editing context * @return the given source {@link Feature}. */ public Feature createTransitionUsage(Feature sourceUsage, Feature targetUsage, Node source, Node target, IDiagramService diagramService, IEditingContext editingContext) { @@ -1043,7 +1055,7 @@ private Element getEdgeSemanticContainer(Node source, Node target, Diagram diagr * <>-> EndFeatureMembership -> RelatedElement = Feature <>-> ReferenceSubsetting -> ReferencedFeature = feature * * @param feature - * The feature to reference subset + * The feature to reference subset * @return */ private EndFeatureMembership createConnectorEndFeatureMembership(Feature feature) { @@ -1062,21 +1074,21 @@ private EndFeatureMembership createConnectorEndFeatureMembership(Feature feature * against possible {@link StateSubactionKind} values to set the new {@link ActionUsage} of the correct kind. * * @param parentState - * The state onto which the action is added + * The state onto which the action is added * @param editingContext - * the {@link IEditingContext} of the tool. It corresponds to a variable accessible from the variable - * manager. + * the {@link IEditingContext} of the tool. It corresponds to a variable accessible from the variable + * manager. * @param diagramContext - * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable - * manager. + * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable + * manager. * @param selectedNode - * the selected node on which the tool has been called. It corresponds to a variable accessible from the - * variable manager. + * the selected node on which the tool has been called. It corresponds to a variable accessible from the + * variable manager. * @param convertedNodes - * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to - * a variable accessible from the variable manager. + * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to + * a variable accessible from the variable manager. * @param actionKind - * The value against which the {@link StateSubactionKind} of the {@link ActionUsage} membership is set. + * The value against which the {@link StateSubactionKind} of the {@link ActionUsage} membership is set. * @return */ public ActionUsage createOwnedAction(Element parentState, IEditingContext editingContext, IDiagramContext diagramContext, Node selectedNode, @@ -1108,23 +1120,23 @@ public ActionUsage createOwnedAction(Element parentState, IEditingContext editin * Called by "New State" tool from StateTransition View StateUsage node. * * @param parentState - * The parent {@link StateDefinition} or {@link StateUsage} + * The parent {@link StateDefinition} or {@link StateUsage} * @param editingContext - * the {@link IEditingContext} of the tool. It corresponds to a variable accessible from the variable - * manager. + * the {@link IEditingContext} of the tool. It corresponds to a variable accessible from the variable + * manager. * @param diagramContext - * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable - * manager. + * the {@link IDiagramContext} of the tool. It corresponds to a variable accessible from the variable + * manager. * @param selectedNode - * the selected node on which the tool has been called. It corresponds to a variable accessible from the - * variable manager. + * the selected node on which the tool has been called. It corresponds to a variable accessible from the + * variable manager. * @param convertedNodes - * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to - * a variable accessible from the variable manager. + * the map of all existing node descriptions in the DiagramDescription of this Diagram. It corresponds to + * a variable accessible from the variable manager. * @param isParallel - * whether or not the created State is set as parallel. + * whether or not the created State is set as parallel. * @param isExhibit - * Whether or not the created State is exhibited or not. + * Whether or not the created State is exhibited or not. * @return the created {@link StateUsage}. */ public StateUsage createChildState(Element parentState, IEditingContext editingContext, IDiagramContext diagramContext, Node selectedNode, @@ -1146,9 +1158,9 @@ public StateUsage createChildState(Element parentState, IEditingContext editingC * Return the real parent {@link Node} given the current object and the selectedNode. * * @param self - * the current object. + * the current object. * @param selectedNode - * the selectedNode (can be a {@link Node} or null (in case of a {@link Diagram}). + * the selectedNode (can be a {@link Node} or null (in case of a {@link Diagram}). * @return the real parent {@link Node} given the current object and the selectedNode. */ public Object getParentViewExpression(Object self, Object selectedNode) { @@ -1165,7 +1177,7 @@ public Object getParentViewExpression(Object self, Object selectedNode) { * Service to retrieve the root elements of the selection dialog of the NamespaceImport creation tool. * * @param editingContext - * the editing context + * the editing context * @return the list of resources that contain at least one {@link Package} */ public List getNamespaceImportSelectionDialogElements(IEditingContext editingContext) { @@ -1175,8 +1187,8 @@ public List getNamespaceImportSelectionDialogElements(IEditingContext .map(IEMFEditingContext::getDomain) .map(EditingDomain::getResourceSet); var resources = optionalResourceSet.map(resourceSet -> resourceSet.getResources().stream() - .filter(resource -> this.containsDirectlyOrIndirectlyInstancesOf(resource, SysmlPackage.eINSTANCE.getPackage())) - .toList()) + .filter(resource -> this.containsDirectlyOrIndirectlyInstancesOf(resource, SysmlPackage.eINSTANCE.getPackage())) + .toList()) .orElseGet(ArrayList::new); return resources.stream().sorted((r1, r2) -> this.getResourceName(r1).compareTo(this.getResourceName(r2))).toList(); } @@ -1185,7 +1197,7 @@ public List getNamespaceImportSelectionDialogElements(IEditingContext * Service to retrieve the children of a given element in the selection dialog of the NamespaceImport creation tool. * * @param self - * an element of the tree + * an element of the tree * @return the list of {@link Package} element found under the given root element. */ public List getNamespaceImportSelectionDialogChildren(Object self) { @@ -1251,7 +1263,7 @@ private List findClosestPackageInChildren(Element element) { * Provides the root elements in the tree of the selection dialog for the StakeholderParameter creation tool. * * @param editingContext - * the (non-{@code null}) {@link IEditingContext}. + * the (non-{@code null}) {@link IEditingContext}. * @return the (non-{@code null}) {@link List} of all {@link Resource} that contain at least one {@link PartUsage}. */ public List getStakeholderSelectionDialogElements(IEditingContext editingContext) { @@ -1262,9 +1274,9 @@ public List getStakeholderSelectionDialogElements(IEditingContext edit * Provides the children of element in the tree of the selection dialog for the StakeholderParameter creation tool. * * @param selectionDialogTreeElement - * a (non-{@code null}) selection dialog tree element. + * a (non-{@code null}) selection dialog tree element. * @return the (non-{@code null}) {@link List} of all children that contain (possibly indirectly) or are - * {@link PartUsage}. + * {@link PartUsage}. */ public List getStakeholderSelectionDialogChildren(Object selectionDialogTreeElement) { return this.getChildrenWithInstancesOf(selectionDialogTreeElement, SysmlPackage.eINSTANCE.getPartUsage()); @@ -1274,7 +1286,7 @@ public List getStakeholderSelectionDialogChildren(Object selec * Provides the root elements in the tree of the selection dialog for the SubjectParameter creation tool. * * @param editingContext - * the (non-{@code null}) {@link IEditingContext}. + * the (non-{@code null}) {@link IEditingContext}. * @return the (non-{@code null}) {@link List} of all {@link Resource} that contain at least one {@link Type}. */ public List getSubjectSelectionDialogElements(IEditingContext editingContext) { @@ -1285,9 +1297,9 @@ public List getSubjectSelectionDialogElements(IEditingContext editingC * Provides the children of element in the tree of the selection dialog for the SubjectParameter creation tool. * * @param selectionDialogTreeElement - * a (non-{@code null}) selection dialog tree element. + * a (non-{@code null}) selection dialog tree element. * @return the (non-{@code null}) {@link List} of all children that contain (possibly indirectly) or are - * {@link Usage}. + * {@link Usage}. */ public List getSubjectSelectionDialogChildren(Object selectionDialogTreeElement) { return this.getChildrenWithInstancesOf(selectionDialogTreeElement, SysmlPackage.eINSTANCE.getUsage()); @@ -1297,7 +1309,7 @@ public List getSubjectSelectionDialogChildren(Object selection * Provides the root elements in the tree of the selection dialog for the ActorParameter creation tool. * * @param editingContext - * the (non-{@code null}) {@link IEditingContext}. + * the (non-{@code null}) {@link IEditingContext}. * @return the (non-{@code null}) {@link List} of all {@link Resource} that contain at least one {@link PartUsage}. */ public List getActorSelectionDialogElements(IEditingContext editingContext) { @@ -1308,9 +1320,9 @@ public List getActorSelectionDialogElements(IEditingContext editingCon * Provides the children of element in the tree of the selection dialog for the ActorParameter creation tool. * * @param selectionDialogTreeElement - * a (non-{@code null}) selection dialog tree element. + * a (non-{@code null}) selection dialog tree element. * @return the (non-{@code null}) {@link List} of all children that contain (possibly indirectly) or are - * {@link PartUsage}. + * {@link PartUsage}. */ public List getActorSelectionDialogChildren(Object selectionDialogTreeElement) { return this.getChildrenWithInstancesOf(selectionDialogTreeElement, SysmlPackage.eINSTANCE.getPartUsage()); @@ -1320,7 +1332,7 @@ public List getActorSelectionDialogChildren(Object selectionDi * Provides the root elements in the tree of the selection dialog for the State sub actions creation tool. * * @param editingContext - * the (non-{@code null}) {@link IEditingContext}. + * the (non-{@code null}) {@link IEditingContext}. * @return the (non-{@code null}) {@link List} of all {@link Resource} that contain at least one {@link ActionUsage}. */ public List getStateSubactionReferenceSelectionDialogElements(IEditingContext editingContext) { @@ -1331,7 +1343,7 @@ public List getStateSubactionReferenceSelectionDialogElements(IEditing * Provides the children of element in the tree of the selection dialog for the State sub actions creation tool. * * @param selectionDialogTreeElement - * a (non-{@code null}) selection dialog tree element. + * a (non-{@code null}) selection dialog tree element. * @return the (non-{@code null}) {@link List} of all children that contain (possibly indirectly) an {@link ActionUsage}. */ public List getStateSubactionReferenceSelectionDialogChildren(Object selectionDialogTreeElement) { @@ -1347,8 +1359,8 @@ private List getAllResourcesWithInstancesOf(IEditingContext editingCon .map(IEMFEditingContext::getDomain) .map(EditingDomain::getResourceSet); var resourcesContainingPartUsage = maybeResourceSet.map(resourceSet -> resourceSet.getResources().stream() - .filter(resource -> this.containsDirectlyOrIndirectlyInstancesOf(resource, eClassifier)) - .toList()) + .filter(resource -> this.containsDirectlyOrIndirectlyInstancesOf(resource, eClassifier)) + .toList()) .orElseGet(ArrayList::new); return resourcesContainingPartUsage.stream().sorted(Comparator.comparing(r -> this.getResourceName(r))).toList(); } diff --git a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/SysONExplorerTreeDescriptionProvider.java b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/SysONExplorerTreeDescriptionProvider.java index 5470b36c6..cec103446 100644 --- a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/SysONExplorerTreeDescriptionProvider.java +++ b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/SysONExplorerTreeDescriptionProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2024 Obeo. + * Copyright (c) 2024, 2025 Obeo. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -67,7 +67,7 @@ private TreeDescription build() { .preconditionExpression("aql:false") .selectableExpression("aql:self.isSelectable()") .titleExpression(SYSON_EXPLORER) - .treeItemIdExpression("aql:self.getTreeItemId()") + .treeItemIdExpression("aql:self.getTreeItemId(editingContext)") .treeItemObjectExpression("aql:id.getTreeItemObject(editingContext)") .treeItemLabelDescriptions(this.createDefaultStyle()) .build(); diff --git a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/ComposedSysONExplorerService.java b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/ComposedSysONExplorerService.java index 71212815d..4a113f07d 100644 --- a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/ComposedSysONExplorerService.java +++ b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/ComposedSysONExplorerService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2024 Obeo. + * Copyright (c) 2024, 2025 Obeo. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -42,10 +42,10 @@ public ComposedSysONExplorerService(List explorer } @Override - public String getTreeItemId(Object self) { + public String getTreeItemId(Object self, IEditingContext editingContext) { return this.getDelegate(self) .map(delegate -> delegate.getTreeItemId(self)) - .orElseGet(() -> this.defaultExplorerService.getTreeItemId(self)); + .orElseGet(() -> this.defaultExplorerService.getTreeItemId(self, editingContext)); } @Override diff --git a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/SysONDefaultExplorerServices.java b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/SysONDefaultExplorerServices.java index 9cd7f46a4..cef17d567 100644 --- a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/SysONDefaultExplorerServices.java +++ b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/SysONDefaultExplorerServices.java @@ -15,6 +15,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.UUID; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EObject; @@ -22,14 +23,17 @@ import org.eclipse.sirius.components.core.api.IContentService; import org.eclipse.sirius.components.core.api.IEditingContext; import org.eclipse.sirius.components.core.api.IIdentityService; +import org.eclipse.sirius.components.core.api.IObjectService; import org.eclipse.sirius.web.application.UUIDParser; import org.eclipse.sirius.web.application.editingcontext.EditingContext; import org.eclipse.sirius.web.application.views.explorer.services.api.IExplorerServices; +import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.RepresentationMetadata; import org.eclipse.sirius.web.domain.boundedcontexts.representationdata.services.api.IRepresentationMetadataSearchService; import org.eclipse.syson.services.UtilService; import org.eclipse.syson.services.api.ISysONResourceService; import org.eclipse.syson.sysml.Element; import org.eclipse.syson.sysml.Namespace; +import org.eclipse.syson.sysml.ViewUsage; import org.eclipse.syson.sysml.util.ElementUtil; import org.eclipse.syson.tree.explorer.view.fragments.LibrariesDirectory; import org.eclipse.syson.tree.explorer.view.services.api.ISysONDefaultExplorerService; @@ -57,17 +61,20 @@ public class SysONDefaultExplorerServices implements ISysONDefaultExplorerServic private final ISysONExplorerFilterService filterService; private final UtilService utilService = new UtilService(); - + private final ISysONResourceService sysONResourceService; + private final IObjectService objectService; + public SysONDefaultExplorerServices(IIdentityService identityService, IContentService contentService, IRepresentationMetadataSearchService representationMetadataSearchService, IExplorerServices explorerServices, - ISysONExplorerFilterService filterService, final ISysONResourceService sysONResourceService) { + ISysONExplorerFilterService filterService, final ISysONResourceService sysONResourceService, IObjectService objectService) { this.identityService = Objects.requireNonNull(identityService); this.contentService = Objects.requireNonNull(contentService); this.representationMetadataSearchService = Objects.requireNonNull(representationMetadataSearchService); this.explorerServices = Objects.requireNonNull(explorerServices); this.filterService = Objects.requireNonNull(filterService); this.sysONResourceService = Objects.requireNonNull(sysONResourceService); + this.objectService = Objects.requireNonNull(objectService); } @Override @@ -89,10 +96,22 @@ public List getElements(IEditingContext editingContext, List act } @Override - public String getTreeItemId(Object self) { + public String getTreeItemId(Object self, IEditingContext editingContext) { String id = null; if (self instanceof ISysONExplorerFragment fragment) { id = fragment.getId(); + } else if (self instanceof ViewUsage viewUsage) { + var optionalSemanticDataId = new UUIDParser().parse(editingContext.getId()); + if (optionalSemanticDataId.isPresent()) { + String viewUsageId = this.identityService.getId(viewUsage); + id = this.representationMetadataSearchService.findAllRepresentationMetadataBySemanticDataAndTargetObjectId(AggregateReference.to(optionalSemanticDataId.get()), viewUsageId) + .stream() + .map(RepresentationMetadata::getId) + .filter(Objects::nonNull) + .map(UUID::toString) + .findAny() + .orElse(viewUsageId); + } } else { id = this.explorerServices.getTreeItemId(self); } @@ -135,33 +154,27 @@ public boolean hasChildren(Object self, IEditingContext editingContext, List contents = this.filterService.applyFilters(this.contentService.getContents(self), activeFilterIds); - hasChildren = !contents.isEmpty() && contents.stream().anyMatch(e -> !(e instanceof EAnnotation)) - || this.hasRepresentation(element, editingContext); - } else { - hasChildren = explorerServices.hasChildren(self, editingContext); + hasChildren = !contents.isEmpty() && contents.stream().anyMatch(e -> !(e instanceof EAnnotation)); + } else if (self instanceof EObject eObject) { + hasChildren = !eObject.eContents().isEmpty(); } return hasChildren; } - private boolean hasRepresentation(EObject self, IEditingContext editingContext) { - var optionalSemanticDataId = new UUIDParser().parse(editingContext.getId()); - if (optionalSemanticDataId.isPresent()) { - String id = this.identityService.getId(self); - return this.representationMetadataSearchService.existAnyRepresentationMetadataForSemanticDataAndTargetObjectId(AggregateReference.to(optionalSemanticDataId.get()), id); - } - return false; - } - @Override public List getChildren(Object self, IEditingContext editingContext, List expandedIds, List activeFilterIds) { List result = new ArrayList<>(); - String id = this.getTreeItemId(self); + String id = this.getTreeItemId(self, editingContext); if (self instanceof ISysONExplorerFragment fragment) { if (expandedIds.contains(id)) { result.addAll(fragment.getChildren(editingContext, expandedIds, activeFilterIds)); } + } else if (self instanceof ViewUsage) { + if (expandedIds.contains(id)) { + result.addAll(this.objectService.getContents(self)); + } } else { - result.addAll(this.explorerServices.getDefaultChildren(self, editingContext, expandedIds)); + result.addAll(this.explorerServices.getDefaultChildren(self, editingContext, expandedIds).stream().filter(child -> !(child instanceof RepresentationMetadata)).toList()); } result = this.filterService.applyFilters(result, activeFilterIds); @@ -201,10 +214,10 @@ public boolean isEditable(Object self) { } else if (self instanceof Resource resource) { result = !(this.filterService.isUserLibrary(resource)) && resource.getContents().stream() - .filter(Namespace.class::isInstance) - .map(Namespace.class::cast) - .flatMap(namespace -> namespace.getOwnedElement().stream()) - .noneMatch(ElementUtil::isFromStandardLibrary); + .filter(Namespace.class::isInstance) + .map(Namespace.class::cast) + .flatMap(namespace -> namespace.getOwnedElement().stream()) + .noneMatch(ElementUtil::isFromStandardLibrary); } return result; } diff --git a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/api/ISysONDefaultExplorerService.java b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/api/ISysONDefaultExplorerService.java index 1cd903877..d3e0b35e3 100644 --- a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/api/ISysONDefaultExplorerService.java +++ b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/api/ISysONDefaultExplorerService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2024 Obeo. + * Copyright (c) 2024, 2025 Obeo. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -23,7 +23,7 @@ */ public interface ISysONDefaultExplorerService { - String getTreeItemId(Object self); + String getTreeItemId(Object self, IEditingContext editingContext); String getKind(Object self); diff --git a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/api/ISysONExplorerService.java b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/api/ISysONExplorerService.java index 4484b523c..bf6b85193 100644 --- a/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/api/ISysONExplorerService.java +++ b/backend/views/syson-tree-explorer-view/src/main/java/org/eclipse/syson/tree/explorer/view/services/api/ISysONExplorerService.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2024 Obeo. + * Copyright (c) 2024, 2025 Obeo. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at @@ -23,7 +23,7 @@ */ public interface ISysONExplorerService { - String getTreeItemId(Object self); + String getTreeItemId(Object self, IEditingContext editingContext); String getKind(Object self); diff --git a/backend/views/syson-tree-explorer-view/src/test/java/org/eclipse/syson/tree/explorer/view/services/SysONDefaultExplorerServicesTest.java b/backend/views/syson-tree-explorer-view/src/test/java/org/eclipse/syson/tree/explorer/view/services/SysONDefaultExplorerServicesTest.java index d4ffdedd6..e62efef73 100644 --- a/backend/views/syson-tree-explorer-view/src/test/java/org/eclipse/syson/tree/explorer/view/services/SysONDefaultExplorerServicesTest.java +++ b/backend/views/syson-tree-explorer-view/src/test/java/org/eclipse/syson/tree/explorer/view/services/SysONDefaultExplorerServicesTest.java @@ -56,16 +56,14 @@ /** * Tests the {@link SysONExplorerFilterService} class. - * + * * @author dvojtise */ public class SysONDefaultExplorerServicesTest { + private final ISysONResourceService sysONResourceService = new SysONResourceService(); private static EditingContext editingContext; - private SysONDefaultExplorerServices sysONDefaultExplorerServices; - - private final ISysONResourceService sysONResourceService = new SysONResourceService(); @BeforeAll static void createEditingContext() { @@ -99,9 +97,9 @@ public void hasChildrenCanHandleNonSysmlContent() { EAttribute c1a2 = EcoreFactory.eINSTANCE.createEAttribute(); c1.getEStructuralFeatures().add(c1a2); - assertThat(sysONDefaultExplorerServices.hasChildren(ePackage, editingContext, List.of(), List.of())).isTrue(); - assertThat(sysONDefaultExplorerServices.hasChildren(c1, editingContext, List.of(), List.of())).isTrue(); - assertThat(sysONDefaultExplorerServices.hasChildren(c1a1, editingContext, List.of(), List.of())).isFalse(); + assertThat(this.sysONDefaultExplorerServices.hasChildren(ePackage, editingContext, List.of(), List.of())).isTrue(); + assertThat(this.sysONDefaultExplorerServices.hasChildren(c1, editingContext, List.of(), List.of())).isTrue(); + assertThat(this.sysONDefaultExplorerServices.hasChildren(c1a1, editingContext, List.of(), List.of())).isFalse(); } /** @@ -163,7 +161,8 @@ public boolean test(Object arg0) { ISysONExplorerFilterService filterService = new SysONExplorerFilterService(this.sysONResourceService); - sysONDefaultExplorerServices = new SysONDefaultExplorerServices(identityService, contentService, representationMetadataSearchService, explorerServices, filterService, this.sysONResourceService); + this.sysONDefaultExplorerServices = new SysONDefaultExplorerServices(identityService, contentService, representationMetadataSearchService, explorerServices, filterService, + this.sysONResourceService, new IObjectService.NoOp()); } } diff --git a/doc/adrs/002_support_representation_only_on_viewusage.Adoc b/doc/adrs/002_support_representation_only_on_viewusage.Adoc new file mode 100644 index 000000000..168aa2c1f --- /dev/null +++ b/doc/adrs/002_support_representation_only_on_viewusage.Adoc @@ -0,0 +1,25 @@ += ADR-002 - Support representation only through ViewUsage + +== Context + +In the SysMLv2 specification, the `ViewDefinition` concept allows defining how to render elements (textual, graphical...) and `ViewUsage` is an instance of a `ViewDefinition`. + +== Decision + +* Explorer in SysON should not provide representation anymore. +Change the behavior of the Sysml custom explorer defined in `SysONExplorerTreeDescriptionProvider` to filter representation from children. + +* `ViewUsage` should open child representation. +A `ViewUsage` can only manage exactly one representation. + +NOTE: The limitation of a single representation per `ViewUsage` should be ensured by the representation creation mechanism that automatically creates a `ViewUsage` as parent. +In the same way, the creation of a `ViewUsage` must automatically create a representation as its child. + +To open a representation, the `selection` must be set to the representation id. +Change the behavior in `SysONExplorerTreeDescriptionProvider` to return by the `treeItemIdExpression` the representation id for `ViewUsage` elements. +The problem with changing only the `treeId` so that it points to the representation id instead of the semantic object id is that all other mechanisms (like the tree's +`getChildren` or `dropElementFromExplorer`, for example) no longer work. +All these mechanisms need to be customized to manage `ViewUsage`. + +NOTE: When selecting a `ViewUsage`, the detail views only display properties from the representation. + diff --git a/doc/content/modules/user-manual/pages/release-notes/2025.6.0.adoc b/doc/content/modules/user-manual/pages/release-notes/2025.6.0.adoc index a6c498066..232bc2b74 100644 --- a/doc/content/modules/user-manual/pages/release-notes/2025.6.0.adoc +++ b/doc/content/modules/user-manual/pages/release-notes/2025.6.0.adoc @@ -30,6 +30,10 @@ Publishing a project with a dependency to a library now correctly produces a lib image::view-usage-nodes.png[ViewUsage nodes, width=65%,height=65%] +- Diagram representations like _General View_ are no longer directly available in the tree explorer. +They are now managed through dedicated `ViewUsage` element. +To open a diagram, you should now select the `ViewUsage` in the explorer. + == Improvements