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 changes/unreleased/use-case-connections.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- The SysML v1 migration writes actors and use cases as the usages a v2 use case model is made of — a UML Actor is a `part` usage, a UseCase a `use case` usage (its subject, includes and behavior inside it) — so each is one element a tool draws once, and writes the lines a use case diagram draws as connections between them: each actor association, «Include», Extend and «Refine» becomes a `connection` named by its kind (`'Operator to Control Instrument'`, `'Control Instrument includes Manipulate Stage'`, `'A extends B'`, `'A refines B'`), hosted by the nearest package holding both ends, with no trailing comment a tool would show as a note; a relationship its author named keeps that name and carries its kind as the connection's `doc` instead, as an extend's extension points and condition are. A refined requirement or block gets one usage in its package only when a connection joins it; a named association's one usage is typed by its `connection def`. Use case diagrams are rendered `asInterconnectionDiagram` over those usages and connections instead of `asTextualNotation`, with their Cameo geometry applied; the interconnection renderer draws use case and requirement usages as nodes and an `include` as the connection's line rather than a nested node. A «Requirement» is a `requirement` usage too, as a tool's users draw one, rather than a `requirement def` with a usage written beside it when a line needs one: a nested requirement is its subrequirement, a «Satisfy» or «Verify» subsets it (`satisfy requirement 'satisfy R' :> R;`), a «DeriveReqt»'s `connection def` ends and a property it types subset it, a «Refine» connection joins it directly, and a requirement table, matrix or «Requirement»-stereotype filter lists the usages by name; an instance specification of a requirement is reported rather than written as an individual. A document query reads a derivation `connection def` whose ends subset requirement usages as relating those usages, and a named satisfy or verify that subsets a requirement usage as satisfying or verifying it too. An «Allocate» whose end is a requirement, actor or use case stays a dependency, as no allocation end can be typed by a usage.
4 changes: 2 additions & 2 deletions client/julia/OpenSysML/test/extended_client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -682,12 +682,12 @@ end
@test occursin("part def Vehicle", migrated.content)
@test migrated.from_format == "xmi"
@test (migrated.report.mapped, migrated.report.approximated,
migrated.report.unmapped, migrated.report.skipped) == (78, 12, 3, 2)
migrated.report.unmapped, migrated.report.skipped) == (77, 13, 3, 2)
@test length(migrated.report.entries) == 95
@test length(by_verdict(migrated.report, VERDICT_UNMAPPED)) == 3
@test migrated.source_path == abspath(vehicle)
inline = migrate_source(conn, read(vehicle), "ttl"; from_format=" XMI ")
@test inline.to_format == "ttl" && inline.report.mapped == 78
@test inline.to_format == "ttl" && inline.report.mapped == 77
@test isempty(inline.report.entries) && inline.source_path === nothing
mktempdir() do directory
output = joinpath(directory, "Vehicle.sysml")
Expand Down
4 changes: 2 additions & 2 deletions client/matlab/tests/test_surface_live.m
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ function test_surface_live()
assert_equal(~isempty(strfind(migrated.content, 'part def Vehicle')), true, 'migrate');
assert_equal(migrated.fromFormat, 'xmi', 'migrate from format');
assert_equal([migrated.report.mapped, migrated.report.approximated, ...
migrated.report.unmapped, migrated.report.skipped], [78 12 3 2], 'migration counts');
migrated.report.unmapped, migrated.report.skipped], [77 13 3 2], 'migration counts');
assert_equal(numel(migrated.report.entries), 95, 'migration entries');
assert_equal(numel(migrated.byVerdict('unmapped')), 3, 'migration unmapped entries');
assert_equal(migrated.sourcePath, opensysml.internal.absolutePath(vehicle), 'migration source path');
fid = fopen(vehicle, 'rb'); vehicleBytes = fread(fid, Inf, 'uint8=>uint8')'; fclose(fid);
inlineMigration = opensysml.migrate(conn, 'ttl', 'content', vehicleBytes, 'fromFormat', ' XMI ');
assert_equal(inlineMigration.toFormat, 'ttl', 'inline migration to Turtle');
assert_equal(inlineMigration.report.mapped, 78, 'inline migration counts');
assert_equal(inlineMigration.report.mapped, 77, 'inline migration counts');
assert_equal(isempty(inlineMigration.report.entries), true, 'inline migration summary only');
assert_equal(isempty(inlineMigration.sourcePath), true, 'inline migration has no source path');
migratedPath = [tempname '.sysml'];
Expand Down
6 changes: 3 additions & 3 deletions client/node/test/migrate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ test("a v1 model migrates from its path, with the summary and the counts", async
);
assert.match(
migration.report.summary,
/^migrated 93 element\(s\): 78 mapped, 12 approximated, 3 unmapped/,
/^migrated 93 element\(s\): 77 mapped, 13 approximated, 3 unmapped/,
);
assert.equal(migration.report.mapped, 78);
assert.equal(migration.report.approximated, 12);
assert.equal(migration.report.mapped, 77);
assert.equal(migration.report.approximated, 13);
assert.equal(migration.report.unmapped, 3);
assert.equal(migration.report.skipped, 2);
assert.notEqual(migration.report.source, "");
Expand Down
2 changes: 1 addition & 1 deletion client/python/opensysml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ def migrate(to_format, file_path=None, content=None, from_format='', report=Fals
>>> import opensysml
>>> migrated = opensysml.migrate("sysml", file_path="Vehicle.mdzip", report=True)
>>> migrated.report.summary
'migrated 93 element(s): 78 mapped, 12 approximated, 3 unmapped (...)'
'migrated 93 element(s): 77 mapped, 13 approximated, 3 unmapped (...)'
>>> migrated.write("Vehicle.sysml")
'Vehicle.sysml'
"""
Expand Down
4 changes: 2 additions & 2 deletions client/rust/opensysml/tests/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ fn a_v1_model_is_migrated_and_refused_by_convert() {
migrated.report.unmapped,
migrated.report.skipped
),
(78, 12, 3, 2)
(77, 13, 3, 2)
);
assert_eq!(migrated.report.entries.len(), 95);
assert_eq!(migrated.report.by_verdict("unmapped").len(), 3);
Expand All @@ -315,7 +315,7 @@ fn a_v1_model_is_migrated_and_refused_by_convert() {
assert_eq!(inline.to_format, "ttl");
assert!(inline.source_path.is_none());
assert!(inline.report.entries.is_empty());
assert_eq!(inline.report.mapped, 78);
assert_eq!(inline.report.mapped, 77);

let refused = connection.convert(
"sysml",
Expand Down
6 changes: 3 additions & 3 deletions conformance/scenarios/16-migrate.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"experimental": true
},
"contains": {
"report.summary": "migrated 93 element(s): 78 mapped, 12 approximated, 3 unmapped"
"report.summary": "migrated 93 element(s): 77 mapped, 13 approximated, 3 unmapped"
},
"non_empty": [
"experimental_notice",
Expand Down Expand Up @@ -63,8 +63,8 @@
"response": {
"from_format": "xmi",
"report": {
"mapped": 78,
"approximated": 12,
"mapped": 77,
"approximated": 13,
"unmapped": 3,
"skipped": 2
}
Expand Down
4 changes: 2 additions & 2 deletions docs/guide/11-migrating-from-sysml-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ need attention first:
## approximated (11)
«Trace» Abstraction Requirements::<Abstraction> _dep_trace (a trace is written as a plain dependency)
«TestCase» Activity Requirements::Mass Test _tc_mass -> Requirements::'Mass Test' (the test case's behavior is not migrated; only its verified requirements are)
Actor Vehicle Design::Driver _actor_driver -> 'Vehicle Design'::Driver (a UML actor is written as a part def)
Actor Vehicle Design::Driver _actor_driver -> 'Vehicle Design'::Driver (a UML actor is written as a part usage)
«FlowPort» Port Vehicle Design::Engine::speedIn _port_speedIn -> 'Vehicle Design'::Engine::speedIn (a port typed by a DataType is written as a port holding one directed attribute)
…
Property Vehicle Design::Vehicle::totalMass _prop_total -> 'Vehicle Design'::Vehicle::totalMass (opaque expression copied verbatim (language SysML))
Expand All @@ -119,7 +119,7 @@ how, or why not. The columns are tab-separated, so `cut` and `awk` read them.
chosen (the root model's members are written at the top level; an English constraint body was
translated to a v2 expression).
- **approximated** — written as the nearest v2 construct, and the note says what was lost. Some
of these are simply how v2 spells the idea (a UML actor is a `part def`; a flow port typed by a
of these are simply how v2 spells the idea (a `«Trace»` is a `dependency`; a flow port typed by a
data type is a port holding one directed attribute; a `«Trace»` is a `dependency`). Others
record a v1 tag that v2 has no home for (`isEncapsulated`, a value type's `unit` and
`quantityKind`), or an opaque expression copied verbatim because its declared language is
Expand Down
52 changes: 32 additions & 20 deletions docs/project/sysml-v1-transformation-census-baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
{
"name": "fixtures",
"files": 101
"files": 103
}
],
"counts": {
Expand Down Expand Up @@ -98,6 +98,10 @@
"pssm": 0,
"fixtures": 1
},
"uml:Actor": {
"pssm": 0,
"fixtures": 8
},
"uml:AddStructuralFeatureValueAction": {
"pssm": 525,
"fixtures": 18
Expand Down Expand Up @@ -136,7 +140,7 @@
},
"uml:Class": {
"pssm": 311,
"fixtures": 488
"fixtures": 490
},
"uml:ClearAssociationAction": {
"pssm": 0,
Expand Down Expand Up @@ -244,7 +248,7 @@
},
"uml:Property": {
"pssm": 25,
"fixtures": 466
"fixtures": 468
},
"uml:Property[qualifier]": {
"pssm": 0,
Expand Down Expand Up @@ -348,7 +352,7 @@
},
"uml:UseCase": {
"pssm": 0,
"fixtures": 10
"fixtures": 12
},
"uml:ValueSpecificationAction": {
"pssm": 1061,
Expand Down Expand Up @@ -20987,16 +20991,18 @@
],
"operations": [],
"ocl": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"status": "faithful",
"status": "approximate",
"implementation": [
"internal/translate/migrate/usecase.go:actorMember",
"internal/translate/migrate/usecase.go:actorLink",
"internal/translate/migrate/classify.go:classifyClass"
],
"tests": [
"tests/migrate/migrate_test.go:TestGoldenNotation"
],
"reason": "",
"scope": []
"reason": "an actor is written as a part usage, not a part def: the actor lines of a use case diagram are connections, which join usages",
"scope": [
"uml:Actor"
]
},
{
"name": "IncludeFeatureTyping_Mapping",
Expand Down Expand Up @@ -21063,16 +21069,18 @@
"type"
],
"ocl": "sha256:719917ab2ec0a4e8566e0084ac378f0182dd8f3ed98522ab6c780ed6a5001349",
"status": "faithful",
"status": "approximate",
"implementation": [
"internal/translate/migrate/usecase.go:actorMember",
"internal/translate/migrate/usecase.go:connectActor",
"internal/translate/migrate/classify.go:classifyClass"
],
"tests": [
"tests/migrate/migrate_test.go:TestGoldenNotation"
],
"reason": "",
"scope": []
"reason": "the use case owns no actor member: the association is written as a connection between the actor's part usage and the use case usage",
"scope": [
"uml:Actor"
]
},
{
"name": "UseCaseActorMembership_Mapping",
Expand All @@ -21089,16 +21097,18 @@
"ownedMemberParameter"
],
"ocl": "sha256:350dd57e7124d89991e86930a62206324b4913cc22f5dfbc212c7fb53353cc02",
"status": "faithful",
"status": "approximate",
"implementation": [
"internal/translate/migrate/usecase.go:actorMember",
"internal/translate/migrate/usecase.go:connectActor",
"internal/translate/migrate/classify.go:classifyClass"
],
"tests": [
"tests/migrate/migrate_test.go:TestGoldenNotation"
],
"reason": "",
"scope": []
"reason": "the use case owns no actor member: the association is written as a connection between the actor's part usage and the use case usage",
"scope": [
"uml:Actor"
]
},
{
"name": "UseCaseActor_Mapping",
Expand All @@ -21116,16 +21126,18 @@
"ownedRelationship"
],
"ocl": "sha256:a3c87cbca08a5c2087397677178ad9e15063e3bad7ab80893904b89e3c79001c",
"status": "faithful",
"status": "approximate",
"implementation": [
"internal/translate/migrate/usecase.go:actorMember",
"internal/translate/migrate/usecase.go:connectActor",
"internal/translate/migrate/classify.go:classifyClass"
],
"tests": [
"tests/migrate/migrate_test.go:TestGoldenNotation"
],
"reason": "",
"scope": []
"reason": "the use case owns no actor member: the association is written as a connection between the actor's part usage and the use case usage",
"scope": [
"uml:Actor"
]
},
{
"name": "UseCaseEmptySubjectReferenceUsage_Mapping",
Expand Down
Loading
Loading