Skip to content

Commit

Permalink
backend/reqif: relation roles export/import roundtrip
Browse files Browse the repository at this point in the history
  • Loading branch information
stanislaw committed Jul 28, 2024
1 parent 96001e7 commit 4726395
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 42 deletions.
80 changes: 71 additions & 9 deletions strictdoc/backend/reqif/p01_sdoc/reqif_to_sdoc_converter.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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_,
Expand All @@ -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,
Expand Down Expand Up @@ -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_
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand Down
84 changes: 61 additions & 23 deletions strictdoc/backend/reqif/p01_sdoc/sdoc_to_reqif_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -22,14 +22,14 @@
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
from reqif.object_lookup import ReqIFObjectLookup
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,
Expand All @@ -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


Expand All @@ -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:
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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[
Expand Down Expand Up @@ -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(
Expand Down
4 changes: 0 additions & 4 deletions strictdoc/backend/reqif/sdoc_reqif_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- TYPE: File

[SECTION]
MID: eece0e6eeb9f4dacbe1026a0ec818b4b
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- TYPE: File

[SECTION]
MID: eece0e6eeb9f4dacbe1026a0ec818b4b
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- TYPE: File

[SECTION]
TITLE: Section #1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- TYPE: File

[SECTION]
TITLE: Section #1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- TYPE: File
- TYPE: Parent
ROLE: Traces

[REQUIREMENT]
UID: REQ-001
Expand All @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ ELEMENTS:
REQUIRED: False
RELATIONS:
- TYPE: Parent
- TYPE: File

[REQUIREMENT_TYPE]
UID: Anonymized-0f5a0a32-034a-aa17-65d0-7387eefa020a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
</ATTRIBUTE-DEFINITION-XHTML>
</SPEC-ATTRIBUTES>
</SPECIFICATION-TYPE>
<SPEC-RELATION-TYPE IDENTIFIER="_gFhrYGojEeuExICsU7Acmg" LONG-NAME="Parent"/>
</SPEC-TYPES>
<SPEC-OBJECTS>
<SPEC-OBJECT IDENTIFIER="_gFhrY2ojEeuExICsU7Acmg" LAST-CHANGE="2021-02-11T12:16:25.409+01:00">
Expand Down

0 comments on commit 4726395

Please sign in to comment.