Skip to content

UML Code Generation ‐ Convention

samatstarion edited this page Jan 16, 2026 · 12 revisions

Code Generation

The SysML2.NET libraries are generated from the MOF XMI for the SysML v2 Abstract Syntax. We make use of convention and template based code generation to convert the information that is stored in this UML model to various C# classes such as DTO's, POCO's, JSON serializers and much more. The Starion Group uml4net library is used to read the UML model. Handlebars templates are used to generate code using the Handlebars.Net library.

The code-generators are executed from the Unit test project called SysML2.NET.CodeGenerator.Tests. The generated code is verified (compared) against so-called expected classes. These are hand-coded and are used to implement a pattern that needs to be generated. An analysis of the SysML2 UML model has been performed to check that all the variations in data-types, multiplicity, inheritance etc. is covered. A number of classes have been selected for which expected classes need to be in place such that the generated code is properly covered.

Class and Interface Generation

The MOF XMI for the SysML v2 Abstract Syntax UML model contains Classes organized in Packages. The UML model makes use of multiple inheritance of UML classes which is not supported by C#. The following structure is used to implement the MOF XMI for the SysML v2 Abstract Syntax in C#:

  • All UML classes are generated as a C# Interface, where each C# Interface contains the defined properties on the UML class as well as the Generalization of the UML class as super interfaces
  • Only concrete UML classes are generated as a C# class implementing the corresponding C# Interface. Each property defined on the C# interface, inlcuding the properties on the general C# interfaces, will find their way into the C# class. See below for property mappings for more details.

Property Variations

The following property variations occur in the UML model, inlcuding the multiplicity, whether they are Derfived, and whether they are Redefined. Interesting variations are orgnized per value types and enumerations and reference types.

  • VALUE:Boolean:1:1
  • VALUE:Boolean:1:1:isDerived
  • VALUE:Boolean:1:1:isDerived:IsRedefined
  • VALUE:Boolean:1:1:IsRedefined
  • VALUE:Integer:1:1
  • VALUE:Real:1:1
  • VALUE:String:0:*
  • VALUE:String:0:*:isDerived
  • VALUE:String:0:1
  • VALUE:String:0:1:isDerived
  • VALUE:String:0:1:isDerived:IsRedefined
  • VALUE:String:0:1:IsRedefined
  • VALUE:String:1:1
  • VALUE:String:1:1:isDerived
  • VALUE:String:1:1:isDerived:IsRedefined
  • VALUE:String:1:1:IsRedefined
  • ENUM:0:1
  • ENUM:1:1
  • ENUM:1:1:IsRedefined
  • REF:0:*:composite:subsetted
  • REF:0:*:composite:subsetted:isDerived
  • REF:0:*:isDerived
  • REF:0:*:isDerived:IsRedefined
  • REF:0:*:Many-to-Many:isDerived
  • REF:0:*:Many-to-Many:isDerived:IsRedefined
  • REF:0:*:Many-to-Many:subsetted
  • REF:0:*:Many-to-Many:subsetted:isDerived
  • REF:0:*:Many-to-Many:subsetted:isDerived:IsRedefined
  • REF:0:*:subsetted:isDerived
  • REF:0:1:composite:subsetted:isDerived
  • REF:0:1:isDerived
  • REF:0:1:isDerived:IsRedefined
  • REF:0:1:isDerived:IsRedefined:Contained
  • REF:0:1:subsetted:Contained
  • REF:0:1:subsetted:isDerived
  • REF:0:1:subsetted:isDerived:Contained
  • REF:0:1:subsetted:isDerived:IsRedefined
  • REF:0:1:subsetted:isDerived:IsRedefined:Contained
  • REF:0:2:Many-to-Many:subsetted:isDerived
  • REF:1:*:Many-to-Many:isDerived
  • REF:1:*:Many-to-Many:IsRedefined
  • REF:1:1:composite:isDerived:IsRedefined
  • REF:1:1:composite:subsetted:isDerived:IsRedefined
  • REF:1:1:isDerived
  • REF:1:1:isDerived:IsRedefined
  • REF:1:1:isDerived:IsRedefined:Contained
  • REF:1:1:IsRedefined
  • REF:1:1:subsetted:isDerived
  • REF:1:1:subsetted:isDerived:IsRedefined
  • REF:1:1:subsetted:isDerived:IsRedefined:Contained
  • REF:1:2:subsetted:isDerived

These property variations can be found in the following classes which need to be implemented a expected classes when testing the expected output of any code generation:

  • class : SysML::Root::Annotations::AnnotatingElement
  • class : SysML::Kernel::Associations::Association
  • class : SysML::Root::Dependencies::Dependency
  • class : SysML::Root::Elements::Element [Abstract]
  • class : SysML::Systems::Enumerations::EnumerationDefinition
  • class : SysML::Core::Features::Feature
  • class : SysML::Core::Features::FeatureTyping
  • class : SysML::Kernel::Interactions::Flow
  • class : SysML::Systems::Requirements::FramedConcernMembership
  • class : SysML::Kernel::Expressions::LiteralInteger
  • class : SysML::Kernel::Expressions::LiteralRational
  • class : SysML::Root::Namespaces::Membership
  • class : SysML::Kernel::Multiplicities::MultiplicityRange
  • class : SysML::Root::Namespaces::OwningMembership
  • class : SysML::Core::Features::ReferenceSubsetting
  • class : SysML::Root::Elements::Relationship [Abstract]
  • class : SysML::Systems::Requirements::RequirementUsage
  • class : SysML::Kernel::Expressions::SelectExpression
  • class : SysML::Core::Classifiers::Subclassification
  • class : SysML::Root::Annotations::TextualRepresentation
  • class : SysML::Systems::DefinitionAndUsage::Usage

