From f8f6628259cf50b272cf0513ebfaf6d43ea8bee9 Mon Sep 17 00:00:00 2001 From: Michael Harbarth Date: Fri, 18 Oct 2024 14:06:19 +0200 Subject: [PATCH] fix: Don't generate associations for primitive types Also move the associations that are generated back into the package they belong, instead of aggregating all of them in the root package. Co-authored-by: Martin Lehmann --- capella_ros_tools/importer.py | 90 ++-- tests/data/data_model/example_msgs.yaml | 685 ++++++++++++------------ 2 files changed, 388 insertions(+), 387 deletions(-) diff --git a/capella_ros_tools/importer.py b/capella_ros_tools/importer.py index 29e5509..24b27f8 100644 --- a/capella_ros_tools/importer.py +++ b/capella_ros_tools/importer.py @@ -35,7 +35,7 @@ def __init__( self.messages = data_model.MessagePkgDef("root", [], []) self._promise_ids: dict[str, None] = {} self._promise_id_refs: dict[str, None] = {} - self._needed_associations: dict[str, str] = {} + self._needed_associations: dict[str, dict[str, tuple[str, str]]] = {} self._license_header = None if license_header_path is not None: self._license_header = license_header_path.read_text("utf-8") @@ -149,7 +149,9 @@ def _convert_class( }, } props.append(prop_yml) - self._needed_associations[prop_promise_id] = promise_id + self._needed_associations.setdefault(pkg_name, {})[ + prop_promise_id + ] = (promise_id, promise_ref) yml = { "promise_id": promise_id, @@ -216,38 +218,58 @@ def to_yaml( p for p in self._promise_id_refs if p not in self._promise_ids ] - associations = [] - for prop_promise_id, promise_id in self._needed_associations.items(): - if prop_promise_id in needed_types: - continue - associations.append( - { - "find": { - "navigable_members": [decl.Promise(prop_promise_id)], - }, - "sync": { - "members": [ - { - "find": { - "type": decl.Promise(promise_id), - }, - "set": { - "_type": "Property", - "kind": "ASSOCIATION", - "min_card": decl.NewObject( - "LiteralNumericValue", value="1" - ), - "max_card": decl.NewObject( - "LiteralNumericValue", value="1" - ), - }, - } - ], - }, - } - ) - if associations: - instructions[0]["sync"]["owned_associations"] = associations + for pkg_name, needed_associations in self._needed_associations.items(): + associations = [] + for prop_promise_id, ( + promise_id, + promise_ref, + ) in needed_associations.items(): + if promise_ref in needed_types: + instructions.append( + { + "parent": decl.Promise(prop_promise_id), + "set": { + "kind": "UNSET", + }, + } + ) + continue + associations.append( + { + "find": { + "navigable_members": [ + decl.Promise(prop_promise_id) + ], + }, + "sync": { + "members": [ + { + "find": { + "type": decl.Promise(promise_id), + }, + "set": { + "_type": "Property", + "kind": "ASSOCIATION", + "min_card": decl.NewObject( + "LiteralNumericValue", value="1" + ), + "max_card": decl.NewObject( + "LiteralNumericValue", value="1" + ), + }, + } + ], + }, + } + ) + + if associations: + package = next( + p + for p in instructions[0]["sync"]["packages"] + if p["find"]["name"] == pkg_name + ) + package["sync"]["owned_associations"] = associations if not needed_types: return decl.dump(instructions) diff --git a/tests/data/data_model/example_msgs.yaml b/tests/data/data_model/example_msgs.yaml index df017f6..9e237bc 100644 --- a/tests/data/data_model/example_msgs.yaml +++ b/tests/data/data_model/example_msgs.yaml @@ -1,412 +1,391 @@ # Copyright DB InfraGO AG and contributors # SPDX-License-Identifier: Apache-2.0 -- parent: !uuid "00000000-0000-0000-0000-000000000000" +- parent: !uuid '00000000-0000-0000-0000-000000000000' sync: - owned_associations: - - find: - navigable_members: - - !promise package1.SampleClass.sample_field1 - sync: - members: + packages: + - find: + name: package1 + sync: + classes: + - find: + name: SampleClass + promise_id: package1.SampleClass + set: + description: 'SampleClass.msg The first comment block at the top of the + file is added to the class description of SampleClass. ' + sync: + properties: - find: - type: !promise package1.SampleClass + name: sample_field1 + promise_id: package1.SampleClass.sample_field1 set: - _type: Property - kind: ASSOCIATION + description: 'This block comment is added to the property description + of sample_field1. This block comment is also added to the property + description of sample_field1. ' + kind: COMPOSITION + max_card: !new_object + _type: LiteralNumericValue + value: '10' min_card: !new_object _type: LiteralNumericValue - value: "1" + value: '0' + type: !promise 'package1.uint8' + - find: + name: sample_field2 + promise_id: package1.SampleClass.sample_field2 + set: + description: 'This block comment is added to the property descriptions + of sample_field2 and sample_field3. ' + kind: COMPOSITION max_card: !new_object _type: LiteralNumericValue - value: "1" - - find: - navigable_members: - - !promise package1.SampleClass.sample_field2 - sync: - members: + value: '*' + min_card: !new_object + _type: LiteralNumericValue + value: '0' + type: !promise 'package2.SampleClassEnum' - find: - type: !promise package1.SampleClass + name: sample_field3 + promise_id: package1.SampleClass.sample_field3 set: - _type: Property - kind: ASSOCIATION + description: 'This block comment is added to the property descriptions + of sample_field2 and sample_field3. ' + kind: COMPOSITION + max_card: !new_object + _type: LiteralNumericValue + value: '3' min_card: !new_object _type: LiteralNumericValue - value: "1" + value: '3' + type: !promise 'package1.uint8' + - find: + name: sample_field4 + promise_id: package1.SampleClass.sample_field4 + set: + description: 'This block comment is added to the property descriptions + of sample_field4 and sample_field5. Fields in SampleClass can reference + enums in other files. The property sample_field4 is of type SampleEnum. + cf. SampleEnum ' + kind: COMPOSITION max_card: !new_object _type: LiteralNumericValue - value: "1" - - find: - navigable_members: - - !promise package1.SampleClass.sample_field3 - sync: - members: + value: '1' + min_card: !new_object + _type: LiteralNumericValue + value: '1' + type: !promise 'SampleEnum.SampleEnum' - find: - type: !promise package1.SampleClass + name: sample_field5 + promise_id: package1.SampleClass.sample_field5 set: - _type: Property - kind: ASSOCIATION + description: 'This block comment is added to the property descriptions + of sample_field4 and sample_field5. This inline comment is added + to the property description of sample_field5. The property sample_field5 + is of type SampleEnumValue. cf. SampleEnum, SAMPLE_ENUM_VALUE_XXX ' + kind: COMPOSITION + max_card: !new_object + _type: LiteralNumericValue + value: '1' min_card: !new_object _type: LiteralNumericValue - value: "1" - max_card: !new_object + value: '1' + type: !promise 'SampleEnum.SampleEnumValue' + enumerations: + - find: + name: SampleEnumValue + promise_id: SampleEnum.SampleEnumValue + set: + description: 'SampleEnum.msg This block comment is added to the enum description + of SampleEnumValue. ' + sync: + literals: + - find: + name: RED + set: + description: '' + value: !new_object _type: LiteralNumericValue - value: "1" - - find: - navigable_members: - - !promise package1.SampleClass.sample_field4 - sync: - members: + value: '0' - find: - type: !promise package1.SampleClass + name: BLUE set: - _type: Property - kind: ASSOCIATION - min_card: !new_object + description: 'This inline comment is added to the enum literal description + of BLUE. ' + value: !new_object _type: LiteralNumericValue - value: "1" - max_card: !new_object + value: '1' + - find: + name: YELLOW + set: + description: 'This block comment is added to the enum literal descriptions + of YELLOW and GREEN. ' + value: !new_object _type: LiteralNumericValue - value: "1" - - find: - navigable_members: - - !promise package1.SampleClass.sample_field5 - sync: - members: + value: '2' - find: - type: !promise package1.SampleClass + name: GREEN set: - _type: Property - kind: ASSOCIATION - min_card: !new_object + description: 'This block comment is added to the enum literal descriptions + of YELLOW and GREEN. ' + value: !new_object _type: LiteralNumericValue - value: "1" - max_card: !new_object + value: '3' + - find: + name: SampleEnum + promise_id: SampleEnum.SampleEnum + set: + description: 'This block comment is added to the enum description of SampleEnum. + In a file, there can only be one or no enum whose literal names do not + share a common prefix. ' + sync: + literals: + - find: + name: OK + set: + description: '' + value: !new_object _type: LiteralNumericValue - value: "1" - - find: - navigable_members: - - !promise package2.SampleClassEnum.status - sync: - members: + value: '0' - find: - type: !promise package2.SampleClassEnum + name: WARN + set: + description: '' + value: !new_object + _type: LiteralNumericValue + value: '1' + - find: + name: ERROR + set: + description: '' + value: !new_object + _type: LiteralNumericValue + value: '2' + - find: + name: STALE + set: + description: '' + value: !new_object + _type: LiteralNumericValue + value: '3' + owned_associations: + - find: + navigable_members: + - !promise 'package1.SampleClass.sample_field2' + sync: + members: + - find: + type: !promise 'package1.SampleClass' set: _type: Property kind: ASSOCIATION + max_card: !new_object + _type: LiteralNumericValue + value: '1' min_card: !new_object _type: LiteralNumericValue - value: "1" + value: '1' + - find: + navigable_members: + - !promise 'package1.SampleClass.sample_field4' + sync: + members: + - find: + type: !promise 'package1.SampleClass' + set: + _type: Property + kind: ASSOCIATION max_card: !new_object _type: LiteralNumericValue - value: "1" - - find: - navigable_members: - - !promise package2.SampleClassEnum.color - sync: - members: + value: '1' + min_card: !new_object + _type: LiteralNumericValue + value: '1' + - find: + navigable_members: + - !promise 'package1.SampleClass.sample_field5' + sync: + members: - find: - type: !promise package2.SampleClassEnum + type: !promise 'package1.SampleClass' set: _type: Property kind: ASSOCIATION + max_card: !new_object + _type: LiteralNumericValue + value: '1' min_card: !new_object _type: LiteralNumericValue - value: "1" + value: '1' + - find: + name: package2 + sync: + classes: + - find: + name: SampleClassEnum + promise_id: package2.SampleClassEnum + set: + description: 'SampleClassEnum.msg Properties in SampleClassEnum can reference + enums in the same file. ' + sync: + properties: + - find: + name: status + promise_id: package2.SampleClassEnum.status + set: + description: 'The property status is of type SampleClassEnumStatus. ' + kind: COMPOSITION max_card: !new_object _type: LiteralNumericValue - value: "1" - - find: - navigable_members: - - !promise package2.SampleClassEnum.field - sync: - members: + value: '1' + min_card: !new_object + _type: LiteralNumericValue + value: '1' + type: !promise 'SampleClassEnum.SampleClassEnumStatus' - find: - type: !promise package2.SampleClassEnum + name: color + promise_id: package2.SampleClassEnum.color set: - _type: Property - kind: ASSOCIATION + description: 'The property color is of type Color. ' + kind: COMPOSITION + max_card: !new_object + _type: LiteralNumericValue + value: '1' min_card: !new_object _type: LiteralNumericValue - value: "1" + value: '1' + type: !promise 'SampleClassEnum.Color' + - find: + name: field + promise_id: package2.SampleClassEnum.field + set: + description: '' + kind: COMPOSITION max_card: !new_object _type: LiteralNumericValue - value: "1" - packages: - - find: - name: package1 - sync: - classes: - - promise_id: package1.SampleClass - find: - name: SampleClass + value: '1' + min_card: !new_object + _type: LiteralNumericValue + value: '1' + type: !promise 'package2.uint8' + enumerations: + - find: + name: SampleClassEnumStatus + promise_id: SampleClassEnum.SampleClassEnumStatus + set: + description: 'This block comment is added to the enum description of SampleClassEnumStatus. ' + sync: + literals: + - find: + name: OK + set: + description: '' + value: !new_object + _type: LiteralNumericValue + value: '0' + - find: + name: WARN + set: + description: '' + value: !new_object + _type: LiteralNumericValue + value: '1' + - find: + name: ERROR set: - description: "SampleClass.msg The first comment block at the top of the file is added to the class description of SampleClass. " - sync: - properties: - - promise_id: package1.SampleClass.sample_field1 - find: - name: sample_field1 - set: - description: "This block comment is added to the property description of sample_field1. This block comment is also added to the property description of sample_field1. " - type: !promise package1.uint8 - kind: COMPOSITION - min_card: !new_object - _type: LiteralNumericValue - value: "0" - max_card: !new_object - _type: LiteralNumericValue - value: "10" - - promise_id: package1.SampleClass.sample_field2 - find: - name: sample_field2 - set: - description: "This block comment is added to the property descriptions of sample_field2 and sample_field3. " - type: !promise package2.SampleClassEnum - kind: COMPOSITION - min_card: !new_object - _type: LiteralNumericValue - value: "0" - max_card: !new_object - _type: LiteralNumericValue - value: "*" - - promise_id: package1.SampleClass.sample_field3 - find: - name: sample_field3 - set: - description: "This block comment is added to the property descriptions of sample_field2 and sample_field3. " - type: !promise package1.uint8 - kind: COMPOSITION - min_card: !new_object - _type: LiteralNumericValue - value: "3" - max_card: !new_object - _type: LiteralNumericValue - value: "3" - - promise_id: package1.SampleClass.sample_field4 - find: - name: sample_field4 - set: - description: "This block comment is added to the property descriptions of sample_field4 and sample_field5. Fields in SampleClass can reference enums in other files. The property sample_field4 is of type SampleEnum. cf. SampleEnum " - type: !promise SampleEnum.SampleEnum - kind: COMPOSITION - min_card: !new_object - _type: LiteralNumericValue - value: "1" - max_card: !new_object - _type: LiteralNumericValue - value: "1" - - promise_id: package1.SampleClass.sample_field5 - find: - name: sample_field5 - set: - description: "This block comment is added to the property descriptions of sample_field4 and sample_field5. This inline comment is added to the property description of sample_field5. The property sample_field5 is of type SampleEnumValue. cf. SampleEnum, SAMPLE_ENUM_VALUE_XXX " - type: !promise SampleEnum.SampleEnumValue - kind: COMPOSITION - min_card: !new_object - _type: LiteralNumericValue - value: "1" - max_card: !new_object - _type: LiteralNumericValue - value: "1" - enumerations: - - promise_id: SampleEnum.SampleEnumValue - find: - name: SampleEnumValue + description: '' + value: !new_object + _type: LiteralNumericValue + value: '2' + - find: + name: STALE set: - description: "SampleEnum.msg This block comment is added to the enum description of SampleEnumValue. " - sync: - literals: - - find: - name: RED - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "0" - - find: - name: BLUE - set: - description: "This inline comment is added to the enum literal description of BLUE. " - value: !new_object - _type: LiteralNumericValue - value: "1" - - find: - name: YELLOW - set: - description: "This block comment is added to the enum literal descriptions of YELLOW and GREEN. " - value: !new_object - _type: LiteralNumericValue - value: "2" - - find: - name: GREEN - set: - description: "This block comment is added to the enum literal descriptions of YELLOW and GREEN. " - value: !new_object - _type: LiteralNumericValue - value: "3" - - promise_id: SampleEnum.SampleEnum - find: - name: SampleEnum + description: '' + value: !new_object + _type: LiteralNumericValue + value: '3' + - find: + name: Color + promise_id: SampleClassEnum.Color + set: + description: 'This block comment is added to the enum description of Color. ' + sync: + literals: + - find: + name: RED set: - description: "This block comment is added to the enum description of SampleEnum. In a file, there can only be one or no enum whose literal names do not share a common prefix. " - sync: - literals: - - find: - name: OK - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "0" - - find: - name: WARN - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "1" - - find: - name: ERROR - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "2" - - find: - name: STALE - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "3" - - find: - name: package2 - sync: - classes: - - promise_id: package2.SampleClassEnum - find: - name: SampleClassEnum + description: '' + value: !new_object + _type: LiteralNumericValue + value: '0' + - find: + name: BLUE set: - description: "SampleClassEnum.msg Properties in SampleClassEnum can reference enums in the same file. " - sync: - properties: - - promise_id: package2.SampleClassEnum.status - find: - name: status - set: - description: "The property status is of type SampleClassEnumStatus. " - type: !promise SampleClassEnum.SampleClassEnumStatus - kind: COMPOSITION - min_card: !new_object - _type: LiteralNumericValue - value: "1" - max_card: !new_object - _type: LiteralNumericValue - value: "1" - - promise_id: package2.SampleClassEnum.color - find: - name: color - set: - description: "The property color is of type Color. " - type: !promise SampleClassEnum.Color - kind: COMPOSITION - min_card: !new_object - _type: LiteralNumericValue - value: "1" - max_card: !new_object - _type: LiteralNumericValue - value: "1" - - promise_id: package2.SampleClassEnum.field - find: - name: field - set: - description: "" - type: !promise package2.uint8 - kind: COMPOSITION - min_card: !new_object - _type: LiteralNumericValue - value: "1" - max_card: !new_object - _type: LiteralNumericValue - value: "1" - enumerations: - - promise_id: SampleClassEnum.SampleClassEnumStatus - find: - name: SampleClassEnumStatus + description: '' + value: !new_object + _type: LiteralNumericValue + value: '1' + - find: + name: YELLOW set: - description: "This block comment is added to the enum description of SampleClassEnumStatus. " - sync: - literals: - - find: - name: OK - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "0" - - find: - name: WARN - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "1" - - find: - name: ERROR - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "2" - - find: - name: STALE - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "3" - - promise_id: SampleClassEnum.Color - find: - name: Color + description: '' + value: !new_object + _type: LiteralNumericValue + value: '2' + owned_associations: + - find: + navigable_members: + - !promise 'package2.SampleClassEnum.status' + sync: + members: + - find: + type: !promise 'package2.SampleClassEnum' set: - description: "This block comment is added to the enum description of Color. " - sync: - literals: - - find: - name: RED - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "0" - - find: - name: BLUE - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "1" - - find: - name: YELLOW - set: - description: "" - value: !new_object - _type: LiteralNumericValue - value: "2" - -- parent: !uuid "00000000-0000-0000-0000-000000000001" + _type: Property + kind: ASSOCIATION + max_card: !new_object + _type: LiteralNumericValue + value: '1' + min_card: !new_object + _type: LiteralNumericValue + value: '1' + - find: + navigable_members: + - !promise 'package2.SampleClassEnum.color' + sync: + members: + - find: + type: !promise 'package2.SampleClassEnum' + set: + _type: Property + kind: ASSOCIATION + max_card: !new_object + _type: LiteralNumericValue + value: '1' + min_card: !new_object + _type: LiteralNumericValue + value: '1' +- parent: !promise 'package1.SampleClass.sample_field1' + set: + kind: UNSET +- parent: !promise 'package1.SampleClass.sample_field3' + set: + kind: UNSET +- parent: !promise 'package2.SampleClassEnum.field' + set: + kind: UNSET +- parent: !uuid '00000000-0000-0000-0000-000000000001' sync: packages: - - find: - name: "Data Types" - sync: - datatypes: - - promise_id: package1.uint8 - find: - name: uint8 - _type: NumericType - - promise_id: package2.uint8 - find: - name: uint8 - _type: NumericType + - find: + name: Data Types + sync: + datatypes: + - find: + _type: NumericType + name: uint8 + promise_id: package1.uint8 + - find: + _type: NumericType + name: uint8 + promise_id: package2.uint8