Skip to content

Commit

Permalink
[802] Handle imported package elements in diagrams
Browse files Browse the repository at this point in the history
Bug: eclipse-syson#802
Signed-off-by: Jerome Gout <[email protected]>
  • Loading branch information
jerome-obeo authored and AxelRICHARD committed Nov 7, 2024
1 parent c9bbe6a commit bba895d
Show file tree
Hide file tree
Showing 51 changed files with 2,604 additions and 74 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

=== New features

- https://github.com/eclipse-syson/syson/issues/802[#802] [diagrams] Handle imported package elements in diagrams.


== v2024.11.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ private FormDescription createDetailsView() {
pageCore.setPreconditionExpression("");
pageCore.setLabelExpression("Core");
pageCore.getGroups().add(this.createCorePropertiesGroup());
pageCore.getGroups().add(this.createExtraMembershipPropertiesGroup());
pageCore.getGroups().add(this.createVisibilityPropertyGroup());
pageCore.getGroups().add(this.createExtraRedefinitionPropertiesGroup());
pageCore.getGroups().add(this.createExtraStatesubactionMembershipKindPropertiesGroup());
pageCore.getGroups().add(this.createExtraSubclassificationPropertiesGroup());
Expand Down Expand Up @@ -341,22 +341,22 @@ private GroupDescription createExtraRequirementConstraintMembershipPropertiesGro
return group;
}