Data Transfer Objects and Plain Old C# Objects

In the SysML2.NET implementation we distinguish between Data Transfer Objects (DTO) and Plain Old C# Objects (POCO). A DTO is an object specificaly designed to transfer data between application layers, while a POCO is a pure domain or model object.

  • The POCO's are therefore a straight UML class to C# class translation, maintaining the package structure, data types and references to other classes.
  • The DTO's are a simplified class where any association to another class is translated to a GUID as opposed to a reference. This matches very well with the serialization of the data where references are also serialized as GUID's

Property Type Mapping Conventions

Data Type Mapping

The following mapping is performed for Data Types that are present in the UML model:

  • Boolean: translates to C# bool
  • UnlimitedNatural: translates to C# string
  • String: translates to C# string
  • Integer: translates to C# int
  • Real: translates to C# double
  • Enumeration: translate to correspondant C# enum

Reference Property Mapping

DTO

Data Transfer Objects (DTO) are classes that have no pointers to other classes and are typically used to transfer data between application layers.

For DTO's, references (pointers) to other classes translate to a Guid.

POCO

A POCO is a pure domain or model object as it is defined in the MOF XMI for the SysML v2 Abstract Syntax.

For POCO's references (pointers) to other classes translate to a reference to the Interface definition of the specified type

Non-Scalar Multiplicity Mapping

For Data Type and Enumeration

  • [0..1]: Translates to nullable (Except for string, which is nullable by definition)
  • [1..]/[n..]: Translates to List{T}

For Reference Property

POCO
  • [0..1]: Not a nullable since a reference type is nullable by definition
  • [1..*]/[n..*]: Translates to List{T}
DTO
  • [0..1]: Translates to Guid?
  • [1..*]/[n..*]: Translates to List{Guid}

Property Naming Convention

  • For all non-derived properties, property name starts with an uppercase, following the C# convention
  • For all derived properties, property name starts with a lowercase.

Redefined Properties

When a property has been redefined on the current context, this property has to be discarded by the class since it does not have any meaning due to the redefinition of it. To discard it, it is declared (generated) with an explicit interface definition.

Property Accessibility

POCO

  • Nominal Case: translates to { get; set; }
  • ReadOnly: translates to { get; }
  • Derived or DerivedUnion: Translates to => this.Compute$PROPERTYNAME$();. This method is hand-coded to implement derive-computation logic

DTO

  • Nominal Case: translates to { get; set; }
  • ReadOnly: translates to { get; }
  • Derived or DerivedUnion: translates to { get; } on interface definition, { get; internal set; } on class implementation

Redefined and Subset implementation

Redefined

Properties that have been redefined expose both a getter and a setter. The getter returns the value of the property that is redefining the current redefined property. The setter shall perform type checking to make sure it is inline with the redefining property.

The Following sections explain the implementation principle of properties that have been redefined. Each case is explained in terms of multiplicity, where the first multiplicity is the one of the redefined property and the second one is for the redefinition. In UML redefinition supports narrowing the Type and Multiplicity, meaning when property A and B exist, and B is the redefinition of A, B can be a narrower type or multiplicity.

Getter
  • [n..*] -> [n..*] : Returns a newly initialized collection to allow safe cast and to not allow direct modification of the redefinition collection via a redefined property
  • [n..*] -> [1..1] : Returns a newly initialized collection that contains only one element, the value of the redefinition
  • [n..*] -> [0..1] : Returns a newly initialized collection that contains only zero element if the value of the redefinition is null, one otherwise
  • [1..1] -> [1..1]/[0..1] -> [0..1] : Returns the value for the redefinition one
  • [1..1] -> [0..1] : Returns the value of the redefinition if not null, the default value otherwise
Setter

If the redefinition is a derived property, the setter does not do anything

  • [n..*] -> [n..*] : Assigns the collection to the redefinition. For POCO, gets only elements of the correct type
  • [n..*] -> [0/1..1] : Assigns the value based on the first value of the collection. For POCO, based on the first value of the collection that matches the target type
  • [0/1..1] -> [0/1..1] : Assigns the value if type matches the target one.

Subset

Not implemented for now

More information coming soon

JSON Serialization

  • Property name follows the CamelCase format
  • @type (string) property required (value is the name of the serialized)
  • @id (uuid) property (optional)

The JSON serialization follows the KERML specification

Data Type serialization

  • Boolean: translates to json bool
  • UnlimitedNatural: translates to json string
  • String: translates to json string
  • Integer: translates to json numeric
  • Real: translates to json numeric
  • Enumeration: translate to full lowercase string

Reference Property

A refence is represented through a JSON object which that contains one property @id with the value of the reference Guid

Multiplicity

  • [0..1]: Always serialized, null in case of null, the value otherwise
  • [1..*]/[n..*]: Serialized through a JSON array

Derived property

The serialization of derived property is possible. Deserialization action can also assign derived properties into DTOs if present inside the JSON payload.

Redefined property

Redefined property are discarded from the serialization.

XMI Serialization

MORE INFORMATION COMING SOON

Clone this wiki locally