diff --git a/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/SysMLElementSerializer.java b/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/SysMLElementSerializer.java index 89890be56..3160d9d73 100644 --- a/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/SysMLElementSerializer.java +++ b/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/SysMLElementSerializer.java @@ -21,6 +21,7 @@ import static org.eclipse.syson.sysml.export.SysMLRelationPredicates.IS_METADATA_USAGE; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.function.Function; @@ -31,15 +32,21 @@ import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.syson.sysml.AttributeUsage; +import org.eclipse.syson.sysml.CollectExpression; import org.eclipse.syson.sysml.Comment; import org.eclipse.syson.sysml.ConjugatedPortDefinition; import org.eclipse.syson.sysml.ConjugatedPortTyping; import org.eclipse.syson.sysml.Definition; import org.eclipse.syson.sysml.Element; +import org.eclipse.syson.sysml.Expression; import org.eclipse.syson.sysml.Feature; +import org.eclipse.syson.sysml.FeatureChainExpression; +import org.eclipse.syson.sysml.FeatureMembership; 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.InvocationExpression; import org.eclipse.syson.sysml.LiteralBoolean; import org.eclipse.syson.sysml.LiteralExpression; import org.eclipse.syson.sysml.LiteralInfinity; @@ -49,16 +56,21 @@ import org.eclipse.syson.sysml.Membership; import org.eclipse.syson.sysml.MembershipImport; import org.eclipse.syson.sysml.Metaclass; +import org.eclipse.syson.sysml.MetadataAccessExpression; import org.eclipse.syson.sysml.MetadataUsage; import org.eclipse.syson.sysml.MultiplicityRange; import org.eclipse.syson.sysml.Namespace; import org.eclipse.syson.sysml.NamespaceImport; +import org.eclipse.syson.sysml.NullExpression; import org.eclipse.syson.sysml.OccurrenceDefinition; +import org.eclipse.syson.sysml.OperatorExpression; import org.eclipse.syson.sysml.OwningMembership; import org.eclipse.syson.sysml.Package; +import org.eclipse.syson.sysml.ParameterMembership; import org.eclipse.syson.sysml.Redefinition; import org.eclipse.syson.sysml.ReferenceSubsetting; import org.eclipse.syson.sysml.Relationship; +import org.eclipse.syson.sysml.SelectExpression; import org.eclipse.syson.sysml.Subclassification; import org.eclipse.syson.sysml.Subsetting; import org.eclipse.syson.sysml.Type; @@ -70,6 +82,8 @@ import org.eclipse.syson.sysml.helper.EMFUtils; import org.eclipse.syson.sysml.helper.LabelConstants; import org.eclipse.syson.sysml.util.SysmlSwitch; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import reactor.util.function.Tuples; @@ -82,6 +96,8 @@ public class SysMLElementSerializer extends SysmlSwitch { private static final Predicate NOT_NULL = s -> s != null; + private static final Logger LOGGER = LoggerFactory.getLogger(SysMLElementSerializer.class); + private String lineSeparator; private String indentation; @@ -129,8 +145,7 @@ public String caseNamespace(Namespace namespace) { if (content != null && !content.isBlank()) { builder.appendIndentedContent(content); } - } - else { + } else { builder.append("namespace "); this.appendChildrenContent(builder, namespace, namespace.getOwnedMembership()); } @@ -139,7 +154,6 @@ public String caseNamespace(Namespace namespace) { @Override public String casePackage(Package pack) { - Appender builder = this.newAppender(); builder.append("package "); @@ -236,15 +250,16 @@ public String caseLiteralInteger(LiteralInteger literal) { @Override public String caseUsage(Usage usage) { - Appender builder = this.newAppender(); this.appendUsagePrefix(builder, usage); - builder.appendSpaceIfNeeded().append(getUsageKeyword(usage)); + builder.appendSpaceIfNeeded().append(this.getUsageKeyword(usage)); this.appendUsageDeclaration(builder, usage); + this.appendUsageCompletion(builder, usage); + List children = usage.getOwnedRelationship().stream().filter(IS_DEFINITION_BODY_ITEM_MEMBER).toList(); this.appendChildrenContent(builder, usage, children); @@ -252,8 +267,109 @@ public String caseUsage(Usage usage) { return builder.toString(); } + @Override + public String caseFeatureReferenceExpression(FeatureReferenceExpression expression) { + Appender builder = this.newAppender(); + + Membership membership = expression.getOwnedMembership().stream() + .findFirst() + .orElse(null); + + if (membership instanceof FeatureMembership feature) { + LOGGER.warn("BodyExpression are not handled yet"); + } else { + this.appendFeatureReferenceMember(builder, membership); + } + + return builder.toString(); + } + + @Override + public String caseOperatorExpression(OperatorExpression op) { + Appender builder = this.newAppender(); + switch (op.getOperator()) { + case "if": + LOGGER.warn("ConditionalExpression are not handled yet"); + break; + case "|": + case "&": + case "xor": + case "..": + case "==": + case "!=": + case "===": + case "!==": + case "<": + case ">": + case "<=": + case ">=": + case "+": + case "-": + case "*": + case "/": + case "%": + case "^": + case "**": + case LabelConstants.CONJUGATED: + case "not": + this.appendBinaryOrUnaryOperatorExpression(builder, op); + break; + case "istype": + case "hastype": + case "@": + case "as": + LOGGER.warn("ClassificationExpression are not handled yet"); + break; + case "all": + LOGGER.warn("ExtentExpression are not handled yet"); + break; + case LabelConstants.OPEN_BRACKET: + this.appendBracketExpression(builder, op); + break; + case "#": + LOGGER.warn("IndexExpression are not handled yet"); + break; + case ",": + LOGGER.warn("SequenceOperatorExpression are not handled yet"); + break; + default: + break; + } + return builder.toString(); + } + + @Override + public String caseInvocationExpression(InvocationExpression expression) { + LOGGER.warn("InvocationExpression are not handled yet"); + return ""; + } + + @Override + public String caseNullExpression(NullExpression expression) { + LOGGER.warn("NullExpression are not handled yet"); + return ""; + } + + @Override + public String caseCollectExpression(CollectExpression expression) { + LOGGER.warn("CollectExpression are not handled yet"); + return ""; + } + + @Override + public String caseSelectExpression(SelectExpression expression) { + LOGGER.warn("SelectExpression are not handled yet"); + return ""; + } + + @Override + public String caseMetadataAccessExpression(MetadataAccessExpression expression) { + LOGGER.warn("MetadataAccessExpression are not handled yet"); + return ""; + } + private String getUsageKeyword(Usage usage) { - return keywordProvider.doSwitch(usage); + return this.keywordProvider.doSwitch(usage); } private void appendFeatureSpecilizationPart(Appender builder, Feature feature) { @@ -379,6 +495,164 @@ private String mapToExpression(Element element, Feature feature) { return exp; } + private void appendUsageCompletion(Appender builder, Usage usage) { + List ownedRelationship = usage.getOwnedRelationship().stream() + .filter(FeatureValue.class::isInstance) + .map(FeatureValue.class::cast) + .collect(Collectors.toList()); + + for (FeatureValue feature : ownedRelationship) { + builder.appendSpaceIfNeeded(); + if (feature.isIsInitial()) { + builder.append(":="); + } else if (feature.isIsDefault()) { + builder.append("default"); + if (feature.isIsInitial()) { + builder.append(":"); + } + builder.append("="); + } else { + builder.append("="); + } + this.appendOwnedExpression(builder, feature.getValue()); + } + + } + + private void appendOwnedExpression(Appender builder, Expression expression) { + if (expression instanceof OperatorExpression op && op.getOperator() != null) { + builder.appendSpaceIfNeeded().append(caseOperatorExpression(op)); + } else { + this.appendPrimaryExpression(builder, expression); + } + } + + private void appendPrimaryExpression(Appender builder, Expression expression) { + if (expression instanceof FeatureChainExpression feature) { + LOGGER.warn("FeatureChainExpression are not handled yet"); + } else { + this.appendNonFeatureChainExpression(builder, expression); + } + } + + private void appendNonFeatureChainExpression(Appender builder, Expression expression) { + if (expression instanceof SelectExpression exp) { + builder.appendSpaceIfNeeded().append(this.caseSelectExpression(exp)); + } else if (expression instanceof CollectExpression exp) { + builder.appendSpaceIfNeeded().append(this.caseCollectExpression(exp)); + } else if (expression instanceof NullExpression exp) { + builder.appendSpaceIfNeeded().append(this.caseNullExpression(exp)); + } else if (expression instanceof LiteralExpression exp) { + builder.appendSpaceIfNeeded().append(this.caseLiteralExpression(exp)); + } else if (expression instanceof FeatureReferenceExpression exp) { + builder.appendSpaceIfNeeded().append(this.caseFeatureReferenceExpression(exp)); + } else if (expression instanceof MetadataAccessExpression exp) { + builder.appendSpaceIfNeeded().append(this.caseMetadataAccessExpression(exp)); + } else if (expression instanceof InvocationExpression exp) { + builder.appendSpaceIfNeeded().append(this.caseInvocationExpression(exp)); + } else { + LOGGER.warn("SequenceExpression are not handled yet"); + } + } + + private void appendSequenceExpressionList(Appender builder, Expression expression) { + if (expression instanceof OperatorExpression op && LabelConstants.COMMA.equals(op.getOperator())) { + LOGGER.warn("SequenceOperatorExpression are not handled yet"); + } else if (expression != null) { + this.appendOwnedExpression(builder, expression); + } + } + + private void appendFeatureReferenceMember(Appender builder, Membership membership) { + if (membership.getMemberElement() instanceof Feature feature) { + builder.appendSpaceIfNeeded().append(this.getDeresolvableName(feature, membership)); + } + } + + private void appendBracketExpression(Appender builder, OperatorExpression expression) { + List features = expression.getOwnedRelationship().stream() + .filter(ParameterMembership.class::isInstance) + .map(ParameterMembership.class::cast) + .toList(); + + if (!features.isEmpty()) { + this.appendPrimaryExpressionMember(builder, features.get(0)); + + builder.appendSpaceIfNeeded().append(expression.getOperator()); + + this.appendSequenceExpressionListMember(builder, features.subList(1, features.size())); + + builder.append(LabelConstants.CLOSE_BRACKET); + } + } + + private void appendSequenceExpressionListMember(Appender builder, List parameters) { + List featureValueList = parameters.stream() + .map(ParameterMembership::getOwnedMemberParameter) + .filter(Objects::nonNull) + .flatMap(parameter -> parameter.getOwnedRelationship().stream()) + .filter(FeatureValue.class::isInstance) + .map(FeatureValue.class::cast) + .toList(); + + for (int i = 0; i < featureValueList.size(); i++) { + Expression expression = featureValueList.get(i).getValue(); + this.appendSequenceExpressionList(builder, expression); + } + } + + private void appendPrimaryExpressionMember(Appender builder, ParameterMembership parameterMembership) { + Feature ownedMemberParameter = parameterMembership.getOwnedMemberParameter(); + if (ownedMemberParameter != null) { + ownedMemberParameter.getOwnedRelationship() + .stream() + .filter(FeatureValue.class::isInstance) + .map(FeatureValue.class::cast) + .forEach(val -> this.appendPrimaryExpression(builder, val.getValue())); + } + } + + private void appendBinaryOperatorExpression(Appender builder, OperatorExpression expression) { + Iterator iterator = expression.getOwnedRelationship().stream() + .filter(ParameterMembership.class::isInstance) + .map(ParameterMembership.class::cast).toList().iterator(); + + if (iterator.hasNext()) { + this.appendArgumentMember(builder, iterator.next()); + } + builder.appendSpaceIfNeeded().append(expression.getOperator()); + while (iterator.hasNext()) { + this.appendArgumentMember(builder, iterator.next()); + } + } + + private void appendBinaryOrUnaryOperatorExpression(Appender builder, OperatorExpression expression) { + List ownedRelationships = expression.getOwnedRelationship().stream() + .filter(ParameterMembership.class::isInstance) + .map(ParameterMembership.class::cast) + .toList(); + + String operator = expression.getOperator(); + List unaryOperators = List.of("+", "-", LabelConstants.CONJUGATED, "not"); + + if (ownedRelationships.size() < 2 && (unaryOperators.contains(operator))) { + LOGGER.warn("UnaryOperatorExpression are not handled yet"); + } else { + this.appendBinaryOperatorExpression(builder, expression); + } + } + + private void appendArgumentMember(Appender builder, ParameterMembership parameterMembership) { + Feature ownedMemberParameter = parameterMembership.getOwnedMemberParameter(); + if (ownedMemberParameter != null) { + ownedMemberParameter.getOwnedRelationship() + .stream() + .filter(FeatureValue.class::isInstance) + .map(FeatureValue.class::cast) + .forEach(val -> this.appendOwnedExpression(builder, val.getValue())); + } + } + @Override public String caseConjugatedPortDefinition(ConjugatedPortDefinition object) { // Conjugated port definition are implicit @@ -386,7 +660,7 @@ public String caseConjugatedPortDefinition(ConjugatedPortDefinition object) { } private String getDefinitionKeyword(Definition def) { - return keywordProvider.doSwitch(def) + " def"; + return this.keywordProvider.doSwitch(def) + " def"; } private void appendDefinition(Appender builder, Definition definition) { @@ -456,7 +730,7 @@ private void appendUsagePrefix(Appender builder, Usage usage) { this.getBasicUsagePrefix(builder, usage); final String isRef; - if (usage.isIsReference() && !isImplicitlyReferencial(usage)) { + if (usage.isIsReference() && !this.isImplicitlyReferencial(usage)) { isRef = "ref"; } else { isRef = ""; diff --git a/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/utils/Appender.java b/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/utils/Appender.java index 9015275ab..ed3acc4fa 100644 --- a/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/utils/Appender.java +++ b/backend/application/syson-sysml-export/src/main/java/org/eclipse/syson/sysml/export/utils/Appender.java @@ -43,7 +43,7 @@ public Appender appendPrintableName(String name) { } public Appender appendSpaceIfNeeded() { - if (!builder.isEmpty() && !endWithSpace()) { + if (!builder.isEmpty() && !endWithSpace() && !endWithBracket()) { append(" "); } return this; @@ -74,6 +74,11 @@ private boolean endWithSpace() { char charAt = builder.charAt(builder.length() - 1); return charAt == ' ' || charAt == '\t'; } + + private boolean endWithBracket() { + char charAt = builder.charAt(builder.length() - 1); + return charAt == '['; + } public Appender append(String str) { if (str != null) { diff --git a/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/SysMLModelToTextSwitchTest.java b/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/SysMLModelToTextSwitchTest.java index d8a2371f4..bdb215435 100644 --- a/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/SysMLModelToTextSwitchTest.java +++ b/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/SysMLModelToTextSwitchTest.java @@ -53,6 +53,8 @@ import org.eclipse.syson.sysml.helper.LabelConstants; import org.eclipse.syson.sysml.util.ModelBuilder; import org.junit.jupiter.api.Test; +import org.eclipse.syson.sysml.export.models.AttributeUsageWithBracketOperatorExpressionTestModel; +import org.eclipse.syson.sysml.export.models.AttributeUsageWithBinaryOperatorExpressionTestModel; /** * Test class for SysMLElementSerializer. @@ -133,13 +135,13 @@ public void packageWithContentWithRootNamespace() { Namespace rootnamespace = this.builder.create(Namespace.class); Package pack1 = this.builder.createInWithName(Package.class, rootnamespace, PACKAGE1); - + NamespaceImport namespaceImport = this.builder.createIn(NamespaceImport.class, pack1); Package pack2 = this.builder.createInWithName(Package.class, pack1, PACKAGE_2); Package pack3 = this.builder.createInWithName(Package.class, pack2, "Package 3"); - + namespaceImport.setImportedNamespace(pack3); // The root namespace should not be serialized @@ -577,22 +579,22 @@ public void partDefinitionFull() { @Test public void enumerationDefinitionAndEnumerationUsage() { - EnumerationDefinition enumDef = builder.createWithName(EnumerationDefinition.class, "Colors"); + EnumerationDefinition enumDef = this.builder.createWithName(EnumerationDefinition.class, "Colors"); - builder.createInWithName(EnumerationUsage.class, enumDef, "black"); + this.builder.createInWithName(EnumerationUsage.class, enumDef, "black"); MetadataDefinition metaData1 = this.fact.createMetadataDefinition(); metaData1.setDeclaredName("m1"); MetadataUsage m1u = this.createMetadataUsage(metaData1); - EnumerationUsage greyLiteral = builder.createInWithName(EnumerationUsage.class, enumDef, "grey"); + EnumerationUsage greyLiteral = this.builder.createInWithName(EnumerationUsage.class, enumDef, "grey"); this.addOwnedMembership(greyLiteral, m1u); - EnumerationUsage redLiteral = builder.createInWithName(EnumerationUsage.class, enumDef, "red"); + EnumerationUsage redLiteral = this.builder.createInWithName(EnumerationUsage.class, enumDef, "red"); - builder.createIn(Comment.class, redLiteral).setBody("A body"); + this.builder.createIn(Comment.class, redLiteral).setBody("A body"); - assertTextualFormEquals(""" + this.assertTextualFormEquals(""" enum def Colors { black; #m1 grey; @@ -671,6 +673,18 @@ public void attributeUsage() { this.assertTextualFormEquals("attribute attribute1;", attributeUsage); } + @Test + public void attributeUsageWithBinaryOperatorExpression() { + AttributeUsageWithBinaryOperatorExpressionTestModel model = new AttributeUsageWithBinaryOperatorExpressionTestModel(); + this.assertTextualFormEquals("attribute attribute1 = bestFuel + idlingFuel * fuel;", model.getAttributeUsage()); + } + + @Test + public void attributeUsageWithBracketOperatorExpression() { + AttributeUsageWithBracketOperatorExpressionTestModel model = new AttributeUsageWithBracketOperatorExpressionTestModel(); + this.assertTextualFormEquals("attribute attribute1 = 80 [millimetre];", model.getAttributeUsage()); + } + @Test public void abstractAttributeUsage() { AttributeUsage attributeUsage = this.builder.createWithName(AttributeUsage.class, ATTRIBUTE1); diff --git a/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/models/AttributeUsageWithBinaryOperatorExpressionTestModel.java b/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/models/AttributeUsageWithBinaryOperatorExpressionTestModel.java new file mode 100644 index 000000000..21a8a0102 --- /dev/null +++ b/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/models/AttributeUsageWithBinaryOperatorExpressionTestModel.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * 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.sysml.export.models; + +import org.eclipse.syson.sysml.AttributeUsage; +import org.eclipse.syson.sysml.Feature; +import org.eclipse.syson.sysml.FeatureReferenceExpression; +import org.eclipse.syson.sysml.FeatureValue; +import org.eclipse.syson.sysml.Membership; +import org.eclipse.syson.sysml.OperatorExpression; +import org.eclipse.syson.sysml.ParameterMembership; +import org.eclipse.syson.sysml.util.ModelBuilder; + +/** + * Test model for AttributeUsage with BinaryOperatorExpression. + * + *
+ * attribute attribute1 = bestFuel + idlingFuel * fuel;
+ * 
+ * + * @author wbilem + */ +public class AttributeUsageWithBinaryOperatorExpressionTestModel { + + private final ModelBuilder builder = new ModelBuilder(); + + private final AttributeUsage attributeUsage; + + private final AttributeUsage bestFuelConsumption; + + private final AttributeUsage idlingFuelConsumption; + + private final AttributeUsage tpdAvg; + + public AttributeUsageWithBinaryOperatorExpressionTestModel() { + this.attributeUsage = this.builder.createWithName(AttributeUsage.class, "attribute1"); + this.bestFuelConsumption = this.builder.createWithName(AttributeUsage.class, "bestFuel"); + this.idlingFuelConsumption = this.builder.createWithName(AttributeUsage.class, "idlingFuel"); + this.tpdAvg = this.builder.createWithName(AttributeUsage.class, "fuel"); + + this.attributeUsageWithBinaryOperatorExpression(); + } + + public AttributeUsage getAttributeUsage() { + return this.attributeUsage; + } + + private void attributeUsageWithBinaryOperatorExpression() { + OperatorExpression plusExpression = this.builder.create(OperatorExpression.class); + plusExpression.setOperator("+"); + + FeatureValue featureValue = this.builder.createIn(FeatureValue.class, this.attributeUsage); + featureValue.getOwnedRelatedElement().add(plusExpression); + + ParameterMembership plusParam1 = this.builder.createIn(ParameterMembership.class, plusExpression); + Feature plusFeature1 = this.builder.create(Feature.class); + plusParam1.getOwnedRelatedElement().add(plusFeature1); + this.createFeatureReference(plusFeature1, this.bestFuelConsumption); + + ParameterMembership plusParam2 = this.builder.createIn(ParameterMembership.class, plusExpression); + Feature plusFeature2 = this.builder.create(Feature.class); + plusParam2.getOwnedRelatedElement().add(plusFeature2); + + OperatorExpression multiplyExpression = this.builder.create(OperatorExpression.class); + multiplyExpression.setOperator("*"); + + FeatureValue featureValue2 = this.builder.createIn(FeatureValue.class, plusFeature2); + featureValue2.getOwnedRelatedElement().add(multiplyExpression); + + plusFeature2.getOwnedRelationship().add(this.builder.createIn(ParameterMembership.class, multiplyExpression)); + + ParameterMembership multiplyParam1 = this.builder.createIn(ParameterMembership.class, multiplyExpression); + Feature multiplyFeature1 = this.builder.create(Feature.class); + multiplyParam1.getOwnedRelatedElement().add(multiplyFeature1); + this.createFeatureReference(multiplyFeature1, this.idlingFuelConsumption); + + ParameterMembership multiplyParam2 = this.builder.createIn(ParameterMembership.class, multiplyExpression); + Feature multiplyFeature2 = this.builder.create(Feature.class); + multiplyParam2.getOwnedRelatedElement().add(multiplyFeature2); + this.createFeatureReference(multiplyFeature2, this.tpdAvg); + } + + private void createFeatureReference(Feature feature, AttributeUsage attr) { + FeatureValue featureValue = this.builder.createIn(FeatureValue.class, feature); + FeatureReferenceExpression featureReferenceExpression = this.builder.create(FeatureReferenceExpression.class); + featureValue.getOwnedRelatedElement().add(featureReferenceExpression); + Membership membership = this.builder.createIn(Membership.class, featureReferenceExpression); + membership.setMemberElement(attr); + } +} diff --git a/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/models/AttributeUsageWithBracketOperatorExpressionTestModel.java b/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/models/AttributeUsageWithBracketOperatorExpressionTestModel.java new file mode 100644 index 000000000..11ec66ed5 --- /dev/null +++ b/backend/application/syson-sysml-export/src/test/java/org/eclipse/syson/sysml/export/models/AttributeUsageWithBracketOperatorExpressionTestModel.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * 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.sysml.export.models; + +import org.eclipse.syson.sysml.AttributeUsage; +import org.eclipse.syson.sysml.Feature; +import org.eclipse.syson.sysml.FeatureReferenceExpression; +import org.eclipse.syson.sysml.FeatureValue; +import org.eclipse.syson.sysml.LiteralInteger; +import org.eclipse.syson.sysml.Membership; +import org.eclipse.syson.sysml.OperatorExpression; +import org.eclipse.syson.sysml.ParameterMembership; +import org.eclipse.syson.sysml.util.ModelBuilder; + +/** + * Test model for AttributeUsage with BracketOperatorExpression. + * + *
+ * attribute attribute1 = 80 [millimetre];
+ * 
+ * + * @author wbilem + */ +public class AttributeUsageWithBracketOperatorExpressionTestModel { + + private final ModelBuilder builder = new ModelBuilder(); + + private final AttributeUsage attributeUsage; + + private final AttributeUsage mm; + + public AttributeUsageWithBracketOperatorExpressionTestModel() { + this.attributeUsage = this.builder.createWithName(AttributeUsage.class, "attribute1"); + this.mm = this.builder.createWithName(AttributeUsage.class, "millimetre"); + + this.attributeUsageWithBracketOperatorExpression(); + } + + public AttributeUsage getAttributeUsage() { + return this.attributeUsage; + } + + private void attributeUsageWithBracketOperatorExpression() { + OperatorExpression bracketExpression = this.builder.create(OperatorExpression.class); + bracketExpression.setOperator("["); + + FeatureValue featureValue = this.builder.createIn(FeatureValue.class, this.attributeUsage); + featureValue.getOwnedRelatedElement().add(bracketExpression); + + ParameterMembership literalParam1 = this.builder.createIn(ParameterMembership.class, bracketExpression); + Feature feature1 = this.builder.create(Feature.class); + literalParam1.getOwnedRelatedElement().add(feature1); + + FeatureValue featureValue2 = this.builder.createIn(FeatureValue.class, feature1); + LiteralInteger literal = this.builder.create(LiteralInteger.class); + literal.setValue(80); + + featureValue2.getOwnedRelatedElement().add(literal); + + ParameterMembership param2 = this.builder.createIn(ParameterMembership.class, bracketExpression); + Feature feature2 = this.builder.create(Feature.class); + param2.getOwnedRelatedElement().add(feature2); + this.createFeatureReference(feature2, this.mm); + } + + private void createFeatureReference(Feature feature, AttributeUsage attr) { + FeatureValue featureValue = this.builder.createIn(FeatureValue.class, feature); + FeatureReferenceExpression featureReferenceExpression = this.builder.create(FeatureReferenceExpression.class); + featureValue.getOwnedRelatedElement().add(featureReferenceExpression); + Membership membership = this.builder.createIn(Membership.class, featureReferenceExpression); + membership.setMemberElement(attr); + } +}