Skip to content

Commit

Permalink
fix: Add association for every composition
Browse files Browse the repository at this point in the history
  • Loading branch information
huyenngn committed Mar 13, 2024
1 parent 9179d6e commit 18b6648
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 153 deletions.
4 changes: 2 additions & 2 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"-i",
"tests/data/data_model/example_msgs",
"-m",
"tests/data/ empty_project_60",
"tests/data/empty_project_60",
"-l",
"la",
"--no-deps"
Expand All @@ -57,7 +57,7 @@
"-i",
"git+https://github.com/DSD-DBS/dsd-ros-msg-definitions-oss",
"-m",
"tests/data/ empty_project_60",
"tests/data/empty_project_60",
"-l",
"la"
]
Expand Down
5 changes: 3 additions & 2 deletions capella_ros_tools/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,22 @@ def import_msgs(
) -> None:
"""Import ROS messages into a Capella data package."""

root_uuid = getattr(model, layer).uuid
root_uuid = getattr(model, layer).data_package.uuid
types_uuid = model.sa.data_package.uuid

yml = importer.Importer(input, no_deps).to_yaml(root_uuid, types_uuid)
if output:
output.write_text(yml, encoding="utf-8")
else:
decl.apply(model, io.StringIO(yml))
model.save()


@cli.command("export")
@click.option(
"-m",
"--model",
type=cli_helpers.ModelCLI,
type=cli_helpers.ModelCLI(),
required=True,
help="Path to the Capella model.",
)
Expand Down
67 changes: 48 additions & 19 deletions capella_ros_tools/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,47 +65,61 @@ def _convert_package(
classes = []
enums = []
packages = []
associations = []

for msg_def in pkg_def.messages:
if msg_def.fields:
classes.append(self._convert_class(pkg_def.name, msg_def))
cls_yml, cls_associations = self._convert_class(
pkg_def.name, msg_def
)
classes.append(cls_yml)
associations.extend(cls_associations)
for enum_def in msg_def.enums:
enums.append(self._convert_enum(enum_def))

for new_pkg in pkg_def.packages:
yml = {
new_yml = {
"find": {
"name": new_pkg.name,
},
}

if new_sync := self._convert_package(new_pkg):
yml["sync"] = new_sync

packages.append(yml)
} | self._convert_package(new_pkg)
packages.append(new_yml)

sync = {}
sync: dict = {}
if classes:
sync["classes"] = classes
if enums:
sync["enumerations"] = enums
if packages:
sync["packages"] = packages

return sync
extend: dict = {}
if associations:
extend["owned_associations"] = associations

yml = {}
if sync:
yml["sync"] = sync
if extend:
yml["extend"] = extend

return yml

def _convert_class(
self, pkg_name: str, msg_def: data_model.MessageDef
) -> dict:
) -> tuple[dict, list[dict]]:
promise_id = f"{pkg_name}.{msg_def.name}"
self._promise_ids.add(promise_id)
props = []
associations = []
for field_def in msg_def.fields:
prop_promise_id = f"{promise_id}.{field_def.name}"
promise_ref = (
f"{field_def.type.package or pkg_name}.{field_def.type.name}"
)
self._promise_id_refs.add(promise_ref)
prop_yml = {
"promise_id": prop_promise_id,
"name": field_def.name,
"type": decl.Promise(promise_ref),
"kind": "COMPOSITION",
Expand All @@ -124,6 +138,25 @@ def _convert_class(
prop_yml["max_value"] = decl.NewObject(
"LiteralNumericValue", value=field_def.type.range.max
)

associations.append(
{
"navigable_members": [decl.Promise(prop_promise_id)],
"members": [
{
"_type": "Property",
"type": decl.Promise(promise_id),
"kind": "ASSOCIATION",
"min_card": decl.NewObject(
"LiteralNumericValue", value="1"
),
"max_card": decl.NewObject(
"LiteralNumericValue", value="1"
),
}
],
}
)
props.append(prop_yml)

yml = {
Expand All @@ -136,7 +169,7 @@ def _convert_class(
"properties": props,
},
}
return yml
return yml, associations

def _convert_enum(self, enum_def: data_model.EnumDef) -> dict:
promise_id = f"types.{enum_def.name}"
Expand All @@ -163,15 +196,11 @@ def _convert_enum(self, enum_def: data_model.EnumDef) -> dict:

return yml

def to_yaml(self, layer_data_uuid: str, sa_data_uuid) -> str:
def to_yaml(self, layer_data_uuid: str, sa_data_uuid: str) -> str:
"""Import ROS messages into a Capella data package."""
instructions = [
{
"parent": decl.UUIDReference(
helpers.UUIDString(layer_data_uuid)
),
"sync": self._convert_package(self.messages),
}
{"parent": decl.UUIDReference(helpers.UUIDString(layer_data_uuid))}
| self._convert_package(self.messages),
]
if needed_types := self._promise_id_refs - self._promise_ids:
datatypes = [
Expand Down
124 changes: 116 additions & 8 deletions tests/data/data_model/example_msgs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
set:
description: "SampleClass.msg The first comment block at the top of the file is added to the class description of SampleClass. "
properties:
- name: sample_field1
- promise_id: package1.SampleClass.sample_field1
name: sample_field1
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
Expand All @@ -30,7 +31,8 @@
max_value: !new_object
_type: LiteralNumericValue
value: "10"
- name: sample_field2
- promise_id: package1.SampleClass.sample_field2
name: sample_field2
description: "This block comment is added to the property descriptions of sample_field2 and sample_field3. "
type: !promise package1.uint8
kind: COMPOSITION
Expand All @@ -40,7 +42,8 @@
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- name: sample_field3
- promise_id: package1.SampleClass.sample_field3
name: sample_field3
description: "This block comment is added to the property descriptions of sample_field2 and sample_field3. "
type: !promise package1.uint8
kind: COMPOSITION
Expand All @@ -50,7 +53,8 @@
max_card: !new_object
_type: LiteralNumericValue
value: "*"
- name: sample_field4
- promise_id: package1.SampleClass.sample_field4
name: sample_field4
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 types.SampleEnum
kind: COMPOSITION
Expand All @@ -60,7 +64,8 @@
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- name: sample_field5
- promise_id: package1.SampleClass.sample_field5
name: sample_field5
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 types.SampleEnumValue
kind: COMPOSITION
Expand Down Expand Up @@ -123,6 +128,68 @@
value: !new_object
_type: LiteralNumericValue
value: "3"
extend:
owned_associations:
- navigable_members:
- !promise package1.SampleClass.sample_field1
members:
- _type: Property
type: !promise package1.SampleClass
kind: ASSOCIATION
min_card: !new_object
_type: LiteralNumericValue
value: "1"
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- navigable_members:
- !promise package1.SampleClass.sample_field2
members:
- _type: Property
type: !promise package1.SampleClass
kind: ASSOCIATION
min_card: !new_object
_type: LiteralNumericValue
value: "1"
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- navigable_members:
- !promise package1.SampleClass.sample_field3
members:
- _type: Property
type: !promise package1.SampleClass
kind: ASSOCIATION
min_card: !new_object
_type: LiteralNumericValue
value: "1"
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- navigable_members:
- !promise package1.SampleClass.sample_field4
members:
- _type: Property
type: !promise package1.SampleClass
kind: ASSOCIATION
min_card: !new_object
_type: LiteralNumericValue
value: "1"
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- navigable_members:
- !promise package1.SampleClass.sample_field5
members:
- _type: Property
type: !promise package1.SampleClass
kind: ASSOCIATION
min_card: !new_object
_type: LiteralNumericValue
value: "1"
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- find:
name: package2
sync:
Expand All @@ -133,7 +200,8 @@
set:
description: "SampleClassEnum.msg Properties in SampleClassEnum can reference enums in the same file. "
properties:
- name: status
- promise_id: package2.SampleClassEnum.status
name: status
description: "The property status is of type SampleClassEnumStatus. "
type: !promise types.SampleClassEnumStatus
kind: COMPOSITION
Expand All @@ -143,7 +211,8 @@
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- name: color
- promise_id: package2.SampleClassEnum.color
name: color
description: "The property color is of type Color. "
type: !promise types.Color
kind: COMPOSITION
Expand All @@ -153,7 +222,8 @@
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- name: field
- promise_id: package2.SampleClassEnum.field
name: field
description: ""
type: !promise package2.uint8
kind: COMPOSITION
Expand Down Expand Up @@ -211,6 +281,44 @@
value: !new_object
_type: LiteralNumericValue
value: "2"
extend:
owned_associations:
- navigable_members:
- !promise package2.SampleClassEnum.status
members:
- _type: Property
type: !promise package2.SampleClassEnum
kind: ASSOCIATION
min_card: !new_object
_type: LiteralNumericValue
value: "1"
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- navigable_members:
- !promise package2.SampleClassEnum.color
members:
- _type: Property
type: !promise package2.SampleClassEnum
kind: ASSOCIATION
min_card: !new_object
_type: LiteralNumericValue
value: "1"
max_card: !new_object
_type: LiteralNumericValue
value: "1"
- navigable_members:
- !promise package2.SampleClassEnum.field
members:
- _type: Property
type: !promise package2.SampleClassEnum
kind: ASSOCIATION
min_card: !new_object
_type: LiteralNumericValue
value: "1"
max_card: !new_object
_type: LiteralNumericValue
value: "1"

- parent: !uuid "00000000-0000-0000-0000-000000000001"
sync:
Expand Down
Loading

0 comments on commit 18b6648

Please sign in to comment.