Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ST6RI-808 Cross Features (KERML_-18, KERML_-140, SYSML2_-416) #608

Merged
merged 49 commits into from
Jan 9, 2025

Conversation

seidewitz
Copy link
Member

@seidewitz seidewitz commented Jan 2, 2025

This pull request implements the new concept of cross features of end feature in KerML and SysML. This corresponds to resolutions for the following issues,as approved in KerML FTF2 Ballot 2 and SysML v2 FTF 2 Ballot 6:

  • KERML_-18 Redundancy in association end multiplicities, ordering, and uniqueness
  • SYSML2_-416 Cross features for connection definitions and connection usages

The PR also implements the resolution to the following issue, as approved in KerML FTF2 Ballot 5, which is necessary for end feature defaults to work properly:

  • KERML_-140 MultiplicityRanges should allow owned members other than bounds

And it includes a technical update related to Xtext parser generation for the SysML grammar.

Overview

A cross feature of an end feature is specified using a new cross subsetting relationship between an end feature and its cross feature. The cross multiplicity of an end feature refers to the multiplicity of its cross feature, rather than the multiplicity of the end feature itself, which is always 1..1. The cross ordering and uniqueness of end features similarly refer to those of their cross feature.

The cross feature of an end feature of may be an owned feature of the type of the other end of a binary association or connector (connection definition or usage in SysML). Alternatively, the end feature itself can own its cross feature, in which case the cross subsetting is implied (this is required for an association or connector with more than two ends).

Separating cross multiplicity from end multiplicity removes the need for "special semantics" for end feature multiplicity. The same core multiplicity, uniqueness, and ordering semantics are now applied to both cross and end features. A pattern of implied relationships for the owned cross features of the ends of n-ary associations and connectors formalizes the semantics of cross multiplicity, uniqueness and ordering in those cases, too.

These changes essentially restore distinctions available in SysML v1, but in a semantically cleaner way. The terminology is somewhat different, though.

  • An end feature corresponds to a "participant property" in SysML v1, representing the participants in the links that are instances of an association. As for a participant property, an association end feature is always owned by its association. (Participant properties were introduced in SysML v1 and are not available in UML itself.)
  • A cross feature corresponds to an "association end property" in UML (and SysML v1), in that the multiplicity, ordering and uniqueness of a UML association end semantically apply to "crossing" or "navigating" the association, rather than to the values of the property itself.
  • An owned cross feature corresponds to an association end in UML that is owned by the association, rather than by the opposite related type.

Concrete Syntax

KerML

Cross subsetting is identified by the crosses keyword or the equivalent symbol =>. For example,

struct LegalEntity {
    feature assetsOwned [*] ordered : Asset;
}
struct Asset {
    feature owningEntities [1..*] : LegalEntity;
}
assoc AssetOwnership {
    end owner : LegalEntity crosses ownedAsset.owningEntities;
    end ownedAsset : Asset crosses owner.assetsOwned;
}

With the specified cross subsetting, creating an AssetOwnership link between a LegalEntity and an Asset means that the Asset must be one of the aassetsOwned by the LegalEntity and that the LegalEntity must be one of the owningEntities of the Asset. As shown above, the target of a cross subsetting relationship must be a feature chain in which the first feature is the other association end and the second feature is the cross feature for that end.

Cross feature multiplicity effectively constrains the number of instances of an association. It applies to each set of instances (links) of the association that have the same (single) values for each of the other ends. For a binary association, this is the same as the number of values resulting from "navigating" across the association from an instance of one related type to instances of the other related type. Cross feature uniqueness and ordering apply to the instances navigated to, preventing duplication among them and ordering them to form a sequence.

If an end instead has an owned cross feature, the cross subsetting is implicit. The cross multiplicity, ordering and non-uniqueness can then be declared directly on an end feature, with a notation that makes it clear that these are properties of the cross feature, not the end feature itself:

assoc AssetOwnership {
    end [1..*] feature owner : LegalEntity;
    end [*] ordered feature ownedAsset : Asset;
}

If no cross feature is given for an end, then its cross multiplicity is effectively 0..* by default.

Connector ends declared in the body of a connector may have cross features, specified using cross subsetting, as for association ends. The cross feature for the connector end further constrains any inherited cross feature(s). In the more common shorthand notation for connectors, the cross multiplicity (but not ordering or non-uniqueness) can be given at the before of the end's related feature (previously this was given after the related feature):

