Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ For example `ViewUsage` elements are no longer rendered in _parts_ compartments.
- https://github.com/eclipse-syson/syson/issues/1949[#1949] [diagrams] Allow redefining a `PartUsage` with the same name as the redefined usage.
- https://github.com/eclipse-syson/syson/issues/1863[#1863] [diagrams] Dropping an elements on a diagram which is already visible gives feedback again.
- https://github.com/eclipse-syson/syson/issues/2026[#2026] [explorer] Fix an issue where creating a new model using the _Create a new model_ action in the _Explorer_ view was not adding the ".sysml" extension to the model name.
- https://github.com/eclipse-syson/syson/issues/1998[#1998] [metamodel] Missing implicit TypeFeaturing.

=== Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@
import org.eclipse.syson.sysml.OwningMembership;
import org.eclipse.syson.sysml.Redefinition;
import org.eclipse.syson.sysml.ReferenceSubsetting;
import org.eclipse.syson.sysml.Specialization;
import org.eclipse.syson.sysml.Subsetting;
import org.eclipse.syson.sysml.SysmlFactory;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.sysml.Type;
import org.eclipse.syson.sysml.TypeFeaturing;
import org.eclipse.syson.sysml.util.ILibraryNamespaceProvider;
import org.eclipse.syson.sysml.util.LibraryNamespaceProvider;

/**
* <!-- begin-user-doc --> An implementation of the model object '<em><b>Feature</b></em>'. <!-- end-user-doc -->
Expand Down Expand Up @@ -462,6 +466,13 @@ public EList<Type> getFeaturingType() {
if (!chainingFeature.isEmpty()) {
featuringTypes.addAll(chainingFeature.get(0).getFeaturingType());
}

// Add implicit featuring type
Type implicitType = this.computeImplicitFeaturingType();
if (implicitType != null) {
featuringTypes.add(implicitType);
}

return new EcoreEList.UnmodifiableEList<>(this, SysmlPackage.eINSTANCE.getFeature_FeaturingType(), featuringTypes.size(), featuringTypes.toArray());
}

Expand Down Expand Up @@ -1539,4 +1550,59 @@ private Collection<Feature> collectTypingFeatures() {
}
return featureCollector;
}

/**
* @generated NOT
*/
private Type computeImplicitFeaturingType() {
Type owningType = this.getOwningType();
Type implicitType = null;
if (owningType != null) {

if (!this.isIsVariable()) {
// KerML 7.3.2.6 “Feature Membership” – “A feature that is declared within the body of a type … automatically has that type as a featuring type.”
// SysML 8.3.3.1.6 FeatureMembership - If the ownedMemberFeature has isVariable = false, then the FeatureMembership implies that the owningType is also a featuringType of the
// ownedMemberFeature.
implicitType = owningType;
} else {
// KerML 8.4.4.3
// Class (or any Type that directly or indirectly specializes Occurrence) may have ownedFeatures with
// isVariable = true. The checkFeatureFeatureMembershipTypeFeaturing constraint requires that such
// variable Features are featured by the snapshots of their owningType.
TypeFeaturing typeFeaturing = SysmlFactory.eINSTANCE.createTypeFeaturing();
typeFeaturing.setIsImplied(true);

// Table 9. Core Semantics Implied Relationships Supporting Kernel Semantics - Note 1
// For the checkFeatureFeatureMembershipTypeFeaturing constraint, if the Feature has
//isVariable = false, then the target Type is the owningType of the Feature. If the Feature has
//isVariable = true and the owningType is the base Class Occurrences::Occurrence, then the
//target is Occurrences::Occurrence::snapshots (see 9.2.4.2.13 ). Otherwise, the target Type shall
//be constructed so as to satisfy the constraint and shall be owned as an ownedRelatedElement of the
//implied TypeFeaturing relationship. For further details, see 8.4.4.3 .
ILibraryNamespaceProvider nsProvider = LibraryNamespaceProvider.getFrom(this);
if (nsProvider == null) {
nsProvider = new LibraryNamespaceProvider(this);
}
Type snapshot = nsProvider.getNamespaceFromLibrary("Occurrences::Occurrence::snapshot", Type.class);
if (owningType == nsProvider.getNamespaceFromLibrary("Occurrences::Occurrence")) {
implicitType = snapshot;
} else {
implicitType = SysmlFactory.eINSTANCE.createFeature();
typeFeaturing.getOwnedRelatedElement().add(implicitType);

Specialization specialization = SysmlFactory.eINSTANCE.createSpecialization();
implicitType.getOwnedRelationship().add(specialization);
specialization.setSpecific(implicitType);
specialization.setGeneral(snapshot);
}

typeFeaturing.setFeaturingType(owningType);
typeFeaturing.setFeatureOfType((Feature) implicitType);
implicitType.getOwnedRelationship().add(typeFeaturing);

}

}
return implicitType;
}
} // FeatureImpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* Copyright (c) 2024, 2026 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
Expand All @@ -12,12 +12,16 @@
*******************************************************************************/
package org.eclipse.syson.sysml.impl;

import static org.junit.Assert.assertNull;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;

import org.eclipse.syson.sysml.Feature;
import org.eclipse.syson.sysml.ItemDefinition;
import org.eclipse.syson.sysml.ItemUsage;
import org.eclipse.syson.sysml.util.ModelBuilder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
Expand Down Expand Up @@ -59,4 +63,22 @@ public void testNames() {
assertEquals("f", f2.effectiveShortName());
}


@Test
@DisplayName("GIVEN a non variable feature in a Type, WHEN computing it's featuring types, THEN the owning type is returned")
public void checkImplicitFeaturingTypeNoVariableFeature() {
var itemDef = this.builder.createWithName(ItemDefinition.class, "ItemDef");
ItemUsage itemUsage = this.builder.createInWithName(ItemUsage.class, itemDef, "ItemUsage");
assertThat(itemUsage.getFeaturingType()).hasSize(1).allMatch(type -> type == itemDef);
}

@Test
@DisplayName("GIVEN a variable feature in a Type, WHEN computing it's featuring types, THEN the owning type is returned")
public void checkImplicitFeaturingTypeVariableFeature() {
var itemDef = this.builder.createWithName(ItemDefinition.class, "ItemDef");
ItemUsage itemUsage = this.builder.createInWithName(ItemUsage.class, itemDef, "ItemUsage");
itemUsage.setIsVariable(true);
assertThat(itemUsage.getFeaturingType()).hasSize(1)
.allMatch(type -> type instanceof Feature feature && feature.getFeaturingType().contains(itemDef));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ part system {

** `Req Id` and `Declared Short Name` properties of `RequirementDefinition` and `RequirementUsage` are now synchronized, as required by the SysMLv2 specification.

* In _Validation_ view:

** Improve the computation of _featuringType_ on `Feature` to avoid getting the following validation error:
+
```
If a Feature is owned via a FeatureMembership, then it must have a featuringType for which the operation isFeaturingType returns true. (checkFeatureFeatureMembershipTypeFeaturing constraint on Feature is not respected for Test::MyItemDef::myFeature)
````

== Improvements

* In diagrams:
Expand Down
Loading