private GroupDescription createExtraMembershipPropertiesGroup() {
private GroupDescription createVisibilityPropertyGroup() {
GroupDescription group = FormFactory.eINSTANCE.createGroupDescription();
group.setDisplayMode(GroupDisplayMode.LIST);
group.setName(MEMBERSHIP_PROPERTIES);
group.setLabelExpression("");
group.setSemanticCandidatesExpression("aql:self.eContainer()->filter(sysml::Membership)");
group.setSemanticCandidatesExpression(AQLUtils.getSelfServiceCallExpression("getVisibilityPropertyOwner"));

RadioDescription radio = FormFactory.eINSTANCE.createRadioDescription();
radio.setName("ExtraRadioVisibilityWidget");
radio.setLabelExpression("Visibility");
radio.setCandidatesExpression("aql:self.getEnumCandidates('" + SysmlPackage.eINSTANCE.getMembership_Visibility().getName() + CLOSING_QUOTE_CLOSING_PARENTHESIS);
radio.setCandidatesExpression(AQLUtils.getSelfServiceCallExpression("getVisibilityEnumLiterals"));
radio.setCandidateLabelExpression("aql:candidate.name");
radio.setValueExpression("aql:self.getEnumValue('" + SysmlPackage.eINSTANCE.getMembership_Visibility().getName() + CLOSING_QUOTE_CLOSING_PARENTHESIS);
radio.setValueExpression(AQLUtils.getSelfServiceCallExpression("getVisibilityValue"));
radio.setIsEnabledExpression(AQL_NOT_SELF_IS_READ_ONLY);
ChangeContext setNewValueOperation = ViewFactory.eINSTANCE.createChangeContext();
setNewValueOperation.setExpression("aql:self.setNewValue('" + SysmlPackage.eINSTANCE.getMembership_Visibility().getName() + "', newValue.instance)");
setNewValueOperation.setExpression(AQLUtils.getSelfServiceCallExpression("setVisibilityValue", "newValue.instance"));
radio.getBody().add(setNewValueOperation);

group.getChildren().add(radio);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*******************************************************************************
* Copyright (c) 2024 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.syson.application.nodes;

import java.text.MessageFormat;
import java.util.Objects;

import org.eclipse.sirius.components.annotations.Immutable;
import org.eclipse.sirius.components.diagrams.INodeStyle;
import org.eclipse.sirius.components.diagrams.LineStyle;

/**
* The SysML imported package node style. This code has been fully inspired from {@link SysMLPackageNodeStyle}.
*
* @author Jerome Gout
*/
@Immutable
public final class SysMLImportedPackageNodeStyle implements INodeStyle {

private String background;

private String borderColor;

private int borderSize;

private LineStyle borderStyle;

private SysMLImportedPackageNodeStyle() {
// Prevent instantiation
}

public static Builder newSysMLImportedPackageNodeStyle() {
return new Builder();
}

public String getBackground() {
return this.background;
}

public String getBorderColor() {
return this.borderColor;
}

public int getBorderSize() {
return this.borderSize;
}

public LineStyle getBorderStyle() {
return this.borderStyle;
}

@Override
public String toString() {
String pattern = "{0} '{'color: {1}, border: '{' background: {2}, size: {3}, style: {4} '}''}'";
return MessageFormat.format(pattern, this.getClass().getSimpleName(), this.background, this.borderColor, this.borderSize, this.borderStyle);
}

/**
* The builder used to create the imported package node style.
*
* @author Jerome Gout
*/
@SuppressWarnings("checkstyle:HiddenField")
public static final class Builder {

private String background;

private String borderColor;

private int borderSize;

private LineStyle borderStyle;

private Builder() {
// Prevent instantiation
}

public Builder background(String background) {
this.background = Objects.requireNonNull(background);
return this;
}

public Builder borderColor(String borderColor) {
this.borderColor = Objects.requireNonNull(borderColor);
return this;
}

public Builder borderSize(int borderSize) {
this.borderSize = borderSize;
return this;
}

public Builder borderStyle(LineStyle borderStyle) {
this.borderStyle = Objects.requireNonNull(borderStyle);
return this;
}

public SysMLImportedPackageNodeStyle build() {
SysMLImportedPackageNodeStyle nodeStyleDescription = new SysMLImportedPackageNodeStyle();
nodeStyleDescription.background = Objects.requireNonNull(this.background);
nodeStyleDescription.borderColor = Objects.requireNonNull(this.borderColor);
nodeStyleDescription.borderSize = this.borderSize;
nodeStyleDescription.borderStyle = Objects.requireNonNull(this.borderStyle);
return nodeStyleDescription;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*******************************************************************************
* Copyright (c) 2024 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
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.syson.application.nodes;

import java.util.Optional;

import org.eclipse.sirius.components.diagrams.INodeStyle;
import org.eclipse.sirius.components.diagrams.LineStyle;
import org.eclipse.sirius.components.view.FixedColor;
import org.eclipse.sirius.components.view.diagram.NodeStyleDescription;
import org.eclipse.sirius.components.view.emf.diagram.INodeStyleProvider;
import org.eclipse.syson.sysmlcustomnodes.SysMLImportedPackageNodeStyleDescription;
import org.springframework.stereotype.Service;

/**
* This class provides style information for the imported package custom node.
* This code has been fully inspired from {@link SysMLPackageNodeStyleProvider}.
*
* @author Jerome Gout
*/
@Service
public class SysMLImportedPackageNodeStyleProvider implements INodeStyleProvider {

public static final String NODE_SYSML_IMPORTED_PACKAGE = "customnode:sysmlimportedpackage";

@Override
public Optional<String> getNodeType(NodeStyleDescription nodeStyle) {
if (nodeStyle instanceof SysMLImportedPackageNodeStyleDescription) {
return Optional.of(NODE_SYSML_IMPORTED_PACKAGE);
}
return Optional.empty();
}

@Override
public Optional<INodeStyle> createNodeStyle(NodeStyleDescription nodeStyle, Optional<String> optionalEditingContextId) {
Optional<INodeStyle> iNodeStyle = Optional.empty();
Optional<String> nodeType = this.getNodeType(nodeStyle);
if (nodeType.isPresent()) {
return Optional.of(SysMLImportedPackageNodeStyle.newSysMLImportedPackageNodeStyle()
.background(Optional.ofNullable(((SysMLImportedPackageNodeStyleDescription) nodeStyle).getBackground())
.filter(FixedColor.class::isInstance)
.map(FixedColor.class::cast)
.map(FixedColor::getValue)
.orElse("transparent"))
.borderColor(Optional.ofNullable(nodeStyle.getBorderColor())
.filter(FixedColor.class::isInstance)
.map(FixedColor.class::cast)
.map(FixedColor::getValue)
.orElse("black"))
.borderSize(nodeStyle.getBorderSize())
.borderStyle(LineStyle.valueOf(nodeStyle.getBorderLineStyle().getLiteral())).build());
}

return iNodeStyle;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ public List<EStructuralFeature> caseNamespaceImport(NamespaceImport object) {
features.add(SysmlPackage.eINSTANCE.getNamespaceImport_ImportedNamespace());
features.add(SysmlPackage.eINSTANCE.getImport_IsImportAll());
features.add(SysmlPackage.eINSTANCE.getImport_IsRecursive());
features.add(SysmlPackage.eINSTANCE.getImport_Visibility());
return features;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.eclipse.syson.sysml.FeatureReferenceExpression;
import org.eclipse.syson.sysml.FeatureTyping;
import org.eclipse.syson.sysml.FeatureValue;
import org.eclipse.syson.sysml.Import;
import org.eclipse.syson.sysml.Membership;
import org.eclipse.syson.sysml.ParameterMembership;
import org.eclipse.syson.sysml.ReferenceSubsetting;
Expand Down Expand Up @@ -184,7 +185,7 @@ public boolean isReadOnly(Element element, EStructuralFeature eStructuralFeature
isReadOnly = isReadOnly || this.isReadOnly(element);
if ((element instanceof StateUsage && SysmlPackage.eINSTANCE.getStateUsage_IsParallel().equals(eStructuralFeature))
|| (element instanceof StateDefinition && SysmlPackage.eINSTANCE.getStateDefinition_IsParallel().equals(eStructuralFeature))) {
isReadOnly = isReadOnly || ((Type) element).getOwnedFeature().stream().filter(TransitionUsage.class::isInstance).findAny().isPresent();
isReadOnly = isReadOnly || ((Type) element).getOwnedFeature().stream().anyMatch(TransitionUsage.class::isInstance);
} else if (element instanceof FeatureMembership && SysmlPackage.eINSTANCE.getFeaturing_Feature().equals(eStructuralFeature)) {
isReadOnly = true;
}
Expand Down Expand Up @@ -393,12 +394,11 @@ public boolean setAcceptActionUsagePayloadParameter(AcceptActionUsage acceptActi
if (newPayloadParameter instanceof Type newType) {
var payloadParam = acceptActionUsage.getPayloadParameter();
if (payloadParam != null) {
var ft = payloadParam.getOwnedRelationship().stream()
payloadParam.getOwnedRelationship().stream()
.filter(FeatureTyping.class::isInstance)
.map(FeatureTyping.class::cast)
.findFirst()
.orElse(null);
ft.setType(newType);
.ifPresent(ft -> ft.setType(newType));
return true;
}
}
Expand All @@ -409,7 +409,7 @@ public boolean setTransitionSourceParameter(TransitionUsage transitionUsage, Ele
if (newSource instanceof ActionUsage au) {
// Update transition source
transitionUsage.getOwnedMembership().stream()
.filter(Membership.class::isInstance)
.filter(Objects::nonNull)
.map(Membership.class::cast)
.findFirst()
.ifPresent(mem -> mem.setMemberElement(au));
Expand Down Expand Up @@ -505,7 +505,7 @@ private Comment getComment(Element self) {
EList<Annotation> ownedAnnotations = self.getOwnedAnnotation();
if (!ownedAnnotations.isEmpty()) {
Optional<Comment> firstComment = ownedAnnotations.stream()
.map(annotation -> annotation.getAnnotatingElement())
.map(Annotation::getAnnotatingElement)
.filter(Comment.class::isInstance)
.map(Comment.class::cast)
.filter(c -> !(c instanceof Documentation))
Expand Down Expand Up @@ -552,6 +552,67 @@ public Element setNewDocumentationValue(Element self, String newValue) {
return self;
}

/**
* Returns the element that owns the visibility feature of the given element.
*
* @param self
* An element for which the visibility owner is being searched.
* @return the element that owns the visibility feature of the given element
*/
public Element getVisibilityPropertyOwner(Element self) {
if (!(self instanceof Import) && (self.eContainer() instanceof Membership membership)) {
return membership;
}
return null;
}

/**
* Returns the enumeration literals for the visibility feature of the given element.
*
* @param self
* An element for which the list of visibility literals are being searched.
* @return the enumeration literals for the visibility feature of the given element.
*/
public List<EEnumLiteral> getVisibilityEnumLiterals(Element self) {
List<EEnumLiteral> result = List.of();
if (self instanceof Membership membership) {
result = this.getEnumCandidates(membership, SysmlPackage.eINSTANCE.getMembership_Visibility().getName());
}
return result;
}

/**
* Returns the visibility value of the given element.
*
* @param self
* An element for which the list of visibility literals are being searched.
* @return the current value of the visibility feature of the given element.
*/
public EEnumLiteral getVisibilityValue(Element self) {
EEnumLiteral result = null;
if (self instanceof Membership membership) {
result = this.getEnumValue(membership, SysmlPackage.eINSTANCE.getMembership_Visibility().getName());
}
return result;
}

/**
* Sets the visibility value of the given element.
*
* @param self
* An element for which the list of visibility literals are being searched.
* @param newValue
* the value to set.
* @return <code>true</code> if the visibility feature of the given element has been properly set and <code>false</code> otherwise.
*/
public boolean setVisibilityValue(Element self, Object newValue) {
boolean result = false;
if (self instanceof Membership membership) {
result = this.setNewValue(membership, SysmlPackage.eINSTANCE.getMembership_Visibility().getName(), newValue);
}
return result;
}

private BiFunction<Element, EStructuralFeature, String> getLabelProvider() {
return new EStructuralFeatureLabelProvider(this.composedAdapterFactory);
}
Expand Down Expand Up @@ -693,5 +754,4 @@ private void checkAndRepairAcceptActionUsageReceiver(AcceptActionUsage aau) {
receiverReturn.getOwnedRelatedElement().add(receiverFeature);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ type SysMLPackageNodeStyle {
background: String!
}

extend union INodeStyle = SysMLImportedPackageNodeStyle

type SysMLImportedPackageNodeStyle {
borderColor: String!
borderSize: Int!
borderStyle: LineStyle!
background: String!
}

extend union INodeStyle = SysMLNoteNodeStyle

type SysMLNoteNodeStyle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ private Collection<String> collectAQLExpressionsInDiagramDescription(DiagramDesc
.map(ChangeContext::getExpression)
.forEach(expressions::add);
}
if (diagramTool instanceof NodeTool nodeTool) {
if (nodeTool.getDialogDescription() instanceof SelectionDialogDescription selectionDialogDescription) {
expressions.add(selectionDialogDescription.getSelectionDialogTreeDescription().getElementsExpression());
expressions.add(selectionDialogDescription.getSelectionDialogTreeDescription().getChildrenExpression());
expressions.add(selectionDialogDescription.getSelectionDialogTreeDescription().getIsSelectableExpression());
}
}
}

EMFUtils.allContainedObjectOfType(diagramDescription, NodeDescription.class)
Expand Down
Loading

0 comments on commit bba895d

Please sign in to comment.