struct WheelAssembly {
    composite feature halfAxles[2] : Axle;
    composite feature wheels[2] : Wheel;
    // Connects each one of the halfAxles to a different one of the wheels.
    connector from [1] halfAxles to [1] wheels;
}

SysML

The crosses keyword can also be used in SysML, with the same meaning as in KerML.

part def LegalEntity {
    ref part assetsOwned [*] ordered : Asset;
}
part def Asset {
    ref part owningEntities [1..*] : LegalEntity;
}
connection def AssetOwnership {
    end part owner : LegalEntity crosses ownedAsset.owningEntities;
    end part ownedAsset : Asset crosses owner.assetsOwned;
}

The notation for owned cross features is also similar:

connection def AssetOwnership {
    end [1..*] part owner : LegalEntity;
    end [*] ordered part ownedAsset : Asset;
}

As is the shorthand notation for connection usages (including interface usages):

part WheelAssembly {
    part halfAxles[2] : Axle;
    part wheels[2] : Wheel;
    // Connects each one of the halfAxles to a different one of the wheels.
    connect [1] halfAxles to [1] wheels;
}

In addition, for SysML, end features always have a default multiplicity of 1..1, even for kinds of usages that would otherwise not have that default if they were not ends.

Abstract Syntax

KerML

Metaclass added:

  • CrossSubsetting

Metaclasses updated:

  • Feature (new attributes, operations and constraints)
  • MultiplicityRange (updated attribute derivations)
  • Type (new operation)

SysML

Metaclass updated:

  • ConnectionDefinition (redefined isSufficient attribute)

Semantics

KerML

The following adapters were updated to implement the semantic rules for owned cross features:

  • FeatureAdapter
  • MultiplicityAdapter

SysML

The following adapters were updated to modify the default multiplicity implementation so that end features of all kinds have a multiplicity default of 1..1:

  • AttributeUsageAdapter
  • ConnectionUsageAdapter
  • ItemUsageAdapter
  • PortUsageAdapter
  • UsageAdapter

Model Libraries

Model library files were updated as necessary for the new cross feature syntax and the reflective abstract syntax models KerML.kerml and SysML.sysml were regenerated.

KerML

Kernel Semantic Library:

  • ControlPerformances.kerml
  • FeatureReferencePerformances.kerml
  • Links.kerml
  • Objects.kerml
  • Occurrences.kerml
  • Performances.kerml
  • StatePerformance.kerml
  • Transfers.kerml
  • TransitionPerformances.kerml

Kernel Function Library:

  • OccurrenceFunctions.kerml

SysML

Systems Library:

  • Allocations.sysml
  • Connection.sysml
  • FlowConnections.sysml
  • Items.sysml
  • States.sysml

Cause and Effect Library:

  • CausationConnections.sysml

Geometry Library:

  • ShapeItems.sysml

Technical Update

