tricc-oo 1.5.13__py3-none-any.whl → 1.6.8__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 +20 -28
- tests/test_build.py +260 -0
- tests/test_cql.py +48 -109
- tests/to_ocl.py +15 -17
- tricc_oo/__init__.py +0 -6
- tricc_oo/converters/codesystem_to_ocl.py +51 -40
- tricc_oo/converters/cql/cqlLexer.py +1 -0
- tricc_oo/converters/cql/cqlListener.py +1 -0
- tricc_oo/converters/cql/cqlParser.py +1 -0
- tricc_oo/converters/cql/cqlVisitor.py +1 -0
- tricc_oo/converters/cql_to_operation.py +129 -123
- tricc_oo/converters/datadictionnary.py +45 -54
- tricc_oo/converters/drawio_type_map.py +146 -65
- tricc_oo/converters/tricc_to_xls_form.py +58 -28
- tricc_oo/converters/utils.py +4 -4
- tricc_oo/converters/xml_to_tricc.py +296 -235
- tricc_oo/models/__init__.py +2 -1
- tricc_oo/models/base.py +333 -305
- tricc_oo/models/calculate.py +66 -51
- tricc_oo/models/lang.py +26 -27
- tricc_oo/models/ocl.py +146 -161
- tricc_oo/models/ordered_set.py +15 -19
- tricc_oo/models/tricc.py +149 -89
- tricc_oo/parsers/xml.py +15 -30
- tricc_oo/serializers/planuml.py +4 -6
- tricc_oo/serializers/xls_form.py +110 -153
- tricc_oo/strategies/input/base_input_strategy.py +28 -32
- tricc_oo/strategies/input/drawio.py +59 -71
- tricc_oo/strategies/output/base_output_strategy.py +151 -65
- tricc_oo/strategies/output/dhis2_form.py +908 -0
- tricc_oo/strategies/output/fhir_form.py +377 -0
- tricc_oo/strategies/output/html_form.py +224 -0
- tricc_oo/strategies/output/openmrs_form.py +694 -0
- tricc_oo/strategies/output/spice.py +106 -127
- tricc_oo/strategies/output/xls_form.py +322 -244
- tricc_oo/strategies/output/xlsform_cdss.py +627 -142
- tricc_oo/strategies/output/xlsform_cht.py +252 -125
- tricc_oo/strategies/output/xlsform_cht_hf.py +13 -24
- tricc_oo/visitors/tricc.py +1424 -1033
- tricc_oo/visitors/utils.py +16 -16
- tricc_oo/visitors/xform_pd.py +91 -89
- {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/METADATA +128 -84
- tricc_oo-1.6.8.dist-info/RECORD +52 -0
- tricc_oo-1.6.8.dist-info/licenses/LICENSE +373 -0
- {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/top_level.txt +0 -0
- tricc_oo-1.5.13.dist-info/RECORD +0 -46
- {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/WHEEL +0 -0
|
@@ -1,14 +1,56 @@
|
|
|
1
|
+
import html2text
|
|
2
|
+
import logging
|
|
1
3
|
import base64
|
|
2
4
|
import os
|
|
3
5
|
import re
|
|
4
|
-
from curses.ascii import isalnum, isalpha, isdigit
|
|
5
6
|
|
|
6
|
-
from numpy import isnan
|
|
7
7
|
|
|
8
|
-
from tricc_oo.converters.utils import
|
|
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.
|
|
11
|
-
from tricc_oo.models.base import
|
|
10
|
+
from tricc_oo.converters.utils import generate_id
|
|
11
|
+
from tricc_oo.models.base import (
|
|
12
|
+
TriccOperator, TriccOperation,
|
|
13
|
+
TriccStatic, TriccReference, TriccNodeType, TriccEdge, OPERATION_LIST
|
|
14
|
+
)
|
|
15
|
+
from tricc_oo.models.calculate import (
|
|
16
|
+
TriccNodeDisplayBridge,
|
|
17
|
+
TriccNodeBridge,
|
|
18
|
+
TriccNodeActivityEnd,
|
|
19
|
+
TriccNodeActivityStart,
|
|
20
|
+
TriccNodeEnd,
|
|
21
|
+
TriccNodeCalculate,
|
|
22
|
+
TriccNodeRhombus,
|
|
23
|
+
TriccNodeDisplayCalculateBase,
|
|
24
|
+
TriccNodeExclusive,
|
|
25
|
+
TriccNodeProposedDiagnosis,
|
|
26
|
+
TriccNodeDiagnosis,
|
|
27
|
+
TriccRhombusMixIn,
|
|
28
|
+
TriccNodeInput,
|
|
29
|
+
|
|
30
|
+
)
|
|
31
|
+
from tricc_oo.models.tricc import (
|
|
32
|
+
TriccNodeCalculateBase,
|
|
33
|
+
TriccNodeMainStart,
|
|
34
|
+
TriccNodeActivity,
|
|
35
|
+
TriccGroup,
|
|
36
|
+
TriccNodeSelect,
|
|
37
|
+
TriccNodeGoTo,
|
|
38
|
+
TriccNodeSelectMultiple,
|
|
39
|
+
TriccNodeInputModel,
|
|
40
|
+
TriccNodeSelectNotAvailable,
|
|
41
|
+
TriccNodeSelectOption,
|
|
42
|
+
TriccNodeDisplayModel,
|
|
43
|
+
TriccNodeMoreInfo,
|
|
44
|
+
TriccNodeText,
|
|
45
|
+
TriccNodeDecimal,
|
|
46
|
+
TriccNodeInteger,
|
|
47
|
+
TriccNodeDate,
|
|
48
|
+
TriccNodeSelectOne,
|
|
49
|
+
TriccNodeSelectYesNo,
|
|
50
|
+
TriccNodeNote,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
12
54
|
from tricc_oo.models.ocl import get_data_type
|
|
13
55
|
from tricc_oo.converters.drawio_type_map import TYPE_MAP
|
|
14
56
|
from tricc_oo.parsers.xml import (
|
|
@@ -20,7 +62,11 @@ from tricc_oo.parsers.xml import (
|
|
|
20
62
|
get_tricc_type_list,
|
|
21
63
|
)
|
|
22
64
|
import hashlib
|
|
23
|
-
from tricc_oo.visitors.tricc import
|
|
65
|
+
from tricc_oo.visitors.tricc import (
|
|
66
|
+
get_select_yes_no_options, get_select_not_available_options,
|
|
67
|
+
set_prev_next_node, inject_node_before,
|
|
68
|
+
merge_node, remove_prev_next, get_activity_wait, get_count_terms_details
|
|
69
|
+
)
|
|
24
70
|
from tricc_oo.converters.datadictionnary import add_concept
|
|
25
71
|
|
|
26
72
|
TRICC_YES_LABEL = ["yes", "oui"]
|
|
@@ -28,15 +74,9 @@ TRICC_NO_LABEL = ["no", "non"]
|
|
|
28
74
|
TRICC_FOLLOW_LABEL = ["follow", "suivre", "continue"]
|
|
29
75
|
NO_LABEL = "NO_LABEL"
|
|
30
76
|
TRICC_LIST_NAME = "list_{0}"
|
|
31
|
-
import logging
|
|
32
|
-
DISPLAY_ATTRIBUTES = [
|
|
33
|
-
'label',
|
|
34
|
-
'hint',
|
|
35
|
-
'help'
|
|
36
|
-
]
|
|
37
|
-
logger = logging.getLogger("default")
|
|
38
|
-
import html2text
|
|
39
77
|
|
|
78
|
+
DISPLAY_ATTRIBUTES = ["label", "hint", "help"]
|
|
79
|
+
logger = logging.getLogger("default")
|
|
40
80
|
|
|
41
81
|
|
|
42
82
|
def get_all_nodes(diagram, activity, nodes):
|
|
@@ -51,29 +91,30 @@ def get_all_nodes(diagram, activity, nodes):
|
|
|
51
91
|
activity,
|
|
52
92
|
attributes=TYPE_MAP[tricc_type]["attributes"],
|
|
53
93
|
mandatory_attributes=TYPE_MAP[tricc_type]["mandatory_attributes"],
|
|
54
|
-
has_options=TYPE_MAP[tricc_type].get(
|
|
94
|
+
has_options=TYPE_MAP[tricc_type].get("has_options", None),
|
|
55
95
|
)
|
|
56
96
|
|
|
57
97
|
return nodes
|
|
58
98
|
|
|
99
|
+
|
|
59
100
|
def create_activity(diagram, media_path, project):
|
|
60
101
|
|
|
61
102
|
external_id = diagram.attrib.get("id")
|
|
62
|
-
id = get_id(
|
|
63
|
-
root = create_root_node(diagram)
|
|
64
|
-
|
|
103
|
+
id = get_id(external_id, diagram.attrib.get("id"))
|
|
104
|
+
root, name = create_root_node(diagram)
|
|
105
|
+
label = diagram.attrib.get("name")
|
|
65
106
|
form_id = diagram.attrib.get("name", None)
|
|
66
107
|
if root is not None:
|
|
67
108
|
activity = TriccNodeActivity(
|
|
68
109
|
root=root,
|
|
69
|
-
name=
|
|
110
|
+
name=name, # start node 'name' is saved in label
|
|
70
111
|
id=id,
|
|
71
112
|
external_id=external_id,
|
|
72
|
-
label=
|
|
113
|
+
label=label,
|
|
73
114
|
form_id=form_id,
|
|
74
115
|
)
|
|
75
116
|
if root.relevance is not None:
|
|
76
|
-
activity.applicability=root.relevance
|
|
117
|
+
activity.applicability = root.relevance
|
|
77
118
|
# activity definition is never instanciated
|
|
78
119
|
if isinstance(root, TriccNodeActivityStart):
|
|
79
120
|
activity.instance = 0
|
|
@@ -85,21 +126,45 @@ def create_activity(diagram, media_path, project):
|
|
|
85
126
|
activity.edges = edges
|
|
86
127
|
nodes = get_nodes(diagram, activity)
|
|
87
128
|
for n in nodes.values():
|
|
88
|
-
|
|
129
|
+
|
|
89
130
|
if (
|
|
90
|
-
issubclass(n.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase))
|
|
131
|
+
issubclass(n.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase))
|
|
91
132
|
and not isinstance(n, (TriccRhombusMixIn, TriccNodeRhombus, TriccNodeDisplayBridge))
|
|
92
|
-
and not n.name.startswith(
|
|
133
|
+
and not n.name.startswith("label_") # FIXME
|
|
93
134
|
):
|
|
94
|
-
system = n.name.split(
|
|
135
|
+
system = n.name.split(".")[0] if "." in n.name else "tricc"
|
|
95
136
|
if isinstance(n, TriccNodeSelectOption) and isinstance(n.select, TriccNodeSelectNotAvailable):
|
|
96
|
-
add_concept(
|
|
137
|
+
add_concept(
|
|
138
|
+
project.code_systems,
|
|
139
|
+
system,
|
|
140
|
+
n.select.name,
|
|
141
|
+
n.label,
|
|
142
|
+
{"datatype": "Boolean", "contextType": get_context_type(n)},
|
|
143
|
+
)
|
|
97
144
|
elif not isinstance(n, TriccNodeSelectNotAvailable):
|
|
98
|
-
add_concept(
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
145
|
+
add_concept(
|
|
146
|
+
project.code_systems,
|
|
147
|
+
system,
|
|
148
|
+
n.name,
|
|
149
|
+
n.label,
|
|
150
|
+
{
|
|
151
|
+
"datatype": get_data_type(n.tricc_type),
|
|
152
|
+
"contextType": get_context_type(n),
|
|
153
|
+
},
|
|
154
|
+
)
|
|
155
|
+
if getattr(n, "save", None):
|
|
156
|
+
system = n.save.split(".")[0] if "." in n.save else "tricc"
|
|
157
|
+
add_concept(
|
|
158
|
+
project.code_systems,
|
|
159
|
+
system,
|
|
160
|
+
n.save,
|
|
161
|
+
n.label,
|
|
162
|
+
{
|
|
163
|
+
"datatype": get_data_type(n.tricc_type),
|
|
164
|
+
"contextType": get_context_type(n),
|
|
165
|
+
},
|
|
166
|
+
)
|
|
167
|
+
|
|
103
168
|
groups = get_groups(diagram, nodes, activity)
|
|
104
169
|
if groups and len(groups) > 0:
|
|
105
170
|
activity.groups = groups
|
|
@@ -110,7 +175,7 @@ def create_activity(diagram, media_path, project):
|
|
|
110
175
|
# link back the activity
|
|
111
176
|
activity.root.activity = activity
|
|
112
177
|
manage_dangling_calculate(activity)
|
|
113
|
-
|
|
178
|
+
|
|
114
179
|
if activity is not None:
|
|
115
180
|
if activity.root is not None:
|
|
116
181
|
project.pages[activity.id] = activity
|
|
@@ -119,7 +184,7 @@ def create_activity(diagram, media_path, project):
|
|
|
119
184
|
activity.root.process == "main" or activity.root.process is None
|
|
120
185
|
):
|
|
121
186
|
project.start_pages["main"] = activity
|
|
122
|
-
activity.root.process =
|
|
187
|
+
activity.root.process = "main"
|
|
123
188
|
elif activity.root.process is not None:
|
|
124
189
|
if activity.root.process not in project.start_pages:
|
|
125
190
|
project.start_pages[activity.root.process] = []
|
|
@@ -127,24 +192,27 @@ def create_activity(diagram, media_path, project):
|
|
|
127
192
|
else:
|
|
128
193
|
logger.warning(
|
|
129
194
|
"Page {0} has a start node but there is already a start node in page {1}".format(
|
|
130
|
-
activity.label,
|
|
195
|
+
activity.label, project.start_pages[activity.root.process][0]
|
|
131
196
|
)
|
|
132
197
|
)
|
|
133
198
|
if images:
|
|
134
199
|
project.images += images
|
|
135
|
-
for node in list(
|
|
200
|
+
for node in list(
|
|
201
|
+
filter(
|
|
202
|
+
lambda p_node: isinstance(p_node, TriccNodeSelectNotAvailable),
|
|
203
|
+
list(activity.nodes.values()),
|
|
204
|
+
)
|
|
205
|
+
):
|
|
136
206
|
prev_node = None
|
|
137
|
-
prev_edges = list(filter(lambda p_e: p_e.target == node.id,list(activity.edges)))
|
|
207
|
+
prev_edges = list(filter(lambda p_e: p_e.target == node.id, list(activity.edges)))
|
|
138
208
|
if len(prev_edges):
|
|
139
209
|
prev_node = [n for n in activity.nodes.values() if n.id in [p_e.source for p_e in prev_edges]]
|
|
140
210
|
if prev_node:
|
|
141
211
|
node.parent = prev_node[0]
|
|
142
|
-
if not
|
|
212
|
+
if not node.parent:
|
|
143
213
|
logger.critical(f"unable to find the parent of the NotApplicable node {node.get_name()}")
|
|
144
214
|
exit(1)
|
|
145
215
|
|
|
146
|
-
|
|
147
|
-
|
|
148
216
|
else:
|
|
149
217
|
return None, None
|
|
150
218
|
logger.warning("root not found for page {0}".format(name))
|
|
@@ -158,10 +226,7 @@ def manage_dangling_calculate(activity):
|
|
|
158
226
|
for n in list(
|
|
159
227
|
filter(
|
|
160
228
|
lambda x: (x.target == node.id or x.target == node)
|
|
161
|
-
and (
|
|
162
|
-
x.source in activity.nodes
|
|
163
|
-
or x.source in activity.nodes.values()
|
|
164
|
-
),
|
|
229
|
+
and (x.source in activity.nodes or x.source in activity.nodes.values()),
|
|
165
230
|
activity.edges,
|
|
166
231
|
)
|
|
167
232
|
)
|
|
@@ -188,7 +253,9 @@ def process_edges(diagram, media_path, activity, nodes):
|
|
|
188
253
|
if image is not None:
|
|
189
254
|
images.append({"file_path": enriched, "image_content": image})
|
|
190
255
|
|
|
191
|
-
elif isinstance(nodes[edge.target], (TriccNodeActivityEnd)) or (
|
|
256
|
+
elif isinstance(nodes[edge.target], (TriccNodeActivityEnd)) or (
|
|
257
|
+
isinstance(nodes[edge.target], (TriccNodeEnd)) and isinstance(activity.root, TriccNodeMainStart)
|
|
258
|
+
):
|
|
192
259
|
end_found = True
|
|
193
260
|
if (
|
|
194
261
|
edge.target in nodes
|
|
@@ -197,19 +264,16 @@ def process_edges(diagram, media_path, activity, nodes):
|
|
|
197
264
|
):
|
|
198
265
|
edge.target = nodes[edge.target].path.id
|
|
199
266
|
# modify edge for selectyesNo
|
|
200
|
-
if edge.source in nodes and isinstance(
|
|
201
|
-
nodes[edge.source], TriccNodeSelectYesNo
|
|
202
|
-
):
|
|
267
|
+
if edge.source in nodes and isinstance(nodes[edge.source], TriccNodeSelectYesNo):
|
|
203
268
|
process_yesno_edge(edge, nodes)
|
|
204
269
|
|
|
205
270
|
# create calculate based on edges label
|
|
206
271
|
elif edge.value is not None:
|
|
207
272
|
label = edge.value.strip()
|
|
273
|
+
label_html_free = html2text.html2text(label)
|
|
208
274
|
processed = False
|
|
209
275
|
calc = None
|
|
210
|
-
if (
|
|
211
|
-
label.lower() in TRICC_FOLLOW_LABEL
|
|
212
|
-
):
|
|
276
|
+
if label.lower() in TRICC_FOLLOW_LABEL:
|
|
213
277
|
if isinstance(nodes[edge.source], TriccNodeRhombus):
|
|
214
278
|
edge.source = nodes[edge.source].path.id
|
|
215
279
|
edge.source_external_id = None
|
|
@@ -221,9 +285,12 @@ def process_edges(diagram, media_path, activity, nodes):
|
|
|
221
285
|
calc = process_factor_edge(edge, nodes)
|
|
222
286
|
elif label.lower() in TRICC_NO_LABEL:
|
|
223
287
|
calc = process_exclusive_edge(edge, nodes)
|
|
224
|
-
elif
|
|
288
|
+
elif any(
|
|
289
|
+
reserved in label_html_free
|
|
290
|
+
for reserved in ([str(o) for o in list(TriccOperator)] + list(OPERATION_LIST.keys()) + ["$this"])
|
|
291
|
+
):
|
|
225
292
|
# manage comment
|
|
226
|
-
calc = process_condition_edge(edge, nodes)
|
|
293
|
+
calc = process_condition_edge(edge, label_html_free, nodes)
|
|
227
294
|
else:
|
|
228
295
|
logger.warning(f"unsupported edge label {label} in {diagram.attrib.get('name', diagram.attrib['id'])}")
|
|
229
296
|
processed = True
|
|
@@ -242,25 +309,23 @@ def process_edges(diagram, media_path, activity, nodes):
|
|
|
242
309
|
"not management found",
|
|
243
310
|
)
|
|
244
311
|
)
|
|
245
|
-
elif edge.source in
|
|
246
|
-
logger.critical(
|
|
247
|
-
"rhombus {} node with labelless edges".format(nodes[edge.source].get_name())
|
|
248
|
-
)
|
|
312
|
+
elif edge.source in nodes and isinstance(nodes[edge.source], TriccNodeRhombus):
|
|
313
|
+
logger.critical("rhombus {} node with labelless edges".format(nodes[edge.source].get_name()))
|
|
249
314
|
if not end_found:
|
|
250
315
|
fake_end = TriccNodeActivityEnd(id=generate_id(f"e{activity.name}"), activity=activity, group=activity)
|
|
251
316
|
last_nodes = [
|
|
252
|
-
n
|
|
317
|
+
n
|
|
318
|
+
for n in list(activity.nodes.values())
|
|
253
319
|
if (
|
|
254
320
|
issubclass(
|
|
255
|
-
n.__class__,
|
|
321
|
+
n.__class__,
|
|
256
322
|
(
|
|
257
|
-
TriccNodeInputModel,
|
|
258
|
-
TriccNodeText,
|
|
323
|
+
TriccNodeInputModel,
|
|
324
|
+
TriccNodeText,
|
|
259
325
|
TriccNodeNote,
|
|
260
|
-
)
|
|
261
|
-
) and (
|
|
262
|
-
not any([n.id == e.source for e in activity.edges])
|
|
326
|
+
),
|
|
263
327
|
)
|
|
328
|
+
and (not any([n.id == e.source for e in activity.edges]))
|
|
264
329
|
)
|
|
265
330
|
]
|
|
266
331
|
if last_nodes:
|
|
@@ -271,10 +336,7 @@ def process_edges(diagram, media_path, activity, nodes):
|
|
|
271
336
|
else:
|
|
272
337
|
logger.warning(f"Activity {activity.label} have no end, calculated might be included in the end definition")
|
|
273
338
|
last_nodes = [
|
|
274
|
-
n for n in list(activity.nodes.values())
|
|
275
|
-
if (
|
|
276
|
-
not any([n.id == e.source for e in activity.edges])
|
|
277
|
-
)
|
|
339
|
+
n for n in list(activity.nodes.values()) if (not any([n.id == e.source for e in activity.edges]))
|
|
278
340
|
]
|
|
279
341
|
if last_nodes:
|
|
280
342
|
for n in last_nodes:
|
|
@@ -283,20 +345,19 @@ def process_edges(diagram, media_path, activity, nodes):
|
|
|
283
345
|
else:
|
|
284
346
|
logger.critical(f"cannot guess end for {activity.get_name()}")
|
|
285
347
|
exit(1)
|
|
286
|
-
|
|
348
|
+
|
|
287
349
|
return images
|
|
288
350
|
|
|
351
|
+
|
|
289
352
|
def get_id(elm_id, activity_id):
|
|
290
|
-
|
|
353
|
+
return str(elm_id) if len(elm_id) > 8 else str(activity_id) + str(elm_id)
|
|
354
|
+
|
|
291
355
|
|
|
292
356
|
def _get_name(name, id, act_id):
|
|
293
|
-
if (
|
|
294
|
-
name is not None
|
|
295
|
-
and (name.endswith(("_", ".")))
|
|
296
|
-
):
|
|
357
|
+
if name is not None and (name.endswith(("_", "."))):
|
|
297
358
|
return name + get_id(id, act_id)
|
|
298
359
|
return name
|
|
299
|
-
|
|
360
|
+
|
|
300
361
|
|
|
301
362
|
def get_nodes(diagram, activity):
|
|
302
363
|
nodes = {activity.root.id: activity.root}
|
|
@@ -304,12 +365,9 @@ def get_nodes(diagram, activity):
|
|
|
304
365
|
new_nodes = {}
|
|
305
366
|
node_to_remove = []
|
|
306
367
|
activity_end_node = None
|
|
307
|
-
end_node = None
|
|
308
368
|
for node in nodes.values():
|
|
309
369
|
# clean name
|
|
310
|
-
if (
|
|
311
|
-
hasattr(node, "name")
|
|
312
|
-
):
|
|
370
|
+
if hasattr(node, "name"):
|
|
313
371
|
node.name = _get_name(node.name, node.id, activity.id)
|
|
314
372
|
if issubclass(node.__class__, TriccRhombusMixIn) and node.path is None:
|
|
315
373
|
# generate rhombuse path
|
|
@@ -331,12 +389,10 @@ def get_nodes(diagram, activity):
|
|
|
331
389
|
next_nodes_id = [e.target for e in activity.edges if e.source == node.id]
|
|
332
390
|
if len(next_nodes_id) > 0:
|
|
333
391
|
|
|
334
|
-
calc = get_activity_wait(
|
|
335
|
-
path, [node], next_nodes_id, node, edge_only=True
|
|
336
|
-
)
|
|
392
|
+
calc = get_activity_wait(path, [node], next_nodes_id, node, edge_only=True)
|
|
337
393
|
new_nodes[calc.id] = calc
|
|
338
394
|
for goto_next_node in next_nodes_id:
|
|
339
|
-
remove_prev_next(node, goto_next_node, activity)
|
|
395
|
+
remove_prev_next(node, goto_next_node, activity)
|
|
340
396
|
elif isinstance(node, TriccNodeActivityEnd):
|
|
341
397
|
if not activity_end_node:
|
|
342
398
|
activity_end_node = node
|
|
@@ -345,12 +401,11 @@ def get_nodes(diagram, activity):
|
|
|
345
401
|
node_to_remove.append(node.id)
|
|
346
402
|
# add activity relevance to calculate
|
|
347
403
|
elif (
|
|
348
|
-
issubclass(node.__class__, TriccNodeDisplayCalculateBase)
|
|
349
|
-
and not getattr(node,
|
|
404
|
+
issubclass(node.__class__, TriccNodeDisplayCalculateBase)
|
|
405
|
+
and not getattr(node, "relevance", None)
|
|
350
406
|
and node.activity.applicability
|
|
351
407
|
):
|
|
352
408
|
node.applicability = node.activity.applicability
|
|
353
|
-
|
|
354
409
|
|
|
355
410
|
nodes.update(new_nodes)
|
|
356
411
|
|
|
@@ -371,7 +426,7 @@ def create_root_node(diagram):
|
|
|
371
426
|
elm = get_tricc_type(diagram, "UserObject", TriccNodeType.start)
|
|
372
427
|
if elm is not None:
|
|
373
428
|
external_id = elm.attrib.get("id")
|
|
374
|
-
id = get_id(
|
|
429
|
+
id = get_id(external_id, diagram.attrib.get("id"))
|
|
375
430
|
node = TriccNodeMainStart(
|
|
376
431
|
id=id,
|
|
377
432
|
external_id=external_id,
|
|
@@ -380,7 +435,7 @@ def create_root_node(diagram):
|
|
|
380
435
|
label=elm.attrib.get("label"),
|
|
381
436
|
form_id=elm.attrib.get("form_id"),
|
|
382
437
|
relevance=elm.attrib.get("relevance"),
|
|
383
|
-
process=elm.attrib.get(
|
|
438
|
+
process=elm.attrib.get("process", "registration"),
|
|
384
439
|
)
|
|
385
440
|
else:
|
|
386
441
|
elm = get_tricc_type(diagram, "object", TriccNodeType.activity_start)
|
|
@@ -388,22 +443,19 @@ def create_root_node(diagram):
|
|
|
388
443
|
elm = get_tricc_type(diagram, "UserObject", TriccNodeType.activity_start)
|
|
389
444
|
if elm is not None:
|
|
390
445
|
external_id = elm.attrib.get("id")
|
|
391
|
-
id = get_id(
|
|
446
|
+
id = get_id(external_id, diagram.attrib.get("id"))
|
|
447
|
+
name = generate_id("start"+external_id)
|
|
392
448
|
node = TriccNodeActivityStart(
|
|
393
449
|
id=id,
|
|
394
450
|
external_id=external_id,
|
|
395
|
-
#parent=elm.attrib.get("parent"),
|
|
396
|
-
name=
|
|
451
|
+
# parent=elm.attrib.get("parent"),
|
|
452
|
+
name=name,
|
|
397
453
|
label=diagram.attrib.get("name"),
|
|
398
454
|
relevance=elm.attrib.get("relevance"),
|
|
399
|
-
instance=int(
|
|
400
|
-
elm.attrib.get("instance")
|
|
401
|
-
if elm.attrib.get("instance") is not None
|
|
402
|
-
else 1
|
|
403
|
-
),
|
|
455
|
+
instance=int(elm.attrib.get("instance") if elm.attrib.get("instance") is not None else 1),
|
|
404
456
|
)
|
|
405
457
|
load_expressions(node)
|
|
406
|
-
return node
|
|
458
|
+
return node, _get_name(elm.attrib.get("name", "act_"), external_id, diagram.attrib.get("id")) if node else None
|
|
407
459
|
|
|
408
460
|
|
|
409
461
|
# converter XML item to object
|
|
@@ -425,6 +477,39 @@ def set_additional_attributes(attribute_names, elm, node):
|
|
|
425
477
|
setattr(node, attributename, attribute)
|
|
426
478
|
|
|
427
479
|
|
|
480
|
+
def get_context_type(node):
|
|
481
|
+
context_type = getattr(node, "context_type", None)
|
|
482
|
+
if context_type:
|
|
483
|
+
return context_type
|
|
484
|
+
if isinstance(node, TriccNodeSelectMultiple):
|
|
485
|
+
return "Question"
|
|
486
|
+
elif isinstance(node, TriccNodeSelectOption):
|
|
487
|
+
if isinstance(node.select, TriccNodeSelectMultiple):
|
|
488
|
+
return "Symptom-Finding"
|
|
489
|
+
else:
|
|
490
|
+
return "Value"
|
|
491
|
+
elif isinstance(node, TriccNodeNote):
|
|
492
|
+
return "InteractSet"
|
|
493
|
+
elif isinstance(
|
|
494
|
+
node,
|
|
495
|
+
(
|
|
496
|
+
TriccNodeDecimal,
|
|
497
|
+
TriccNodeInteger,
|
|
498
|
+
TriccNodeText,
|
|
499
|
+
TriccNodeDate,
|
|
500
|
+
TriccNodeSelectOne,
|
|
501
|
+
TriccNodeSelectYesNo,
|
|
502
|
+
TriccNodeSelectNotAvailable,
|
|
503
|
+
TriccNodeInput,
|
|
504
|
+
),
|
|
505
|
+
):
|
|
506
|
+
return "Symptom-Finding"
|
|
507
|
+
elif isinstance(node, (TriccNodeProposedDiagnosis, TriccNodeDiagnosis)):
|
|
508
|
+
return "Diagnosis"
|
|
509
|
+
elif issubclass(node.__class__, TriccNodeCalculateBase):
|
|
510
|
+
return "Calculation"
|
|
511
|
+
else:
|
|
512
|
+
return "Misc"
|
|
428
513
|
|
|
429
514
|
|
|
430
515
|
def get_select_options(diagram, select_node, nodes):
|
|
@@ -435,16 +520,12 @@ def get_select_options(diagram, select_node, nodes):
|
|
|
435
520
|
for elm in list:
|
|
436
521
|
name = elm.attrib.get("name")
|
|
437
522
|
if name in options_name_list and not name.endswith("_"):
|
|
438
|
-
logger.critical(
|
|
439
|
-
"Select question {0} have twice the option name {1}".format(
|
|
440
|
-
select_node.get_name(), name
|
|
441
|
-
)
|
|
442
|
-
)
|
|
523
|
+
logger.critical("Select question {0} have twice the option name {1}".format(select_node.get_name(), name))
|
|
443
524
|
else:
|
|
444
525
|
options_name_list.append(name)
|
|
445
|
-
|
|
526
|
+
|
|
446
527
|
external_id = elm.attrib.get("id")
|
|
447
|
-
id = get_id(external_id, diagram.attrib.get(
|
|
528
|
+
id = get_id(external_id, diagram.attrib.get("id"))
|
|
448
529
|
option = TriccNodeSelectOption(
|
|
449
530
|
id=id,
|
|
450
531
|
label=elm.attrib.get("label"),
|
|
@@ -453,8 +534,8 @@ def get_select_options(diagram, select_node, nodes):
|
|
|
453
534
|
list_name=select_node.list_name,
|
|
454
535
|
activity=select_node.activity,
|
|
455
536
|
group=select_node.group,
|
|
456
|
-
|
|
457
|
-
set_additional_attributes(["save", "relevance"], elm, option)
|
|
537
|
+
)
|
|
538
|
+
set_additional_attributes(["save", "relevance", "context_type"], elm, option)
|
|
458
539
|
load_expressions(option)
|
|
459
540
|
options[i] = option
|
|
460
541
|
nodes[id] = option
|
|
@@ -464,7 +545,7 @@ def get_select_options(diagram, select_node, nodes):
|
|
|
464
545
|
else:
|
|
465
546
|
return options
|
|
466
547
|
|
|
467
|
-
|
|
548
|
+
# TBR START
|
|
468
549
|
|
|
469
550
|
|
|
470
551
|
def get_max_version(dict):
|
|
@@ -484,11 +565,10 @@ def get_max_named_version(calculates, name):
|
|
|
484
565
|
return max
|
|
485
566
|
|
|
486
567
|
|
|
487
|
-
|
|
488
568
|
def inject_bridge_path(node, nodes):
|
|
489
569
|
calc_name = "p" + node.id
|
|
490
570
|
calc_id = generate_id(calc_name)
|
|
491
|
-
|
|
571
|
+
|
|
492
572
|
data = {
|
|
493
573
|
"id": calc_id,
|
|
494
574
|
"group": node.group,
|
|
@@ -501,22 +581,16 @@ def inject_bridge_path(node, nodes):
|
|
|
501
581
|
nodes[n.source]
|
|
502
582
|
for n in list(
|
|
503
583
|
filter(
|
|
504
|
-
lambda x: (x.target == node.id or x.target == node)
|
|
505
|
-
and x.source in nodes,
|
|
584
|
+
lambda x: (x.target == node.id or x.target == node) and x.source in nodes,
|
|
506
585
|
node.activity.edges,
|
|
507
586
|
)
|
|
508
587
|
)
|
|
509
588
|
]
|
|
510
|
-
if (
|
|
511
|
-
|
|
589
|
+
if (
|
|
590
|
+
len(prev_nodes) > 1
|
|
591
|
+
and sum(
|
|
512
592
|
[
|
|
513
|
-
(
|
|
514
|
-
0
|
|
515
|
-
if issubclass(
|
|
516
|
-
n.__class__, (TriccNodeDisplayCalculateBase, TriccNodeRhombus)
|
|
517
|
-
)
|
|
518
|
-
else 1
|
|
519
|
-
)
|
|
593
|
+
(0 if issubclass(n.__class__, (TriccNodeDisplayCalculateBase, TriccNodeRhombus)) else 1)
|
|
520
594
|
for n in prev_nodes
|
|
521
595
|
]
|
|
522
596
|
)
|
|
@@ -545,7 +619,7 @@ def enrich_node(diagram, media_path, edge, node, activity, help_before=False):
|
|
|
545
619
|
# get node and process type
|
|
546
620
|
type, message = get_message(diagram, edge.source_external_id)
|
|
547
621
|
if type is not None:
|
|
548
|
-
if type ==
|
|
622
|
+
if type == "help":
|
|
549
623
|
help = TriccNodeMoreInfo(
|
|
550
624
|
id=generate_id(),
|
|
551
625
|
name=f"{node.name}.more_info",
|
|
@@ -553,7 +627,7 @@ def enrich_node(diagram, media_path, edge, node, activity, help_before=False):
|
|
|
553
627
|
parent=node,
|
|
554
628
|
required=None,
|
|
555
629
|
)
|
|
556
|
-
#node.help = message
|
|
630
|
+
# node.help = message
|
|
557
631
|
if help_before:
|
|
558
632
|
inject_node_before(help, node, activity)
|
|
559
633
|
else:
|
|
@@ -585,34 +659,41 @@ def enrich_node(diagram, media_path, edge, node, activity, help_before=False):
|
|
|
585
659
|
return None, None
|
|
586
660
|
else:
|
|
587
661
|
logger.warning(f"edge from an unsuported node {edge.source_external_id}")
|
|
588
|
-
|
|
662
|
+
|
|
589
663
|
return None, None
|
|
590
664
|
|
|
591
665
|
|
|
592
|
-
get_style_dict
|
|
666
|
+
def get_style_dict(style):
|
|
667
|
+
return dict(item.split("=", 1) for item in style.split(";") if "=" in item)
|
|
593
668
|
|
|
594
669
|
|
|
595
|
-
def severity_from_color(color):
|
|
596
|
-
if color ==
|
|
597
|
-
return
|
|
598
|
-
elif color ==
|
|
599
|
-
return
|
|
670
|
+
def severity_from_color(color):
|
|
671
|
+
if color == "#fff2cc":
|
|
672
|
+
return "moderate"
|
|
673
|
+
elif color == "#f8cecc":
|
|
674
|
+
return "severe"
|
|
600
675
|
else:
|
|
601
|
-
return
|
|
602
|
-
|
|
676
|
+
return "light"
|
|
603
677
|
|
|
604
678
|
|
|
605
679
|
def add_tricc_base_node(
|
|
606
|
-
diagram,
|
|
680
|
+
diagram,
|
|
681
|
+
nodes,
|
|
682
|
+
type,
|
|
683
|
+
list,
|
|
684
|
+
group,
|
|
685
|
+
attributes=[],
|
|
686
|
+
mandatory_attributes=[],
|
|
687
|
+
has_options=None,
|
|
607
688
|
):
|
|
608
689
|
for elm in list:
|
|
609
690
|
external_id = elm.attrib.get("id")
|
|
610
|
-
id = get_id(
|
|
611
|
-
|
|
691
|
+
id = get_id(external_id, diagram.attrib.get("id"))
|
|
692
|
+
elm.attrib.get("parent")
|
|
612
693
|
node = type(
|
|
613
694
|
external_id=external_id,
|
|
614
695
|
id=id,
|
|
615
|
-
#parent=parent,
|
|
696
|
+
# parent=parent,
|
|
616
697
|
group=group,
|
|
617
698
|
activity=group,
|
|
618
699
|
**set_mandatory_attribute(elm, mandatory_attributes, diagram),
|
|
@@ -630,102 +711,99 @@ def add_tricc_base_node(
|
|
|
630
711
|
node.options = get_select_yes_no_options(node, group)
|
|
631
712
|
nodes[node.options[0].id] = node.options[0]
|
|
632
713
|
nodes[node.options[1].id] = node.options[1]
|
|
633
|
-
elif type == TriccNodeProposedDiagnosis and getattr(node,
|
|
714
|
+
elif type == TriccNodeProposedDiagnosis and getattr(node, "severity", "") is None:
|
|
634
715
|
mxcell = get_mxcell(diagram, external_id)
|
|
635
|
-
styles = get_style_dict(mxcell.attrib.get(
|
|
636
|
-
if
|
|
637
|
-
node.severity = severity_from_color(styles[
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
716
|
+
styles = get_style_dict(mxcell.attrib.get("style", ""))
|
|
717
|
+
if "fillColor" in styles and styles["fillColor"] != "none":
|
|
718
|
+
node.severity = severity_from_color(styles["fillColor"])
|
|
719
|
+
|
|
641
720
|
set_additional_attributes(attributes, elm, node)
|
|
642
721
|
load_expressions(node)
|
|
643
722
|
nodes[id] = node
|
|
644
723
|
|
|
645
724
|
|
|
646
725
|
def load_expressions(node):
|
|
647
|
-
if getattr(node,
|
|
648
|
-
node.
|
|
649
|
-
if getattr(node,
|
|
650
|
-
node.
|
|
651
|
-
if getattr(node,
|
|
652
|
-
node.
|
|
653
|
-
if getattr(node,
|
|
726
|
+
if getattr(node, "constraint", None):
|
|
727
|
+
node.constraint = parse_expression("", node.constraint)
|
|
728
|
+
if getattr(node, "expression", None):
|
|
729
|
+
node.expression = parse_expression("", node.expression)
|
|
730
|
+
if getattr(node, "relevance", None):
|
|
731
|
+
node.relevance = parse_expression("", node.relevance)
|
|
732
|
+
if getattr(node, "trigger", None):
|
|
733
|
+
node.trigger = parse_expression("", node.trigger)
|
|
734
|
+
if getattr(node, "default", None):
|
|
735
|
+
node.default = parse_expression("", node.default)
|
|
736
|
+
if getattr(node, "reference", None):
|
|
654
737
|
if isinstance(node, TriccNodeRhombus):
|
|
655
738
|
node.label = remove_html(node.label)
|
|
656
739
|
node.expression_reference = parse_expression(node.label, node.reference)
|
|
657
740
|
else:
|
|
658
|
-
node.expression_reference = parse_expression(
|
|
659
|
-
|
|
741
|
+
node.expression_reference = parse_expression("", node.reference)
|
|
742
|
+
|
|
660
743
|
node.reference = node.expression_reference.get_references()
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
744
|
+
|
|
664
745
|
|
|
665
746
|
def parse_expression(label=None, expression=None):
|
|
666
747
|
if expression:
|
|
667
|
-
ref_pattern = r
|
|
668
|
-
|
|
748
|
+
ref_pattern = r"(\$\{[^\}]+\})"
|
|
749
|
+
# only if simple ref
|
|
669
750
|
if not re.search(ref_pattern, expression):
|
|
670
751
|
operation = transform_cql_to_operation(expression, label)
|
|
671
752
|
if isinstance(operation, TriccReference):
|
|
672
753
|
if label:
|
|
673
|
-
if label[0] ==
|
|
754
|
+
if label[0] == "[" and label[-1] == "]":
|
|
674
755
|
operation = TriccOperation(
|
|
675
756
|
operator=TriccOperator.SELECTED,
|
|
676
757
|
reference=[
|
|
677
758
|
operation,
|
|
678
|
-
TriccReference(operation.value + label)
|
|
679
|
-
]
|
|
759
|
+
TriccReference(operation.value + label),
|
|
760
|
+
],
|
|
680
761
|
)
|
|
681
762
|
else:
|
|
682
763
|
for operator in OPERATION_LIST:
|
|
683
764
|
if operator in label:
|
|
684
|
-
if operator ==
|
|
685
|
-
operator =
|
|
765
|
+
if operator == "==":
|
|
766
|
+
operator = "="
|
|
686
767
|
terms = label.split(operator)
|
|
687
768
|
operation = transform_cql_to_operation(
|
|
688
769
|
f"{expression} {operator} {terms[1].replace('?', '').strip()}",
|
|
689
|
-
label
|
|
770
|
+
label,
|
|
690
771
|
)
|
|
691
772
|
break
|
|
692
773
|
# implied is true
|
|
693
774
|
if isinstance(operation, TriccReference):
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
775
|
+
operation = TriccOperation(
|
|
776
|
+
operator=TriccOperator.ISTRUE,
|
|
777
|
+
reference=[
|
|
778
|
+
operation,
|
|
779
|
+
],
|
|
780
|
+
)
|
|
781
|
+
|
|
701
782
|
else:
|
|
702
783
|
pass
|
|
703
784
|
|
|
704
785
|
else:
|
|
705
|
-
operation = transform_cql_to_operation(
|
|
706
|
-
|
|
707
|
-
label
|
|
708
|
-
)
|
|
709
|
-
|
|
786
|
+
operation = transform_cql_to_operation(expression.replace("${", '"').replace("}", '"'), label)
|
|
787
|
+
|
|
710
788
|
if operation is None:
|
|
711
789
|
logger.warning(f"unable to parse: {expression} ")
|
|
712
790
|
return expression
|
|
713
791
|
return operation
|
|
714
|
-
|
|
792
|
+
|
|
715
793
|
|
|
716
794
|
def set_mandatory_attribute(elm, mandatory_attributes, diagram=None):
|
|
717
795
|
param = {}
|
|
718
|
-
diagram_id = diagram.attrib.get(
|
|
796
|
+
diagram_id = diagram.attrib.get("id")
|
|
719
797
|
for attributes in mandatory_attributes:
|
|
720
|
-
if attributes ==
|
|
798
|
+
if attributes == "name":
|
|
721
799
|
name = elm.attrib.get("name")
|
|
722
800
|
id = elm.attrib.get("id")
|
|
723
801
|
attribute_value = _get_name(name, id, diagram_id)
|
|
724
|
-
elif attributes ==
|
|
802
|
+
elif attributes == "list_name":
|
|
725
803
|
name = elm.attrib.get("name")
|
|
726
804
|
id = elm.attrib.get("id")
|
|
727
|
-
attribute_value = TRICC_LIST_NAME.format(clean_str(_get_name(name, id, diagram_id), replace_dots=
|
|
728
|
-
else:
|
|
805
|
+
attribute_value = TRICC_LIST_NAME.format(clean_str(_get_name(name, id, diagram_id), replace_dots=True))
|
|
806
|
+
else:
|
|
729
807
|
attribute_value = elm.attrib.get(attributes)
|
|
730
808
|
if attribute_value is None:
|
|
731
809
|
if elm.attrib.get("label") is not None:
|
|
@@ -734,21 +812,19 @@ def set_mandatory_attribute(elm, mandatory_attributes, diagram=None):
|
|
|
734
812
|
display_name = elm.attrib.get("name")
|
|
735
813
|
else:
|
|
736
814
|
display_name = elm.attrib.get("id")
|
|
737
|
-
|
|
815
|
+
|
|
738
816
|
if attributes == "source":
|
|
739
817
|
if elm.attrib.get("target") is not None:
|
|
740
|
-
logger.critical(
|
|
741
|
-
"the attibute target is {}".format(elm.attrib.get("target"))
|
|
742
|
-
)
|
|
818
|
+
logger.critical("the attibute target is {}".format(elm.attrib.get("target")))
|
|
743
819
|
elif attributes == "target":
|
|
744
820
|
if elm.attrib.get("source") is not None:
|
|
745
|
-
logger.critical(
|
|
746
|
-
|
|
747
|
-
)
|
|
748
|
-
|
|
821
|
+
logger.critical("the attibute target is {}".format(elm.attrib.get("source")))
|
|
822
|
+
|
|
749
823
|
logger.critical(
|
|
750
824
|
"the attibute {} is mandatory but not found in {} within group {}".format(
|
|
751
|
-
attributes,
|
|
825
|
+
attributes,
|
|
826
|
+
display_name,
|
|
827
|
+
diagram.attrib.get("name") if diagram is not None else "",
|
|
752
828
|
)
|
|
753
829
|
)
|
|
754
830
|
exit(1)
|
|
@@ -770,15 +846,15 @@ def clean_link(link):
|
|
|
770
846
|
return link_parts[1]
|
|
771
847
|
|
|
772
848
|
|
|
773
|
-
def get_groups(diagram, nodes,
|
|
849
|
+
def get_groups(diagram, nodes, activity):
|
|
774
850
|
groups = {}
|
|
775
851
|
list = get_tricc_type_list(diagram, "object", TriccNodeType.page)
|
|
776
852
|
for elm in list:
|
|
777
|
-
add_group(elm, diagram, nodes, groups,
|
|
853
|
+
add_group(elm, diagram, nodes, groups, activity, activity)
|
|
778
854
|
return groups
|
|
779
855
|
|
|
780
856
|
|
|
781
|
-
def add_group(elm, diagram, nodes, groups, parent_group):
|
|
857
|
+
def add_group(elm, diagram, nodes, groups, parent_group, activity):
|
|
782
858
|
external_id = elm.attrib.get("id")
|
|
783
859
|
id = get_id(external_id, diagram.attrib.get("id"))
|
|
784
860
|
if id not in groups:
|
|
@@ -788,11 +864,10 @@ def add_group(elm, diagram, nodes, groups, parent_group):
|
|
|
788
864
|
id=id,
|
|
789
865
|
external_id=external_id,
|
|
790
866
|
group=parent_group,
|
|
867
|
+
activity=activity,
|
|
791
868
|
)
|
|
792
869
|
# get elememt witn parent = id and tricc_type defiend
|
|
793
|
-
list_child = get_tricc_type_list(
|
|
794
|
-
diagram, ["object", "UserObject"], tricc_type=None, parent_id=id
|
|
795
|
-
)
|
|
870
|
+
list_child = get_tricc_type_list(diagram, ["object", "UserObject"], tricc_type=None, parent_id=id)
|
|
796
871
|
add_group_to_child(group, diagram, list_child, nodes, groups, parent_group)
|
|
797
872
|
if group is not None:
|
|
798
873
|
groups[group.id] = group
|
|
@@ -808,12 +883,10 @@ def add_group_to_child(group, diagram, list_child, nodes, groups, parent_group):
|
|
|
808
883
|
tricc_type=None,
|
|
809
884
|
parent_id=child_elm.attrib.get("id"),
|
|
810
885
|
)
|
|
811
|
-
add_group_to_child(
|
|
812
|
-
group, diagram, list_sub_child, nodes, groups, parent_group
|
|
813
|
-
)
|
|
886
|
+
add_group_to_child(group, diagram, list_sub_child, nodes, groups, parent_group)
|
|
814
887
|
elif child_elm.attrib.get("tricc_type") == TriccNodeType.page:
|
|
815
888
|
child_group_id = child_elm.attrib.get("id")
|
|
816
|
-
if not
|
|
889
|
+
if child_group_id not in groups:
|
|
817
890
|
child_group = add_group(child_elm, diagram, nodes, groups, group)
|
|
818
891
|
else:
|
|
819
892
|
child_group = groups[child_group_id]
|
|
@@ -838,16 +911,14 @@ def add_image_from_style(style, path):
|
|
|
838
911
|
image_attrib = None
|
|
839
912
|
if style is not None and "image=data:image/" in style:
|
|
840
913
|
image_attrib = style.split("image=data:image/")
|
|
841
|
-
if image_attrib is not None and len(image_attrib)== 2:
|
|
914
|
+
if image_attrib is not None and len(image_attrib) == 2:
|
|
842
915
|
image_parts = image_attrib[1].split(",")
|
|
843
916
|
if len(image_parts) == 2:
|
|
844
917
|
payload = image_parts[1][:-1]
|
|
845
|
-
image_name = hashlib.md5(payload.encode(
|
|
918
|
+
image_name = hashlib.md5(payload.encode("utf-8")).hexdigest()
|
|
846
919
|
path = os.path.join(path, "images")
|
|
847
920
|
file_name = os.path.join(path, image_name + "." + image_parts[0])
|
|
848
|
-
if not (
|
|
849
|
-
os.path.isdir(path)
|
|
850
|
-
): # check if it exists, because if it does, error will be raised
|
|
921
|
+
if not (os.path.isdir(path)): # check if it exists, because if it does, error will be raised
|
|
851
922
|
# (later change to make folder complaint to CHT)
|
|
852
923
|
os.makedirs(path, exist_ok=True)
|
|
853
924
|
with open(file_name, "wb") as fh:
|
|
@@ -857,13 +928,6 @@ def add_image_from_style(style, path):
|
|
|
857
928
|
return None, None
|
|
858
929
|
|
|
859
930
|
|
|
860
|
-
def get_contained_main_node(diagram, id):
|
|
861
|
-
list = get_mxcell_parent_list(diagram, id, media_nodes)
|
|
862
|
-
if isinstance(list, List) and len(list) > 0:
|
|
863
|
-
# use only the first one
|
|
864
|
-
return list[0]
|
|
865
|
-
|
|
866
|
-
|
|
867
931
|
def get_message(diagram, id):
|
|
868
932
|
elm = get_elm(diagram, id)
|
|
869
933
|
if elm is not None:
|
|
@@ -884,14 +948,12 @@ def get_edges(diagram):
|
|
|
884
948
|
id = get_id(external_id, diagram.attrib.get("id"))
|
|
885
949
|
edge = TriccEdge(
|
|
886
950
|
id=id,
|
|
887
|
-
**set_mandatory_attribute(
|
|
888
|
-
elm, ["source", "parent", "target"], diagram
|
|
889
|
-
),
|
|
951
|
+
**set_mandatory_attribute(elm, ["source", "parent", "target"], diagram),
|
|
890
952
|
)
|
|
891
953
|
edge.source_external_id = edge.source
|
|
892
954
|
edge.target_external_id = edge.target
|
|
893
|
-
edge.source = get_id(edge.source,
|
|
894
|
-
edge.target = get_id(edge.target,
|
|
955
|
+
edge.source = get_id(edge.source, diagram.attrib.get("id"))
|
|
956
|
+
edge.target = get_id(edge.target, diagram.attrib.get("id"))
|
|
895
957
|
set_additional_attributes(["value"], elm, edge)
|
|
896
958
|
if edge.value is not None:
|
|
897
959
|
edge.value = remove_html(edge.value)
|
|
@@ -899,7 +961,7 @@ def get_edges(diagram):
|
|
|
899
961
|
return edges
|
|
900
962
|
|
|
901
963
|
|
|
902
|
-
|
|
964
|
+
# Process edges
|
|
903
965
|
|
|
904
966
|
|
|
905
967
|
def process_factor_edge(edge, nodes):
|
|
@@ -908,7 +970,10 @@ def process_factor_edge(edge, nodes):
|
|
|
908
970
|
source = nodes[edge.source]
|
|
909
971
|
return TriccNodeCalculate(
|
|
910
972
|
id=edge.id,
|
|
911
|
-
expression_reference=TriccOperation(
|
|
973
|
+
expression_reference=TriccOperation(
|
|
974
|
+
TriccOperator.MULTIPLIED,
|
|
975
|
+
[TriccReference(nodes[edge.source].name), TriccStatic(float(factor))],
|
|
976
|
+
),
|
|
912
977
|
reference=[TriccReference(source.name)],
|
|
913
978
|
activity=source.activity,
|
|
914
979
|
group=source.group,
|
|
@@ -917,15 +982,20 @@ def process_factor_edge(edge, nodes):
|
|
|
917
982
|
return None
|
|
918
983
|
|
|
919
984
|
|
|
920
|
-
def process_condition_edge(edge, nodes):
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
operation = parse_expression('', expression=label.replace('$this', node_ref ))
|
|
985
|
+
def process_condition_edge(edge, label, nodes):
|
|
986
|
+
source = nodes[edge.source]
|
|
987
|
+
node_ref = f'"{source.name}"'
|
|
988
|
+
if "$this" in label:
|
|
989
|
+
operation = parse_expression("", expression=label.replace("$this", node_ref))
|
|
926
990
|
else:
|
|
927
991
|
operation = parse_expression(label, expression=node_ref)
|
|
992
|
+
|
|
928
993
|
if operation and isinstance(operation, TriccOperation):
|
|
994
|
+
# special management for simple operation
|
|
995
|
+
if issubclass(source.__class__, TriccNodeSelect) and "$this" not in label:
|
|
996
|
+
operation.replace_node(
|
|
997
|
+
TriccReference(source.name),
|
|
998
|
+
get_count_terms_details(source, None, False))
|
|
929
999
|
# insert rhombus
|
|
930
1000
|
return TriccNodeRhombus(
|
|
931
1001
|
id=edge.id,
|
|
@@ -934,13 +1004,10 @@ def process_condition_edge(edge, nodes):
|
|
|
934
1004
|
path=nodes[edge.source],
|
|
935
1005
|
activity=nodes[edge.source].activity,
|
|
936
1006
|
group=nodes[edge.source].group,
|
|
937
|
-
label=label
|
|
1007
|
+
label=label,
|
|
938
1008
|
)
|
|
939
1009
|
|
|
940
1010
|
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
1011
|
def process_exclusive_edge(edge, nodes):
|
|
945
1012
|
error = None
|
|
946
1013
|
if issubclass(nodes[edge.source].__class__, TriccNodeCalculateBase):
|
|
@@ -971,9 +1038,7 @@ def process_exclusive_edge(edge, nodes):
|
|
|
971
1038
|
|
|
972
1039
|
def process_yesno_edge(edge, nodes):
|
|
973
1040
|
if not edge.value:
|
|
974
|
-
logger.critical(
|
|
975
|
-
"yesNo {} node with labelless edges".format(nodes[edge.source].get_name())
|
|
976
|
-
)
|
|
1041
|
+
logger.critical("yesNo {} node with labelless edges".format(nodes[edge.source].get_name()))
|
|
977
1042
|
exit(1)
|
|
978
1043
|
label = edge.value.strip().lower()
|
|
979
1044
|
yes_option = None
|
|
@@ -992,8 +1057,4 @@ def process_yesno_edge(edge, nodes):
|
|
|
992
1057
|
edge.source = no_option.id
|
|
993
1058
|
edge.source_external_id = None
|
|
994
1059
|
else:
|
|
995
|
-
logger.warning(
|
|
996
|
-
"edge {0} is coming from select {1}".format(
|
|
997
|
-
edge.id, nodes[edge.source].get_name()
|
|
998
|
-
)
|
|
999
|
-
)
|
|
1060
|
+
logger.warning("edge {0} is coming from select {1}".format(edge.id, nodes[edge.source].get_name()))
|