diff --git a/capella2polarion/elements/serialize.py b/capella2polarion/elements/serialize.py
index 6a0bfcf8..7a1ee35d 100644
--- a/capella2polarion/elements/serialize.py
+++ b/capella2polarion/elements/serialize.py
@@ -4,6 +4,7 @@
from __future__ import annotations
import base64
+import collections
import collections.abc as cabc
import logging
import mimetypes
@@ -113,6 +114,7 @@ def _generic_work_item(
raw_description = getattr(obj, "description", markupsafe.Markup(""))
uuids, value = _sanitize_description(obj, raw_description, ctx)
ctx.setdefault("DESCR_REFERENCES", {})[obj.uuid] = uuids
+ requirement_types = _get_requirement_types_text(obj)
return CapellaWorkItem(
type=helpers.resolve_element_type(xtype),
title=obj.name,
@@ -120,9 +122,48 @@ def _generic_work_item(
description=value,
status="open",
uuid_capella=obj.uuid,
+ **requirement_types,
)
+def _get_requirement_types_text(
+ obj: common.GenericElement,
+) -> dict[str, dict[str, str]]:
+ type_texts = collections.defaultdict(list)
+ for req in obj.requirements:
+ if req is None:
+ logger.error(
+ "RequirementsRelation with broken target found %r", obj.name
+ )
+ continue
+
+ if not (req.type and req.text):
+ logger.warning(
+ "Requirement without text or type found %r", req.name
+ )
+ continue
+
+ type_texts[req.type.long_name].append(req.text)
+ return _format_texts(type_texts)
+
+
+def _format_texts(
+ type_texts: dict[str, list[str]]
+) -> dict[str, dict[str, str]]:
+ def _format(texts: list[str]) -> dict[str, str]:
+ if len(texts) > 1:
+ items = "".join(f"
{text}" for text in texts)
+ text = f""
+ else:
+ text = texts[0]
+ return {"type": "text/html", "value": text}
+
+ requirement_types = {}
+ for typ, texts in type_texts.items():
+ requirement_types[typ.lower()] = _format(texts)
+ return requirement_types
+
+
def _sanitize_description(
obj: common.GenericElement, descr: markupsafe.Markup, ctx: dict[str, t.Any]
) -> tuple[list[str], markupsafe.Markup]:
diff --git a/tests/test_elements.py b/tests/test_elements.py
index de07e915..7d0f5800 100644
--- a/tests/test_elements.py
+++ b/tests/test_elements.py
@@ -62,6 +62,12 @@
TEST_WI_CHECKSUM = (
"73508ec0c3048c5b33316dfa56ef5e5f4179ff69efaa209e47ab65b111415e82"
)
+TEST_REQ_TEXT = (
+ "Test requirement 1 really l o n g text that is way too long to "
+ "display here as that
\n\n< > " '
\n\n\n\t- "
+ "This is a list
\n\t- an unordered one
\n
\n\n\n\t"
+ "- Ordered list
\n\t- Ok
\n
\n"
+)
class TestDiagramElements:
@@ -478,7 +484,7 @@ def test__decode_diagram():
@pytest.mark.parametrize(
"uuid,expected",
[
- (
+ pytest.param(
TEST_ELEMENT_UUID,
{
"type": "logicalComponent",
@@ -486,9 +492,14 @@ def test__decode_diagram():
"uuid_capella": TEST_ELEMENT_UUID,
"description_type": "text/html",
"description": markupsafe.Markup(TEST_DESCR),
+ "reqtype": {
+ "type": "text/html",
+ "value": markupsafe.Markup(TEST_REQ_TEXT),
+ },
},
+ id="logicalComponent",
),
- (
+ pytest.param(
TEST_OCAP_UUID,
{
"type": "operationalCapability",
@@ -501,8 +512,9 @@ def test__decode_diagram():
"postCondition": {"type": "text/html", "value": ""},
},
},
+ id="operationalCapability",
),
- (
+ pytest.param(
TEST_WE_UUID,
{
"type": "entity",
@@ -511,8 +523,9 @@ def test__decode_diagram():
"description_type": "text/html",
"description": markupsafe.Markup(TEST_WE_DESCR),
},
+ id="entity",
),
- (
+ pytest.param(
TEST_ACTOR_UUID,
{
"type": "logicalActor",
@@ -524,8 +537,9 @@ def test__decode_diagram():
"and greatest mage of all time.\n"
),
},
+ id="logicalActor",
),
- (
+ pytest.param(
TEST_PHYS_COMP,
{
"type": "physicalComponent",
@@ -534,8 +548,9 @@ def test__decode_diagram():
"description_type": "text/html",
"description": markupsafe.Markup(""),
},
+ id="physicalComponent",
),
- (
+ pytest.param(
TEST_PHYS_NODE,
{
"type": "physicalComponentNode",
@@ -544,8 +559,9 @@ def test__decode_diagram():
"description_type": "text/html",
"description": markupsafe.Markup(""),
},
+ id="physicalComponentNode",
),
- (
+ pytest.param(
TEST_SCENARIO,
{
"type": "scenario",
@@ -558,8 +574,9 @@ def test__decode_diagram():
"postCondition": {"type": "text/html", "value": ""},
},
},
+ id="scenario",
),
- (
+ pytest.param(
TEST_CAP_REAL,
{
"type": "capabilityRealization",
@@ -572,8 +589,9 @@ def test__decode_diagram():
"postCondition": {"type": "text/html", "value": ""},
},
},
+ id="capabilityRealization",
),
- (
+ pytest.param(
TEST_CONSTRAINT,
{
"type": "constraint",
@@ -584,6 +602,7 @@ def test__decode_diagram():
"This is a test context.Make Food"
),
},
+ id="constraint",
),
],
)