tricc-oo 1.5.26__py3-none-any.whl → 1.6.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tests/build.py +1 -0
- tricc_oo/converters/codesystem_to_ocl.py +4 -4
- tricc_oo/converters/datadictionnary.py +1 -1
- tricc_oo/converters/drawio_type_map.py +11 -11
- tricc_oo/converters/tricc_to_xls_form.py +16 -7
- tricc_oo/converters/xml_to_tricc.py +41 -23
- tricc_oo/models/base.py +4 -2
- tricc_oo/serializers/xls_form.py +56 -17
- tricc_oo/strategies/output/base_output_strategy.py +7 -0
- tricc_oo/strategies/output/dhis2_form.py +908 -0
- tricc_oo/strategies/output/openmrs_form.py +52 -5
- tricc_oo/strategies/output/xls_form.py +62 -32
- tricc_oo/strategies/output/xlsform_cht.py +135 -1
- tricc_oo/visitors/tricc.py +180 -90
- {tricc_oo-1.5.26.dist-info → tricc_oo-1.6.14.dist-info}/METADATA +2 -1
- {tricc_oo-1.5.26.dist-info → tricc_oo-1.6.14.dist-info}/RECORD +19 -18
- {tricc_oo-1.5.26.dist-info → tricc_oo-1.6.14.dist-info}/WHEEL +0 -0
- {tricc_oo-1.5.26.dist-info → tricc_oo-1.6.14.dist-info}/licenses/LICENSE +0 -0
- {tricc_oo-1.5.26.dist-info → tricc_oo-1.6.14.dist-info}/top_level.txt +0 -0
tests/build.py
CHANGED
|
@@ -6,6 +6,7 @@ from tricc_oo.strategies.output.xls_form import XLSFormStrategy # noqa: F401
|
|
|
6
6
|
from tricc_oo.strategies.output.openmrs_form import OpenMRSStrategy # noqa: F401
|
|
7
7
|
from tricc_oo.strategies.output.fhir_form import FHIRStrategy # noqa: F401
|
|
8
8
|
from tricc_oo.strategies.output.html_form import HTMLStrategy # noqa: F401
|
|
9
|
+
from tricc_oo.strategies.output.dhis2_form import DHIS2Strategy # noqa: F401
|
|
9
10
|
from tricc_oo.strategies.input.drawio import DrawioStrategy # noqa: F401
|
|
10
11
|
import getopt
|
|
11
12
|
import logging
|
|
@@ -31,16 +31,16 @@ def extract_properties_metadata(fhir_cs: CodeSystem) -> Dict[str, Dict]:
|
|
|
31
31
|
|
|
32
32
|
property_types[prop.code] = {
|
|
33
33
|
"name": prop.code,
|
|
34
|
-
"
|
|
34
|
+
"dataType": ocl_type,
|
|
35
35
|
"description": prop.description if hasattr(prop, "description") else "",
|
|
36
36
|
}
|
|
37
37
|
return property_types
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def get_fhir_concept_datatype(concept):
|
|
41
|
-
datatype = extract_concept_properties(concept, ["
|
|
41
|
+
datatype = extract_concept_properties(concept, ["dataType"])
|
|
42
42
|
if datatype:
|
|
43
|
-
return datatype["
|
|
43
|
+
return datatype["dataType"]
|
|
44
44
|
else:
|
|
45
45
|
return OclConstants.DATA_TYPE_NONE
|
|
46
46
|
|
|
@@ -84,7 +84,7 @@ def get_attributes_from_concept_properties(concept, property_types: Dict) -> Lis
|
|
|
84
84
|
"type": "Attribute",
|
|
85
85
|
"attribute_type": code,
|
|
86
86
|
"value": value,
|
|
87
|
-
"value_type": property_types[code]["
|
|
87
|
+
"value_type": property_types[code]["dataType"],
|
|
88
88
|
}
|
|
89
89
|
)
|
|
90
90
|
return attributes
|
|
@@ -103,7 +103,7 @@ def check_and_add_concept(code_system: CodeSystem, code: str, display: str, attr
|
|
|
103
103
|
# TODO support other type of Codesystem Concept Property Value
|
|
104
104
|
existing_attributes
|
|
105
105
|
if p.valueString != v:
|
|
106
|
-
logger.warning(f"conflicting value for property {k}
|
|
106
|
+
logger.warning(f"conflicting value for concept `{concept.code}` property ` {k}`: {p.valueString} != {v}")
|
|
107
107
|
if not existing_attributes:
|
|
108
108
|
new_concept.property.append(CodeSystemConceptProperty(code=k, valueString=v))
|
|
109
109
|
|
|
@@ -47,7 +47,7 @@ TYPE_MAP = {
|
|
|
47
47
|
},
|
|
48
48
|
TriccNodeType.note: {
|
|
49
49
|
"objects": ["UserObject", "object"],
|
|
50
|
-
"attributes": ["relevance", "priority", "
|
|
50
|
+
"attributes": ["relevance", "priority", "concept_type"],
|
|
51
51
|
"mandatory_attributes": ["label", "name"],
|
|
52
52
|
"model": TriccNodeNote,
|
|
53
53
|
},
|
|
@@ -76,7 +76,7 @@ TYPE_MAP = {
|
|
|
76
76
|
"priority",
|
|
77
77
|
"trigger",
|
|
78
78
|
"default",
|
|
79
|
-
"
|
|
79
|
+
"concept_type",
|
|
80
80
|
],
|
|
81
81
|
"mandatory_attributes": ["label", "name", "list_name"],
|
|
82
82
|
"model": TriccNodeSelectOne,
|
|
@@ -94,7 +94,7 @@ TYPE_MAP = {
|
|
|
94
94
|
"priority",
|
|
95
95
|
"trigger",
|
|
96
96
|
"default",
|
|
97
|
-
"
|
|
97
|
+
"concept_type",
|
|
98
98
|
],
|
|
99
99
|
"mandatory_attributes": ["label", "name", "list_name"],
|
|
100
100
|
"model": TriccNodeSelectMultiple,
|
|
@@ -112,7 +112,7 @@ TYPE_MAP = {
|
|
|
112
112
|
"priority",
|
|
113
113
|
"trigger",
|
|
114
114
|
"default",
|
|
115
|
-
"
|
|
115
|
+
"concept_type",
|
|
116
116
|
],
|
|
117
117
|
"mandatory_attributes": ["label", "name"],
|
|
118
118
|
"model": TriccNodeDecimal,
|
|
@@ -130,7 +130,7 @@ TYPE_MAP = {
|
|
|
130
130
|
"priority",
|
|
131
131
|
"trigger",
|
|
132
132
|
"default",
|
|
133
|
-
"
|
|
133
|
+
"concept_type",
|
|
134
134
|
],
|
|
135
135
|
"mandatory_attributes": ["label", "name"],
|
|
136
136
|
"model": TriccNodeInteger,
|
|
@@ -145,7 +145,7 @@ TYPE_MAP = {
|
|
|
145
145
|
"default",
|
|
146
146
|
"constraint",
|
|
147
147
|
"constraint_message",
|
|
148
|
-
"
|
|
148
|
+
"concept_type",
|
|
149
149
|
],
|
|
150
150
|
"mandatory_attributes": ["label", "name"],
|
|
151
151
|
"model": TriccNodeText,
|
|
@@ -160,7 +160,7 @@ TYPE_MAP = {
|
|
|
160
160
|
"default",
|
|
161
161
|
"constraint",
|
|
162
162
|
"constraint_message",
|
|
163
|
-
"
|
|
163
|
+
"concept_type",
|
|
164
164
|
],
|
|
165
165
|
"mandatory_attributes": ["label", "name"],
|
|
166
166
|
"model": TriccNodeDate,
|
|
@@ -183,7 +183,7 @@ TYPE_MAP = {
|
|
|
183
183
|
"save",
|
|
184
184
|
"reference",
|
|
185
185
|
"trigger",
|
|
186
|
-
"
|
|
186
|
+
"concept_type",
|
|
187
187
|
"remote_reference",
|
|
188
188
|
],
|
|
189
189
|
"mandatory_attributes": ["name", "label"],
|
|
@@ -217,7 +217,7 @@ TYPE_MAP = {
|
|
|
217
217
|
},
|
|
218
218
|
TriccNodeType.not_available: {
|
|
219
219
|
"objects": ["UserObject", "object"],
|
|
220
|
-
"attributes": ["
|
|
220
|
+
"attributes": ["concept_type"],
|
|
221
221
|
"mandatory_attributes": ["label", "name", "list_name"],
|
|
222
222
|
"model": TriccNodeSelectNotAvailable,
|
|
223
223
|
},
|
|
@@ -233,7 +233,7 @@ TYPE_MAP = {
|
|
|
233
233
|
"priority",
|
|
234
234
|
"trigger",
|
|
235
235
|
"default",
|
|
236
|
-
"
|
|
236
|
+
"concept_type",
|
|
237
237
|
],
|
|
238
238
|
"mandatory_attributes": ["label", "name", "list_name"],
|
|
239
239
|
"model": TriccNodeSelectYesNo,
|
|
@@ -295,7 +295,7 @@ TYPE_MAP = {
|
|
|
295
295
|
},
|
|
296
296
|
TriccNodeType.input: {
|
|
297
297
|
"objects": ["UserObject", "object"],
|
|
298
|
-
"attributes": ["save", "reference", "
|
|
298
|
+
"attributes": ["save", "reference", "data_type", "concept_type"],
|
|
299
299
|
"mandatory_attributes": ["name", "label"],
|
|
300
300
|
"model": TriccNodeInput,
|
|
301
301
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from tricc_oo.converters.utils import clean_name
|
|
3
|
-
from tricc_oo.models.tricc import TriccNodeSelectOption, TRICC_TRUE_VALUE, TRICC_FALSE_VALUE
|
|
2
|
+
from tricc_oo.converters.utils import clean_name
|
|
3
|
+
from tricc_oo.models.tricc import TriccNodeSelectOption, TRICC_TRUE_VALUE, TRICC_FALSE_VALUE, TriccNodeActivity
|
|
4
4
|
from tricc_oo.models.calculate import TriccNodeInput
|
|
5
5
|
from tricc_oo.models.base import TriccNodeBaseModel, TriccStatic, TriccReference
|
|
6
6
|
|
|
@@ -36,13 +36,15 @@ def get_export_name(node, replace_dots=True):
|
|
|
36
36
|
elif isinstance(node, bool):
|
|
37
37
|
return BOOLEAN_MAP[str(TRICC_TRUE_VALUE)] if node else BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]
|
|
38
38
|
elif isinstance(node, TriccReference):
|
|
39
|
-
logger.warning(f"Reference {node.value} use in export, bad
|
|
39
|
+
logger.warning(f"Reference {node.value} use in export, bad serialization probable")
|
|
40
40
|
return str(node.value)
|
|
41
41
|
elif isinstance(node, (str, TriccStatic, TriccNodeSelectOption)):
|
|
42
42
|
if isinstance(node, TriccNodeSelectOption):
|
|
43
43
|
value = node.name
|
|
44
44
|
elif isinstance(node, TriccStatic):
|
|
45
45
|
value = node.value
|
|
46
|
+
if isinstance(value, TriccNodeSelectOption):
|
|
47
|
+
value = value.name
|
|
46
48
|
else:
|
|
47
49
|
value = node
|
|
48
50
|
if isinstance(value, bool): # or r.value in ('true', 'false')
|
|
@@ -51,10 +53,12 @@ def get_export_name(node, replace_dots=True):
|
|
|
51
53
|
export_name = BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]
|
|
52
54
|
elif value == TRICC_FALSE_VALUE:
|
|
53
55
|
export_name = BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]
|
|
54
|
-
elif
|
|
55
|
-
export_name =
|
|
56
|
+
elif value == '$this':
|
|
57
|
+
export_name = '.'
|
|
58
|
+
elif isinstance(value, str) and not isinstance(node, str):
|
|
59
|
+
export_name = f"'{value}'"
|
|
56
60
|
else:
|
|
57
|
-
export_name =
|
|
61
|
+
export_name = value
|
|
58
62
|
if hasattr(node, 'export_name'):
|
|
59
63
|
node.export_name = export_name
|
|
60
64
|
return export_name
|
|
@@ -62,7 +66,12 @@ def get_export_name(node, replace_dots=True):
|
|
|
62
66
|
return node
|
|
63
67
|
else:
|
|
64
68
|
node.gen_name()
|
|
65
|
-
if isinstance(node,
|
|
69
|
+
if isinstance(node, TriccNodeActivity) and getattr(node, 'instance', 1) > 1:
|
|
70
|
+
node.export_name = clean_name(
|
|
71
|
+
node.name + INSTANCE_SEPARATOR + str(node.instance),
|
|
72
|
+
replace_dots=replace_dots,
|
|
73
|
+
)
|
|
74
|
+
elif isinstance(node, TriccNodeSelectOption):
|
|
66
75
|
node.export_name = node.name
|
|
67
76
|
elif node.last is False:
|
|
68
77
|
node.export_name = clean_name(
|
|
@@ -7,7 +7,7 @@ import re
|
|
|
7
7
|
|
|
8
8
|
from tricc_oo.converters.utils import remove_html, clean_str
|
|
9
9
|
from tricc_oo.converters.cql_to_operation import transform_cql_to_operation
|
|
10
|
-
from tricc_oo.converters.utils import generate_id
|
|
10
|
+
from tricc_oo.converters.utils import generate_id
|
|
11
11
|
from tricc_oo.models.base import (
|
|
12
12
|
TriccOperator, TriccOperation,
|
|
13
13
|
TriccStatic, TriccReference, TriccNodeType, TriccEdge, OPERATION_LIST
|
|
@@ -101,16 +101,16 @@ def create_activity(diagram, media_path, project):
|
|
|
101
101
|
|
|
102
102
|
external_id = diagram.attrib.get("id")
|
|
103
103
|
id = get_id(external_id, diagram.attrib.get("id"))
|
|
104
|
-
root = create_root_node(diagram)
|
|
105
|
-
|
|
104
|
+
root, name = create_root_node(diagram)
|
|
105
|
+
label = diagram.attrib.get("name")
|
|
106
106
|
form_id = diagram.attrib.get("name", None)
|
|
107
107
|
if root is not None:
|
|
108
108
|
activity = TriccNodeActivity(
|
|
109
109
|
root=root,
|
|
110
|
-
name=
|
|
110
|
+
name=name, # start node 'name' is saved in label
|
|
111
111
|
id=id,
|
|
112
112
|
external_id=external_id,
|
|
113
|
-
label=
|
|
113
|
+
label=label,
|
|
114
114
|
form_id=form_id,
|
|
115
115
|
)
|
|
116
116
|
if root.relevance is not None:
|
|
@@ -128,9 +128,9 @@ def create_activity(diagram, media_path, project):
|
|
|
128
128
|
for n in nodes.values():
|
|
129
129
|
|
|
130
130
|
if (
|
|
131
|
-
issubclass(n.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase))
|
|
131
|
+
issubclass(n.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase, TriccNodeInput))
|
|
132
132
|
and not isinstance(n, (TriccRhombusMixIn, TriccNodeRhombus, TriccNodeDisplayBridge))
|
|
133
|
-
and not n.name.startswith("label_")
|
|
133
|
+
and not n.name.startswith("label_") # FIXME
|
|
134
134
|
):
|
|
135
135
|
system = n.name.split(".")[0] if "." in n.name else "tricc"
|
|
136
136
|
if isinstance(n, TriccNodeSelectOption) and isinstance(n.select, TriccNodeSelectNotAvailable):
|
|
@@ -139,7 +139,7 @@ def create_activity(diagram, media_path, project):
|
|
|
139
139
|
system,
|
|
140
140
|
n.select.name,
|
|
141
141
|
n.label,
|
|
142
|
-
{"
|
|
142
|
+
{"dataType": "Boolean", "conceptType": get_concept_type(n)},
|
|
143
143
|
)
|
|
144
144
|
elif not isinstance(n, TriccNodeSelectNotAvailable):
|
|
145
145
|
add_concept(
|
|
@@ -148,8 +148,20 @@ def create_activity(diagram, media_path, project):
|
|
|
148
148
|
n.name,
|
|
149
149
|
n.label,
|
|
150
150
|
{
|
|
151
|
-
"
|
|
152
|
-
"
|
|
151
|
+
"dataType": get_data_type(n.tricc_type),
|
|
152
|
+
"conceptType": get_concept_type(n),
|
|
153
|
+
},
|
|
154
|
+
)
|
|
155
|
+
elif not issubclass(n.__class__, TriccNodeCalculate):
|
|
156
|
+
system = n.name.split(".")[0] if "." in n.name else "calculate"
|
|
157
|
+
add_concept(
|
|
158
|
+
project.code_systems,
|
|
159
|
+
system,
|
|
160
|
+
n.name,
|
|
161
|
+
n.label,
|
|
162
|
+
{
|
|
163
|
+
"dataType": get_data_type(n.tricc_type),
|
|
164
|
+
"conceptType": get_concept_type(n),
|
|
153
165
|
},
|
|
154
166
|
)
|
|
155
167
|
if getattr(n, "save", None):
|
|
@@ -160,8 +172,8 @@ def create_activity(diagram, media_path, project):
|
|
|
160
172
|
n.save,
|
|
161
173
|
n.label,
|
|
162
174
|
{
|
|
163
|
-
"
|
|
164
|
-
"
|
|
175
|
+
"dataType": get_data_type(n.tricc_type),
|
|
176
|
+
"conceptType": get_concept_type(n),
|
|
165
177
|
},
|
|
166
178
|
)
|
|
167
179
|
|
|
@@ -175,7 +187,7 @@ def create_activity(diagram, media_path, project):
|
|
|
175
187
|
# link back the activity
|
|
176
188
|
activity.root.activity = activity
|
|
177
189
|
manage_dangling_calculate(activity)
|
|
178
|
-
|
|
190
|
+
# assign the process
|
|
179
191
|
if activity is not None:
|
|
180
192
|
if activity.root is not None:
|
|
181
193
|
project.pages[activity.id] = activity
|
|
@@ -197,6 +209,7 @@ def create_activity(diagram, media_path, project):
|
|
|
197
209
|
)
|
|
198
210
|
if images:
|
|
199
211
|
project.images += images
|
|
212
|
+
# Assign parent to NotAvailable
|
|
200
213
|
for node in list(
|
|
201
214
|
filter(
|
|
202
215
|
lambda p_node: isinstance(p_node, TriccNodeSelectNotAvailable),
|
|
@@ -444,17 +457,18 @@ def create_root_node(diagram):
|
|
|
444
457
|
if elm is not None:
|
|
445
458
|
external_id = elm.attrib.get("id")
|
|
446
459
|
id = get_id(external_id, diagram.attrib.get("id"))
|
|
460
|
+
name = generate_id("start"+external_id)
|
|
447
461
|
node = TriccNodeActivityStart(
|
|
448
462
|
id=id,
|
|
449
463
|
external_id=external_id,
|
|
450
464
|
# parent=elm.attrib.get("parent"),
|
|
451
|
-
name=
|
|
465
|
+
name=name,
|
|
452
466
|
label=diagram.attrib.get("name"),
|
|
453
467
|
relevance=elm.attrib.get("relevance"),
|
|
454
468
|
instance=int(elm.attrib.get("instance") if elm.attrib.get("instance") is not None else 1),
|
|
455
469
|
)
|
|
456
470
|
load_expressions(node)
|
|
457
|
-
return node
|
|
471
|
+
return node, _get_name(elm.attrib.get("name", "act_"), external_id, diagram.attrib.get("id")) if node else None
|
|
458
472
|
|
|
459
473
|
|
|
460
474
|
# converter XML item to object
|
|
@@ -476,10 +490,10 @@ def set_additional_attributes(attribute_names, elm, node):
|
|
|
476
490
|
setattr(node, attributename, attribute)
|
|
477
491
|
|
|
478
492
|
|
|
479
|
-
def
|
|
480
|
-
|
|
481
|
-
if
|
|
482
|
-
return
|
|
493
|
+
def get_concept_type(node):
|
|
494
|
+
concept_type = getattr(node, "concept_type", None)
|
|
495
|
+
if concept_type:
|
|
496
|
+
return concept_type
|
|
483
497
|
if isinstance(node, TriccNodeSelectMultiple):
|
|
484
498
|
return "Question"
|
|
485
499
|
elif isinstance(node, TriccNodeSelectOption):
|
|
@@ -534,7 +548,7 @@ def get_select_options(diagram, select_node, nodes):
|
|
|
534
548
|
activity=select_node.activity,
|
|
535
549
|
group=select_node.group,
|
|
536
550
|
)
|
|
537
|
-
set_additional_attributes(["save", "relevance", "
|
|
551
|
+
set_additional_attributes(["save", "relevance", "concept_type"], elm, option)
|
|
538
552
|
load_expressions(option)
|
|
539
553
|
options[i] = option
|
|
540
554
|
nodes[id] = option
|
|
@@ -624,6 +638,8 @@ def enrich_node(diagram, media_path, edge, node, activity, help_before=False):
|
|
|
624
638
|
name=f"{node.name}.more_info",
|
|
625
639
|
label=message,
|
|
626
640
|
parent=node,
|
|
641
|
+
group=node.group,
|
|
642
|
+
activity=node.activity,
|
|
627
643
|
required=None,
|
|
628
644
|
)
|
|
629
645
|
# node.help = message
|
|
@@ -799,9 +815,11 @@ def set_mandatory_attribute(elm, mandatory_attributes, diagram=None):
|
|
|
799
815
|
id = elm.attrib.get("id")
|
|
800
816
|
attribute_value = _get_name(name, id, diagram_id)
|
|
801
817
|
elif attributes == "list_name":
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
818
|
+
attribute_value = elm.attrib.get("list_name", None)
|
|
819
|
+
if not attribute_value:
|
|
820
|
+
name = elm.attrib.get("name")
|
|
821
|
+
id = elm.attrib.get("id")
|
|
822
|
+
attribute_value = TRICC_LIST_NAME.format(clean_str(_get_name(name, id, diagram_id), replace_dots=True))
|
|
805
823
|
else:
|
|
806
824
|
attribute_value = elm.attrib.get(attributes)
|
|
807
825
|
if attribute_value is None:
|
tricc_oo/models/base.py
CHANGED
|
@@ -11,7 +11,7 @@ from tricc_oo.models.ordered_set import OrderedSet
|
|
|
11
11
|
|
|
12
12
|
logger = logging.getLogger("default")
|
|
13
13
|
|
|
14
|
-
Expression = Annotated[str, StringConstraints(pattern=r"
|
|
14
|
+
Expression = Annotated[str, StringConstraints(pattern=r".+")]
|
|
15
15
|
|
|
16
16
|
triccId = Annotated[str, StringConstraints(pattern=r"^[^\\/\: ]+$")]
|
|
17
17
|
|
|
@@ -274,7 +274,7 @@ class TriccNodeBaseModel(TriccBaseModel):
|
|
|
274
274
|
|
|
275
275
|
|
|
276
276
|
class TriccStatic(BaseModel):
|
|
277
|
-
value: Union[str, float, int, bool]
|
|
277
|
+
value: Union[str, float, int, bool, TriccNodeBaseModel]
|
|
278
278
|
|
|
279
279
|
def __init__(self, value):
|
|
280
280
|
super().__init__(value=value)
|
|
@@ -494,6 +494,8 @@ class TriccOperation(BaseModel):
|
|
|
494
494
|
return "mixed"
|
|
495
495
|
else:
|
|
496
496
|
return rtype.pop()
|
|
497
|
+
else:
|
|
498
|
+
return self.get_reference_datatype(self.reference)
|
|
497
499
|
|
|
498
500
|
def get_reference_datatype(self, references):
|
|
499
501
|
rtype = set()
|
tricc_oo/serializers/xls_form.py
CHANGED
|
@@ -6,16 +6,17 @@ from tricc_oo.converters.tricc_to_xls_form import (
|
|
|
6
6
|
get_export_name, BOOLEAN_MAP
|
|
7
7
|
)
|
|
8
8
|
from tricc_oo.models.lang import SingletonLangClass
|
|
9
|
-
from tricc_oo.converters.utils import clean_name, remove_html
|
|
9
|
+
from tricc_oo.converters.utils import clean_name, remove_html, generate_id
|
|
10
10
|
from tricc_oo.models.base import (
|
|
11
11
|
TriccOperator,
|
|
12
12
|
TriccOperation, TriccStatic, TriccReference, and_join, TriccNodeType
|
|
13
13
|
)
|
|
14
14
|
from tricc_oo.models.calculate import (
|
|
15
15
|
TriccNodeDisplayCalculateBase,
|
|
16
|
+
TriccNodeCalculate
|
|
16
17
|
)
|
|
17
18
|
from tricc_oo.models.tricc import (
|
|
18
|
-
|
|
19
|
+
TriccNodeBaseModel, TriccNodeSelectMultiple, TriccNodeSelectOption,
|
|
19
20
|
TriccNodeSelectOne,
|
|
20
21
|
TriccNodeSelect,
|
|
21
22
|
TriccNodeMoreInfo,
|
|
@@ -31,6 +32,7 @@ from tricc_oo.visitors.tricc import (
|
|
|
31
32
|
get_applicability_expression,
|
|
32
33
|
get_prev_instance_skip_expression,
|
|
33
34
|
get_process_skip_expression,
|
|
35
|
+
process_operation_reference,
|
|
34
36
|
)
|
|
35
37
|
|
|
36
38
|
logger = logging.getLogger("default")
|
|
@@ -39,6 +41,9 @@ langs = SingletonLangClass()
|
|
|
39
41
|
TRICC_CALC_EXPRESSION = "${{{0}}}>0"
|
|
40
42
|
|
|
41
43
|
|
|
44
|
+
def get_export_group_name(in_node): return f"gcalc_{get_export_name(in_node)}"
|
|
45
|
+
|
|
46
|
+
|
|
42
47
|
def start_group(
|
|
43
48
|
strategy,
|
|
44
49
|
cur_group,
|
|
@@ -58,10 +63,38 @@ def start_group(
|
|
|
58
63
|
|
|
59
64
|
else:
|
|
60
65
|
groups[name] = 0
|
|
61
|
-
is_activity = isinstance(cur_group, TriccNodeActivity)
|
|
62
66
|
relevance = relevance and cur_group.relevance is not None and cur_group.relevance != ""
|
|
67
|
+
past_instances = len(getattr(cur_group.base_instance, "instances", []))
|
|
68
|
+
group_calc_required = relevance is not None and (len(str(relevance)) > 100 or past_instances > 1)
|
|
69
|
+
calc = None
|
|
70
|
+
if group_calc_required and getattr(cur_group.relevance, 'operator', None) != TriccOperator.ISTRUE:
|
|
71
|
+
|
|
72
|
+
calc = TriccNodeCalculate(
|
|
73
|
+
id=generate_id(get_export_group_name(name)),
|
|
74
|
+
group=cur_group.group,
|
|
75
|
+
activity=cur_group.activity,
|
|
76
|
+
name=get_export_group_name(name),
|
|
77
|
+
expression=cur_group.relevance
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if calc not in cur_group.activity.calculates:
|
|
81
|
+
process_reference(
|
|
82
|
+
calc,
|
|
83
|
+
processed_nodes,
|
|
84
|
+
calculates=kwargs.get('calculates', None),
|
|
85
|
+
used_calculates=kwargs.get('used_calculates', None),
|
|
86
|
+
replace_reference=True,
|
|
87
|
+
warn=False,
|
|
88
|
+
codesystems=kwargs.get('codesystems', None)
|
|
89
|
+
)
|
|
90
|
+
cur_group.activity.calculates.append(calc)
|
|
91
|
+
cur_group.activity.nodes[calc.id] = calc
|
|
92
|
+
processed_nodes.add(calc)
|
|
63
93
|
|
|
64
|
-
|
|
94
|
+
cur_group.relevance = TriccOperation(
|
|
95
|
+
TriccOperator.ISTRUE,
|
|
96
|
+
[calc]
|
|
97
|
+
)
|
|
65
98
|
|
|
66
99
|
relevance_expression = cur_group.relevance
|
|
67
100
|
relevance_expression = get_applicability_expression(cur_group, processed_nodes, process, relevance_expression)
|
|
@@ -69,14 +102,20 @@ def start_group(
|
|
|
69
102
|
relevance_expression = get_process_skip_expression(cur_group, processed_nodes, process, relevance_expression)
|
|
70
103
|
|
|
71
104
|
if not relevance:
|
|
72
|
-
|
|
105
|
+
relevance_expression_str = ""
|
|
73
106
|
elif isinstance(relevance_expression, (TriccOperation, TriccStatic)):
|
|
74
|
-
relevance_expression =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
107
|
+
relevance_expression = process_operation_reference(
|
|
108
|
+
relevance_expression,
|
|
109
|
+
cur_group,
|
|
110
|
+
processed_nodes=processed_nodes,
|
|
111
|
+
calculates=kwargs.get('calculates', None),
|
|
112
|
+
used_calculates=kwargs.get('used_calculates', None),
|
|
113
|
+
replace_reference=True,
|
|
114
|
+
warn=False,
|
|
115
|
+
codesystems=kwargs.get('codesystems', None),
|
|
116
|
+
) or relevance_expression
|
|
117
|
+
if relevance_expression:
|
|
118
|
+
relevance_expression_str = strategy.get_tricc_operation_expression(relevance_expression)
|
|
80
119
|
|
|
81
120
|
# group
|
|
82
121
|
values = []
|
|
@@ -91,23 +130,23 @@ def start_group(
|
|
|
91
130
|
if relevance_expression is True:
|
|
92
131
|
values.append("")
|
|
93
132
|
else:
|
|
94
|
-
values.append(
|
|
133
|
+
values.append(relevance_expression_str)
|
|
95
134
|
|
|
96
135
|
else:
|
|
97
136
|
values.append(get_xfrom_trad(strategy, cur_group, column, SURVEY_MAP))
|
|
98
137
|
df_survey.loc[len(df_survey)] = values
|
|
99
138
|
|
|
100
139
|
# calc
|
|
101
|
-
if
|
|
140
|
+
if calc and len(df_calculate[df_calculate["name"] == get_export_group_name(name)]) == 0:
|
|
102
141
|
calc_values = []
|
|
103
142
|
for column in SURVEY_MAP:
|
|
104
143
|
if column == "type":
|
|
105
144
|
calc_values.append("calculate")
|
|
106
145
|
elif column == "name":
|
|
107
|
-
value =
|
|
146
|
+
value = get_export_name(calc)
|
|
108
147
|
calc_values.append(value)
|
|
109
148
|
elif column == "calculation":
|
|
110
|
-
calc_values.append(
|
|
149
|
+
calc_values.append(f"number({strategy.get_tricc_operation_expression(calc.expression)})")
|
|
111
150
|
elif column == "relevance":
|
|
112
151
|
calc_values.append("")
|
|
113
152
|
else:
|
|
@@ -376,7 +415,7 @@ def get_attr_if_exists(strategy, node, column, map_array):
|
|
|
376
415
|
|
|
377
416
|
elif isinstance(value, (TriccOperation, TriccStatic, TriccReference)):
|
|
378
417
|
expression = strategy.get_tricc_operation_expression(value)
|
|
379
|
-
return expression
|
|
418
|
+
return expression
|
|
380
419
|
elif value is not None:
|
|
381
420
|
return str(value) if not isinstance(value, dict) else value
|
|
382
421
|
else:
|
|
@@ -399,7 +438,7 @@ def get_more_info_select(strategy, node):
|
|
|
399
438
|
if column == "type":
|
|
400
439
|
values.append("select_one more_info")
|
|
401
440
|
elif column == "label":
|
|
402
|
-
values.append(
|
|
441
|
+
values.append(strategy.get_empty_label())
|
|
403
442
|
elif column == "name":
|
|
404
443
|
values.append(get_export_name(node) + "_optin")
|
|
405
444
|
elif column == "hint":
|
|
@@ -43,6 +43,9 @@ class BaseOutPutStrategy:
|
|
|
43
43
|
|
|
44
44
|
self.export(self.project.start_pages, version=version)
|
|
45
45
|
|
|
46
|
+
logger.info("validate the output")
|
|
47
|
+
self.validate()
|
|
48
|
+
|
|
46
49
|
# walking function
|
|
47
50
|
def process_base(self, start_pages, **kwargs):
|
|
48
51
|
# for each node, check if condition is required issubclass(TriccNodeDisplayModel)
|
|
@@ -106,6 +109,10 @@ class BaseOutPutStrategy:
|
|
|
106
109
|
def export(self, **kwargs):
|
|
107
110
|
pass
|
|
108
111
|
|
|
112
|
+
@abc.abstractmethod
|
|
113
|
+
def validate(self):
|
|
114
|
+
pass
|
|
115
|
+
|
|
109
116
|
def tricc_operation_equal(self, ref_expressions):
|
|
110
117
|
# r[0] = r[1]
|
|
111
118
|
raise NotImplementedError("This type of opreration is not supported in this strategy")
|