diff --git a/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py b/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py
index 2f129905a..8d0b559db 100644
--- a/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py
+++ b/strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py
@@ -1,5 +1,5 @@
# mypy: disable-error-code="no-untyped-def,union-attr,operator"
-from typing import Dict, List, Optional, Union
+from typing import Any, Dict, List, Optional, Tuple, Union
from reqif.models.reqif_data_type import ReqIFDataTypeDefinitionEnumeration
from reqif.models.reqif_spec_object import ReqIFSpecObject
@@ -34,7 +34,9 @@
GrammarElementFieldMultipleChoice,
GrammarElementFieldSingleChoice,
GrammarElementFieldString,
+ GrammarElementRelationParent,
)
+from strictdoc.helpers.ordered_set import OrderedSet
from strictdoc.helpers.string import (
create_safe_requirement_tag_string,
ensure_newline,
@@ -49,6 +51,12 @@ def __init__(self, *, enable_mid: bool, import_markup: Optional[str]):
self.map_spec_object_type_identifier_to_grammar_node_tags: Dict[
str, GrammarElement
] = {}
+ self.map_source_target_pairs_to_spec_relation_types: Dict[
+ Tuple[str, str], Any
+ ] = {}
+ self.unique_grammar_element_relations: Dict[
+ GrammarElement, OrderedSet[Tuple[str, Optional[str]]]
+ ] = {}
class P01_ReqIFToSDocConverter:
@@ -69,6 +77,16 @@ def convert_reqif_bundle(
):
return []
+ for (
+ spec_relation_
+ ) in reqif_bundle.core_content.req_if_content.spec_relations:
+ spec_relation_type_ = reqif_bundle.lookup.get_spec_type_by_ref(
+ spec_relation_.relation_type_ref
+ )
+ context.map_source_target_pairs_to_spec_relation_types[
+ (spec_relation_.source, spec_relation_.target)
+ ] = spec_relation_type_
+
documents: List[SDocDocument] = []
for (
specification
@@ -131,7 +149,9 @@ def _create_document_from_reqif_specification(
# StrictDoc document is not created with irrelevant grammar elements that
# actually belong to other Specifications in this ReqIF bundle.
# Using Dict as an ordered set.
- spec_object_type_identifiers_used_by_this_document: Dict[str, None] = {}
+ spec_object_type_identifiers_used_by_this_document: OrderedSet[str] = (
+ OrderedSet()
+ )
def node_converter_lambda(
current_hierarchy_,
@@ -140,9 +160,9 @@ def node_converter_lambda(
spec_object = reqif_bundle.get_spec_object_by_ref(
current_hierarchy_.spec_object
)
- spec_object_type_identifiers_used_by_this_document[
+ spec_object_type_identifiers_used_by_this_document.add(
spec_object.spec_object_type
- ] = None
+ )
is_section = P01_ReqIFToSDocConverter.is_spec_object_section(
spec_object,
@@ -181,7 +201,7 @@ def node_converter_lambda(
elements: List[GrammarElement] = []
for (
spec_object_type_identifier_
- ) in spec_object_type_identifiers_used_by_this_document.keys():
+ ) in spec_object_type_identifiers_used_by_this_document:
spec_object_type: ReqIFSpecObjectType = (
reqif_bundle.lookup.get_spec_type_by_ref(
spec_object_type_identifier_
@@ -194,7 +214,13 @@ def node_converter_lambda(
spec_object_type_identifier_
]
)
+ if len(grammar_element.relations) == 0:
+ grammar_element.relations = create_default_relations(
+ grammar_element
+ )
+
elements.append(grammar_element)
+
grammar: DocumentGrammar
if len(elements) > 0:
grammar = DocumentGrammar(parent=document, elements=elements)
@@ -288,9 +314,6 @@ def create_grammar_element_from_spec_object_type(
fields=fields,
relations=[],
)
- requirement_element.relations = create_default_relations(
- requirement_element
- )
return requirement_element
@staticmethod
@@ -523,6 +546,45 @@ def create_requirement_from_spec_object(
)
parent_refs: List[Reference] = []
for spec_object_parent in spec_object_parents:
+ spec_relation_type = (
+ context.map_source_target_pairs_to_spec_relation_types[
+ (spec_object.identifier, spec_object_parent)
+ ]
+ )
+
+ relation_role = (
+ spec_relation_type.long_name
+ if spec_relation_type.long_name is not None
+ else None
+ )
+ if relation_role == "Parent":
+ relation_role = None
+
+ if (
+ grammar_element
+ not in context.unique_grammar_element_relations
+ ):
+ context.unique_grammar_element_relations[
+ grammar_element
+ ] = OrderedSet()
+
+ if (
+ "Parent",
+ relation_role,
+ ) not in context.unique_grammar_element_relations[
+ grammar_element
+ ]:
+ context.unique_grammar_element_relations[
+ grammar_element
+ ].add(("Parent", relation_role))
+ grammar_element.relations.append(
+ GrammarElementRelationParent(
+ parent=grammar_element,
+ relation_type="Parent",
+ relation_role=relation_role,
+ )
+ )
+
parent_spec_object_parent = (
reqif_bundle.lookup.get_spec_object_by_ref(
spec_object_parent
@@ -535,7 +597,7 @@ def create_requirement_from_spec_object(
parent_spec_object_parent.attribute_map[
foreign_key_id_or_none
].value,
- role=None,
+ role=relation_role,
)
)
if len(parent_refs) > 0:
diff --git a/strictdoc/backend/reqif/p01_sdoc/sdoc_to_reqif_converter.py b/strictdoc/backend/reqif/p01_sdoc/sdoc_to_reqif_converter.py
index 57a4e0234..f34b7a28f 100644
--- a/strictdoc/backend/reqif/p01_sdoc/sdoc_to_reqif_converter.py
+++ b/strictdoc/backend/reqif/p01_sdoc/sdoc_to_reqif_converter.py
@@ -3,7 +3,7 @@
import uuid
from collections import defaultdict
from enum import Enum
-from typing import Dict, List
+from typing import Dict, List, Optional, Tuple
from reqif.models.reqif_core_content import ReqIFCoreContent
from reqif.models.reqif_data_type import (
@@ -22,6 +22,7 @@
SpecAttributeDefinition,
)
from reqif.models.reqif_spec_relation import ReqIFSpecRelation
+from reqif.models.reqif_spec_relation_type import ReqIFSpecRelationType
from reqif.models.reqif_specification import ReqIFSpecification
from reqif.models.reqif_specification_type import ReqIFSpecificationType
from reqif.models.reqif_types import SpecObjectAttributeType
@@ -29,7 +30,6 @@
from reqif.reqif_bundle import ReqIFBundle
from strictdoc.backend.reqif.sdoc_reqif_fields import (
- SDOC_SPEC_RELATION_PARENT_TYPE_SINGLETON,
SDOC_SPECIFICATION_TYPE_SINGLETON,
SDOC_TO_REQIF_FIELD_MAP,
ReqIFChapterField,
@@ -38,18 +38,22 @@
from strictdoc.backend.sdoc.models.document import SDocDocument
from strictdoc.backend.sdoc.models.document_grammar import DocumentGrammar
from strictdoc.backend.sdoc.models.node import SDocNode
-from strictdoc.backend.sdoc.models.reference import ParentReqReference
+from strictdoc.backend.sdoc.models.reference import (
+ ChildReqReference,
+ ParentReqReference,
+ Reference,
+)
from strictdoc.backend.sdoc.models.section import SDocSection
from strictdoc.backend.sdoc.models.type_system import (
GrammarElementField,
GrammarElementFieldMultipleChoice,
GrammarElementFieldSingleChoice,
GrammarElementFieldString,
- ReferenceType,
)
from strictdoc.core.document_iterator import DocumentCachingIterator
from strictdoc.core.document_tree import DocumentTree
from strictdoc.helpers.cast import assert_cast
+from strictdoc.helpers.ordered_set import OrderedSet
from strictdoc.helpers.string import escape
@@ -69,10 +73,15 @@ def __init__(self, *, multiline_is_xhtml: bool, enable_mid: bool):
self.multiline_is_xhtml: bool = multiline_is_xhtml
self.enable_mid: bool = enable_mid
self.map_uid_to_spec_objects: Dict[str, ReqIFSpecObject] = {}
- self.map_uid_to_parent_uids: Dict[str, List[str]] = {}
+ self.map_node_uids_to_their_relations: Dict[str, List[Reference]] = (
+ defaultdict(list)
+ )
self.map_grammar_node_tags_to_spec_object_type: Dict[
SDocDocument, Dict[str, ReqIFSpecObjectType]
] = defaultdict(dict)
+ self.map_spec_relation_tuple_to_spec_relation_type: Dict[
+ Tuple[str, Optional[str]], ReqIFSpecRelationType
+ ] = {}
class P01_SDocToReqIFObjectConverter:
@@ -334,18 +343,31 @@ def convert_document_tree(
for (
requirement_id,
- parent_uids,
- ) in context.map_uid_to_parent_uids.items():
+ node_relations_,
+ ) in context.map_node_uids_to_their_relations.items():
spec_object = context.map_uid_to_spec_objects[requirement_id]
- for parent_uid in parent_uids:
- parent_spec_object = context.map_uid_to_spec_objects[parent_uid]
+ for node_relation_ in node_relations_:
+ # For now, the File-relations are not supported.
+ if not isinstance(
+ node_relation_, (ParentReqReference, ChildReqReference)
+ ):
+ continue
+ related_node_uid = node_relation_.ref_uid
+ parent_spec_object = context.map_uid_to_spec_objects[
+ related_node_uid
+ ]
+ spec_relation_type: ReqIFSpecRelationType = (
+ context.map_spec_relation_tuple_to_spec_relation_type[
+ (node_relation_.ref_type, node_relation_.role)
+ ]
+ )
spec_relations.append(
ReqIFSpecRelation(
xml_node=None,
description=None,
identifier=generate_unique_identifier("SPEC-RELATION"),
last_change=None,
- relation_type_ref=SDOC_SPEC_RELATION_PARENT_TYPE_SINGLETON,
+ relation_type_ref=spec_relation_type.identifier,
source=spec_object.identifier,
target=parent_spec_object.identifier,
values_attribute=None,
@@ -544,18 +566,10 @@ def _convert_requirement_to_spec_object(
attributes.append(attribute)
if requirement.reserved_uid is not None:
- parent_references: List[str] = []
- for reference in requirement.relations:
- if reference.ref_type != ReferenceType.PARENT:
- continue
- parent_reference: ParentReqReference = assert_cast(
- reference, ParentReqReference
- )
- parent_references.append(parent_reference.ref_uid)
-
- context.map_uid_to_parent_uids[requirement.reserved_uid] = (
- parent_references
- )
+ if len(requirement.relations) > 0:
+ context.map_node_uids_to_their_relations[
+ requirement.reserved_uid
+ ] = requirement.relations
spec_object_type: ReqIFSpecObjectType = (
context.map_grammar_node_tags_to_spec_object_type[
@@ -670,7 +684,31 @@ def _convert_document_grammar_to_spec_types(
] = section_spec_type
spec_object_types.append(section_spec_type)
- return spec_object_types
+ # Using dict as an ordered set.
+ spec_relation_tuples: OrderedSet = OrderedSet()
+ for element_ in grammar.elements:
+ for relation_ in element_.relations:
+ spec_relation_tuples.add(
+ (relation_.relation_type, relation_.relation_role)
+ )
+
+ spec_relation_types: List = []
+ for spec_relation_tuple_ in spec_relation_tuples:
+ spec_relation_type_name = (
+ spec_relation_tuple_[1]
+ if spec_relation_tuple_[1] is not None
+ else spec_relation_tuple_[0]
+ )
+ spec_relation_type = ReqIFSpecRelationType(
+ identifier=generate_unique_identifier(spec_relation_type_name),
+ long_name=spec_relation_type_name,
+ )
+ spec_relation_types.append(spec_relation_type)
+ context.map_spec_relation_tuple_to_spec_relation_type[
+ spec_relation_tuple_
+ ] = spec_relation_type
+
+ return spec_object_types + spec_relation_types
@classmethod
def _create_section_spec_object_type(
diff --git a/strictdoc/backend/reqif/sdoc_reqif_fields.py b/strictdoc/backend/reqif/sdoc_reqif_fields.py
index 2a159dafd..ec0f2e8f3 100644
--- a/strictdoc/backend/reqif/sdoc_reqif_fields.py
+++ b/strictdoc/backend/reqif/sdoc_reqif_fields.py
@@ -62,7 +62,3 @@ class ReqIFChapterField:
]
SDOC_SPECIFICATION_TYPE_SINGLETON = "SDOC_SPECIFICATION_TYPE_SINGLETON"
-
-SDOC_SPEC_RELATION_PARENT_TYPE_SINGLETON = (
- "SDOC_SPEC_RELATION_PARENT_TYPE_SINGLETON"
-)
diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/01_cli_option/sample.sdoc b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/01_cli_option/sample.sdoc
index cc1a3c2bc..a35afd3bd 100644
--- a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/01_cli_option/sample.sdoc
+++ b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/01_cli_option/sample.sdoc
@@ -37,7 +37,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- - TYPE: File
[SECTION]
MID: eece0e6eeb9f4dacbe1026a0ec818b4b
diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/02_toml_option/sample.sdoc b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/02_toml_option/sample.sdoc
index cc1a3c2bc..a35afd3bd 100644
--- a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/02_toml_option/sample.sdoc
+++ b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-enable-mid/02_toml_option/sample.sdoc
@@ -37,7 +37,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- - TYPE: File
[SECTION]
MID: eece0e6eeb9f4dacbe1026a0ec818b4b
diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-import-markup/01_cli_option/sample.sdoc b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-import-markup/01_cli_option/sample.sdoc
index d1b9c6dc6..34625faa2 100644
--- a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-import-markup/01_cli_option/sample.sdoc
+++ b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-import-markup/01_cli_option/sample.sdoc
@@ -33,7 +33,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- - TYPE: File
[SECTION]
TITLE: Section #1
diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-import-markup/02_toml_option/sample.sdoc b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-import-markup/02_toml_option/sample.sdoc
index d1b9c6dc6..34625faa2 100644
--- a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-import-markup/02_toml_option/sample.sdoc
+++ b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/--reqif-import-markup/02_toml_option/sample.sdoc
@@ -33,7 +33,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- - TYPE: File
[SECTION]
TITLE: Section #1
diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/13_refs/sample.sdoc b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/70_relations/sample.sdoc
similarity index 82%
rename from tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/13_refs/sample.sdoc
rename to tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/70_relations/sample.sdoc
index 690a2dcb3..773ec2d67 100644
--- a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/13_refs/sample.sdoc
+++ b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/70_relations/sample.sdoc
@@ -31,7 +31,8 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- - TYPE: File
+ - TYPE: Parent
+ ROLE: Traces
[REQUIREMENT]
UID: REQ-001
@@ -43,3 +44,11 @@ TITLE: Requirement #2
RELATIONS:
- TYPE: Parent
VALUE: REQ-001
+
+[REQUIREMENT]
+UID: REQ-003
+TITLE: Requirement #3
+RELATIONS:
+- TYPE: Parent
+ VALUE: REQ-001
+ ROLE: Traces
diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/13_refs/test.itest b/tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/70_relations/test.itest
similarity index 100%
rename from tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/13_refs/test.itest
rename to tests/integration/backend/reqif/profiles/p01_sdoc/end_to_end/70_relations/test.itest
diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/examples/01_sample/output2/sample.sdoc b/tests/integration/backend/reqif/profiles/p01_sdoc/examples/01_sample/output2/sample.sdoc
index 3c27ba6f0..411e97f2b 100644
--- a/tests/integration/backend/reqif/profiles/p01_sdoc/examples/01_sample/output2/sample.sdoc
+++ b/tests/integration/backend/reqif/profiles/p01_sdoc/examples/01_sample/output2/sample.sdoc
@@ -16,7 +16,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- - TYPE: File
[REQUIREMENT_TYPE]
UID: Anonymized-0f5a0a32-034a-aa17-65d0-7387eefa020a
diff --git a/tests/integration/backend/reqif/profiles/p01_sdoc/examples/01_sample/sample.reqif b/tests/integration/backend/reqif/profiles/p01_sdoc/examples/01_sample/sample.reqif
index 55e6bd41d..d7fd4d693 100644
--- a/tests/integration/backend/reqif/profiles/p01_sdoc/examples/01_sample/sample.reqif
+++ b/tests/integration/backend/reqif/profiles/p01_sdoc/examples/01_sample/sample.reqif
@@ -56,6 +56,7 @@
+