|
19 | 19 |
|
20 | 20 | import java.io.IOException; |
21 | 21 | import java.util.List; |
| 22 | +import java.util.Objects; |
22 | 23 | import java.util.Optional; |
23 | 24 | import java.util.UUID; |
24 | 25 |
|
|
38 | 39 | import org.eclipse.syson.AbstractIntegrationTests; |
39 | 40 | import org.eclipse.syson.services.UtilService; |
40 | 41 | import org.eclipse.syson.sysml.ActionUsage; |
| 42 | +import org.eclipse.syson.sysml.AttributeUsage; |
41 | 43 | import org.eclipse.syson.sysml.ConjugatedPortDefinition; |
42 | 44 | import org.eclipse.syson.sysml.DecisionNode; |
43 | 45 | import org.eclipse.syson.sysml.Expression; |
|
47 | 49 | import org.eclipse.syson.sysml.LiteralInteger; |
48 | 50 | import org.eclipse.syson.sysml.LiteralString; |
49 | 51 | import org.eclipse.syson.sysml.Membership; |
| 52 | +import org.eclipse.syson.sysml.MultiplicityRange; |
50 | 53 | import org.eclipse.syson.sysml.OperatorExpression; |
51 | 54 | import org.eclipse.syson.sysml.PartUsage; |
52 | 55 | import org.eclipse.syson.sysml.PortDefinition; |
@@ -642,6 +645,89 @@ public void checkAttributeUsageLiteralStringValueTest() throws IOException { |
642 | 645 | }).check(input); |
643 | 646 | } |
644 | 647 |
|
| 648 | + @Test |
| 649 | + @DisplayName("Given a PartUsage with a Multiplicity with LiteralInteger bounds, when importing the model, then the Multiplicity value is set") |
| 650 | + public void checkPartUsageMultiplicityLiteralIntegerBoundsValueTest() throws IOException { |
| 651 | + var input = """ |
| 652 | + part myPart[1..2]; |
| 653 | + """; |
| 654 | + this.checker.checkImportedModel(resource -> { |
| 655 | + List<PartUsage> partUsages = EMFUtils.allContainedObjectOfType(resource, PartUsage.class).toList(); |
| 656 | + assertThat(partUsages).hasSize(1); |
| 657 | + PartUsage partUsage = partUsages.get(0); |
| 658 | + assertThat(partUsage.getMultiplicity()).isInstanceOf(MultiplicityRange.class); |
| 659 | + MultiplicityRange multiplicityRange = (MultiplicityRange) partUsage.getMultiplicity(); |
| 660 | + assertThat(multiplicityRange.getLowerBound()).isInstanceOf(LiteralInteger.class); |
| 661 | + LiteralInteger multiplicityRangerLowerBound = (LiteralInteger) multiplicityRange.getLowerBound(); |
| 662 | + assertThat(multiplicityRangerLowerBound.getValue()).isEqualTo(1); |
| 663 | + assertThat(multiplicityRange.getUpperBound()).isInstanceOf(LiteralInteger.class); |
| 664 | + LiteralInteger multiplicityRangeUpperBound = (LiteralInteger) multiplicityRange.getUpperBound(); |
| 665 | + assertThat(multiplicityRangeUpperBound.getValue()).isEqualTo(2); |
| 666 | + }).check(input); |
| 667 | + } |
| 668 | + |
| 669 | + @Test |
| 670 | + @DisplayName("Given a PartUsage with a Multiplicity with FeatureReferenceExpression bounds, when importing the model, then the Multiplicity value is set") |
| 671 | + public void checkPartUsageMultiplicityChainedFeatureReferenceExpressionBoundsTest() throws IOException { |
| 672 | + // The result of the bound expression(s) of a MultiplicityRange must be typed by ScalarValues::Integer (see |
| 673 | + // KerML 8.3.4.11.2). |
| 674 | + var input = """ |
| 675 | + part bounds { |
| 676 | + attribute lower:ScalarValues::Integer = 1; |
| 677 | + part upperBounds { |
| 678 | + attribute upper:ScalarValues::Integer = 2; |
| 679 | + } |
| 680 | + } |
| 681 | +
|
| 682 | + part myPart[bounds::lower..bounds::upperBounds::upper]; |
| 683 | + """; |
| 684 | + this.checker.checkImportedModel(resource -> { |
| 685 | + Optional<PartUsage> optionalPartUsage = EMFUtils.allContainedObjectOfType(resource, PartUsage.class) |
| 686 | + .filter(partUsage -> Objects.equals(partUsage.getName(), "myPart")) |
| 687 | + .findFirst(); |
| 688 | + assertThat(optionalPartUsage).isPresent(); |
| 689 | + assertThat(optionalPartUsage.get().getMultiplicity()).isInstanceOf(MultiplicityRange.class); |
| 690 | + MultiplicityRange multiplicityRange = (MultiplicityRange) optionalPartUsage.get().getMultiplicity(); |
| 691 | + assertThat(multiplicityRange.getLowerBound()).isInstanceOf(FeatureReferenceExpression.class); |
| 692 | + FeatureReferenceExpression multiplicityRangeLowerBound = (FeatureReferenceExpression) multiplicityRange.getLowerBound(); |
| 693 | + assertThat(multiplicityRangeLowerBound.getReferent()) |
| 694 | + .isInstanceOf(AttributeUsage.class) |
| 695 | + .returns("lower", Feature::getName); |
| 696 | + assertThat(multiplicityRange.getUpperBound()).isInstanceOf(FeatureReferenceExpression.class); |
| 697 | + FeatureReferenceExpression multiplicityRangeUpperBound = (FeatureReferenceExpression) multiplicityRange.getUpperBound(); |
| 698 | + assertThat(multiplicityRangeUpperBound.getReferent()) |
| 699 | + .isInstanceOf(AttributeUsage.class) |
| 700 | + .returns("upper", Feature::getName); |
| 701 | + }).check(input); |
| 702 | + } |
| 703 | + |
| 704 | + @Test |
| 705 | + @DisplayName("Given a PartUsage with a Multiplicity with top-level FeatureReferenceExpression bounds, when importing the model, then the Multiplicity value is set ") |
| 706 | + public void checkPartUsageMultiplicityTopLevelFeatureReferenceExpressionBoundTest() throws IOException { |
| 707 | + var input = """ |
| 708 | + attribute lower:ScalarValues::Integer = 1; |
| 709 | + attribute upper:ScalarValues::Integer = 2; |
| 710 | + part myPart[lower..upper]; |
| 711 | + """; |
| 712 | + this.checker.checkImportedModel(resource -> { |
| 713 | + List<PartUsage> partUsages = EMFUtils.allContainedObjectOfType(resource, PartUsage.class).toList(); |
| 714 | + assertThat(partUsages).hasSize(1); |
| 715 | + PartUsage partUsage = partUsages.get(0); |
| 716 | + assertThat(partUsage.getMultiplicity()).isInstanceOf(MultiplicityRange.class); |
| 717 | + MultiplicityRange multiplicityRange = (MultiplicityRange) partUsage.getMultiplicity(); |
| 718 | + assertThat(multiplicityRange.getLowerBound()).isInstanceOf(FeatureReferenceExpression.class); |
| 719 | + FeatureReferenceExpression multiplicityRangeLowerBound = (FeatureReferenceExpression) multiplicityRange.getLowerBound(); |
| 720 | + assertThat(multiplicityRangeLowerBound.getReferent()) |
| 721 | + .isInstanceOf(AttributeUsage.class) |
| 722 | + .returns("lower", Feature::getName); |
| 723 | + assertThat(multiplicityRange.getUpperBound()).isInstanceOf(FeatureReferenceExpression.class); |
| 724 | + FeatureReferenceExpression multiplicityRangeUpperBound = (FeatureReferenceExpression) multiplicityRange.getUpperBound(); |
| 725 | + assertThat(multiplicityRangeUpperBound.getReferent()) |
| 726 | + .isInstanceOf(AttributeUsage.class) |
| 727 | + .returns("upper", Feature::getName); |
| 728 | + }).check(input); |
| 729 | + } |
| 730 | + |
645 | 731 | private void assertOperatorExpressionGuard(TransitionUsage t1, String expectedOperator, Class<?> expectedFirstParameterType, Class<?> expectedSecondParameterType) { |
646 | 732 | EList<Expression> guardExpression1 = t1.getGuardExpression(); |
647 | 733 | assertThat(guardExpression1).hasSize(1); |
|
0 commit comments