The parsers used for KerML and SysML are generated from the Xtext grammar, ultimately producing Java parser classes. The generated Java classes include state transition tables that are captured as string initializers for static fields. There is a known issue with Xtext that, if a grammar is complex enough, the internal parser class can exceed the Java static initializer limit of 64K. There seems to currently be no fix for this within the Xtext project. (See eclipse-xtext/xtext#2537.)

The SysML grammar has been close to this limit a number of times, but adjustments in the grammar have resolved the problem in the past. However, the changes to the SysML grammar introduced in this PR seem to caused an exceptionally large increase in the size of the InternalSysMLParser class. The only way found to resolve this was to divide the code for this class across a series of small classes, which inherit from each other in a chain that ends in InternalSysMLParser.

In order to not have to manual split the InternalSysMLParser each time it is regenerated, this PR adds an InternalParserSplitterFragment to the GenerateSysML workflow. After the InternalSysMLParser class is generated in the usual way, the new workflow fragment automatically splits it into smaller files, all of which are within the 64K static initializer limit. The resulting InternalSysMLParser then operates exactly as it would have without the error in the original.

seidewitz added 30 commits May 13, 2024 14:28
- Also added setting delegates for new Feature and CrossSubsetting
derived properties.
- Also allowed an end feature to have an optional owned crossing
feature.
- Moved multiplicity before reference subsetting and had it parse into
an owned crossing feature.
- Add a cross subsetting to an end feature that has an owned crossing
feature does not have a non-implied owned cross subsetting.

- Add specializations to an owned crossing feature:
  - All specializations from the owning end feature, other than
    redefinitions, reference subsettings and cross subsettings.
  - Subsetting of any owned crossing features from end features
    redefined by the owning end feauture.

- Add the opposite end of the owning end feature of an owned crossing
feature as a featuring type of the crossing feature, if it does not have
any non-implied owned type featurings. (Note that this currently only
works properly for binary associations and connectors.)

- Also revised multiplicity type featuring transformation.
- And validation check for multiplicity of end features (currently as a
warning).

- Also revised feature typing transformation for Multiplicity.
- Moved end multiplicity and added cross subsetting as approproate.
- CrossMultiplying::typeMultiplied and Type::multiplyingType
- Used "multiplies" keyword for cross multiplying. Changed kyword for
cross subsetting to "crosses".
- ...to properly handle cases when target element is owned.
- Basic prefix flags (abstract, composite, etc.) now get set on the
owned crossing feature.
- Also corrected declaration of association Occurrences::without.
- Removed creation of intersection type if other end has multiple
types.
- Added subclassification to product type if owned cross feature is
owned by a redefining end feature.
- Used semantic-equivalent features for cartesian products.
@seidewitz seidewitz changed the title St6 ri 808 Cross Features (KERML_-18, KERML_-140, SYSML2_-416) Jan 2, 2025
Copy link
Contributor

@ujhelyiz ujhelyiz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems reasonable to me, except for a stray .gitignore added to the Xtext-generated files, which seems erroneous.

@himi
Copy link
Member

himi commented Jan 3, 2025

I've just started my review and I found the syntax highlighting configuration had not been updated. I'm not so familiar with the official process but they could be updated by xtext_grammar_converter.py. Could you please take care of it?

@himi
Copy link
Member

himi commented Jan 4, 2025

I tested it with

package ST6RI808K {
    struct LegalEntity {
    	feature assetsOwned [*] ordered : Asset;
    }
    struct Asset {
    	feature owningEntities [1..*] : LegalEntity;
    }
    assoc AssetOwnership {
    	end owner : LegalEntity => ownedAsset.owningEntities;
    	end ownedAsset : Asset crosses owner.assetsOwned;
    }
    assoc AssetOwnership2 {
    	end [1..*] feature owner2 : LegalEntity;
    	end [*] ordered feature ownedAsset2 : Asset;
    }
}

AssetOwnership looks good. It is parsed correctly as intended and I could even visualize CrossSubsettings. However, the feature chains of the implicit CrossSubsettings of AssetOwnership2 looks incorrect. The outline view of the first CrossSubsetting is :
Screenshot 2025-01-03 at 6 59 39 PM

I guess it should have no feature chain in this case.

@seidewitz
Copy link
Member Author

However, the feature chains of the implicit CrossSubsettings of AssetOwnership2 looks incorrect.

This is actually correct. A CrossSubsetting is required to target a feature chain of exactly two features, the first of which is the opposite end (in a binary association) to the end that owns the CrossSubsetting and the second of which is the cross feature.

In the case you showed, you didn't name the owned cross features, which is why the feature chain looks strange. However, if you give the owned cross features names:

    assoc AssetOwnership2 {
    	end owningEntities [1..*] feature owner2 : LegalEntity;
    	end assetsOwned [*] ordered feature ownedAsset2 : Asset;
    }

then the outline looks like this:
image
and you can see that the feature chain is exactly parallel to the target ownedAsset.owningEntities of the explicit CrossSubsetting of owner in AssetOwnership. (And, if you look at the details of the owned cross feature owningEntities, you will see that it has an implicit FeatureTyping by Asset, so the feature chain is semantically valid.)

The rather extensive set of rules for implied relationships for owned cross features (particularly for n-ary associations and connectors with n >2, which I left out of the PR description) is covered in the approved update to the semantics of associations in the resolution to KERML_-18. Of course, that won't actually be in the KerML specification document until the next release!

(By the way, you can find examples of binary associations with unowned cross features, binary associations owned cross features and n-ary association with owned cross features in the repository on this branch in kerml/src/examples/Association Examples.)

@seidewitz
Copy link
Member Author

I've just started my review and I found the syntax highlighting configuration had not been updated. I'm not so familiar with the official process but they could be updated by xtext_grammar_converter.py. Could you please take care of it?

This has been updated.

Copy link
Member

@himi himi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@seidewitz, thank you for your detailed explanation. I confirmed that it worked as you explained. I understand that feature chains of CrossSubsetting is similar to Subsetting of the ends of FlowConnectionUsage and looks consistent. I also checked the validation rules and confirmed they worked.

I want to properly visualize such CrossSubsettings but it should be a different story.

@seidewitz
Copy link
Member Author

@ujhelyiz @himi
I have added an internal parser splitter fragment to the GenerateSysML workflow. Could one or both of you try it and confirm that it works for you?

@himi
Copy link
Member

himi commented Jan 8, 2025

I see. Would you like me to test it on non MacOS environment (such as Windows)? Actually, that's an interesting solution.

@seidewitz
Copy link
Member Author

I see. Would you like me to test it on non MacOS environment (such as Windows)? Actually, that's an interesting solution.

Sure, testing it on Windows is probably a good idea.

@himi
Copy link
Member

himi commented Jan 9, 2025

I tested it with my MacOS (Sonoma 14.7.1). I could successfully executed Generate KerML (kerml) Language Infrastructure launch configuration, but could not execute Generate SysML (sysml) Language Infrastructure without
changing the heap memory option to -Xmx8192m (even -Xmx4096m did not work!). Didn't it happen in your environment? If it happens, I think we need to update the launch configuration.

@seidewitz
Copy link
Member Author

I tested it with my MacOS (Sonoma 14.7.1). I could successfully executed Generate KerML (kerml) Language Infrastructure launch configuration, but could not execute Generate SysML (sysml) Language Infrastructure without changing the heap memory option to -Xmx8192m (even -Xmx4096m did not work!). Didn't it happen in your environment? If it happens, I think we need to update the launch configuration.

I was not using the Generate KerML (kerml) Language Infrastructure launcher. I was running it from the GenerateSysML.mwe file, which creates a launcher that has no Xmx option set. This runs to completion.

The Generate KerML (kerml) Language Infrastructure also work if the Xmx option is removed. Try that. If it works for you, too, then I would suggest updating the launcher to remove the option and just use the default based on physical memory.

Otherwise, yeah, we probably need to set it very large. But most people don't need to be generating the parser, anyway (even most developers).

@seidewitz seidewitz self-assigned this Jan 9, 2025
@seidewitz seidewitz added this to the 2024-12 milestone Jan 9, 2025
@ujhelyiz
Copy link
Contributor

ujhelyiz commented Jan 9, 2025

I have managed to generate the parser without issues. The generation took around 4 minutes on my computer.

@himi
Copy link
Member

himi commented Jan 9, 2025

@seidewitz, thank you. I could execute successfully on Windows. However still in my MacOS, directly executing GenerateSysML.mwe still throws OutOfMemoryError. I'm guessing it may depend on JRE and I'm using OpenAdopt JRE for both machines. So let me suggest adding -Xmx8192m to the launcher configuration. Anyway, the results exactly match the original you committed as long as it's successfully executed.

I found this article and it seems the default max heap size depends on the computer physical memory amount! If that's true, that explains this result because my Mac M1 mini has only 16GB memory (but it could finish it less than 2min :)

https://stackoverflow.com/questions/4667483/how-is-the-default-max-java-heap-size-determined

@seidewitz
Copy link
Member Author

Yes, the default heap limit is some percentage of the physical memory. I have 32G on my Mac, so I guess that is why I didn't have a problem!

I have now changed the heap limit to 8192m in the Generate KerML (kerml) Language Infrastructure launcher and confirmed that this runs successfully in my Mac environment, too.

@seidewitz seidewitz merged commit 8074029 into master Jan 9, 2025
1 check passed
@himi
Copy link
Member

himi commented Jan 9, 2025

Thank you. Of course that worked in my MacOS environment.

@seidewitz seidewitz changed the title Cross Features (KERML_-18, KERML_-140, SYSML2_-416) ST6RI-808 Cross Features (KERML_-18, KERML_-140, SYSML2_-416) Jan 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants