Path:
strictdoc/core/transforms/update_grammar_element.py
Lines:
132
Non-empty lines:
110
Non-empty lines covered with requirements:
110 / 110 (100.0%)
Functions:
3
Functions covered by requirements:
3 / 3 (100.0%)
1
"""2
@relation(SDOC-SRS-56, scope=file)3
"""4
5
from collections import OrderedDict
6
from typing import Dict, List, Optional, Set, Tuple
7
8
from strictdoc.backend.sdoc.models.document import SDocDocument
9
from strictdoc.backend.sdoc.models.grammar_element import (
10
GrammarElement,
11
GrammarElementField,
12
)13
from strictdoc.backend.sdoc.models.node import SDocNode, SDocNodeField
14
from strictdoc.core.traceability_index import (
15
TraceabilityIndex,
16
)17
from strictdoc.export.html.form_objects.grammar_element_form_object import (
18
GrammarElementFormObject,
19
)20
from strictdoc.helpers.cast import assert_cast
21
22
23
class UpdateGrammarElementCommand:
24
def __init__(
25
self,
26
*,
27
form_object: GrammarElementFormObject,
28
document: SDocDocument,
29
traceability_index: TraceabilityIndex,
30
):31
self.form_object: GrammarElementFormObject = form_object
32
self.document: SDocDocument = document
33
self.traceability_index: TraceabilityIndex = traceability_index
34
35
def perform(self) -> None:
36
form_object: GrammarElementFormObject = self.form_object
37
document: SDocDocument = self.document
38
assert document.grammar is not None
39
40
existing_element: GrammarElement = document.grammar.get_element_by_mid(
41
form_object.element_mid
42
)43
44
grammar_fields: Dict[str, GrammarElementField] = {}
45
for grammar_field in existing_element.fields:
46
grammar_fields[grammar_field.mid] = grammar_field
47
48
# Prepare fields that could have been renamed by the user has just saved the form.49
renamed_fields_lookup = {}
50
for field in form_object.fields:
51
if field.field_mid not in grammar_fields:
52
continue53
existing_field = grammar_fields[field.field_mid]
54
if field.field_name != existing_field.title:
55
renamed_fields_lookup[field.field_name] = existing_field.title
56
57
#58
# Convert the form object to an updated grammar element.59
#60
assert document.grammar is not None
61
updated_element: GrammarElement = (
62
form_object.convert_to_grammar_element(document.grammar)
63
)64
65
#66
# Compare if anything was changed in the new grammar.67
#68
document_grammar_field_names = updated_element.get_field_titles()
69
70
existing_requirement_element = document.grammar.elements_by_type[
71
existing_element.tag
72
]73
74
document.grammar.update_element(existing_element, updated_element)
75
76
document_iterator = self.traceability_index.document_iterators[document]
77
78
for node, _ in document_iterator.all_content():
79
if not isinstance(node, SDocNode):
80
continue81
82
requirement: SDocNode = assert_cast(node, SDocNode)
83
if requirement.node_type != updated_element.tag:
84
continue85
86
requirement_field_names = list(
87
requirement.ordered_fields_lookup.keys()
88
)89
90
# Rewrite requirement fields because some fields could have been91
# renamed.92
new_ordered_fields_lookup: OrderedDict[str, List[SDocNodeField]] = (
93
OrderedDict()
94
)95
96
for document_grammar_field_name in document_grammar_field_names:
97
# We need to find a previous field name in case the field was98
# renamed.99
previous_field_name = renamed_fields_lookup.get(
100
document_grammar_field_name, document_grammar_field_name
101
)102
103
# If the field does not exist in the grammar fields anymore,104
# delete the requirement field.105
if previous_field_name not in requirement_field_names:
106
continue107
108
previous_fields: List[SDocNodeField] = (
109
requirement.ordered_fields_lookup[previous_field_name]
110
)111
for previous_field in previous_fields:
112
previous_field.field_name = document_grammar_field_name
113
114
new_ordered_fields_lookup[document_grammar_field_name] = (
115
previous_fields116
)117
118
registered_relation_types: Set[Tuple[str, Optional[str]]] = set()
119
for relation in existing_requirement_element.relations:
120
registered_relation_types.add(
121
(relation.relation_type, relation.relation_role)
122
)123
if len(requirement.relations) > 0:
124
new_relations = []
125
for requirement_relation_ in requirement.relations:
126
if (
127
requirement_relation_.ref_type,
128
requirement_relation_.role,
129
) in registered_relation_types:
130
new_relations.append(requirement_relation_)
131
requirement.relations = new_relations
132
requirement.ordered_fields_lookup = new_ordered_fields_lookup