tricc-oo 1.5.22__py3-none-any.whl → 1.5.24__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 +17 -23
- tests/test_cql.py +37 -108
- 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 +125 -123
- tricc_oo/converters/datadictionnary.py +45 -54
- tricc_oo/converters/drawio_type_map.py +143 -61
- tricc_oo/converters/tricc_to_xls_form.py +14 -24
- tricc_oo/converters/utils.py +3 -3
- tricc_oo/converters/xml_to_tricc.py +286 -231
- tricc_oo/models/__init__.py +2 -1
- tricc_oo/models/base.py +300 -308
- tricc_oo/models/calculate.py +63 -49
- 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 +145 -89
- tricc_oo/parsers/xml.py +15 -30
- tricc_oo/serializers/planuml.py +4 -6
- tricc_oo/serializers/xls_form.py +81 -135
- 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 +142 -67
- 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 +647 -0
- tricc_oo/strategies/output/spice.py +106 -127
- tricc_oo/strategies/output/xls_form.py +263 -222
- tricc_oo/strategies/output/xlsform_cdss.py +623 -142
- tricc_oo/strategies/output/xlsform_cht.py +108 -115
- tricc_oo/strategies/output/xlsform_cht_hf.py +13 -24
- tricc_oo/visitors/tricc.py +1297 -1016
- tricc_oo/visitors/utils.py +16 -16
- tricc_oo/visitors/xform_pd.py +91 -89
- {tricc_oo-1.5.22.dist-info → tricc_oo-1.5.24.dist-info}/METADATA +127 -84
- tricc_oo-1.5.24.dist-info/RECORD +50 -0
- tricc_oo-1.5.24.dist-info/licenses/LICENSE +373 -0
- tricc_oo-1.5.22.dist-info/RECORD +0 -46
- {tricc_oo-1.5.22.dist-info → tricc_oo-1.5.24.dist-info}/WHEEL +0 -0
- {tricc_oo-1.5.22.dist-info → tricc_oo-1.5.24.dist-info}/top_level.txt +0 -0
tricc_oo/visitors/tricc.py
CHANGED
|
@@ -1,65 +1,119 @@
|
|
|
1
1
|
import re
|
|
2
2
|
import logging
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
import requests
|
|
4
|
+
import base64
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from tricc_oo.converters.utils import generate_id
|
|
8
|
+
from tricc_oo.models.base import (
|
|
9
|
+
TriccBaseModel, TriccNodeType,
|
|
10
|
+
TriccOperator, TriccOperation, TriccStatic, TriccReference, not_clean,
|
|
11
|
+
and_join, or_join, clean_or_list, nand_join, TriccEdge
|
|
12
|
+
)
|
|
13
|
+
from tricc_oo.models.ordered_set import OrderedSet
|
|
14
|
+
from tricc_oo.models.calculate import (
|
|
15
|
+
TriccNodeDisplayBridge,
|
|
16
|
+
TriccNodeBridge,
|
|
17
|
+
TriccNodeWait,
|
|
18
|
+
TriccNodeCalculate,
|
|
19
|
+
TriccNodeRhombus,
|
|
20
|
+
TriccNodeDisplayCalculateBase,
|
|
21
|
+
TriccNodeExclusive,
|
|
22
|
+
TriccNodeProposedDiagnosis,
|
|
23
|
+
TriccNodeCount,
|
|
24
|
+
TriccNodeAdd,
|
|
25
|
+
TriccNodeFakeCalculateBase,
|
|
26
|
+
TriccRhombusMixIn,
|
|
27
|
+
TriccNodeInput,
|
|
28
|
+
TriccNodeActivityEnd,
|
|
29
|
+
TriccNodeActivityStart,
|
|
30
|
+
TriccNodeEnd,
|
|
31
|
+
get_node_from_id,
|
|
32
|
+
|
|
33
|
+
)
|
|
34
|
+
from tricc_oo.models.tricc import (
|
|
35
|
+
TriccNodeCalculateBase, TriccNodeActivity, TriccNodeBaseModel, TriccNodeNumber,
|
|
36
|
+
TriccNodeSelectMultiple,
|
|
37
|
+
TriccNodeSelectOne,
|
|
38
|
+
TriccNodeSelectOption,
|
|
39
|
+
TriccNodeSelectYesNo,
|
|
40
|
+
TriccNodeInputModel,
|
|
41
|
+
TriccNodeSelect,
|
|
42
|
+
TriccNodeSelectNotAvailable,
|
|
43
|
+
TriccNodeMoreInfo,
|
|
44
|
+
TriccNodeDisplayModel,
|
|
45
|
+
TriccNodeMainStart,
|
|
46
|
+
TriccNodeAcceptDiagnostic,
|
|
47
|
+
)
|
|
7
48
|
from tricc_oo.visitors.utils import PROCESSES
|
|
49
|
+
from tricc_oo.converters.cql_to_operation import transform_cql_to_operation
|
|
8
50
|
from tricc_oo.converters.datadictionnary import lookup_codesystems_code
|
|
51
|
+
from tricc_oo.converters.tricc_to_xls_form import get_list_names, get_export_name
|
|
9
52
|
|
|
10
53
|
logger = logging.getLogger("default")
|
|
11
54
|
ONE_QUESTION_AT_A_TIME = False
|
|
12
55
|
|
|
13
|
-
TRICC_TRUE_VALUE =
|
|
14
|
-
TRICC_FALSE_VALUE =
|
|
56
|
+
TRICC_TRUE_VALUE = "true"
|
|
57
|
+
TRICC_FALSE_VALUE = "false"
|
|
58
|
+
|
|
15
59
|
|
|
16
|
-
def merge_node(from_node,to_node):
|
|
60
|
+
def merge_node(from_node, to_node):
|
|
17
61
|
if from_node.activity != to_node.activity:
|
|
18
62
|
logger.critical("Cannot merge nodes from different activities")
|
|
19
|
-
elif issubclass(from_node.__class__, TriccNodeCalculateBase) and issubclass(
|
|
63
|
+
elif issubclass(from_node.__class__, TriccNodeCalculateBase) and issubclass(
|
|
64
|
+
to_node.__class__, TriccNodeCalculateBase
|
|
65
|
+
):
|
|
20
66
|
for e in to_node.activity.edges:
|
|
21
67
|
if e.target == from_node.id:
|
|
22
68
|
e.target = to_node.id
|
|
23
69
|
else:
|
|
24
70
|
logger.critical("Cannot merge not calculate nodes ")
|
|
25
|
-
|
|
71
|
+
|
|
26
72
|
|
|
27
73
|
def get_max_version(dict):
|
|
28
74
|
max_version = None
|
|
29
75
|
for id, sim_node in dict.items():
|
|
30
|
-
if max_version is None or
|
|
76
|
+
if max_version is None or max_version.version < sim_node.version:
|
|
31
77
|
max_version = sim_node
|
|
32
78
|
return max_version
|
|
33
79
|
|
|
80
|
+
|
|
34
81
|
def get_versions(name, iterable):
|
|
35
82
|
return [n for n in iterable if version_filter(name)(n)]
|
|
36
83
|
|
|
84
|
+
|
|
37
85
|
def version_filter(name):
|
|
38
|
-
return
|
|
86
|
+
return (
|
|
87
|
+
lambda item: hasattr(item, "name")
|
|
88
|
+
and ((isinstance(item, TriccNodeEnd) and name == item.get_reference()) or item.name == name)
|
|
89
|
+
and not isinstance(item, TriccNodeSelectOption)
|
|
90
|
+
)
|
|
91
|
+
|
|
39
92
|
|
|
40
|
-
def get_last_version(name, processed_nodes,
|
|
93
|
+
def get_last_version(name, processed_nodes, _list=None):
|
|
41
94
|
max_version = None
|
|
42
95
|
if isinstance(_list, dict):
|
|
43
96
|
_list = _list[name].values() if name in _list else []
|
|
44
97
|
if _list is None:
|
|
45
98
|
if isinstance(processed_nodes, OrderedSet):
|
|
46
99
|
return processed_nodes.find_last(version_filter(name))
|
|
47
|
-
else:
|
|
100
|
+
else:
|
|
48
101
|
_list = get_versions(name, processed_nodes)
|
|
49
102
|
if _list:
|
|
50
|
-
for
|
|
103
|
+
for sim_node in _list:
|
|
51
104
|
# get the max version while not taking a node that have a next node before next calc
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
or
|
|
105
|
+
if (
|
|
106
|
+
max_version is None
|
|
107
|
+
or max_version.activity.path_len < sim_node.activity.path_len
|
|
108
|
+
or max_version.path_len < sim_node.path_len
|
|
55
109
|
or (max_version.path_len == sim_node.path_len and hash(max_version.id) < hash(sim_node.id))
|
|
56
|
-
|
|
110
|
+
):
|
|
57
111
|
max_version = sim_node
|
|
58
112
|
if not max_version:
|
|
59
|
-
already_processed = list(filter(lambda p_node: hasattr(p_node,
|
|
113
|
+
already_processed = list(filter(lambda p_node: hasattr(p_node, "name") and p_node.name == name, _list))
|
|
60
114
|
if already_processed:
|
|
61
|
-
max_version = sorted(
|
|
62
|
-
|
|
115
|
+
max_version = sorted(already_processed, key=lambda x: x.path_len, reverse=False)[0]
|
|
116
|
+
|
|
63
117
|
return max_version
|
|
64
118
|
|
|
65
119
|
|
|
@@ -67,324 +121,321 @@ def get_last_version(name, processed_nodes, _list=None):
|
|
|
67
121
|
# node is the node to calculate
|
|
68
122
|
# processed_nodes are the list of processed nodes
|
|
69
123
|
def get_node_expressions(node, processed_nodes, process=None):
|
|
70
|
-
get_overall_exp = issubclass(node.__class__, TriccNodeCalculateBase) and not issubclass(
|
|
124
|
+
get_overall_exp = issubclass(node.__class__, TriccNodeCalculateBase) and not issubclass(
|
|
125
|
+
node.__class__, (TriccNodeDisplayBridge, TriccNodeBridge)
|
|
126
|
+
)
|
|
71
127
|
expression = None
|
|
72
128
|
# in case of recursive call processed_nodes will be None
|
|
73
129
|
if processed_nodes is None or is_ready_to_process(node, processed_nodes=processed_nodes):
|
|
74
|
-
expression = get_node_expression(
|
|
75
|
-
|
|
130
|
+
expression = get_node_expression(
|
|
131
|
+
node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
|
|
132
|
+
)
|
|
133
|
+
|
|
76
134
|
# if get_overall_exp:
|
|
77
|
-
# if expression and (not isinstance(expression, str) or expression != '')
|
|
135
|
+
# if expression and (not isinstance(expression, str) or expression != '')
|
|
136
|
+
# and expression is not TriccStatic(True) :
|
|
78
137
|
# num_expression = TriccOperation(
|
|
79
138
|
# TriccOperator.CAST_NUMBER,
|
|
80
139
|
# [expression]
|
|
81
140
|
# )
|
|
82
141
|
# elif expression is TriccStatic(True) or (not expression and get_overall_exp):
|
|
83
|
-
# expression = TriccStatic(True)
|
|
142
|
+
# expression = TriccStatic(True)
|
|
84
143
|
# else:
|
|
85
144
|
# expression = None
|
|
86
145
|
if (
|
|
87
|
-
issubclass(node.__class__, TriccNodeCalculateBase)
|
|
88
|
-
and not isinstance(expression, (TriccStatic, TriccReference, TriccOperation))
|
|
89
|
-
and str(expression) !=
|
|
146
|
+
issubclass(node.__class__, TriccNodeCalculateBase)
|
|
147
|
+
and not isinstance(expression, (TriccStatic, TriccReference, TriccOperation))
|
|
148
|
+
and str(expression) != ""
|
|
90
149
|
and not isinstance(node, (TriccNodeWait, TriccNodeActivityEnd, TriccNodeActivityStart, TriccNodeEnd))
|
|
91
150
|
):
|
|
92
151
|
logger.warning("Calculate {0} returning no calculations".format(node.get_name()))
|
|
93
152
|
expression = TriccStatic(True)
|
|
94
153
|
return expression
|
|
95
154
|
|
|
155
|
+
|
|
96
156
|
def set_last_version_false(node, processed_nodes):
|
|
97
|
-
if isinstance(node, (
|
|
157
|
+
if isinstance(node, (TriccNodeSelectOption)):
|
|
98
158
|
return
|
|
99
159
|
node_name = node.name if not isinstance(node, TriccNodeEnd) else node.get_reference()
|
|
100
|
-
#last_version = get_last_version(node_name, processed_nodes) if issubclass(node.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase, TriccNodeEnd)) and not isinstance(node, TriccNodeSelectOption) else None
|
|
101
160
|
last_version = processed_nodes.find_prev(node, version_filter(node_name))
|
|
102
|
-
if last_version and getattr(node,
|
|
103
|
-
# 0-100 for manually specified instance. 100-200 for auto instance
|
|
161
|
+
if last_version and getattr(node, "process", "") != "pause":
|
|
162
|
+
# 0-100 for manually specified instance. 100-200 for auto instance
|
|
104
163
|
node.version = get_next_version(node.name, processed_nodes, last_version.version, 0)
|
|
105
164
|
last_version.last = False
|
|
106
165
|
node.path_len = max(node.path_len, last_version.path_len + 1)
|
|
107
166
|
return last_version
|
|
108
|
-
|
|
167
|
+
|
|
168
|
+
|
|
109
169
|
def get_version_inheritance(node, last_version, processed_nodes):
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
'$this',
|
|
150
|
-
last_version
|
|
151
|
-
]
|
|
152
|
-
)
|
|
153
|
-
|
|
170
|
+
# FIXME this is for XLS form where only calculate are evaluated
|
|
171
|
+
# for a activity that is not triggered
|
|
172
|
+
if not issubclass(node.__class__, (TriccNodeInputModel)):
|
|
173
|
+
node.last = True
|
|
174
|
+
if issubclass(node.__class__, (TriccNodeDisplayCalculateBase, TriccNodeEnd)) and node.name is not None:
|
|
175
|
+
# logger.debug("set last to false for node {}
|
|
176
|
+
# and add its link it to next one".format(last_used_calc.get_name()))
|
|
177
|
+
if node.prev_nodes:
|
|
178
|
+
set_prev_next_node(last_version, node)
|
|
179
|
+
else:
|
|
180
|
+
expression = node.expression or node.expression_reference or getattr(node, "relevance", None)
|
|
181
|
+
expression = merge_expression(expression, last_version)
|
|
182
|
+
if node.expression:
|
|
183
|
+
node.expression = expression
|
|
184
|
+
elif node.expression_reference:
|
|
185
|
+
node.expression_reference = expression
|
|
186
|
+
elif node.relevance:
|
|
187
|
+
node.relevance = expression
|
|
188
|
+
else:
|
|
189
|
+
node.last = False
|
|
190
|
+
calc = TriccNodeCalculate(
|
|
191
|
+
id=generate_id(f"save{node.id}"),
|
|
192
|
+
name=node.name,
|
|
193
|
+
path_len=node.path_len + 1,
|
|
194
|
+
# version=get_next_version(node.name, processed_nodes, node.version+2),
|
|
195
|
+
expression=merge_expression(node, last_version),
|
|
196
|
+
label=f"merge{node.id}",
|
|
197
|
+
last=True,
|
|
198
|
+
activity=node.activity,
|
|
199
|
+
group=node.group,
|
|
200
|
+
)
|
|
201
|
+
node.activity.nodes[calc.id] = calc
|
|
202
|
+
node.activity.calculates.append(calc)
|
|
203
|
+
# set_last_version_false(calc, processed_nodes)
|
|
204
|
+
processed_nodes.add(calc)
|
|
205
|
+
if issubclass(node.__class__, TriccNodeInputModel):
|
|
206
|
+
node.expression = TriccOperation(TriccOperator.COALESCE, ["$this", last_version])
|
|
207
|
+
|
|
208
|
+
|
|
154
209
|
def merge_expression(expression, last_version):
|
|
155
210
|
datatype = expression.get_datatype()
|
|
156
|
-
if datatype ==
|
|
157
|
-
expression = or_join(
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
elif datatype == 'number':
|
|
162
|
-
expression = TriccOperation(
|
|
163
|
-
TriccOperator.PLUS,
|
|
164
|
-
[last_version, expression]
|
|
165
|
-
)
|
|
211
|
+
if datatype == "boolean":
|
|
212
|
+
expression = or_join([TriccOperation(TriccOperator.ISTRUE, [last_version]), expression])
|
|
213
|
+
|
|
214
|
+
elif datatype == "number":
|
|
215
|
+
expression = TriccOperation(TriccOperator.PLUS, [last_version, expression])
|
|
166
216
|
else:
|
|
167
|
-
expression = TriccOperation(
|
|
168
|
-
TriccOperator.COALESCE,
|
|
169
|
-
[last_version, expression]
|
|
170
|
-
)
|
|
217
|
+
expression = TriccOperation(TriccOperator.COALESCE, [last_version, expression])
|
|
171
218
|
return expression
|
|
172
219
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
220
|
+
|
|
221
|
+
def load_calculate(
|
|
222
|
+
node, processed_nodes, stashed_nodes, calculates, used_calculates, warn=False, process=None, **kwargs
|
|
223
|
+
):
|
|
224
|
+
# used_calculates dict[name, Dict[id, node]]
|
|
225
|
+
# processed_nodes Dict[id, node]
|
|
226
|
+
# calculates dict[name, Dict[id, node]]
|
|
227
|
+
|
|
180
228
|
if node not in processed_nodes:
|
|
181
229
|
# generate condition
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
warn = warn,
|
|
191
|
-
codesystems= kwargs.get('codesystems', None)
|
|
192
|
-
)
|
|
230
|
+
if is_ready_to_process(node, processed_nodes, True) and process_reference(
|
|
231
|
+
node,
|
|
232
|
+
processed_nodes=processed_nodes,
|
|
233
|
+
calculates=calculates,
|
|
234
|
+
used_calculates=used_calculates,
|
|
235
|
+
replace_reference=False,
|
|
236
|
+
warn=warn,
|
|
237
|
+
codesystems=kwargs.get("codesystems", None),
|
|
193
238
|
):
|
|
194
|
-
if kwargs.get(
|
|
195
|
-
logger.debug(
|
|
239
|
+
if kwargs.get("warn", True):
|
|
240
|
+
logger.debug("Processing relevance for node {0}".format(node.get_name()))
|
|
196
241
|
# tricc diagnostic have the same name as proposed diag but will be serialised with different names
|
|
197
242
|
|
|
198
|
-
last_version =
|
|
243
|
+
last_version = set_last_version_false(node, processed_nodes)
|
|
199
244
|
if last_version:
|
|
200
245
|
last_version = get_version_inheritance(node, last_version, processed_nodes)
|
|
201
246
|
|
|
202
|
-
generate_calculates(node,calculates, used_calculates,processed_nodes=processed_nodes, process=process)
|
|
203
|
-
|
|
204
|
-
|
|
247
|
+
generate_calculates(node, calculates, used_calculates, processed_nodes=processed_nodes, process=process)
|
|
205
248
|
|
|
206
|
-
|
|
207
|
-
if hasattr(node,
|
|
249
|
+
# if has prev, create condition
|
|
250
|
+
if hasattr(node, "relevance") and (node.relevance is None or isinstance(node.relevance, TriccOperation)):
|
|
208
251
|
node.relevance = get_node_expressions(node, processed_nodes=processed_nodes, process=process)
|
|
209
252
|
# manage not Available
|
|
210
253
|
if isinstance(node, TriccNodeSelectNotAvailable):
|
|
211
254
|
# update the checkbox
|
|
212
|
-
if node.parent:
|
|
255
|
+
if node.parent:
|
|
213
256
|
if len(node.prev_nodes) == 1:
|
|
214
257
|
prev = list(node.prev_nodes)[0]
|
|
215
258
|
if isinstance(prev, TriccNodeMoreInfo) and prev.parent.name == node.name:
|
|
216
259
|
prev.parent = node
|
|
217
|
-
|
|
218
|
-
|
|
260
|
+
|
|
219
261
|
# managing more info on NotAvaialbee
|
|
220
262
|
parent_empty = TriccOperation(TriccOperator.ISNULL, [node.parent])
|
|
221
|
-
node.relevance
|
|
263
|
+
node.relevance = and_join([node.parent.relevance, parent_empty])
|
|
222
264
|
node.required = parent_empty
|
|
223
265
|
node.constraint = parent_empty
|
|
224
266
|
node.constraint_message = "Cannot be selected with a value entered above"
|
|
225
267
|
# update the check box parent : create loop error
|
|
226
268
|
node.parent.required = None # "${{{0}}}=''".format(node.name)
|
|
227
269
|
else:
|
|
228
|
-
logger.warning("not available node {} does't have a single parent".format(node.get_name()))
|
|
270
|
+
logger.warning("not available node {} does't have a single parent".format(node.get_name()))
|
|
229
271
|
elif isinstance(node.relevance, TriccOperation):
|
|
230
272
|
relevance_reference = list(node.relevance.get_references())
|
|
231
273
|
for r in relevance_reference:
|
|
232
|
-
if issubclass(r.__class__, (TriccNodeDisplayCalculateBase
|
|
274
|
+
if issubclass(r.__class__, (TriccNodeDisplayCalculateBase)):
|
|
233
275
|
add_used_calculate(node, r, calculates, used_calculates, processed_nodes)
|
|
234
|
-
|
|
235
|
-
if last_version and hasattr(node,
|
|
276
|
+
|
|
277
|
+
if last_version and hasattr(node, "relevance"):
|
|
236
278
|
if isinstance(node, TriccNodeInputModel):
|
|
237
|
-
version_relevance =
|
|
238
|
-
TriccOperator.ISNULL,
|
|
239
|
-
[last_version]
|
|
240
|
-
)
|
|
279
|
+
version_relevance = TriccOperation(TriccOperator.ISNULL, [last_version])
|
|
241
280
|
elif last_version.relevance:
|
|
242
|
-
|
|
243
|
-
last_version.relevance
|
|
244
|
-
)
|
|
281
|
+
version_relevance = not_clean(last_version.relevance)
|
|
245
282
|
elif last_version.activity.relevance:
|
|
246
283
|
version_relevance = not_clean(
|
|
247
|
-
|
|
284
|
+
last_version.activity.relevance,
|
|
248
285
|
)
|
|
249
286
|
else:
|
|
250
287
|
version_relevance = None
|
|
251
|
-
|
|
288
|
+
|
|
252
289
|
if version_relevance:
|
|
253
|
-
if getattr(node,
|
|
254
|
-
node.relevance = and_join(
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
node.relevance
|
|
258
|
-
])
|
|
259
|
-
|
|
260
|
-
elif hasattr(node, 'relevance'):
|
|
290
|
+
if getattr(node, "relevance", None):
|
|
291
|
+
node.relevance = and_join([version_relevance, node.relevance])
|
|
292
|
+
|
|
293
|
+
elif hasattr(node, "relevance"):
|
|
261
294
|
node.relevance = version_relevance
|
|
262
295
|
|
|
263
|
-
#if hasattr(node, 'next_nodes'):
|
|
264
|
-
|
|
296
|
+
# if hasattr(node, 'next_nodes'):
|
|
297
|
+
# node.next_nodes=reorder_node_list(node.next_nodes, node.group)
|
|
265
298
|
process_reference(
|
|
266
|
-
node,
|
|
267
|
-
processed_nodes=processed_nodes,
|
|
299
|
+
node,
|
|
300
|
+
processed_nodes=processed_nodes,
|
|
268
301
|
calculates=calculates,
|
|
269
|
-
used_calculates=used_calculates,
|
|
270
|
-
replace_reference=True,
|
|
271
|
-
warn
|
|
272
|
-
codesystems=
|
|
302
|
+
used_calculates=used_calculates,
|
|
303
|
+
replace_reference=True,
|
|
304
|
+
warn=warn,
|
|
305
|
+
codesystems=kwargs.get("codesystems", None),
|
|
273
306
|
)
|
|
274
307
|
if isinstance(node, (TriccNodeMainStart, TriccNodeActivityStart)):
|
|
275
308
|
process_reference(
|
|
276
309
|
node.activity,
|
|
277
|
-
processed_nodes=processed_nodes,
|
|
310
|
+
processed_nodes=processed_nodes,
|
|
278
311
|
calculates=calculates,
|
|
279
|
-
used_calculates=used_calculates,
|
|
280
|
-
replace_reference=True,
|
|
281
|
-
warn
|
|
282
|
-
codesystems=
|
|
312
|
+
used_calculates=used_calculates,
|
|
313
|
+
replace_reference=True,
|
|
314
|
+
warn=warn,
|
|
315
|
+
codesystems=kwargs.get("codesystems", None),
|
|
283
316
|
)
|
|
284
317
|
|
|
285
318
|
return True
|
|
286
319
|
# not ready to process or already processed
|
|
287
320
|
|
|
288
321
|
return False
|
|
289
|
-
|
|
290
322
|
|
|
291
323
|
|
|
292
|
-
def get_max_named_version(calculates,name):
|
|
324
|
+
def get_max_named_version(calculates, name):
|
|
293
325
|
max = 0
|
|
294
|
-
if name
|
|
295
|
-
for
|
|
326
|
+
if name in calculates:
|
|
327
|
+
for node in calculates[name].values():
|
|
296
328
|
if node.version > max:
|
|
297
329
|
max = node.version
|
|
298
330
|
return max
|
|
299
331
|
|
|
332
|
+
|
|
300
333
|
def get_count_node(node):
|
|
301
334
|
count_id = generate_id(f"count{node.id}")
|
|
302
|
-
count_name = "cnt_"+count_id
|
|
335
|
+
count_name = "cnt_" + count_id
|
|
303
336
|
return TriccNodeCount(
|
|
304
|
-
id
|
|
305
|
-
group
|
|
306
|
-
activity
|
|
307
|
-
label
|
|
308
|
-
name
|
|
309
|
-
path_len=node.path_len
|
|
337
|
+
id=count_id,
|
|
338
|
+
group=node.group,
|
|
339
|
+
activity=node.activity,
|
|
340
|
+
label="count: " + node.get_name(),
|
|
341
|
+
name=count_name,
|
|
342
|
+
path_len=node.path_len,
|
|
310
343
|
)
|
|
311
|
-
|
|
312
|
-
### Function that inject a wait after path that will wait for the nodes
|
|
313
|
-
def get_activity_wait(prev_nodes, nodes_to_wait, next_nodes, replaced_node = None, edge_only = False, activity = None):
|
|
314
344
|
|
|
315
|
-
|
|
345
|
+
|
|
346
|
+
# Function that inject a wait after path that will wait for the nodes
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def get_activity_wait(prev_nodes, nodes_to_wait, next_nodes, replaced_node=None, edge_only=False, activity=None):
|
|
350
|
+
|
|
351
|
+
if issubclass(nodes_to_wait.__class__, TriccBaseModel):
|
|
316
352
|
nodes_to_wait = [nodes_to_wait]
|
|
317
|
-
if issubclass(prev_nodes.__class__,TriccBaseModel):
|
|
353
|
+
if issubclass(prev_nodes.__class__, TriccBaseModel):
|
|
318
354
|
prev_nodes = set([prev_nodes])
|
|
319
355
|
elif isinstance(prev_nodes, list):
|
|
320
356
|
prev_nodes = set(prev_nodes)
|
|
321
|
-
|
|
357
|
+
|
|
322
358
|
iterator = iter(prev_nodes)
|
|
323
359
|
prev_node = next(iterator)
|
|
324
360
|
path = prev_node if len(prev_nodes) == 1 else get_bridge_path(prev_nodes, activity)
|
|
325
|
-
|
|
361
|
+
|
|
326
362
|
activity = activity or prev_node.activity
|
|
327
363
|
calc_node = TriccNodeWait(
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
364
|
+
id=generate_id(f"ar{''.join([x.id for x in nodes_to_wait])}{activity.id}"),
|
|
365
|
+
reference=nodes_to_wait,
|
|
366
|
+
activity=activity,
|
|
367
|
+
group=activity,
|
|
368
|
+
path=path,
|
|
369
|
+
)
|
|
334
370
|
|
|
335
|
-
#start the wait and the next_nodes from the prev_nodes
|
|
336
|
-
#add the wait as dependency of the next_nodes
|
|
371
|
+
# start the wait and the next_nodes from the prev_nodes
|
|
372
|
+
# add the wait as dependency of the next_nodes
|
|
337
373
|
|
|
338
|
-
|
|
374
|
+
# add edge between rhombus and node
|
|
339
375
|
|
|
340
|
-
set_prev_next_node(path,calc_node, edge_only=edge_only, activity=activity
|
|
376
|
+
set_prev_next_node(path, calc_node, edge_only=edge_only, activity=activity)
|
|
341
377
|
for next_node in next_nodes:
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
set_prev_next_node(calc_node,next_node, edge_only=edge_only,activity=activity)
|
|
347
|
-
|
|
348
|
-
|
|
378
|
+
# if prev != replaced_node and next_node != replaced_node :
|
|
379
|
+
# set_prev_next_node(prev,next_node,replaced_node)
|
|
380
|
+
# if first:
|
|
381
|
+
# first = False
|
|
382
|
+
set_prev_next_node(calc_node, next_node, edge_only=edge_only, activity=activity)
|
|
383
|
+
|
|
349
384
|
return calc_node
|
|
350
|
-
|
|
351
|
-
|
|
385
|
+
|
|
386
|
+
|
|
387
|
+
def get_bridge_path(prev_nodes, node=None, edge_only=False):
|
|
352
388
|
iterator = iter(prev_nodes)
|
|
353
|
-
p_p_node = next(iterator)
|
|
389
|
+
p_p_node = next(iterator)
|
|
354
390
|
if node is None:
|
|
355
391
|
node = p_p_node
|
|
356
|
-
calc_id
|
|
357
|
-
calc_name = "path_"+calc_id
|
|
392
|
+
calc_id = generate_id(f"br{''.join([x.id for x in prev_nodes])}{node.id}")
|
|
393
|
+
calc_name = "path_" + calc_id
|
|
358
394
|
data = {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
395
|
+
"id": calc_id,
|
|
396
|
+
"group": node.group,
|
|
397
|
+
"activity": node.activity,
|
|
398
|
+
"label": "path: " + (node.get_name()),
|
|
399
|
+
"name": calc_name,
|
|
400
|
+
"path_len": node.path_len + 1 * (node == p_p_node),
|
|
365
401
|
}
|
|
366
|
-
|
|
367
|
-
if
|
|
368
|
-
|
|
402
|
+
|
|
403
|
+
if (
|
|
404
|
+
len(prev_nodes) > 1
|
|
405
|
+
and sum(
|
|
406
|
+
[0 if issubclass(n.__class__, (TriccNodeDisplayCalculateBase, TriccNodeRhombus)) else 1 for n in prev_nodes]
|
|
407
|
+
)
|
|
408
|
+
> 0
|
|
409
|
+
):
|
|
410
|
+
calc = TriccNodeDisplayBridge(**data)
|
|
369
411
|
else:
|
|
370
|
-
calc =
|
|
412
|
+
calc = TriccNodeBridge(**data)
|
|
371
413
|
return calc
|
|
372
|
-
|
|
414
|
+
|
|
415
|
+
|
|
373
416
|
def inject_bridge_path(node, nodes):
|
|
374
417
|
|
|
375
|
-
prev_nodes = [
|
|
418
|
+
prev_nodes = [
|
|
419
|
+
nodes[n.source]
|
|
420
|
+
for n in list(
|
|
421
|
+
filter(
|
|
422
|
+
lambda x: (x.target == node.id or x.target == node) and x.source in list(nodes.keys()),
|
|
423
|
+
node.activity.edges,
|
|
424
|
+
)
|
|
425
|
+
)
|
|
426
|
+
]
|
|
376
427
|
if prev_nodes:
|
|
377
|
-
calc = get_bridge_path(prev_nodes, node,edge_only=True)
|
|
428
|
+
calc = get_bridge_path(prev_nodes, node, edge_only=True)
|
|
378
429
|
|
|
379
430
|
for e in node.activity.edges:
|
|
380
431
|
if e.target == node.id:
|
|
381
432
|
# if e.source in node.activity.nodes and len(node.activity.nodes[e.source].next_nodes):
|
|
382
433
|
# set_prev_next_node(node.activity[e.source], node, edge_only=True, replaced_node=node)
|
|
383
434
|
# else:
|
|
384
|
-
|
|
385
|
-
|
|
435
|
+
e.target = calc.id
|
|
436
|
+
|
|
386
437
|
# add edge between bridge and node
|
|
387
|
-
set_prev_next_node(calc,node,edge_only=True, activity=node.activity)
|
|
438
|
+
set_prev_next_node(calc, node, edge_only=True, activity=node.activity)
|
|
388
439
|
node.path_len += 1
|
|
389
440
|
return calc
|
|
390
441
|
|
|
@@ -394,45 +445,50 @@ def inject_node_before(before, node, activity):
|
|
|
394
445
|
before.activity = activity
|
|
395
446
|
activity.nodes[before.id] = before
|
|
396
447
|
nodes = activity.nodes
|
|
397
|
-
prev_nodes = node.prev_nodes.union(
|
|
448
|
+
prev_nodes = node.prev_nodes.union(
|
|
449
|
+
set(
|
|
450
|
+
nodes[n.source]
|
|
451
|
+
for n in list(
|
|
452
|
+
filter(lambda x: (x.target == node.id or x.target == node) and x.source in nodes, node.activity.edges)
|
|
453
|
+
)
|
|
454
|
+
)
|
|
455
|
+
)
|
|
398
456
|
edge_processed = False
|
|
399
457
|
before.path_len = node.path_len
|
|
400
458
|
for e in node.activity.edges:
|
|
401
459
|
if e.target == node.id:
|
|
402
460
|
e.target = before.id
|
|
403
|
-
for p in prev_nodes:
|
|
404
|
-
prev_processed = len(node.next_nodes) > 0
|
|
461
|
+
for p in prev_nodes:
|
|
405
462
|
if node in p.next_nodes:
|
|
406
463
|
p.next_nodes.remove(node)
|
|
407
464
|
p.next_nodes.append(before)
|
|
408
465
|
|
|
409
466
|
# add edge between bridge and node
|
|
410
|
-
set_prev_next_node(before,node,edge_only=not edge_processed, activity=node.activity)
|
|
467
|
+
set_prev_next_node(before, node, edge_only=not edge_processed, activity=node.activity)
|
|
411
468
|
node.path_len += 1
|
|
412
469
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
def generate_calculates(node,calculates, used_calculates,processed_nodes, process):
|
|
470
|
+
|
|
471
|
+
def generate_calculates(node, calculates, used_calculates, processed_nodes, process):
|
|
416
472
|
list_calc = []
|
|
417
473
|
count_node = None
|
|
418
|
-
|
|
474
|
+
# add select calcualte
|
|
419
475
|
if issubclass(node.__class__, TriccNodeCalculateBase):
|
|
420
476
|
if isinstance(node, TriccNodeRhombus):
|
|
421
477
|
if (
|
|
422
478
|
(node.expression_reference is None or isinstance(node.expression_reference, TriccOperation))
|
|
423
479
|
and isinstance(node.reference, list)
|
|
424
|
-
and len(node.reference)==1
|
|
480
|
+
and len(node.reference) == 1
|
|
425
481
|
and issubclass(node.reference[0].__class__, TriccNodeSelect)
|
|
426
482
|
):
|
|
427
483
|
|
|
428
484
|
count_node = get_count_node(node)
|
|
429
485
|
list_calc.append(count_node)
|
|
430
|
-
set_prev_next_node(node.reference[0],count_node)
|
|
431
|
-
node.path_len+=1
|
|
432
|
-
|
|
486
|
+
set_prev_next_node(node.reference[0], count_node)
|
|
487
|
+
node.path_len += 1
|
|
488
|
+
|
|
433
489
|
if isinstance(node.expression_reference, TriccOperation):
|
|
434
490
|
node.expression_reference.replace_node(node.reference, count_node)
|
|
435
|
-
node.reference[0] =
|
|
491
|
+
node.reference[0] = count_node
|
|
436
492
|
# elif isinstance(node.reference, TriccOperation):
|
|
437
493
|
# references = node.reference.get_references()
|
|
438
494
|
# if len(references) == 1 and issubclass(node.reference[0].__class__, TriccNodeSelect):
|
|
@@ -445,68 +501,67 @@ def generate_calculates(node,calculates, used_calculates,processed_nodes, proces
|
|
|
445
501
|
processed_nodes.add(count_node)
|
|
446
502
|
add_calculate(calculates, count_node)
|
|
447
503
|
add_used_calculate(
|
|
448
|
-
node,
|
|
449
|
-
count_node,
|
|
450
|
-
calculates=calculates,
|
|
504
|
+
node,
|
|
505
|
+
count_node,
|
|
506
|
+
calculates=calculates,
|
|
451
507
|
used_calculates=used_calculates,
|
|
452
|
-
processed_nodes=processed_nodes
|
|
508
|
+
processed_nodes=processed_nodes,
|
|
453
509
|
)
|
|
454
|
-
|
|
455
|
-
|
|
510
|
+
|
|
456
511
|
# if a prev node is a calculate then it must be added in used_calc
|
|
457
512
|
for prev in node.prev_nodes:
|
|
458
513
|
add_used_calculate(
|
|
459
|
-
node,
|
|
460
|
-
prev,
|
|
461
|
-
calculates=calculates,
|
|
462
|
-
used_calculates=used_calculates,
|
|
463
|
-
processed_nodes=processed_nodes
|
|
514
|
+
node, prev, calculates=calculates, used_calculates=used_calculates, processed_nodes=processed_nodes
|
|
464
515
|
)
|
|
465
|
-
#if the node have a save
|
|
466
|
-
if hasattr(node,
|
|
516
|
+
# if the node have a save
|
|
517
|
+
if hasattr(node, "save") and node.save is not None and node.save != "":
|
|
467
518
|
# get fragments type.name.icdcode
|
|
468
|
-
calculate_name=node.save
|
|
519
|
+
calculate_name = node.save
|
|
469
520
|
if node.name != calculate_name:
|
|
470
521
|
calc_id = generate_id(f"autosave{node.id}")
|
|
471
522
|
if issubclass(node.__class__, TriccNodeSelect) or isinstance(node, TriccNodeSelectNotAvailable):
|
|
472
|
-
expression = get_count_terms_details(
|
|
523
|
+
expression = get_count_terms_details(node, processed_nodes, True, False, process)
|
|
473
524
|
else:
|
|
474
|
-
expression = get_node_expression(node,processed_nodes,True,True)
|
|
525
|
+
expression = get_node_expression(node, processed_nodes, True, True)
|
|
475
526
|
calc_node = TriccNodeCalculate(
|
|
476
527
|
name=calculate_name,
|
|
477
|
-
id
|
|
478
|
-
group
|
|
479
|
-
#version=get_next_version(calculate_name, processed_nodes, node.version+2),
|
|
480
|
-
activity
|
|
481
|
-
label
|
|
482
|
-
path_len=node.path_len+ 1,
|
|
528
|
+
id=calc_id,
|
|
529
|
+
group=node.group,
|
|
530
|
+
# version=get_next_version(calculate_name, processed_nodes, node.version+2),
|
|
531
|
+
activity=node.activity,
|
|
532
|
+
label="save: " + node.get_name(),
|
|
533
|
+
path_len=node.path_len + 1,
|
|
483
534
|
last=True,
|
|
484
|
-
expression=expression
|
|
535
|
+
expression=expression,
|
|
485
536
|
)
|
|
486
537
|
node.activity.calculates.append(calc_node)
|
|
487
538
|
last_version = set_last_version_false(calc_node, processed_nodes)
|
|
488
539
|
if last_version:
|
|
489
540
|
calc_node.expression = merge_expression(calc_node.expression, last_version)
|
|
490
541
|
processed_nodes.add(calc_node)
|
|
491
|
-
logger.debug(
|
|
492
|
-
|
|
542
|
+
logger.debug(
|
|
543
|
+
"generate_save_calculate:{}:{} as {}".format(
|
|
544
|
+
calc_node.tricc_type, node.name if hasattr(node, "name") else node.id, calculate_name
|
|
545
|
+
)
|
|
546
|
+
)
|
|
547
|
+
|
|
493
548
|
list_calc.append(calc_node)
|
|
494
|
-
#add_save_calculate(calc_node, calculates, used_calculates,processed_nodes)
|
|
549
|
+
# add_save_calculate(calc_node, calculates, used_calculates,processed_nodes)
|
|
495
550
|
for calc in list_calc:
|
|
496
551
|
node.activity.nodes[calc.id] = calc
|
|
497
552
|
add_calculate(calculates, calc)
|
|
498
553
|
return list_calc
|
|
499
554
|
|
|
500
555
|
|
|
501
|
-
|
|
502
556
|
def add_calculate(calculates, calc_node):
|
|
503
557
|
if issubclass(calc_node.__class__, TriccNodeDisplayCalculateBase):
|
|
504
558
|
if calc_node.name not in calculates:
|
|
505
|
-
calculates[calc_node.name]= {}
|
|
559
|
+
calculates[calc_node.name] = {}
|
|
506
560
|
calculates[calc_node.name][calc_node.id] = calc_node
|
|
507
561
|
|
|
562
|
+
|
|
508
563
|
def get_option_code_from_label(node, option_label):
|
|
509
|
-
if hasattr(node,
|
|
564
|
+
if hasattr(node, "options"):
|
|
510
565
|
for i in node.options:
|
|
511
566
|
if node.options[i].label.strip() == option_label.strip():
|
|
512
567
|
return node.options[i].name
|
|
@@ -515,43 +570,95 @@ def get_option_code_from_label(node, option_label):
|
|
|
515
570
|
logger.critical(f"node {node.get_name()} has no options")
|
|
516
571
|
|
|
517
572
|
|
|
518
|
-
|
|
519
|
-
|
|
573
|
+
# CQL is deined as a cql library and this code will
|
|
574
|
+
# parse the definition and will extract the logic under the define statement
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def extract_with_regex(data):
|
|
578
|
+
text = data
|
|
579
|
+
# Pattern to match define statement and capture the name and body
|
|
580
|
+
pattern = r'define\s+"([^"]+)":\s*(.*)'
|
|
581
|
+
match = re.search(pattern, text, re.DOTALL)
|
|
582
|
+
|
|
583
|
+
if match:
|
|
584
|
+
definition_name = match.group(1)
|
|
585
|
+
definition_body = match.group(2).strip()
|
|
586
|
+
return {"name": definition_name, "body": definition_body, "full": match.group(0)}
|
|
587
|
+
return None
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
def process_reference(
|
|
591
|
+
node, processed_nodes, calculates, used_calculates=None, replace_reference=False, warn=False, codesystems=None
|
|
592
|
+
):
|
|
593
|
+
# process a remote reference coded as a cql
|
|
594
|
+
if getattr(node, "remote_reference", None):
|
|
595
|
+
remote_reference_url = node.remote_reference
|
|
596
|
+
print(f"Fetching remote reference from {remote_reference_url}")
|
|
597
|
+
response = requests.get(remote_reference_url)
|
|
598
|
+
response_json = response.json()
|
|
599
|
+
cql_content = response_json["content"][0]["data"]
|
|
600
|
+
decode_cql_content = base64.b64decode(cql_content).decode("utf-8")
|
|
601
|
+
definition = extract_with_regex(decode_cql_content)
|
|
602
|
+
|
|
603
|
+
if definition:
|
|
604
|
+
cql_expression = definition["body"]
|
|
605
|
+
|
|
606
|
+
# We use `transform_cql_to_operation` to parse the raw CQL string.
|
|
607
|
+
operation = transform_cql_to_operation(cql_expression, context=f"remote reference for {node.get_name()}")
|
|
608
|
+
|
|
609
|
+
if not operation:
|
|
610
|
+
logger.error(f"Failed to parse remote CQL expression for node {node.get_name()}: {cql_expression}")
|
|
611
|
+
return False
|
|
612
|
+
|
|
613
|
+
# The parsed operation is assigned to `expression_reference`.
|
|
614
|
+
# The original code incorrectly assigned the raw string to `node.reference`
|
|
615
|
+
# and had an unreachable `if isinstance(cql_expression, list):` block.
|
|
616
|
+
node.expression_reference = operation
|
|
617
|
+
node.remote_reference = None
|
|
618
|
+
|
|
619
|
+
# By setting `expression_reference` and clearing `remote_reference`,
|
|
620
|
+
# we can now re-process this node. A recursive call to `process_reference`
|
|
621
|
+
# will now enter the `elif getattr(node, 'expression_reference', None):`
|
|
622
|
+
# block, which will correctly handle the newly parsed expression.
|
|
623
|
+
return process_reference(
|
|
624
|
+
node, processed_nodes, calculates, used_calculates, replace_reference, warn, codesystems
|
|
625
|
+
)
|
|
626
|
+
|
|
627
|
+
elif getattr(node, "expression_reference", None):
|
|
520
628
|
modified_expression = process_operation_reference(
|
|
521
|
-
node.expression_reference,
|
|
522
|
-
node,
|
|
629
|
+
node.expression_reference,
|
|
630
|
+
node,
|
|
523
631
|
processed_nodes=processed_nodes,
|
|
524
|
-
calculates=calculates,
|
|
525
|
-
used_calculates=used_calculates,
|
|
632
|
+
calculates=calculates,
|
|
633
|
+
used_calculates=used_calculates,
|
|
526
634
|
replace_reference=replace_reference,
|
|
527
|
-
warn=warn,
|
|
528
|
-
codesystems=codesystems
|
|
635
|
+
warn=warn,
|
|
636
|
+
codesystems=codesystems,
|
|
529
637
|
)
|
|
530
638
|
if modified_expression is False:
|
|
531
639
|
return False
|
|
532
640
|
elif modified_expression and replace_reference:
|
|
533
641
|
node.reference = list(modified_expression.get_references())
|
|
534
642
|
node.expression_reference = modified_expression
|
|
535
|
-
|
|
643
|
+
|
|
644
|
+
elif getattr(node, "reference", None):
|
|
536
645
|
reference = node.reference
|
|
537
646
|
if isinstance(reference, list):
|
|
538
647
|
if isinstance(node, TriccNodeWait):
|
|
539
|
-
reference = [TriccOperation(TriccOperator.ISTRUE,[n]) for n in reference]
|
|
540
|
-
if len(node.reference) == 1
|
|
648
|
+
reference = [TriccOperation(TriccOperator.ISTRUE, [n]) for n in reference]
|
|
649
|
+
if len(node.reference) == 1:
|
|
541
650
|
operation = reference[0]
|
|
542
651
|
else:
|
|
543
|
-
operation = and_join(
|
|
544
|
-
reference
|
|
545
|
-
)
|
|
652
|
+
operation = and_join(reference)
|
|
546
653
|
modified_expression = process_operation_reference(
|
|
547
|
-
operation,
|
|
654
|
+
operation,
|
|
548
655
|
node,
|
|
549
656
|
processed_nodes=processed_nodes,
|
|
550
|
-
calculates=calculates,
|
|
551
|
-
used_calculates=used_calculates,
|
|
657
|
+
calculates=calculates,
|
|
658
|
+
used_calculates=used_calculates,
|
|
552
659
|
replace_reference=replace_reference,
|
|
553
|
-
warn=warn,
|
|
554
|
-
codesystems=codesystems
|
|
660
|
+
warn=warn,
|
|
661
|
+
codesystems=codesystems,
|
|
555
662
|
)
|
|
556
663
|
if modified_expression is False:
|
|
557
664
|
return False
|
|
@@ -561,14 +668,14 @@ def process_reference(node, processed_nodes, calculates, used_calculates=None,
|
|
|
561
668
|
node.expression_reference = modified_expression
|
|
562
669
|
elif isinstance(node.reference, (TriccOperation, TriccReference)):
|
|
563
670
|
modified_expression = process_operation_reference(
|
|
564
|
-
node.reference,
|
|
565
|
-
node,
|
|
671
|
+
node.reference,
|
|
672
|
+
node,
|
|
566
673
|
processed_nodes=processed_nodes,
|
|
567
|
-
calculates=calculates,
|
|
568
|
-
used_calculates=used_calculates,
|
|
674
|
+
calculates=calculates,
|
|
675
|
+
used_calculates=used_calculates,
|
|
569
676
|
replace_reference=replace_reference,
|
|
570
|
-
warn=warn,
|
|
571
|
-
codesystems=codesystems
|
|
677
|
+
warn=warn,
|
|
678
|
+
codesystems=codesystems,
|
|
572
679
|
)
|
|
573
680
|
if modified_expression is False:
|
|
574
681
|
return False
|
|
@@ -576,95 +683,95 @@ def process_reference(node, processed_nodes, calculates, used_calculates=None,
|
|
|
576
683
|
node.reference = list(modified_expression.get_references())
|
|
577
684
|
node.expression_reference = modified_expression
|
|
578
685
|
|
|
579
|
-
if isinstance(getattr(node,
|
|
686
|
+
if isinstance(getattr(node, "relevance", None), (TriccOperation, TriccReference)):
|
|
580
687
|
modified_expression = process_operation_reference(
|
|
581
|
-
node.relevance,
|
|
582
|
-
node,
|
|
688
|
+
node.relevance,
|
|
689
|
+
node,
|
|
583
690
|
processed_nodes=processed_nodes,
|
|
584
|
-
calculates=calculates,
|
|
585
|
-
used_calculates=used_calculates,
|
|
691
|
+
calculates=calculates,
|
|
692
|
+
used_calculates=used_calculates,
|
|
586
693
|
replace_reference=replace_reference,
|
|
587
|
-
warn=warn,
|
|
588
|
-
codesystems=codesystems
|
|
694
|
+
warn=warn,
|
|
695
|
+
codesystems=codesystems,
|
|
589
696
|
)
|
|
590
697
|
if modified_expression is False:
|
|
591
698
|
return False
|
|
592
699
|
elif modified_expression and replace_reference:
|
|
593
700
|
node.relevance = modified_expression
|
|
594
|
-
|
|
595
|
-
if isinstance(getattr(node,
|
|
701
|
+
|
|
702
|
+
if isinstance(getattr(node, "trigger", None), (TriccOperation, TriccReference)):
|
|
596
703
|
modified_expression = process_operation_reference(
|
|
597
|
-
node.trigger,
|
|
598
|
-
node,
|
|
704
|
+
node.trigger,
|
|
705
|
+
node,
|
|
599
706
|
processed_nodes=processed_nodes,
|
|
600
|
-
calculates=calculates,
|
|
601
|
-
used_calculates=used_calculates,
|
|
707
|
+
calculates=calculates,
|
|
708
|
+
used_calculates=used_calculates,
|
|
602
709
|
replace_reference=replace_reference,
|
|
603
|
-
warn=warn,
|
|
604
|
-
codesystems=codesystems
|
|
710
|
+
warn=warn,
|
|
711
|
+
codesystems=codesystems,
|
|
605
712
|
)
|
|
606
713
|
if modified_expression is False:
|
|
607
714
|
return False
|
|
608
715
|
elif modified_expression and replace_reference:
|
|
609
716
|
node.trigger = modified_expression
|
|
610
|
-
if isinstance(getattr(node,
|
|
717
|
+
if isinstance(getattr(node, "constraint", None), (TriccOperation, TriccReference)):
|
|
611
718
|
modified_expression = process_operation_reference(
|
|
612
|
-
node.constraint,
|
|
613
|
-
node,
|
|
719
|
+
node.constraint,
|
|
720
|
+
node,
|
|
614
721
|
processed_nodes=processed_nodes,
|
|
615
|
-
calculates=calculates,
|
|
616
|
-
used_calculates=used_calculates,
|
|
722
|
+
calculates=calculates,
|
|
723
|
+
used_calculates=used_calculates,
|
|
617
724
|
replace_reference=replace_reference,
|
|
618
|
-
warn=warn,
|
|
619
|
-
codesystems=codesystems
|
|
725
|
+
warn=warn,
|
|
726
|
+
codesystems=codesystems,
|
|
620
727
|
)
|
|
621
728
|
if modified_expression is False:
|
|
622
729
|
return False
|
|
623
730
|
elif modified_expression and replace_reference:
|
|
624
731
|
node.constraint = modified_expression
|
|
625
|
-
|
|
626
|
-
if isinstance(getattr(node,
|
|
732
|
+
|
|
733
|
+
if isinstance(getattr(node, "default", None), (TriccOperation, TriccReference)):
|
|
627
734
|
modified_expression = process_operation_reference(
|
|
628
|
-
node.default,
|
|
629
|
-
node,
|
|
735
|
+
node.default,
|
|
736
|
+
node,
|
|
630
737
|
processed_nodes=processed_nodes,
|
|
631
|
-
calculates=calculates,
|
|
632
|
-
used_calculates=used_calculates,
|
|
738
|
+
calculates=calculates,
|
|
739
|
+
used_calculates=used_calculates,
|
|
633
740
|
replace_reference=replace_reference,
|
|
634
|
-
warn=warn,
|
|
635
|
-
codesystems=codesystems
|
|
636
|
-
)
|
|
741
|
+
warn=warn,
|
|
742
|
+
codesystems=codesystems,
|
|
743
|
+
)
|
|
637
744
|
if modified_expression is False:
|
|
638
745
|
return False
|
|
639
746
|
elif modified_expression and replace_reference:
|
|
640
747
|
node.relevance = modified_expression
|
|
641
|
-
|
|
642
|
-
if isinstance(getattr(node,
|
|
748
|
+
|
|
749
|
+
if isinstance(getattr(node, "expression", None), (TriccOperation, TriccReference)):
|
|
643
750
|
modified_expression = process_operation_reference(
|
|
644
|
-
node.expression,
|
|
645
|
-
node,
|
|
751
|
+
node.expression,
|
|
752
|
+
node,
|
|
646
753
|
processed_nodes=processed_nodes,
|
|
647
|
-
calculates=calculates,
|
|
648
|
-
used_calculates=used_calculates,
|
|
754
|
+
calculates=calculates,
|
|
755
|
+
used_calculates=used_calculates,
|
|
649
756
|
replace_reference=replace_reference,
|
|
650
|
-
warn=warn,
|
|
651
|
-
codesystems=codesystems
|
|
757
|
+
warn=warn,
|
|
758
|
+
codesystems=codesystems,
|
|
652
759
|
)
|
|
653
760
|
if modified_expression is False:
|
|
654
761
|
return False
|
|
655
762
|
elif modified_expression and replace_reference:
|
|
656
763
|
node.expression = modified_expression
|
|
657
|
-
|
|
658
|
-
if isinstance(getattr(node,
|
|
764
|
+
|
|
765
|
+
if isinstance(getattr(node, "applicability", None), (TriccOperation, TriccReference)):
|
|
659
766
|
modified_expression = process_operation_reference(
|
|
660
|
-
node.applicability,
|
|
661
|
-
node,
|
|
767
|
+
node.applicability,
|
|
768
|
+
node,
|
|
662
769
|
processed_nodes=processed_nodes,
|
|
663
|
-
calculates=calculates,
|
|
664
|
-
used_calculates=used_calculates,
|
|
770
|
+
calculates=calculates,
|
|
771
|
+
used_calculates=used_calculates,
|
|
665
772
|
replace_reference=replace_reference,
|
|
666
|
-
warn=warn,
|
|
667
|
-
codesystems=codesystems
|
|
773
|
+
warn=warn,
|
|
774
|
+
codesystems=codesystems,
|
|
668
775
|
)
|
|
669
776
|
if modified_expression is False:
|
|
670
777
|
return False
|
|
@@ -672,7 +779,17 @@ def process_reference(node, processed_nodes, calculates, used_calculates=None,
|
|
|
672
779
|
node.applicability = modified_expression
|
|
673
780
|
return True
|
|
674
781
|
|
|
675
|
-
|
|
782
|
+
|
|
783
|
+
def process_operation_reference(
|
|
784
|
+
operation,
|
|
785
|
+
node,
|
|
786
|
+
processed_nodes,
|
|
787
|
+
calculates,
|
|
788
|
+
used_calculates=None,
|
|
789
|
+
replace_reference=False,
|
|
790
|
+
warn=False,
|
|
791
|
+
codesystems=None,
|
|
792
|
+
):
|
|
676
793
|
modified_operation = None
|
|
677
794
|
node_reference = []
|
|
678
795
|
reference = []
|
|
@@ -680,13 +797,13 @@ def process_operation_reference(operation, node, processed_nodes, calculates, us
|
|
|
680
797
|
ref_list = [r.value for r in operation.get_references() if isinstance(r, TriccReference)]
|
|
681
798
|
real_ref_list = [r for r in operation.get_references() if issubclass(r.__class__, TriccNodeBaseModel)]
|
|
682
799
|
for ref in ref_list:
|
|
683
|
-
if ref.endswith(
|
|
684
|
-
terms = ref[:-1].split(
|
|
800
|
+
if ref.endswith("]"):
|
|
801
|
+
terms = ref[:-1].split("[")
|
|
685
802
|
option_label = terms[1]
|
|
686
803
|
ref = terms[0]
|
|
687
804
|
else:
|
|
688
805
|
option_label = None
|
|
689
|
-
node_in_act = [n for n in node.activity.nodes.values() if n.name == ref and n != node]
|
|
806
|
+
node_in_act = [n for n in node.activity.nodes.values() if n.name == ref and n != node]
|
|
690
807
|
if node_in_act:
|
|
691
808
|
if any(n not in processed_nodes for n in node_in_act):
|
|
692
809
|
return False
|
|
@@ -694,16 +811,16 @@ def process_operation_reference(operation, node, processed_nodes, calculates, us
|
|
|
694
811
|
last_found = node_in_act[0]
|
|
695
812
|
else:
|
|
696
813
|
last_found = get_last_version(name=ref, processed_nodes=processed_nodes)
|
|
697
|
-
if last_found is None:
|
|
814
|
+
if last_found is None:
|
|
698
815
|
if codesystems:
|
|
699
|
-
concept =
|
|
816
|
+
concept = lookup_codesystems_code(codesystems, ref)
|
|
700
817
|
if not concept:
|
|
701
818
|
logger.critical(f"reference {ref} not found in the project for{str(node)} ")
|
|
702
819
|
exit(1)
|
|
703
820
|
else:
|
|
704
821
|
if warn:
|
|
705
822
|
logger.debug(f"reference {ref}::{concept.display} not yet processed {node.get_name()}")
|
|
706
|
-
|
|
823
|
+
|
|
707
824
|
elif warn:
|
|
708
825
|
logger.debug(f"reference {ref} not found for a calculate {node.get_name()}")
|
|
709
826
|
return False
|
|
@@ -711,7 +828,9 @@ def process_operation_reference(operation, node, processed_nodes, calculates, us
|
|
|
711
828
|
node_reference.append(last_found)
|
|
712
829
|
reference.append(TriccReference(ref))
|
|
713
830
|
if replace_reference:
|
|
714
|
-
if not issubclass(
|
|
831
|
+
if not issubclass(
|
|
832
|
+
last_found.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase, TriccNodeInput)
|
|
833
|
+
):
|
|
715
834
|
last_found = get_node_expression(last_found, processed_nodes, is_prev=True)
|
|
716
835
|
if isinstance(operation, (TriccOperation)):
|
|
717
836
|
if modified_operation is None:
|
|
@@ -723,118 +842,141 @@ def process_operation_reference(operation, node, processed_nodes, calculates, us
|
|
|
723
842
|
# Resolve human-readable label
|
|
724
843
|
option_code = get_option_code_from_label(last_found, option_label)
|
|
725
844
|
if option_code:
|
|
726
|
-
modified_operation = replace_code_reference(
|
|
845
|
+
modified_operation = replace_code_reference(
|
|
846
|
+
operation, old=f"{ref}[{option_label}]", new=option_code
|
|
847
|
+
)
|
|
727
848
|
else:
|
|
728
849
|
if warn:
|
|
729
850
|
logger.warning(f"Could not resolve label '{option_label}' for reference {ref}")
|
|
730
851
|
return False
|
|
731
|
-
if hasattr(last_found,
|
|
732
|
-
path_len = last_found.path_len
|
|
852
|
+
if hasattr(last_found, "path_len"):
|
|
853
|
+
path_len = last_found.path_len
|
|
733
854
|
elif isinstance(last_found, TriccOperation):
|
|
734
|
-
path_len =
|
|
855
|
+
path_len = max(getattr(n, "path_len", 0) for n in last_found.get_references())
|
|
735
856
|
else:
|
|
736
857
|
path_len = 0
|
|
737
858
|
node.path_len = max(node.path_len, path_len)
|
|
738
859
|
for ref in real_ref_list:
|
|
739
860
|
if is_prev_processed(ref, node, processed_nodes=processed_nodes, local=False) is False:
|
|
740
861
|
return False
|
|
741
|
-
|
|
862
|
+
|
|
742
863
|
if used_calculates is not None:
|
|
743
864
|
for ref_nodes in node_reference:
|
|
744
865
|
if issubclass(ref_nodes.__class__, TriccNodeCalculateBase):
|
|
745
866
|
add_used_calculate(node, ref_nodes, calculates, used_calculates, processed_nodes=processed_nodes)
|
|
746
867
|
return modified_operation
|
|
747
868
|
|
|
869
|
+
|
|
748
870
|
def replace_code_reference(expression, old, new):
|
|
749
871
|
if isinstance(expression, str):
|
|
750
|
-
return
|
|
872
|
+
return expression.replace(old, f"'{new}'")
|
|
751
873
|
if isinstance(expression, TriccOperation):
|
|
752
874
|
expression.replace_node(TriccReference(old), TriccStatic(new))
|
|
753
875
|
return expression
|
|
754
|
-
|
|
876
|
+
|
|
877
|
+
|
|
878
|
+
# add_used_calculate(node, calc_node, calculates, used_calculates, processed_nodes)
|
|
879
|
+
|
|
755
880
|
|
|
756
881
|
def add_used_calculate(node, prev_node, calculates, used_calculates, processed_nodes):
|
|
757
882
|
if issubclass(prev_node.__class__, TriccNodeDisplayCalculateBase):
|
|
758
883
|
if prev_node in processed_nodes:
|
|
759
884
|
# if not a verison, index will equal -1
|
|
760
|
-
if prev_node.name not in calculates
|
|
885
|
+
if prev_node.name not in calculates:
|
|
761
886
|
logger.debug("node {} refered before being processed".format(node.get_name()))
|
|
762
887
|
return False
|
|
763
|
-
max_version = prev_node#get_max_version(calculates[node_clean_name])
|
|
888
|
+
max_version = prev_node # get_max_version(calculates[node_clean_name])
|
|
764
889
|
if prev_node.name not in used_calculates:
|
|
765
890
|
used_calculates[prev_node.name] = {}
|
|
766
|
-
#save the max version only once
|
|
891
|
+
# save the max version only once
|
|
767
892
|
if max_version.id not in used_calculates[prev_node.name]:
|
|
768
893
|
used_calculates[prev_node.name][max_version.id] = max_version
|
|
769
894
|
else:
|
|
770
|
-
logger.debug(
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
895
|
+
logger.debug(
|
|
896
|
+
"load_calculate_version_requirement: failed for {0} , prev Node {1} ".format(
|
|
897
|
+
node.get_name(), prev_node.get_name()
|
|
898
|
+
)
|
|
899
|
+
)
|
|
900
|
+
|
|
901
|
+
|
|
902
|
+
def get_select_not_available_options(node, group, label):
|
|
903
|
+
return {
|
|
904
|
+
0: TriccNodeSelectOption(
|
|
905
|
+
id=generate_id(f"notavaialble{node.id}"),
|
|
906
|
+
name="1",
|
|
907
|
+
label=label,
|
|
908
|
+
select=node,
|
|
909
|
+
group=group,
|
|
910
|
+
list_name=node.list_name,
|
|
911
|
+
)
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
|
|
783
915
|
def get_select_yes_no_options(node, group):
|
|
784
916
|
yes = TriccNodeSelectOption(
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
917
|
+
id=generate_id(f"yes{node.id}"),
|
|
918
|
+
name=f"{TRICC_TRUE_VALUE}",
|
|
919
|
+
label="Yes",
|
|
920
|
+
select=node,
|
|
921
|
+
group=group,
|
|
922
|
+
list_name=node.list_name,
|
|
923
|
+
)
|
|
792
924
|
no = TriccNodeSelectOption(
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
return {0:yes, 1:no
|
|
925
|
+
id=generate_id(f"no{node.id}"),
|
|
926
|
+
name=f"{TRICC_FALSE_VALUE}",
|
|
927
|
+
label="No",
|
|
928
|
+
select=node,
|
|
929
|
+
group=group,
|
|
930
|
+
list_name=node.list_name,
|
|
931
|
+
)
|
|
932
|
+
return {0: yes, 1: no}
|
|
933
|
+
|
|
801
934
|
|
|
802
|
-
# walkthough all node in an iterative way, the same node might be parsed 2 times
|
|
935
|
+
# walkthough all node in an iterative way, the same node might be parsed 2 times
|
|
803
936
|
# therefore to avoid double processing the nodes variable saves the node already processed
|
|
804
937
|
# there 2 strategies : process it the first time or the last time (wait that all the previuous node are processed)
|
|
805
938
|
|
|
806
|
-
|
|
807
|
-
|
|
939
|
+
|
|
940
|
+
def walktrhough_tricc_node_processed_stached(
|
|
941
|
+
node,
|
|
942
|
+
callback,
|
|
943
|
+
processed_nodes,
|
|
944
|
+
stashed_nodes,
|
|
945
|
+
path_len,
|
|
946
|
+
recursive=False,
|
|
947
|
+
warn=False,
|
|
948
|
+
node_path=[],
|
|
949
|
+
process=None,
|
|
950
|
+
**kwargs,
|
|
951
|
+
):
|
|
808
952
|
ended_activity = False
|
|
809
953
|
# logger.debug("walkthrough::{}::{}".format(callback.__name__, node.get_name()))
|
|
810
|
-
|
|
811
|
-
path_len = max(node.activity.path_len, *[0
|
|
812
|
-
if hasattr(node,
|
|
813
|
-
path_len = max(path_len, *[0
|
|
814
|
-
if hasattr(node,
|
|
954
|
+
|
|
955
|
+
path_len = max(node.activity.path_len, *[0, *[getattr(n, "path_len", 0) + 1 for n in node.activity.prev_nodes]]) + 1
|
|
956
|
+
if hasattr(node, "prev_nodes"):
|
|
957
|
+
path_len = max(path_len, *[0, *[getattr(n, "path_len", 0) + 1 for n in node.prev_nodes]])
|
|
958
|
+
if hasattr(node, "get_references"):
|
|
815
959
|
references = node.get_references()
|
|
816
960
|
if references:
|
|
817
|
-
path_len = max(path_len, *[0
|
|
961
|
+
path_len = max(path_len, *[0, *[getattr(n, "path_len", 0) + 1 for n in references]])
|
|
818
962
|
node.path_len = max(node.path_len, path_len)
|
|
819
963
|
prev_process = process[0] if process else None
|
|
820
|
-
if isinstance(node, TriccNodeActivity) and getattr(node.root,
|
|
964
|
+
if isinstance(node, TriccNodeActivity) and getattr(node.root, "process", None):
|
|
821
965
|
if process is None:
|
|
822
966
|
process = [node.root.process]
|
|
823
967
|
else:
|
|
824
968
|
process[0] = node.root.process
|
|
825
|
-
if (
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
**kwargs
|
|
834
|
-
)
|
|
969
|
+
if callback(
|
|
970
|
+
node,
|
|
971
|
+
processed_nodes=processed_nodes,
|
|
972
|
+
stashed_nodes=stashed_nodes,
|
|
973
|
+
warn=warn,
|
|
974
|
+
node_path=node_path,
|
|
975
|
+
process=process,
|
|
976
|
+
**kwargs,
|
|
835
977
|
):
|
|
836
978
|
node_path.append(node)
|
|
837
|
-
# node processing succeed
|
|
979
|
+
# node processing succeed
|
|
838
980
|
if not isinstance(node, TriccNodeActivity) and node not in processed_nodes:
|
|
839
981
|
processed_nodes.add(node)
|
|
840
982
|
if warn:
|
|
@@ -845,7 +987,11 @@ def walktrhough_tricc_node_processed_stached(node, callback, processed_nodes, st
|
|
|
845
987
|
processed_nodes.add(node.activity)
|
|
846
988
|
ended_activity = True
|
|
847
989
|
if warn:
|
|
848
|
-
logger.debug(
|
|
990
|
+
logger.debug(
|
|
991
|
+
"{}::{}: processed ({})".format(
|
|
992
|
+
callback.__name__, node.activity.get_name(), len(processed_nodes)
|
|
993
|
+
)
|
|
994
|
+
)
|
|
849
995
|
elif node in stashed_nodes:
|
|
850
996
|
stashed_nodes.remove(node)
|
|
851
997
|
# logger.debug("{}::{}: unstashed ({})".format(callback.__name__, node.get_name(), len(stashed_nodes)))
|
|
@@ -856,90 +1002,118 @@ def walktrhough_tricc_node_processed_stached(node, callback, processed_nodes, st
|
|
|
856
1002
|
if recursive:
|
|
857
1003
|
for gp in node.activity.groups.values():
|
|
858
1004
|
walktrhough_tricc_node_processed_stached(
|
|
859
|
-
gp,
|
|
1005
|
+
gp,
|
|
860
1006
|
callback,
|
|
861
|
-
processed_nodes=processed_nodes,
|
|
862
|
-
stashed_nodes=stashed_nodes,
|
|
1007
|
+
processed_nodes=processed_nodes,
|
|
1008
|
+
stashed_nodes=stashed_nodes,
|
|
863
1009
|
path_len=path_len,
|
|
864
1010
|
recursive=recursive,
|
|
865
|
-
warn
|
|
866
|
-
node_path
|
|
867
|
-
**kwargs
|
|
1011
|
+
warn=warn,
|
|
1012
|
+
node_path=node_path.copy(),
|
|
1013
|
+
**kwargs,
|
|
868
1014
|
)
|
|
869
1015
|
for c in node.activity.calculates:
|
|
870
|
-
if len(c.prev_nodes)== 0:
|
|
1016
|
+
if len(c.prev_nodes) == 0:
|
|
871
1017
|
walktrhough_tricc_node_processed_stached(
|
|
872
1018
|
c,
|
|
873
1019
|
callback,
|
|
874
|
-
processed_nodes=processed_nodes,
|
|
875
|
-
stashed_nodes=stashed_nodes,
|
|
1020
|
+
processed_nodes=processed_nodes,
|
|
1021
|
+
stashed_nodes=stashed_nodes,
|
|
876
1022
|
path_len=path_len,
|
|
877
1023
|
recursive=recursive,
|
|
878
|
-
warn
|
|
879
|
-
node_path
|
|
880
|
-
**kwargs
|
|
881
|
-
)
|
|
1024
|
+
warn=warn,
|
|
1025
|
+
node_path=node_path.copy(),
|
|
1026
|
+
**kwargs,
|
|
1027
|
+
)
|
|
882
1028
|
else:
|
|
883
|
-
stashed_nodes += [c for c in node.activity.calculates if len(c.prev_nodes)== 0]
|
|
1029
|
+
stashed_nodes += [c for c in node.activity.calculates if len(c.prev_nodes) == 0]
|
|
884
1030
|
stashed_nodes += node.activity.groups.values()
|
|
885
1031
|
elif issubclass(node.__class__, TriccNodeSelect):
|
|
886
1032
|
for option in node.options.values():
|
|
887
|
-
option.path_len = max(path_len,
|
|
888
|
-
callback(
|
|
1033
|
+
option.path_len = max(path_len, option.path_len)
|
|
1034
|
+
callback(
|
|
1035
|
+
option,
|
|
1036
|
+
processed_nodes=processed_nodes,
|
|
1037
|
+
stashed_nodes=stashed_nodes,
|
|
1038
|
+
warn=warn,
|
|
1039
|
+
node_path=node_path,
|
|
1040
|
+
**kwargs,
|
|
1041
|
+
)
|
|
889
1042
|
if option not in processed_nodes:
|
|
890
1043
|
processed_nodes.add(option)
|
|
891
1044
|
if warn:
|
|
892
1045
|
logger.debug(
|
|
893
|
-
"{}::{}: processed ({})".format(callback.__name__, option.get_name(), len(processed_nodes))
|
|
894
|
-
|
|
895
|
-
|
|
1046
|
+
"{}::{}: processed ({})".format(callback.__name__, option.get_name(), len(processed_nodes))
|
|
1047
|
+
)
|
|
1048
|
+
walkthrough_tricc_option(
|
|
1049
|
+
node,
|
|
1050
|
+
callback,
|
|
1051
|
+
processed_nodes,
|
|
1052
|
+
stashed_nodes,
|
|
1053
|
+
path_len + 1,
|
|
1054
|
+
recursive,
|
|
1055
|
+
warn=warn,
|
|
1056
|
+
node_path=node_path,
|
|
1057
|
+
**kwargs,
|
|
1058
|
+
)
|
|
896
1059
|
if isinstance(node, TriccNodeActivity):
|
|
897
1060
|
if node.root not in processed_nodes:
|
|
898
1061
|
if node.root is not None:
|
|
899
|
-
node.root.path_len = max(path_len,
|
|
1062
|
+
node.root.path_len = max(path_len, node.root.path_len)
|
|
900
1063
|
if recursive:
|
|
901
|
-
walktrhough_tricc_node_processed_stached(
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1064
|
+
walktrhough_tricc_node_processed_stached(
|
|
1065
|
+
node.root,
|
|
1066
|
+
callback,
|
|
1067
|
+
processed_nodes,
|
|
1068
|
+
stashed_nodes,
|
|
1069
|
+
path_len,
|
|
1070
|
+
recursive,
|
|
1071
|
+
warn=warn,
|
|
1072
|
+
node_path=node_path.copy(),
|
|
1073
|
+
**kwargs,
|
|
1074
|
+
)
|
|
910
1075
|
elif node.root not in stashed_nodes:
|
|
911
|
-
#stashed_nodes.insert(0,node.root)
|
|
912
1076
|
stashed_nodes.insert_at_top(node.root)
|
|
913
|
-
# if node.calculates:
|
|
914
|
-
# stashed_nodes += node.calculates
|
|
915
|
-
# for gp in node.groups:
|
|
916
|
-
# stashed_nodes.add(gp)
|
|
917
|
-
# # stashed_nodes.insert(0,gp)
|
|
918
1077
|
return
|
|
919
1078
|
elif ended_activity:
|
|
920
1079
|
for next_node in node.next_nodes:
|
|
921
1080
|
if next_node not in stashed_nodes:
|
|
922
|
-
#stashed_nodes.insert(0,next_node)
|
|
1081
|
+
# stashed_nodes.insert(0,next_node)
|
|
923
1082
|
if recursive:
|
|
924
|
-
walktrhough_tricc_node_processed_stached(
|
|
925
|
-
|
|
1083
|
+
walktrhough_tricc_node_processed_stached(
|
|
1084
|
+
next_node,
|
|
1085
|
+
callback,
|
|
1086
|
+
processed_nodes,
|
|
1087
|
+
stashed_nodes,
|
|
1088
|
+
path_len,
|
|
1089
|
+
recursive,
|
|
1090
|
+
warn=warn,
|
|
1091
|
+
node_path=node_path.copy(),
|
|
1092
|
+
**kwargs,
|
|
1093
|
+
)
|
|
926
1094
|
else:
|
|
927
1095
|
stashed_nodes.insert_at_top(next_node)
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
elif hasattr(node, 'next_nodes') and len(node.next_nodes) > 0 and not isinstance(node, TriccNodeActivity):
|
|
1096
|
+
|
|
1097
|
+
elif hasattr(node, "next_nodes") and len(node.next_nodes) > 0 and not isinstance(node, TriccNodeActivity):
|
|
931
1098
|
if recursive:
|
|
932
|
-
walkthrough_tricc_next_nodes(
|
|
933
|
-
|
|
1099
|
+
walkthrough_tricc_next_nodes(
|
|
1100
|
+
node,
|
|
1101
|
+
callback,
|
|
1102
|
+
processed_nodes,
|
|
1103
|
+
stashed_nodes,
|
|
1104
|
+
path_len + 1,
|
|
1105
|
+
recursive,
|
|
1106
|
+
warn=warn,
|
|
1107
|
+
node_path=node_path,
|
|
1108
|
+
**kwargs,
|
|
1109
|
+
)
|
|
934
1110
|
else:
|
|
935
1111
|
for nn in node.next_nodes:
|
|
936
1112
|
if nn not in stashed_nodes:
|
|
937
1113
|
stashed_nodes.insert_at_top(nn)
|
|
938
1114
|
if not recursive:
|
|
939
1115
|
reorder_node_list(stashed_nodes, node.group, processed_nodes)
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1116
|
+
|
|
943
1117
|
else:
|
|
944
1118
|
if prev_process and process and prev_process != process[0]:
|
|
945
1119
|
process[0] = prev_process
|
|
@@ -950,8 +1124,10 @@ def walktrhough_tricc_node_processed_stached(node, callback, processed_nodes, st
|
|
|
950
1124
|
logger.debug("{}::{}: stashed({})".format(callback.__name__, node.get_name(), len(stashed_nodes)))
|
|
951
1125
|
|
|
952
1126
|
|
|
953
|
-
def walkthrough_tricc_next_nodes(
|
|
954
|
-
|
|
1127
|
+
def walkthrough_tricc_next_nodes(
|
|
1128
|
+
node, callback, processed_nodes, stashed_nodes, path_len, recursive, warn=False, node_path=[], **kwargs
|
|
1129
|
+
):
|
|
1130
|
+
|
|
955
1131
|
if not recursive:
|
|
956
1132
|
for next_node in node.next_nodes:
|
|
957
1133
|
if next_node not in stashed_nodes:
|
|
@@ -961,73 +1137,100 @@ def walkthrough_tricc_next_nodes(node, callback, processed_nodes, stashed_nodes,
|
|
|
961
1137
|
for next_node in list_next:
|
|
962
1138
|
if not isinstance(node, (TriccNodeActivityEnd, TriccNodeEnd)):
|
|
963
1139
|
if next_node not in processed_nodes:
|
|
964
|
-
walktrhough_tricc_node_processed_stached(
|
|
965
|
-
|
|
1140
|
+
walktrhough_tricc_node_processed_stached(
|
|
1141
|
+
next_node,
|
|
1142
|
+
callback,
|
|
1143
|
+
processed_nodes,
|
|
1144
|
+
stashed_nodes,
|
|
1145
|
+
path_len + 1,
|
|
1146
|
+
recursive,
|
|
1147
|
+
warn=warn,
|
|
1148
|
+
node_path=node_path.copy(),
|
|
1149
|
+
**kwargs,
|
|
1150
|
+
)
|
|
966
1151
|
else:
|
|
967
1152
|
logger.critical(
|
|
968
|
-
"{}::end node of {} has a next node".format(callback.__name__, node.activity.get_name())
|
|
1153
|
+
"{}::end node of {} has a next node".format(callback.__name__, node.activity.get_name())
|
|
1154
|
+
)
|
|
969
1155
|
exit(1)
|
|
970
1156
|
|
|
971
1157
|
|
|
972
|
-
def walkthrough_tricc_option(
|
|
1158
|
+
def walkthrough_tricc_option(
|
|
1159
|
+
node, callback, processed_nodes, stashed_nodes, path_len, recursive, warn=False, node_path=[], **kwargs
|
|
1160
|
+
):
|
|
973
1161
|
if not recursive:
|
|
974
1162
|
for option in node.options.values():
|
|
975
|
-
if hasattr(option,
|
|
1163
|
+
if hasattr(option, "next_nodes") and len(option.next_nodes) > 0:
|
|
976
1164
|
for next_node in option.next_nodes:
|
|
977
1165
|
if next_node not in stashed_nodes:
|
|
978
1166
|
stashed_nodes.insert_at_top(next_node)
|
|
979
|
-
#stashed_nodes.insert(0,next_node)
|
|
1167
|
+
# stashed_nodes.insert(0,next_node)
|
|
980
1168
|
else:
|
|
981
1169
|
list_option = []
|
|
982
1170
|
while not all(elem in list_option for elem in list(node.options.values())):
|
|
983
1171
|
for option in node.options.values():
|
|
984
1172
|
if option not in list_option:
|
|
985
1173
|
list_option.append(option)
|
|
986
|
-
# then walk the options
|
|
987
|
-
if hasattr(option,
|
|
1174
|
+
# then walk the options
|
|
1175
|
+
if hasattr(option, "next_nodes") and len(option.next_nodes) > 0:
|
|
988
1176
|
list_next = set(option.next_nodes)
|
|
989
1177
|
for next_node in list_next:
|
|
990
1178
|
if next_node not in processed_nodes:
|
|
991
|
-
walktrhough_tricc_node_processed_stached(
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1179
|
+
walktrhough_tricc_node_processed_stached(
|
|
1180
|
+
next_node,
|
|
1181
|
+
callback,
|
|
1182
|
+
processed_nodes,
|
|
1183
|
+
stashed_nodes,
|
|
1184
|
+
path_len + 1,
|
|
1185
|
+
recursive,
|
|
1186
|
+
warn=warn,
|
|
1187
|
+
node_path=node_path.copy(),
|
|
1188
|
+
**kwargs,
|
|
1189
|
+
)
|
|
1190
|
+
|
|
995
1191
|
|
|
996
1192
|
def get_next_version(name, processed_nodes, version=0, min=100):
|
|
997
|
-
return
|
|
1193
|
+
return (
|
|
1194
|
+
max(
|
|
1195
|
+
version,
|
|
1196
|
+
min,
|
|
1197
|
+
*[
|
|
1198
|
+
(getattr(n, "version", None) or getattr(n, "instance", None) or 0)
|
|
1199
|
+
for n in get_versions(name, processed_nodes)
|
|
1200
|
+
],
|
|
1201
|
+
)
|
|
1202
|
+
+ 1
|
|
1203
|
+
)
|
|
998
1204
|
|
|
999
1205
|
|
|
1000
1206
|
def get_data_for_log(node):
|
|
1001
1207
|
return "{}:{}|{} {}:{}".format(
|
|
1002
1208
|
node.group.get_name() if node.group is not None else node.activity.get_name(),
|
|
1003
|
-
node.group.instance if node.group is not None else node.activity.instance
|
|
1209
|
+
node.group.instance if node.group is not None else node.activity.instance,
|
|
1004
1210
|
node.__class__,
|
|
1005
1211
|
node.get_name(),
|
|
1006
|
-
node.instance
|
|
1212
|
+
node.instance,
|
|
1213
|
+
)
|
|
1214
|
+
|
|
1007
1215
|
|
|
1008
1216
|
def stashed_node_func(node, callback, recursive=False, **kwargs):
|
|
1009
|
-
processed_nodes = kwargs.pop(
|
|
1010
|
-
stashed_nodes = kwargs.pop(
|
|
1011
|
-
process = kwargs.pop(
|
|
1217
|
+
processed_nodes = kwargs.pop("processed_nodes", OrderedSet())
|
|
1218
|
+
stashed_nodes = kwargs.pop("stashed_nodes", OrderedSet())
|
|
1219
|
+
process = kwargs.pop("process", ["main"])
|
|
1012
1220
|
path_len = 0
|
|
1013
|
-
|
|
1221
|
+
|
|
1014
1222
|
walktrhough_tricc_node_processed_stached(
|
|
1015
|
-
node,
|
|
1016
|
-
|
|
1017
|
-
processed_nodes,
|
|
1018
|
-
stashed_nodes,
|
|
1019
|
-
path_len,
|
|
1020
|
-
recursive,
|
|
1021
|
-
process=process,
|
|
1022
|
-
**kwargs)
|
|
1223
|
+
node, callback, processed_nodes, stashed_nodes, path_len, recursive, process=process, **kwargs
|
|
1224
|
+
)
|
|
1023
1225
|
# callback( node, **kwargs)
|
|
1024
|
-
|
|
1226
|
+
# MANAGE STASHED NODES
|
|
1025
1227
|
prev_stashed_nodes = stashed_nodes.copy()
|
|
1026
1228
|
loop_count = 0
|
|
1027
1229
|
len_prev_processed_nodes = 0
|
|
1028
1230
|
while len(stashed_nodes) > 0:
|
|
1029
|
-
loop_count = check_stashed_loop(
|
|
1030
|
-
|
|
1231
|
+
loop_count = check_stashed_loop(
|
|
1232
|
+
stashed_nodes, prev_stashed_nodes, processed_nodes, len_prev_processed_nodes, loop_count
|
|
1233
|
+
)
|
|
1031
1234
|
prev_stashed_nodes = stashed_nodes.copy()
|
|
1032
1235
|
len_prev_processed_nodes = len(processed_nodes)
|
|
1033
1236
|
if len(stashed_nodes) > 0:
|
|
@@ -1035,11 +1238,13 @@ def stashed_node_func(node, callback, recursive=False, **kwargs):
|
|
|
1035
1238
|
# remove duplicates
|
|
1036
1239
|
if s_node in stashed_nodes:
|
|
1037
1240
|
stashed_nodes.remove(s_node)
|
|
1038
|
-
if kwargs.get(
|
|
1039
|
-
logger.debug(
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1241
|
+
if kwargs.get("warn", True):
|
|
1242
|
+
logger.debug(
|
|
1243
|
+
"{}:: {}: unstashed for processing ({})::{}".format(
|
|
1244
|
+
callback.__name__, s_node.__class__, get_data_for_log(s_node), len(stashed_nodes)
|
|
1245
|
+
)
|
|
1246
|
+
)
|
|
1247
|
+
warn = loop_count >= (9 * len(stashed_nodes) + 1)
|
|
1043
1248
|
walktrhough_tricc_node_processed_stached(
|
|
1044
1249
|
s_node,
|
|
1045
1250
|
callback,
|
|
@@ -1049,77 +1254,87 @@ def stashed_node_func(node, callback, recursive=False, **kwargs):
|
|
|
1049
1254
|
recursive,
|
|
1050
1255
|
warn=warn,
|
|
1051
1256
|
process=process,
|
|
1052
|
-
**kwargs
|
|
1257
|
+
**kwargs,
|
|
1258
|
+
)
|
|
1053
1259
|
|
|
1054
1260
|
|
|
1055
1261
|
# check if the all the prev nodes are processed
|
|
1056
1262
|
def is_ready_to_process(in_node, processed_nodes, strict=True, local=False):
|
|
1057
1263
|
if isinstance(in_node, TriccNodeSelectOption):
|
|
1058
1264
|
node = in_node.select
|
|
1059
|
-
elif (
|
|
1060
|
-
isinstance(in_node, (TriccNodeActivityStart, TriccNodeMainStart)) ):
|
|
1265
|
+
elif isinstance(in_node, (TriccNodeActivityStart, TriccNodeMainStart)):
|
|
1061
1266
|
# check before
|
|
1062
1267
|
return True
|
|
1063
1268
|
else:
|
|
1064
1269
|
node = in_node
|
|
1065
|
-
if hasattr(node,
|
|
1270
|
+
if hasattr(node, "prev_nodes"):
|
|
1066
1271
|
# ensure the previous node of the select are processed, not the option prev nodes
|
|
1067
1272
|
for prev_node in node.prev_nodes:
|
|
1068
1273
|
if is_prev_processed(prev_node, node, processed_nodes, local) is False:
|
|
1069
1274
|
return False
|
|
1070
1275
|
return True
|
|
1071
|
-
|
|
1276
|
+
|
|
1277
|
+
|
|
1072
1278
|
def is_prev_processed(prev_node, node, processed_nodes, local):
|
|
1073
|
-
if hasattr(prev_node,
|
|
1074
|
-
return
|
|
1279
|
+
if hasattr(prev_node, "select"):
|
|
1280
|
+
return is_prev_processed(prev_node.select, node, processed_nodes, local)
|
|
1075
1281
|
if prev_node not in processed_nodes and (not local):
|
|
1076
1282
|
if isinstance(prev_node, TriccNodeExclusive):
|
|
1077
1283
|
iterator = iter(prev_node.prev_nodes)
|
|
1078
1284
|
p_n_node = next(iterator)
|
|
1079
|
-
logger.debug(
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1285
|
+
logger.debug(
|
|
1286
|
+
"is_ready_to_process:failed:via_excl: {} - {} > {} {}:{}".format(
|
|
1287
|
+
get_data_for_log(p_n_node), prev_node.get_name(), node.__class__, node.get_name(), node.instance
|
|
1288
|
+
)
|
|
1289
|
+
)
|
|
1083
1290
|
|
|
1084
1291
|
else:
|
|
1085
|
-
logger.debug(
|
|
1086
|
-
|
|
1087
|
-
|
|
1292
|
+
logger.debug(
|
|
1293
|
+
"is_ready_to_process:failed: {} -> {} {}:{}".format(
|
|
1294
|
+
get_data_for_log(prev_node), node.__class__, node.get_name(), node.instance
|
|
1295
|
+
)
|
|
1296
|
+
)
|
|
1088
1297
|
|
|
1089
|
-
logger.debug(
|
|
1090
|
-
|
|
1091
|
-
|
|
1298
|
+
logger.debug(
|
|
1299
|
+
"prev node node {}:{} for node {} not in processed".format(
|
|
1300
|
+
prev_node.__class__, prev_node.get_name(), node.get_name()
|
|
1301
|
+
)
|
|
1302
|
+
)
|
|
1092
1303
|
return False
|
|
1093
1304
|
return True
|
|
1094
1305
|
|
|
1095
1306
|
|
|
1307
|
+
def print_trace(node, prev_node, processed_nodes, stashed_nodes, history=[]):
|
|
1096
1308
|
|
|
1097
|
-
def print_trace(node, prev_node, processed_nodes, stashed_nodes, history = []):
|
|
1098
|
-
|
|
1099
1309
|
if node != prev_node:
|
|
1100
1310
|
if node in processed_nodes:
|
|
1101
|
-
logger.warning(
|
|
1102
|
-
|
|
1103
|
-
|
|
1311
|
+
logger.warning(
|
|
1312
|
+
"print trace :: node {} was the last not processed ({}):{}".format(
|
|
1313
|
+
get_data_for_log(prev_node), node.id, ">".join(history)
|
|
1314
|
+
)
|
|
1315
|
+
)
|
|
1316
|
+
# processed_nodes.add(prev_node)
|
|
1104
1317
|
return False
|
|
1105
1318
|
elif node in history:
|
|
1106
|
-
logger.critical(
|
|
1107
|
-
|
|
1319
|
+
logger.critical(
|
|
1320
|
+
"print trace :: CYCLE node {} found in history ({})".format(
|
|
1321
|
+
get_data_for_log(prev_node), ">".join(history)
|
|
1322
|
+
)
|
|
1323
|
+
)
|
|
1108
1324
|
exit(1)
|
|
1109
1325
|
elif node in stashed_nodes:
|
|
1110
1326
|
# logger.debug("print trace :: node {}::{} in stashed".format(node.__class__,node.get_name()))
|
|
1111
1327
|
return False
|
|
1112
1328
|
# else:
|
|
1113
|
-
# logger.debug("print trace :: node {} not processed/stashed".format(node.get_name()))
|
|
1329
|
+
# logger.debug("print trace :: node {} not processed/stashed".format(node.get_name()))
|
|
1114
1330
|
return True
|
|
1115
1331
|
|
|
1116
1332
|
|
|
1117
|
-
def reverse_walkthrough(in_node, next_node, callback, processed_nodes, stashed_nodes, history
|
|
1333
|
+
def reverse_walkthrough(in_node, next_node, callback, processed_nodes, stashed_nodes, history=[]):
|
|
1118
1334
|
# transform dead-end nodes
|
|
1119
1335
|
if next_node == in_node and next_node not in stashed_nodes:
|
|
1120
1336
|
# workaround fir loop
|
|
1121
1337
|
return False
|
|
1122
|
-
|
|
1123
1338
|
|
|
1124
1339
|
if isinstance(in_node, TriccNodeSelectOption):
|
|
1125
1340
|
node = in_node.select
|
|
@@ -1132,53 +1347,79 @@ def reverse_walkthrough(in_node, next_node, callback, processed_nodes, stashed_n
|
|
|
1132
1347
|
if isinstance(in_node, TriccNodeActivity):
|
|
1133
1348
|
prev_nodes = set(in_node.get_end_nodes())
|
|
1134
1349
|
for prev in prev_nodes:
|
|
1135
|
-
reverse_walkthrough(
|
|
1136
|
-
|
|
1350
|
+
reverse_walkthrough(
|
|
1351
|
+
prev,
|
|
1352
|
+
next_node,
|
|
1353
|
+
callback,
|
|
1354
|
+
processed_nodes=processed_nodes,
|
|
1355
|
+
stashed_nodes=stashed_nodes,
|
|
1356
|
+
history=history,
|
|
1357
|
+
)
|
|
1358
|
+
if hasattr(node, "prev_nodes"):
|
|
1137
1359
|
if node.prev_nodes:
|
|
1138
1360
|
for prev in node.prev_nodes:
|
|
1139
|
-
reverse_walkthrough(
|
|
1361
|
+
reverse_walkthrough(
|
|
1362
|
+
prev,
|
|
1363
|
+
node,
|
|
1364
|
+
callback,
|
|
1365
|
+
processed_nodes=processed_nodes,
|
|
1366
|
+
stashed_nodes=stashed_nodes,
|
|
1367
|
+
history=history,
|
|
1368
|
+
)
|
|
1140
1369
|
elif node in node.activity.calculates:
|
|
1141
|
-
reverse_walkthrough(
|
|
1370
|
+
reverse_walkthrough(
|
|
1371
|
+
prev,
|
|
1372
|
+
node.activity.root,
|
|
1373
|
+
callback,
|
|
1374
|
+
processed_nodes=processed_nodes,
|
|
1375
|
+
stashed_nodes=stashed_nodes,
|
|
1376
|
+
history=history,
|
|
1377
|
+
)
|
|
1142
1378
|
|
|
1143
1379
|
if issubclass(node.__class__, TriccRhombusMixIn):
|
|
1144
1380
|
if isinstance(node.reference, list):
|
|
1145
1381
|
for ref in node.reference:
|
|
1146
|
-
reverse_walkthrough(
|
|
1147
|
-
|
|
1148
|
-
|
|
1382
|
+
reverse_walkthrough(
|
|
1383
|
+
ref,
|
|
1384
|
+
node,
|
|
1385
|
+
callback,
|
|
1386
|
+
processed_nodes=processed_nodes,
|
|
1387
|
+
stashed_nodes=stashed_nodes,
|
|
1388
|
+
history=history,
|
|
1389
|
+
)
|
|
1149
1390
|
|
|
1150
1391
|
|
|
1151
1392
|
def get_prev_node_by_name(processed_nodes, name, node):
|
|
1152
|
-
# look for the node in the same activity
|
|
1153
|
-
last_calc = get_last_version(
|
|
1154
|
-
name,
|
|
1155
|
-
processed_nodes
|
|
1156
|
-
)
|
|
1393
|
+
# look for the node in the same activity
|
|
1394
|
+
last_calc = get_last_version(name, processed_nodes)
|
|
1157
1395
|
if last_calc:
|
|
1158
1396
|
return last_calc
|
|
1159
|
-
|
|
1397
|
+
|
|
1160
1398
|
filtered = list(
|
|
1161
|
-
filter(
|
|
1162
|
-
hasattr(p_node,
|
|
1163
|
-
and p_node.name == name
|
|
1164
|
-
and p_node.instance == node.instance
|
|
1165
|
-
and p_node.path_len <= node.path_len,
|
|
1166
|
-
|
|
1399
|
+
filter(
|
|
1400
|
+
lambda p_node: hasattr(p_node, "name")
|
|
1401
|
+
and p_node.name == name
|
|
1402
|
+
and p_node.instance == node.instance
|
|
1403
|
+
and p_node.path_len <= node.path_len,
|
|
1404
|
+
processed_nodes,
|
|
1405
|
+
)
|
|
1406
|
+
)
|
|
1167
1407
|
if len(filtered) == 0:
|
|
1168
|
-
filtered = list(filter(lambda p_node: hasattr(p_node,
|
|
1408
|
+
filtered = list(filter(lambda p_node: hasattr(p_node, "name") and p_node.name == name, processed_nodes))
|
|
1169
1409
|
if len(filtered) > 0:
|
|
1170
1410
|
return sorted(filtered, key=lambda x: x.path_len, reverse=False)[0]
|
|
1171
1411
|
|
|
1412
|
+
|
|
1172
1413
|
MIN_LOOP_COUNT = 10
|
|
1173
1414
|
|
|
1415
|
+
|
|
1174
1416
|
def check_stashed_loop(stashed_nodes, prev_stashed_nodes, processed_nodes, len_prev_processed_nodes, loop_count):
|
|
1175
|
-
|
|
1176
|
-
|
|
1417
|
+
|
|
1177
1418
|
if len(stashed_nodes) == len(prev_stashed_nodes):
|
|
1178
|
-
# to avoid checking the details
|
|
1179
|
-
if loop_count<=0:
|
|
1419
|
+
# to avoid checking the details
|
|
1420
|
+
if loop_count <= 0:
|
|
1180
1421
|
if loop_count < -MIN_LOOP_COUNT:
|
|
1181
|
-
loop_count = MIN_LOOP_COUNT+1
|
|
1422
|
+
loop_count = MIN_LOOP_COUNT + 1
|
|
1182
1423
|
else:
|
|
1183
1424
|
loop_count -= 1
|
|
1184
1425
|
if loop_count > MIN_LOOP_COUNT:
|
|
@@ -1186,51 +1427,56 @@ def check_stashed_loop(stashed_nodes, prev_stashed_nodes, processed_nodes, len_p
|
|
|
1186
1427
|
loop_count += 1
|
|
1187
1428
|
if loop_count > max(MIN_LOOP_COUNT, 11 * len(prev_stashed_nodes) + 1):
|
|
1188
1429
|
logger.critical("Stashed node list was unchanged: loop likely or unresolved dependence")
|
|
1189
|
-
waited, looped =
|
|
1430
|
+
waited, looped = get_all_dependant(stashed_nodes, stashed_nodes, processed_nodes)
|
|
1190
1431
|
logger.debug(f"{len(looped)} nodes waiting stashed nodes")
|
|
1191
1432
|
logger.info("unresolved reference")
|
|
1192
1433
|
for es_node in [n for n in stashed_nodes if isinstance(n, TriccReference)]:
|
|
1193
|
-
logger.info(
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1434
|
+
logger.info(
|
|
1435
|
+
"Stashed node {}:{}|{} {}".format(
|
|
1436
|
+
es_node.activity.get_name() if hasattr(es_node, "activity") else "",
|
|
1437
|
+
es_node.activity.instance if hasattr(es_node, "activity") else "",
|
|
1438
|
+
es_node.__class__,
|
|
1439
|
+
es_node.get_name(),
|
|
1440
|
+
)
|
|
1441
|
+
)
|
|
1442
|
+
for es_node in [
|
|
1443
|
+
node for node_list in looped.values() for node in node_list if isinstance(node, TriccReference)
|
|
1444
|
+
]:
|
|
1445
|
+
logger.info(
|
|
1446
|
+
"looped node {}:{}|{} {}".format(
|
|
1447
|
+
es_node.activity.get_name() if hasattr(es_node, "activity") else "",
|
|
1448
|
+
es_node.activity.instance if hasattr(es_node, "activity") else "",
|
|
1449
|
+
es_node.__class__,
|
|
1450
|
+
es_node.get_name(),
|
|
1451
|
+
)
|
|
1452
|
+
)
|
|
1453
|
+
for es_node in [
|
|
1454
|
+
node for node_list in waited.values() for node in node_list if isinstance(node, TriccReference)
|
|
1455
|
+
]:
|
|
1456
|
+
logger.info(
|
|
1457
|
+
"waited node {}:{}|{} {}".format(
|
|
1458
|
+
es_node.activity.get_name() if hasattr(es_node, "activity") else "",
|
|
1459
|
+
es_node.activity.instance if hasattr(es_node, "activity") else "",
|
|
1460
|
+
es_node.__class__,
|
|
1461
|
+
es_node.get_name(),
|
|
1462
|
+
)
|
|
1463
|
+
)
|
|
1210
1464
|
logger.info("looped nodes")
|
|
1211
1465
|
for dep_list in looped:
|
|
1212
1466
|
for d in looped[dep_list]:
|
|
1213
1467
|
if str(d) in looped:
|
|
1214
|
-
logger.critical("[{}] depends on [{}]".format(
|
|
1215
|
-
dep_list, str(d)
|
|
1216
|
-
))
|
|
1468
|
+
logger.critical("[{}] depends on [{}]".format(dep_list, str(d)))
|
|
1217
1469
|
else:
|
|
1218
|
-
logger.error("[{}] depends on [{}]".format(
|
|
1219
|
-
dep_list, str(d)
|
|
1220
|
-
))
|
|
1470
|
+
logger.error("[{}] depends on [{}]".format(dep_list, str(d)))
|
|
1221
1471
|
if dep_list in waited:
|
|
1222
1472
|
for d in waited[dep_list]:
|
|
1223
|
-
logger.warning("[{}] depends on [{}]".format(
|
|
1224
|
-
dep_list, str(d)
|
|
1225
|
-
))
|
|
1473
|
+
logger.warning("[{}] depends on [{}]".format(dep_list, str(d)))
|
|
1226
1474
|
logger.info("waited nodes")
|
|
1227
1475
|
for dep_list in waited:
|
|
1228
1476
|
if dep_list not in looped:
|
|
1229
1477
|
for d in waited[dep_list]:
|
|
1230
|
-
logger.warning("[{}] depends on [{}]".format(
|
|
1231
|
-
|
|
1232
|
-
))
|
|
1233
|
-
|
|
1478
|
+
logger.warning("[{}] depends on [{}]".format(dep_list, d.get_name()))
|
|
1479
|
+
|
|
1234
1480
|
if len(stashed_nodes) == len(prev_stashed_nodes):
|
|
1235
1481
|
exit(1)
|
|
1236
1482
|
else:
|
|
@@ -1239,6 +1485,7 @@ def check_stashed_loop(stashed_nodes, prev_stashed_nodes, processed_nodes, len_p
|
|
|
1239
1485
|
loop_count = 0
|
|
1240
1486
|
return loop_count
|
|
1241
1487
|
|
|
1488
|
+
|
|
1242
1489
|
def add_to_tree(tree, n, d):
|
|
1243
1490
|
n_str = str(n)
|
|
1244
1491
|
if n_str not in tree:
|
|
@@ -1247,10 +1494,10 @@ def add_to_tree(tree, n, d):
|
|
|
1247
1494
|
tree[n_str].append(d)
|
|
1248
1495
|
return tree
|
|
1249
1496
|
|
|
1250
|
-
|
|
1251
|
-
def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None
|
|
1497
|
+
|
|
1498
|
+
def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None, looped=None, path=None):
|
|
1252
1499
|
if path is None:
|
|
1253
|
-
path =[]
|
|
1500
|
+
path = []
|
|
1254
1501
|
if looped is None:
|
|
1255
1502
|
looped = {}
|
|
1256
1503
|
if waited is None:
|
|
@@ -1260,50 +1507,55 @@ def get_all_dependant(loop, stashed_nodes, processed_nodes, depth=0, waited=None
|
|
|
1260
1507
|
cur_path = path.copy()
|
|
1261
1508
|
cur_path.append(n)
|
|
1262
1509
|
dependant = OrderedSet()
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
dependant = dependant | n.prev_nodes
|
|
1268
|
-
if hasattr(n, 'get_references'):
|
|
1269
|
-
dependant = dependant | (n.get_references() or OrderedSet())
|
|
1510
|
+
if hasattr(n, "prev_nodes") and n.prev_nodes:
|
|
1511
|
+
dependant = dependant | n.prev_nodes
|
|
1512
|
+
if hasattr(n, "get_references"):
|
|
1513
|
+
dependant = dependant | (n.get_references() or OrderedSet())
|
|
1270
1514
|
if not isinstance(dependant, list):
|
|
1271
1515
|
pass
|
|
1272
1516
|
for d in dependant:
|
|
1273
1517
|
if d in path:
|
|
1274
|
-
logger.warning(
|
|
1518
|
+
logger.warning(
|
|
1519
|
+
f"loop {str(d)} already in path {'::'.join(map(str, path))} "
|
|
1520
|
+
)
|
|
1275
1521
|
if isinstance(d, TriccNodeSelectOption):
|
|
1276
1522
|
d = d.select
|
|
1277
|
-
|
|
1523
|
+
|
|
1278
1524
|
if isinstance(d, TriccReference):
|
|
1279
1525
|
if not any(n.name == d.value for n in processed_nodes):
|
|
1280
1526
|
if not any(n.name == d.value for n in stashed_nodes):
|
|
1281
1527
|
waited = add_to_tree(waited, n, d)
|
|
1282
|
-
else
|
|
1528
|
+
else:
|
|
1283
1529
|
looped = add_to_tree(looped, n, d)
|
|
1284
|
-
|
|
1530
|
+
|
|
1285
1531
|
elif d not in processed_nodes:
|
|
1286
1532
|
if d in stashed_nodes:
|
|
1287
1533
|
looped = add_to_tree(looped, n, d)
|
|
1288
|
-
else
|
|
1534
|
+
else:
|
|
1289
1535
|
waited = add_to_tree(waited, n, d)
|
|
1290
1536
|
all_dependant = all_dependant.union(dependant)
|
|
1291
1537
|
if depth < MAX_DRILL:
|
|
1292
|
-
waited, looped =
|
|
1293
|
-
|
|
1538
|
+
waited, looped = get_all_dependant(
|
|
1539
|
+
all_dependant, stashed_nodes, processed_nodes, depth + 1, waited, looped, path=cur_path
|
|
1540
|
+
)
|
|
1541
|
+
|
|
1294
1542
|
return waited, looped
|
|
1295
1543
|
|
|
1296
1544
|
|
|
1297
1545
|
MAX_DRILL = 3
|
|
1298
1546
|
|
|
1547
|
+
|
|
1299
1548
|
def get_last_end_node(processed_nodes, process=None):
|
|
1300
|
-
end_name =
|
|
1549
|
+
end_name = "tricc_end_"
|
|
1301
1550
|
if process:
|
|
1302
1551
|
end_name += process
|
|
1303
1552
|
return get_last_version(end_name, processed_nodes)
|
|
1304
1553
|
|
|
1554
|
+
|
|
1305
1555
|
# Set the source next node to target and clean next nodes of replace node
|
|
1306
|
-
|
|
1556
|
+
|
|
1557
|
+
|
|
1558
|
+
def set_prev_next_node(source_node, target_node, replaced_node=None, edge_only=False, activity=None):
|
|
1307
1559
|
activity = activity or source_node.activity
|
|
1308
1560
|
source_id, source_node = get_node_from_id(activity, source_node, edge_only)
|
|
1309
1561
|
target_id, target_node = get_node_from_id(activity, target_node, edge_only)
|
|
@@ -1311,36 +1563,39 @@ def set_prev_next_node(source_node, target_node, replaced_node=None, edge_only =
|
|
|
1311
1563
|
if not edge_only:
|
|
1312
1564
|
set_prev_node(source_node, target_node, replaced_node, edge_only)
|
|
1313
1565
|
set_next_node(source_node, target_node, replaced_node, edge_only)
|
|
1314
|
-
|
|
1315
|
-
if activity and not any([(e.source == source_id) and (
|
|
1566
|
+
|
|
1567
|
+
if activity and not any([(e.source == source_id) and (e.target == target_id) for e in activity.edges]):
|
|
1316
1568
|
label = "continue" if issubclass(source_node.__class__, TriccNodeSelect) else None
|
|
1317
|
-
activity.edges.append(TriccEdge(id
|
|
1569
|
+
activity.edges.append(TriccEdge(id=generate_id(), source=source_id, target=target_id, value=label))
|
|
1570
|
+
|
|
1318
1571
|
|
|
1319
1572
|
def remove_prev_next(prev_node, next_node, activity=None):
|
|
1320
1573
|
activity = activity or prev_node.activity
|
|
1321
|
-
if hasattr(prev_node,
|
|
1574
|
+
if hasattr(prev_node, "next_nodes") and next_node in prev_node.next_nodes:
|
|
1322
1575
|
prev_node.next_nodes.remove(next_node)
|
|
1323
|
-
if hasattr(next_node,
|
|
1576
|
+
if hasattr(next_node, "prev_nodes") and prev_node in next_node.prev_nodes:
|
|
1324
1577
|
next_node.prev_nodes.remove(prev_node)
|
|
1325
|
-
|
|
1578
|
+
|
|
1326
1579
|
for e in list(activity.edges):
|
|
1327
|
-
if
|
|
1580
|
+
if e.target == getattr(next_node, "id", next_node) and e.source == getattr(prev_node, "id", prev_node):
|
|
1328
1581
|
activity.edges.remove(e)
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
def set_next_node(source_node, target_node, replaced_node=None, edge_only = False, activity=None):
|
|
1582
|
+
|
|
1583
|
+
|
|
1584
|
+
def set_next_node(source_node, target_node, replaced_node=None, edge_only=False, activity=None):
|
|
1333
1585
|
activity = activity or source_node.activity
|
|
1334
1586
|
replace_target = None
|
|
1335
|
-
if not edge_only:
|
|
1336
|
-
if replaced_node is not None and hasattr(source_node,
|
|
1587
|
+
if not edge_only:
|
|
1588
|
+
if replaced_node is not None and hasattr(source_node, "path") and replaced_node == source_node.path:
|
|
1337
1589
|
source_node.path = target_node
|
|
1338
|
-
elif
|
|
1590
|
+
elif (
|
|
1591
|
+
replaced_node is not None and hasattr(source_node, "next_nodes") and replaced_node in source_node.next_nodes
|
|
1592
|
+
):
|
|
1339
1593
|
replace_target = True
|
|
1340
1594
|
source_node.next_nodes.remove(replaced_node)
|
|
1341
|
-
if hasattr(replaced_node,
|
|
1595
|
+
if hasattr(replaced_node, "prev_nodes") and source_node in replaced_node.prev_nodes:
|
|
1342
1596
|
replaced_node.prev_nodes.remove(source_node)
|
|
1343
|
-
#if replaced_node is not None and hasattr(target_node, 'next_nodes')
|
|
1597
|
+
# if replaced_node is not None and hasattr(target_node, 'next_nodes')
|
|
1598
|
+
# and replaced_node in target_node.next_nodes:
|
|
1344
1599
|
# target_node.next_nodes.remove(replaced_node)
|
|
1345
1600
|
if target_node not in source_node.next_nodes:
|
|
1346
1601
|
source_node.next_nodes.add(target_node)
|
|
@@ -1359,31 +1614,34 @@ def set_next_node(source_node, target_node, replaced_node=None, edge_only = Fals
|
|
|
1359
1614
|
if replaced_node and replace_target:
|
|
1360
1615
|
if replaced_node.id in replaced_node.activity.nodes:
|
|
1361
1616
|
del replaced_node.activity.nodes[replaced_node.id]
|
|
1362
|
-
next_edges = set(
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1617
|
+
next_edges = set(
|
|
1618
|
+
[
|
|
1619
|
+
e for e in replaced_node.activity.edges
|
|
1620
|
+
if (e.target == replaced_node.id or e.target == replaced_node)
|
|
1621
|
+
] + [
|
|
1622
|
+
e for e in activity.edges
|
|
1623
|
+
if (e.target == replaced_node.id or e.target == replaced_node)
|
|
1624
|
+
]
|
|
1625
|
+
)
|
|
1626
|
+
if len(next_edges) == 0:
|
|
1627
|
+
for e in next_edges:
|
|
1369
1628
|
e.target = target_node.id
|
|
1370
1629
|
|
|
1371
|
-
|
|
1372
1630
|
|
|
1373
1631
|
# Set the target_node prev node to source and clean prev nodes of replace_node
|
|
1374
|
-
def set_prev_node(source_node, target_node, replaced_node=None, edge_only
|
|
1632
|
+
def set_prev_node(source_node, target_node, replaced_node=None, edge_only=False, activity=None):
|
|
1375
1633
|
activity = activity or source_node.activity
|
|
1376
1634
|
replace_source = False
|
|
1377
1635
|
# update the prev node of the target not if not an end node
|
|
1378
1636
|
# update directly the prev node of the target
|
|
1379
|
-
if replaced_node is not None and hasattr(target_node,
|
|
1637
|
+
if replaced_node is not None and hasattr(target_node, "path") and replaced_node == target_node.path:
|
|
1380
1638
|
target_node.path = source_node
|
|
1381
|
-
if replaced_node is not None and hasattr(target_node,
|
|
1639
|
+
if replaced_node is not None and hasattr(target_node, "prev_nodes") and replaced_node in target_node.prev_nodes:
|
|
1382
1640
|
replace_source = True
|
|
1383
1641
|
target_node.prev_nodes.remove(replaced_node)
|
|
1384
|
-
if hasattr(replaced_node,
|
|
1642
|
+
if hasattr(replaced_node, "next_nodes") and source_node in replaced_node.next_nodes:
|
|
1385
1643
|
replaced_node.next_nodes.remove(source_node)
|
|
1386
|
-
#if replaced_node is not None and hasattr(source_node, 'prev_nodes') and replaced_node in source_node.prev_nodes:
|
|
1644
|
+
# if replaced_node is not None and hasattr(source_node, 'prev_nodes') and replaced_node in source_node.prev_nodes:
|
|
1387
1645
|
# source_node.prev_nodes.remove(replaced_node)
|
|
1388
1646
|
if source_node not in target_node.prev_nodes:
|
|
1389
1647
|
target_node.prev_nodes.add(source_node)
|
|
@@ -1391,18 +1649,17 @@ def set_prev_node(source_node, target_node, replaced_node=None, edge_only = Fals
|
|
|
1391
1649
|
activity.nodes[source_node.id] = source_node
|
|
1392
1650
|
if replaced_node and replace_source:
|
|
1393
1651
|
if replaced_node.id in replaced_node.activity.nodes:
|
|
1394
|
-
|
|
1395
|
-
next_edges = set(
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
for e in next_edges:
|
|
1652
|
+
del replaced_node.activity.nodes[replaced_node.id]
|
|
1653
|
+
next_edges = set(
|
|
1654
|
+
[e for e in replaced_node.activity.edges if (e.source == replaced_node.id or e.source == replaced_node)]
|
|
1655
|
+
+ [e for e in activity.edges if (e.source == replaced_node.id or e.source == replaced_node)]
|
|
1656
|
+
)
|
|
1657
|
+
if len(next_edges) == 0:
|
|
1658
|
+
for e in next_edges:
|
|
1402
1659
|
e.target = target_node.id
|
|
1403
|
-
|
|
1404
1660
|
|
|
1405
|
-
|
|
1661
|
+
|
|
1662
|
+
def replace_node(old, new, page=None):
|
|
1406
1663
|
if page is None:
|
|
1407
1664
|
page = old.activity
|
|
1408
1665
|
logger.debug("replacing node {} with node {} from page {}".format(old.get_name(), new.get_name(), page.get_name()))
|
|
@@ -1429,23 +1686,25 @@ def replace_node(old, new, page = None):
|
|
|
1429
1686
|
if edge.target == old.id:
|
|
1430
1687
|
edge.target = new.id
|
|
1431
1688
|
|
|
1432
|
-
|
|
1689
|
+
|
|
1690
|
+
def replace_prev_next_node(prev_node, next_node, old_node, force=False):
|
|
1433
1691
|
replace_prev_node(prev_node, next_node, old_node)
|
|
1434
1692
|
replace_next_node(prev_node, next_node, old_node)
|
|
1435
1693
|
|
|
1436
|
-
|
|
1437
|
-
|
|
1694
|
+
|
|
1695
|
+
def replace_prev_node(prev_node, next_node, old_node, force=False):
|
|
1696
|
+
# create a copy pf the list
|
|
1438
1697
|
list_nodes = list(next_node.prev_nodes)
|
|
1439
1698
|
# replace in case old node is found
|
|
1440
1699
|
for p_n_node in list_nodes:
|
|
1441
1700
|
if p_n_node == old_node or force:
|
|
1442
1701
|
set_prev_next_node(prev_node, next_node, old_node)
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
def replace_next_node(prev_node,next_node,old_node):
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
def replace_next_node(prev_node, next_node, old_node):
|
|
1446
1705
|
list_nodes = list(prev_node.next_nodes)
|
|
1447
1706
|
for n_p_node in list_nodes:
|
|
1448
|
-
if n_p_node == old_node
|
|
1707
|
+
if n_p_node == old_node:
|
|
1449
1708
|
set_prev_next_node(prev_node, next_node, old_node)
|
|
1450
1709
|
|
|
1451
1710
|
|
|
@@ -1458,6 +1717,7 @@ ACTIVE_ACTIVITY_LOWER_PRIORITY = 3000
|
|
|
1458
1717
|
RHOMBUS_PRIORITY = 1000
|
|
1459
1718
|
DEFAULT_PRIORITY = 2000
|
|
1460
1719
|
|
|
1720
|
+
|
|
1461
1721
|
def reorder_node_list(node_list, group, processed_nodes):
|
|
1462
1722
|
# Cache active activities for O(1) lookup
|
|
1463
1723
|
active_activities = {n.activity for n in processed_nodes}
|
|
@@ -1493,49 +1753,51 @@ def reorder_node_list(node_list, group, processed_nodes):
|
|
|
1493
1753
|
|
|
1494
1754
|
# Sort in place, highest priority first
|
|
1495
1755
|
node_list.sort(key=get_priority, reverse=True)
|
|
1496
|
-
|
|
1756
|
+
|
|
1757
|
+
|
|
1497
1758
|
def loop_info(loop, **kwargs):
|
|
1498
1759
|
logger.critical("dependency details")
|
|
1499
1760
|
for n in loop:
|
|
1500
|
-
i=0
|
|
1761
|
+
i = 0
|
|
1501
1762
|
logger.critical(f"{i}: {n.__class__}::{n.get_name()}")
|
|
1502
1763
|
i += 1
|
|
1503
1764
|
|
|
1504
1765
|
|
|
1505
|
-
def has_loop(
|
|
1766
|
+
def has_loop(
|
|
1767
|
+
node, processed_nodes, stashed_nodes, warn, node_path=[], action_on_loop=loop_info, action_on_other=None, **kwargs
|
|
1768
|
+
):
|
|
1506
1769
|
next_nodes = get_extended_next_nodes(node)
|
|
1507
|
-
for next_node in next_nodes:
|
|
1770
|
+
for next_node in next_nodes:
|
|
1508
1771
|
if next_node in node_path:
|
|
1509
1772
|
loop_start_key = node_path.index(next_node)
|
|
1510
1773
|
loop = node_path[loop_start_key:]
|
|
1511
1774
|
loop.append(node)
|
|
1512
1775
|
loop.append(next_node)
|
|
1513
1776
|
action_on_loop(loop, **kwargs)
|
|
1514
|
-
return False
|
|
1777
|
+
return False
|
|
1515
1778
|
if callable(action_on_other):
|
|
1516
1779
|
action_on_other(next_node, **kwargs)
|
|
1517
1780
|
return True
|
|
1518
|
-
|
|
1519
|
-
|
|
1781
|
+
|
|
1520
1782
|
|
|
1521
1783
|
def get_extended_next_nodes(node):
|
|
1522
|
-
|
|
1523
|
-
nodes =
|
|
1524
|
-
if issubclass(node.__class__, TriccNodeSelect
|
|
1784
|
+
|
|
1785
|
+
nodes = node.next_nodes if hasattr(node, "next_nodes") else set()
|
|
1786
|
+
if issubclass(node.__class__, TriccNodeSelect):
|
|
1525
1787
|
for o in node.options.values():
|
|
1526
1788
|
nodes = nodes | o.next_nodes
|
|
1527
|
-
if isinstance(node, (
|
|
1789
|
+
if isinstance(node, (TriccNodeActivity)):
|
|
1528
1790
|
nodes = nodes | node.root.next_nodes
|
|
1529
1791
|
return nodes
|
|
1530
|
-
|
|
1792
|
+
|
|
1531
1793
|
|
|
1532
1794
|
# calculate or retrieve a node expression
|
|
1533
|
-
def get_node_expression(
|
|
1795
|
+
def get_node_expression(in_node, processed_nodes, get_overall_exp=False, is_prev=False, negate=False, process=None):
|
|
1534
1796
|
# in case of calculate we only use the select multiple if none is not selected
|
|
1535
1797
|
expression = None
|
|
1536
1798
|
negate_expression = None
|
|
1537
1799
|
node = in_node
|
|
1538
|
-
if isinstance(node, (TriccNodeActivityStart,TriccNodeMainStart)):
|
|
1800
|
+
if isinstance(node, (TriccNodeActivityStart, TriccNodeMainStart)):
|
|
1539
1801
|
if is_prev and get_overall_exp:
|
|
1540
1802
|
expression = get_node_expression(
|
|
1541
1803
|
node.activity,
|
|
@@ -1543,13 +1805,13 @@ def get_node_expression( in_node, processed_nodes, get_overall_exp=False, is_pre
|
|
|
1543
1805
|
get_overall_exp=True,
|
|
1544
1806
|
is_prev=is_prev,
|
|
1545
1807
|
negate=negate,
|
|
1546
|
-
process=process
|
|
1808
|
+
process=process,
|
|
1547
1809
|
)
|
|
1548
1810
|
if isinstance(node, TriccNodeMainStart):
|
|
1549
|
-
expression =
|
|
1811
|
+
expression = get_applicability_expression(node.activity, processed_nodes, process, expression)
|
|
1550
1812
|
elif isinstance(node, (TriccNodeActivityStart)):
|
|
1551
1813
|
return TriccStatic(True)
|
|
1552
|
-
|
|
1814
|
+
|
|
1553
1815
|
elif isinstance(node, TriccNodeWait):
|
|
1554
1816
|
if is_prev:
|
|
1555
1817
|
# the wait don't do any calculation with the reference it is only use to wait until the reference are valid
|
|
@@ -1558,86 +1820,78 @@ def get_node_expression( in_node, processed_nodes, get_overall_exp=False, is_pre
|
|
|
1558
1820
|
processed_nodes=processed_nodes,
|
|
1559
1821
|
get_overall_exp=get_overall_exp,
|
|
1560
1822
|
is_prev=True,
|
|
1561
|
-
process=process
|
|
1562
|
-
|
|
1823
|
+
process=process,
|
|
1824
|
+
)
|
|
1563
1825
|
else:
|
|
1564
|
-
#it is a empty calculate
|
|
1826
|
+
# it is a empty calculate
|
|
1565
1827
|
return None
|
|
1566
1828
|
elif isinstance(node, TriccNodeRhombus):
|
|
1567
|
-
|
|
1568
|
-
# expression = TriccOperation(
|
|
1569
|
-
# TriccOperator.ISTRUE,
|
|
1570
|
-
# [node]
|
|
1571
|
-
# )
|
|
1572
|
-
# else:
|
|
1573
|
-
expression = get_rhombus_terms(node, processed_nodes, process=process) # if issubclass(node.__class__, TricNodeDisplayCalulate) else TRICC_CALC_EXPRESSION.format(get_export_name(node)) #
|
|
1829
|
+
expression = get_rhombus_terms(node, processed_nodes, process=process)
|
|
1574
1830
|
negate_expression = not_clean(expression)
|
|
1575
|
-
if node.path is None
|
|
1831
|
+
if node.path is None:
|
|
1576
1832
|
if len(node.prev_nodes) == 1:
|
|
1577
1833
|
node.path = list(node.prev_nodes)[0]
|
|
1578
1834
|
elif len(node.prev_nodes) > 1:
|
|
1579
1835
|
logger.critical(f"missing path for Rhombus {node.get_name()}")
|
|
1580
1836
|
exit(1)
|
|
1581
1837
|
prev_exp = get_node_expression(
|
|
1582
|
-
node.path,
|
|
1583
|
-
|
|
1584
|
-
get_overall_exp=get_overall_exp,
|
|
1585
|
-
is_prev=True,
|
|
1586
|
-
process=process)
|
|
1838
|
+
node.path, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, is_prev=True, process=process
|
|
1839
|
+
)
|
|
1587
1840
|
if prev_exp and expression:
|
|
1588
1841
|
expression = and_join([prev_exp, expression])
|
|
1589
|
-
negate_expression = and_join([
|
|
1590
|
-
prev_exp,
|
|
1591
|
-
negate_expression
|
|
1592
|
-
])
|
|
1842
|
+
negate_expression = and_join([prev_exp, negate_expression])
|
|
1593
1843
|
|
|
1594
1844
|
elif prev_exp:
|
|
1595
|
-
|
|
1845
|
+
|
|
1596
1846
|
logger.error(f"useless rhombus {node.get_name()}")
|
|
1597
1847
|
expression = prev_exp
|
|
1598
1848
|
negate_expression = prev_exp
|
|
1599
1849
|
logger.critical(f"Rhombus without expression {node.get_name()}")
|
|
1600
1850
|
elif is_prev and issubclass(node.__class__, TriccNodeDisplayCalculateBase):
|
|
1601
1851
|
expression = TriccOperation(TriccOperator.ISTRUE, [node])
|
|
1602
|
-
elif hasattr(node,
|
|
1852
|
+
elif hasattr(node, "expression_reference") and isinstance(node.expression_reference, TriccOperation):
|
|
1603
1853
|
# if issubclass(node.__class__, TriccNodeDisplayCalculateBase):
|
|
1604
1854
|
# expression = TriccOperation(
|
|
1605
1855
|
# TriccOperator.CAST_NUMBER,
|
|
1606
1856
|
# [node.expression_reference])
|
|
1607
|
-
# else:
|
|
1608
|
-
expression = node.expression_reference
|
|
1857
|
+
# else:
|
|
1858
|
+
expression = node.expression_reference
|
|
1609
1859
|
elif is_prev and isinstance(node, TriccNodeSelectOption):
|
|
1610
1860
|
if negate:
|
|
1611
1861
|
negate_expression = get_selected_option_expression(node, negate)
|
|
1612
1862
|
else:
|
|
1613
1863
|
expression = get_selected_option_expression(node, negate)
|
|
1614
|
-
#TODO remove that and manage it on the "Save" part
|
|
1864
|
+
# TODO remove that and manage it on the "Save" part
|
|
1615
1865
|
elif is_prev and isinstance(node, TriccNodeSelectNotAvailable):
|
|
1616
|
-
expression =
|
|
1617
|
-
TriccOperator.SELECTED,
|
|
1618
|
-
[
|
|
1619
|
-
node,
|
|
1620
|
-
TriccStatic(1)
|
|
1621
|
-
]
|
|
1622
|
-
)
|
|
1866
|
+
expression = TriccOperation(TriccOperator.SELECTED, [node, TriccStatic(1)])
|
|
1623
1867
|
elif issubclass(node.__class__, TriccNodeCalculateBase):
|
|
1624
1868
|
if negate:
|
|
1625
|
-
negate_expression = get_calculation_terms(
|
|
1869
|
+
negate_expression = get_calculation_terms(
|
|
1870
|
+
node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, negate=True, process=process
|
|
1871
|
+
)
|
|
1626
1872
|
else:
|
|
1627
|
-
expression = get_calculation_terms(
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
elif
|
|
1873
|
+
expression = get_calculation_terms(
|
|
1874
|
+
node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
|
|
1875
|
+
)
|
|
1876
|
+
|
|
1877
|
+
elif (
|
|
1878
|
+
(not is_prev or not ONE_QUESTION_AT_A_TIME)
|
|
1879
|
+
and hasattr(node, "relevance")
|
|
1880
|
+
and isinstance(node.relevance, (TriccOperation, TriccStatic))
|
|
1881
|
+
):
|
|
1882
|
+
expression = node.relevance
|
|
1883
|
+
elif ONE_QUESTION_AT_A_TIME and is_prev and not get_overall_exp and hasattr(node, "required") and node.required:
|
|
1632
1884
|
expression = get_required_node_expression(node)
|
|
1633
|
-
|
|
1885
|
+
|
|
1634
1886
|
if expression is None:
|
|
1635
|
-
expression = get_prev_node_expression(
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
#
|
|
1639
|
-
|
|
1640
|
-
|
|
1887
|
+
expression = get_prev_node_expression(
|
|
1888
|
+
node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
|
|
1889
|
+
)
|
|
1890
|
+
# in_node not in processed_nodes is need for calculates that can but run after the end of the activity
|
|
1891
|
+
# if isinstance(node, TriccNodeActivitiy) and not prev:
|
|
1892
|
+
# expression = get_applicability_expression(node, processed_nodes, process, expression)
|
|
1893
|
+
# expression = get_prev_instance_skip_expression(node, processed_nodes, process, expression)
|
|
1894
|
+
# expression = get_process_skip_expression(node, processed_nodes, process, expression)
|
|
1641
1895
|
if negate:
|
|
1642
1896
|
if negate_expression is not None:
|
|
1643
1897
|
return negate_expression
|
|
@@ -1648,64 +1902,50 @@ def get_node_expression( in_node, processed_nodes, get_overall_exp=False, is_pre
|
|
|
1648
1902
|
# exit(1)
|
|
1649
1903
|
else:
|
|
1650
1904
|
return expression
|
|
1651
|
-
|
|
1905
|
+
|
|
1906
|
+
|
|
1652
1907
|
def get_applicability_expression(node, processed_nodes, process, expression=None):
|
|
1653
|
-
if isinstance(node.applicability,(TriccStatic,TriccOperation, TriccReference)):
|
|
1908
|
+
if isinstance(node.applicability, (TriccStatic, TriccOperation, TriccReference)):
|
|
1654
1909
|
if expression:
|
|
1655
1910
|
expression = and_join([node.applicability, expression])
|
|
1656
1911
|
else:
|
|
1657
1912
|
expression = node.applicability
|
|
1658
|
-
|
|
1913
|
+
|
|
1659
1914
|
return expression
|
|
1660
|
-
|
|
1661
1915
|
|
|
1662
1916
|
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
1917
|
def get_prev_instance_skip_expression(node, processed_nodes, process, expression=None):
|
|
1666
1918
|
if node.base_instance is not None:
|
|
1667
|
-
activity = node
|
|
1668
1919
|
expression_inputs = []
|
|
1669
|
-
past_instances = [
|
|
1670
|
-
n for n in processed_nodes if getattr(n.base_instance, 'id', None) == node.base_instance.id
|
|
1671
|
-
]
|
|
1920
|
+
past_instances = [n for n in processed_nodes if getattr(n.base_instance, "id", None) == node.base_instance.id]
|
|
1672
1921
|
for past_instance in past_instances:
|
|
1673
1922
|
add_sub_expression(
|
|
1674
|
-
expression_inputs,
|
|
1923
|
+
expression_inputs,
|
|
1675
1924
|
get_node_expression(
|
|
1676
|
-
past_instance,
|
|
1677
|
-
|
|
1678
|
-
get_overall_exp=True,
|
|
1679
|
-
is_prev=True,
|
|
1680
|
-
process=process
|
|
1681
|
-
)
|
|
1925
|
+
past_instance, processed_nodes=processed_nodes, get_overall_exp=True, is_prev=True, process=process
|
|
1926
|
+
),
|
|
1682
1927
|
)
|
|
1683
1928
|
if expression and expression_inputs:
|
|
1684
1929
|
add_sub_expression(expression_inputs, expression)
|
|
1685
1930
|
expression = nand_join(expression, or_join(expression_inputs))
|
|
1686
1931
|
elif expression_inputs:
|
|
1687
|
-
expression =
|
|
1932
|
+
expression = negate_term(or_join(expression_inputs))
|
|
1688
1933
|
return expression
|
|
1689
1934
|
|
|
1690
1935
|
|
|
1691
1936
|
# end def
|
|
1692
1937
|
def get_process_skip_expression(node, processed_nodes, process, expression=None):
|
|
1693
|
-
list_ends = OrderedSet(
|
|
1694
|
-
filter(
|
|
1695
|
-
lambda x: issubclass(x.__class__, TriccNodeEnd),
|
|
1696
|
-
processed_nodes
|
|
1697
|
-
)
|
|
1698
|
-
)
|
|
1938
|
+
list_ends = OrderedSet(filter(lambda x: issubclass(x.__class__, TriccNodeEnd), processed_nodes))
|
|
1699
1939
|
if list_ends:
|
|
1700
1940
|
end_expressions = []
|
|
1701
1941
|
f_end_expression = get_end_expression(list_ends)
|
|
1702
1942
|
if f_end_expression:
|
|
1703
1943
|
end_expressions.append(f_end_expression)
|
|
1704
|
-
b_end_expression = get_end_expression(list_ends,
|
|
1944
|
+
b_end_expression = get_end_expression(list_ends, "pause")
|
|
1705
1945
|
if b_end_expression:
|
|
1706
|
-
end_expressions.append(b_end_expression)
|
|
1946
|
+
end_expressions.append(b_end_expression)
|
|
1707
1947
|
if process[0] in PROCESSES:
|
|
1708
|
-
for p in PROCESSES[PROCESSES.index(process[0])+1:]:
|
|
1948
|
+
for p in PROCESSES[PROCESSES.index(process[0]) + 1:]:
|
|
1709
1949
|
p_end_expression = get_end_expression(list_ends, p)
|
|
1710
1950
|
if p_end_expression:
|
|
1711
1951
|
end_expressions.append(p_end_expression)
|
|
@@ -1717,16 +1957,12 @@ def get_process_skip_expression(node, processed_nodes, process, expression=None)
|
|
|
1717
1957
|
else:
|
|
1718
1958
|
expression = and_join(end_expressions)
|
|
1719
1959
|
return expression
|
|
1720
|
-
|
|
1960
|
+
|
|
1961
|
+
|
|
1721
1962
|
def get_end_expression(processed_nodes, process=None):
|
|
1722
1963
|
end_node = get_last_end_node(processed_nodes, process)
|
|
1723
1964
|
if end_node:
|
|
1724
|
-
return TriccOperation(
|
|
1725
|
-
TriccOperator.ISNOTTRUE,
|
|
1726
|
-
[end_node]
|
|
1727
|
-
)
|
|
1728
|
-
|
|
1729
|
-
|
|
1965
|
+
return TriccOperation(TriccOperator.ISNOTTRUE, [end_node])
|
|
1730
1966
|
|
|
1731
1967
|
|
|
1732
1968
|
def export_proposed_diags(activity, diags=None, **kwargs):
|
|
@@ -1736,11 +1972,10 @@ def export_proposed_diags(activity, diags=None, **kwargs):
|
|
|
1736
1972
|
if isinstance(node, TriccNodeActivity):
|
|
1737
1973
|
diags = export_proposed_diags(node, diags, **kwargs)
|
|
1738
1974
|
if isinstance(node, TriccNodeProposedDiagnosis):
|
|
1739
|
-
if node.last is not False
|
|
1740
|
-
|
|
1741
|
-
diags.append(node)
|
|
1975
|
+
if node.last is not False and not any([diag.name == node.name for diag in diags]):
|
|
1976
|
+
diags.append(node)
|
|
1742
1977
|
return diags
|
|
1743
|
-
|
|
1978
|
+
|
|
1744
1979
|
|
|
1745
1980
|
def get_accept_diagnostic_node(code, display, severity, priority, activity):
|
|
1746
1981
|
node = TriccNodeAcceptDiagnostic(
|
|
@@ -1751,11 +1986,12 @@ def get_accept_diagnostic_node(code, display, severity, priority, activity):
|
|
|
1751
1986
|
activity=activity,
|
|
1752
1987
|
group=activity,
|
|
1753
1988
|
severity=severity,
|
|
1754
|
-
priority=priority
|
|
1989
|
+
priority=priority,
|
|
1755
1990
|
)
|
|
1756
1991
|
node.options = get_select_accept_reject_options(node, node.activity)
|
|
1757
1992
|
return node
|
|
1758
1993
|
|
|
1994
|
+
|
|
1759
1995
|
def get_diagnostic_node(code, display, severity, priority, activity):
|
|
1760
1996
|
node = TriccNodeCalculate(
|
|
1761
1997
|
id=generate_id("final." + code),
|
|
@@ -1764,51 +2000,48 @@ def get_diagnostic_node(code, display, severity, priority, activity):
|
|
|
1764
2000
|
activity=activity,
|
|
1765
2001
|
group=activity,
|
|
1766
2002
|
priority=priority,
|
|
1767
|
-
expression_reference=or_join(
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
TriccOperator.SELECTED,
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
])
|
|
2003
|
+
expression_reference=or_join(
|
|
2004
|
+
[
|
|
2005
|
+
TriccOperation(TriccOperator.ISTRUE, [TriccReference("pre_final." + code)]),
|
|
2006
|
+
TriccOperation(TriccOperator.SELECTED, [TriccReference("tricc.manual.diag"), TriccStatic(code)]),
|
|
2007
|
+
]
|
|
2008
|
+
),
|
|
1774
2009
|
)
|
|
1775
2010
|
return node
|
|
1776
2011
|
|
|
2012
|
+
|
|
1777
2013
|
def get_select_accept_reject_options(node, group):
|
|
1778
2014
|
yes = TriccNodeSelectOption(
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
2015
|
+
id=generate_id(f"accept{node.id}"),
|
|
2016
|
+
name=f"{TRICC_TRUE_VALUE}",
|
|
2017
|
+
label="Accept",
|
|
2018
|
+
select=node,
|
|
2019
|
+
group=group,
|
|
2020
|
+
list_name=node.list_name,
|
|
2021
|
+
)
|
|
1786
2022
|
no = TriccNodeSelectOption(
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
return {0:yes, 1:no
|
|
2023
|
+
id=generate_id(f"reject{node.id}"),
|
|
2024
|
+
name=f"{TRICC_FALSE_VALUE}",
|
|
2025
|
+
label="Reject",
|
|
2026
|
+
select=node,
|
|
2027
|
+
group=group,
|
|
2028
|
+
list_name=node.list_name,
|
|
2029
|
+
)
|
|
2030
|
+
return {0: yes, 1: no}
|
|
2031
|
+
|
|
1795
2032
|
|
|
1796
2033
|
def create_determine_diagnosis_activity(diags):
|
|
1797
2034
|
start = TriccNodeMainStart(
|
|
1798
|
-
id=generate_id(
|
|
1799
|
-
name="start.determine-diagnosis",
|
|
1800
|
-
process='determine-diagnosis'
|
|
2035
|
+
id=generate_id("start.determine-diagnosis"), name="start.determine-diagnosis", process="determine-diagnosis"
|
|
1801
2036
|
)
|
|
1802
2037
|
|
|
1803
|
-
|
|
1804
2038
|
activity = TriccNodeActivity(
|
|
1805
|
-
id=generate_id(
|
|
1806
|
-
name=
|
|
1807
|
-
label=
|
|
2039
|
+
id=generate_id("activity-determine-diagnosis"),
|
|
2040
|
+
name="determine-diagnosis",
|
|
2041
|
+
label="Classifications",
|
|
1808
2042
|
root=start,
|
|
1809
2043
|
)
|
|
1810
2044
|
|
|
1811
|
-
|
|
1812
2045
|
start.activity = activity
|
|
1813
2046
|
start.group = activity
|
|
1814
2047
|
diags_conf = []
|
|
@@ -1818,17 +2051,16 @@ def create_determine_diagnosis_activity(diags):
|
|
|
1818
2051
|
activity=activity,
|
|
1819
2052
|
group=activity,
|
|
1820
2053
|
)
|
|
1821
|
-
activity.nodes[end.id]=end
|
|
1822
|
-
|
|
2054
|
+
activity.nodes[end.id] = end
|
|
2055
|
+
|
|
1823
2056
|
f = TriccNodeSelectMultiple(
|
|
1824
2057
|
name="tricc.manual.diag",
|
|
1825
|
-
label="Add
|
|
1826
|
-
list_name=
|
|
2058
|
+
label="Add classifications",
|
|
2059
|
+
list_name="manual_diag",
|
|
1827
2060
|
id=generate_id("tricc.manual.diag"),
|
|
1828
2061
|
activity=activity,
|
|
1829
2062
|
group=activity,
|
|
1830
2063
|
required=TriccStatic(False),
|
|
1831
|
-
|
|
1832
2064
|
)
|
|
1833
2065
|
for proposed in diags:
|
|
1834
2066
|
d = get_accept_diagnostic_node(proposed.name, proposed.label, proposed.severity, proposed.priority, activity)
|
|
@@ -1837,14 +2069,12 @@ def create_determine_diagnosis_activity(diags):
|
|
|
1837
2069
|
r = TriccNodeRhombus(
|
|
1838
2070
|
path=start,
|
|
1839
2071
|
id=generate_id(f"proposed-rhombus{proposed.id}"),
|
|
1840
|
-
expression_reference=TriccOperation(
|
|
1841
|
-
TriccOperator.ISTRUE,
|
|
1842
|
-
[TriccReference(proposed.name)]
|
|
1843
|
-
),
|
|
2072
|
+
expression_reference=TriccOperation(TriccOperator.ISTRUE, [TriccReference(proposed.name)]),
|
|
1844
2073
|
reference=[TriccReference(proposed.name)],
|
|
1845
2074
|
activity=activity,
|
|
1846
2075
|
priority=proposed.priority,
|
|
1847
|
-
group=activity
|
|
2076
|
+
group=activity,
|
|
2077
|
+
)
|
|
1848
2078
|
activity.calculates.append(r)
|
|
1849
2079
|
activity.calculates.append(c)
|
|
1850
2080
|
set_prev_next_node(r, d, edge_only=False)
|
|
@@ -1852,11 +2082,11 @@ def create_determine_diagnosis_activity(diags):
|
|
|
1852
2082
|
wait2 = get_activity_wait([activity.root], diags_conf, [f], edge_only=False)
|
|
1853
2083
|
activity.nodes[d.options[0].id] = d.options[0]
|
|
1854
2084
|
activity.nodes[d.options[1].id] = d.options[1]
|
|
1855
|
-
activity.nodes[d.id]=d
|
|
1856
|
-
activity.nodes[r.id]=r
|
|
1857
|
-
activity.nodes[c.id]=c
|
|
1858
|
-
activity.nodes[f.id]=f
|
|
1859
|
-
activity.nodes[wait2.id]=wait2
|
|
2085
|
+
activity.nodes[d.id] = d
|
|
2086
|
+
activity.nodes[r.id] = r
|
|
2087
|
+
activity.nodes[c.id] = c
|
|
2088
|
+
activity.nodes[f.id] = f
|
|
2089
|
+
activity.nodes[wait2.id] = wait2
|
|
1860
2090
|
# fallback
|
|
1861
2091
|
|
|
1862
2092
|
options = [
|
|
@@ -1866,220 +2096,182 @@ def create_determine_diagnosis_activity(diags):
|
|
|
1866
2096
|
label=d.label,
|
|
1867
2097
|
list_name=f.list_name,
|
|
1868
2098
|
relevance=d.activity.applicability,
|
|
1869
|
-
select=f
|
|
1870
|
-
)
|
|
2099
|
+
select=f,
|
|
2100
|
+
)
|
|
2101
|
+
for d in diags
|
|
1871
2102
|
]
|
|
1872
|
-
f.options=dict(zip(range(0, len(options)), options))
|
|
1873
|
-
activity.nodes[f.id]=f
|
|
2103
|
+
f.options = dict(zip(range(0, len(options)), options))
|
|
2104
|
+
activity.nodes[f.id] = f
|
|
1874
2105
|
set_prev_next_node(f, end, edge_only=False)
|
|
1875
|
-
|
|
2106
|
+
|
|
1876
2107
|
return activity
|
|
1877
|
-
|
|
1878
|
-
|
|
2108
|
+
|
|
2109
|
+
|
|
2110
|
+
def get_prev_node_expression(node, processed_nodes, get_overall_exp=False, excluded_name=None, process=None):
|
|
1879
2111
|
expression = None
|
|
1880
2112
|
if node is None:
|
|
1881
2113
|
pass
|
|
1882
2114
|
# when getting the prev node, we calculate the
|
|
1883
|
-
if hasattr(node,
|
|
2115
|
+
if hasattr(node, "expression_inputs") and len(node.expression_inputs) > 0:
|
|
1884
2116
|
expression_inputs = node.expression_inputs
|
|
1885
2117
|
expression_inputs = clean_or_list(expression_inputs)
|
|
1886
2118
|
else:
|
|
1887
|
-
expression_inputs = []
|
|
2119
|
+
expression_inputs = []
|
|
1888
2120
|
prev_activities = {}
|
|
1889
2121
|
for prev_node in node.prev_nodes:
|
|
1890
2122
|
if prev_node.activity.id not in prev_activities:
|
|
1891
|
-
prev_activities[prev_node.activity.id]=[]
|
|
2123
|
+
prev_activities[prev_node.activity.id] = []
|
|
1892
2124
|
prev_activities[prev_node.activity.id].append(prev_node)
|
|
1893
|
-
|
|
2125
|
+
|
|
1894
2126
|
for act_id in prev_activities:
|
|
1895
2127
|
act_expression_inputs = []
|
|
1896
2128
|
for prev_node in prev_activities[act_id]:
|
|
1897
|
-
if
|
|
1898
|
-
|
|
2129
|
+
if (
|
|
2130
|
+
excluded_name is None
|
|
2131
|
+
or prev_node != excluded_name
|
|
2132
|
+
or (
|
|
2133
|
+
# or isinstance(prev_node, TriccNodeActivityEnd):
|
|
2134
|
+
isinstance(excluded_name, str)
|
|
2135
|
+
and hasattr(prev_node, "name")
|
|
2136
|
+
and prev_node.name != excluded_name
|
|
2137
|
+
)
|
|
2138
|
+
):
|
|
1899
2139
|
# the rhombus should calculate only reference
|
|
1900
2140
|
sub = get_node_expression(
|
|
1901
2141
|
prev_node,
|
|
1902
2142
|
processed_nodes=processed_nodes,
|
|
1903
2143
|
get_overall_exp=get_overall_exp,
|
|
1904
2144
|
is_prev=True,
|
|
1905
|
-
process=process
|
|
1906
|
-
|
|
1907
|
-
|
|
2145
|
+
process=process,
|
|
2146
|
+
)
|
|
2147
|
+
if isinstance(node, TriccNodeActivity) or get_overall_exp:
|
|
2148
|
+
add_sub_expression(act_expression_inputs, sub)
|
|
1908
2149
|
else:
|
|
1909
|
-
add_sub_expression(expression_inputs, sub
|
|
1910
|
-
|
|
2150
|
+
add_sub_expression(expression_inputs, sub)
|
|
2151
|
+
|
|
1911
2152
|
if act_expression_inputs:
|
|
1912
2153
|
act_sub = or_join(act_expression_inputs)
|
|
1913
|
-
if act_sub == TriccStatic(True):
|
|
1914
|
-
|
|
2154
|
+
if act_sub == TriccStatic(True):
|
|
2155
|
+
act_sub = get_node_expression(
|
|
1915
2156
|
prev_node.activity,
|
|
1916
2157
|
processed_nodes=processed_nodes,
|
|
1917
2158
|
get_overall_exp=True,
|
|
1918
2159
|
is_prev=True,
|
|
1919
2160
|
negate=False,
|
|
1920
|
-
process=process
|
|
2161
|
+
process=process,
|
|
1921
2162
|
)
|
|
1922
|
-
add_sub_expression(expression_inputs, act_sub
|
|
2163
|
+
add_sub_expression(expression_inputs, act_sub)
|
|
1923
2164
|
# avoid void is there is not conditions to avoid looping too much itme
|
|
1924
2165
|
# expression_inputs = clean_or_list(
|
|
1925
2166
|
# [
|
|
1926
|
-
# get_tricc_operation_operand(e)
|
|
1927
|
-
# if isinstance(expression, TriccOperation)
|
|
1928
|
-
# else e
|
|
2167
|
+
# get_tricc_operation_operand(e)
|
|
2168
|
+
# if isinstance(expression, TriccOperation)
|
|
2169
|
+
# else e
|
|
1929
2170
|
# for e in expression_inputs])
|
|
1930
|
-
|
|
2171
|
+
|
|
1931
2172
|
if expression_inputs:
|
|
1932
|
-
expression =
|
|
1933
|
-
expression_inputs
|
|
1934
|
-
)
|
|
2173
|
+
expression = or_join(expression_inputs)
|
|
1935
2174
|
# if isinstance(node, TriccNodeExclusive):
|
|
1936
2175
|
# expression = TRICC_NEGATE.format(expression)
|
|
1937
|
-
# only used for activityStart
|
|
2176
|
+
# only used for activityStart
|
|
1938
2177
|
else:
|
|
1939
2178
|
expression = TriccStatic(True)
|
|
1940
2179
|
return expression
|
|
1941
2180
|
|
|
1942
|
-
|
|
2181
|
+
|
|
2182
|
+
def get_activity_end_terms(node, processed_nodes, process=None):
|
|
1943
2183
|
end_nodes = node.get_end_nodes()
|
|
1944
2184
|
expression_inputs = []
|
|
1945
2185
|
for end_node in end_nodes:
|
|
1946
2186
|
add_sub_expression(
|
|
1947
2187
|
expression_inputs,
|
|
1948
2188
|
get_node_expression(
|
|
1949
|
-
end_node,
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
2189
|
+
end_node, processed_nodes=processed_nodes, get_overall_exp=False, is_prev=True, process=process
|
|
2190
|
+
),
|
|
2191
|
+
)
|
|
2192
|
+
|
|
2193
|
+
return or_join(expression_inputs)
|
|
1954
2194
|
|
|
1955
|
-
return or_join(expression_inputs)
|
|
1956
2195
|
|
|
1957
|
-
def get_count_terms(
|
|
2196
|
+
def get_count_terms(node, processed_nodes, get_overall_exp, negate=False, process=None):
|
|
1958
2197
|
terms = []
|
|
1959
|
-
|
|
2198
|
+
|
|
1960
2199
|
for prev_node in node.prev_nodes:
|
|
1961
|
-
term = get_count_terms_details(
|
|
2200
|
+
term = get_count_terms_details(prev_node, processed_nodes, get_overall_exp, negate, process)
|
|
1962
2201
|
if term:
|
|
1963
2202
|
terms.append(term)
|
|
1964
2203
|
if len(terms) == 1:
|
|
1965
|
-
return TriccOperation(
|
|
1966
|
-
TriccOperator.CAST_NUMBER,
|
|
1967
|
-
[terms[0]]
|
|
1968
|
-
)
|
|
2204
|
+
return TriccOperation(TriccOperator.CAST_NUMBER, [terms[0]])
|
|
1969
2205
|
elif len(terms) > 0:
|
|
1970
|
-
return TriccOperation(
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
TriccOperator.SELECTED,
|
|
1983
|
-
[
|
|
1984
|
-
prev_node,
|
|
1985
|
-
TriccStatic('opt_none')
|
|
1986
|
-
]
|
|
1987
|
-
)
|
|
1988
|
-
if isinstance(prev_node, TriccNodeSelectYesNo):
|
|
2206
|
+
return TriccOperation(TriccOperator.PLUS, [TriccOperation(TriccOperator.CAST_NUMBER, [term]) for term in terms])
|
|
2207
|
+
|
|
2208
|
+
|
|
2209
|
+
def get_count_terms_details(prev_node, processed_nodes, get_overall_exp, negate=False, process=None):
|
|
2210
|
+
operation_none = TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic("opt_none")])
|
|
2211
|
+
if isinstance(prev_node, TriccNodeSelectYesNo):
|
|
2212
|
+
return TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic(prev_node.options[0].name)])
|
|
2213
|
+
elif issubclass(prev_node.__class__, TriccNodeSelect):
|
|
2214
|
+
if negate:
|
|
2215
|
+
return
|
|
2216
|
+
# terms.append(TRICC_SELECT_MULTIPLE_CALC_NONE_EXPRESSION.format(get_export_name(prev_node)))
|
|
2217
|
+
else:
|
|
1989
2218
|
return TriccOperation(
|
|
1990
|
-
TriccOperator.
|
|
2219
|
+
TriccOperator.MINUS,
|
|
1991
2220
|
[
|
|
1992
|
-
prev_node,
|
|
1993
|
-
|
|
1994
|
-
]
|
|
2221
|
+
TriccOperation(TriccOperator.COUNT, [prev_node]),
|
|
2222
|
+
TriccOperation(TriccOperator.CAST_NUMBER, [operation_none]),
|
|
2223
|
+
],
|
|
1995
2224
|
)
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
TriccOperation(
|
|
2005
|
-
TriccOperator.NATIVE,
|
|
2006
|
-
[
|
|
2007
|
-
'count-selected',
|
|
2008
|
-
prev_node
|
|
2009
|
-
]
|
|
2010
|
-
),TriccOperation(
|
|
2011
|
-
TriccOperator.CAST_NUMBER,
|
|
2012
|
-
[
|
|
2013
|
-
operation_none
|
|
2014
|
-
]
|
|
2015
|
-
)
|
|
2016
|
-
])
|
|
2017
|
-
#terms.append(TRICC_SELECT_MULTIPLE_CALC_EXPRESSION.format(get_export_name(prev_node)))
|
|
2018
|
-
elif isinstance(prev_node, (TriccNodeSelectNotAvailable)):
|
|
2225
|
+
# terms.append(TRICC_SELECT_MULTIPLE_CALC_EXPRESSION.format(get_export_name(prev_node)))
|
|
2226
|
+
elif isinstance(prev_node, (TriccNodeSelectNotAvailable)):
|
|
2227
|
+
return TriccOperation(TriccOperator.SELECTED, [prev_node, TriccStatic("1")])
|
|
2228
|
+
# terms.append(TRICC_SELECTED_EXPRESSION.format(get_export_name(prev_node), '1'))
|
|
2229
|
+
elif isinstance(prev_node, TriccNodeSelectOption):
|
|
2230
|
+
return get_selected_option_expression(prev_node, negate)
|
|
2231
|
+
else:
|
|
2232
|
+
if negate:
|
|
2019
2233
|
return TriccOperation(
|
|
2020
|
-
TriccOperator.
|
|
2234
|
+
TriccOperator.CAST_NUMBER,
|
|
2021
2235
|
[
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
]
|
|
2025
|
-
)
|
|
2026
|
-
#terms.append(TRICC_SELECTED_EXPRESSION.format(get_export_name(prev_node), '1'))
|
|
2027
|
-
elif isinstance(prev_node, TriccNodeSelectOption):
|
|
2028
|
-
return get_selected_option_expression(prev_node, negate)
|
|
2029
|
-
else:
|
|
2030
|
-
if negate:
|
|
2031
|
-
return TriccOperation(
|
|
2032
|
-
TriccOperator.CAST_NUMBER,
|
|
2236
|
+
TriccOperation(
|
|
2237
|
+
TriccOperator.NATIVE,
|
|
2033
2238
|
[
|
|
2034
2239
|
TriccOperation(
|
|
2035
|
-
TriccOperator.
|
|
2240
|
+
TriccOperator.CAST_NUMBER,
|
|
2036
2241
|
[
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
]
|
|
2049
|
-
)
|
|
2050
|
-
]
|
|
2242
|
+
get_node_expression(
|
|
2243
|
+
prev_node,
|
|
2244
|
+
processed_nodes=processed_nodes,
|
|
2245
|
+
get_overall_exp=True,
|
|
2246
|
+
is_prev=True,
|
|
2247
|
+
process=process,
|
|
2248
|
+
)
|
|
2249
|
+
],
|
|
2250
|
+
),
|
|
2251
|
+
TriccStatic("0"),
|
|
2252
|
+
],
|
|
2051
2253
|
)
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
is_prev=True,
|
|
2062
|
-
process=process)
|
|
2063
|
-
]
|
|
2254
|
+
],
|
|
2255
|
+
)
|
|
2256
|
+
|
|
2257
|
+
else:
|
|
2258
|
+
return TriccOperation(
|
|
2259
|
+
TriccOperator.CAST_NUMBER,
|
|
2260
|
+
[
|
|
2261
|
+
get_node_expression(
|
|
2262
|
+
prev_node, processed_nodes=processed_nodes, get_overall_exp=True, is_prev=True, process=process
|
|
2064
2263
|
)
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2264
|
+
],
|
|
2265
|
+
)
|
|
2266
|
+
|
|
2267
|
+
|
|
2268
|
+
def get_add_terms(node, processed_nodes, get_overall_exp=False, negate=False, process=None):
|
|
2069
2269
|
if negate:
|
|
2070
2270
|
logger.warning("negate not supported for Add node {}".format(node.get_name()))
|
|
2071
2271
|
terms = []
|
|
2072
2272
|
for prev_node in node.prev_nodes:
|
|
2073
2273
|
if issubclass(prev_node, TriccNodeNumber) or isinstance(node, TriccNodeCount):
|
|
2074
|
-
terms.append(
|
|
2075
|
-
TriccOperation(
|
|
2076
|
-
TriccOperator.COALESCE,
|
|
2077
|
-
[
|
|
2078
|
-
prev_node,
|
|
2079
|
-
TriccStatic(0)
|
|
2080
|
-
]
|
|
2081
|
-
)
|
|
2082
|
-
)
|
|
2274
|
+
terms.append(TriccOperation(TriccOperator.COALESCE, [prev_node, TriccStatic(0)]))
|
|
2083
2275
|
else:
|
|
2084
2276
|
terms.append(
|
|
2085
2277
|
TriccOperation(
|
|
@@ -2089,33 +2281,28 @@ def get_add_terms( node, processed_nodes, get_overall_exp=False, negate=False, p
|
|
|
2089
2281
|
prev_node,
|
|
2090
2282
|
processed_nodes=processed_nodes,
|
|
2091
2283
|
get_overall_exp=True,
|
|
2092
|
-
is_prev=True,
|
|
2093
|
-
process=process
|
|
2094
|
-
|
|
2284
|
+
is_prev=True,
|
|
2285
|
+
process=process,
|
|
2286
|
+
)
|
|
2287
|
+
],
|
|
2095
2288
|
)
|
|
2096
2289
|
)
|
|
2097
2290
|
if len(terms) > 0:
|
|
2098
2291
|
operation = terms[0]
|
|
2099
2292
|
if len(terms) > 1:
|
|
2100
2293
|
for term in terms[1:]:
|
|
2101
|
-
operation = TriccOperation(
|
|
2102
|
-
TriccOperator.ADD,
|
|
2103
|
-
[
|
|
2104
|
-
operation,
|
|
2105
|
-
term
|
|
2106
|
-
]
|
|
2107
|
-
)
|
|
2294
|
+
operation = TriccOperation(TriccOperator.ADD, [operation, term])
|
|
2108
2295
|
return operation
|
|
2109
|
-
|
|
2110
|
-
|
|
2296
|
+
|
|
2297
|
+
|
|
2298
|
+
def get_rhombus_terms(node, processed_nodes, get_overall_exp=False, negate=False, process=None):
|
|
2111
2299
|
expression = None
|
|
2112
2300
|
left_term = None
|
|
2113
|
-
operator = None
|
|
2114
2301
|
if node.reference is not None:
|
|
2115
2302
|
if isinstance(node.reference, set):
|
|
2116
2303
|
node.reference = list(node.reference)
|
|
2117
2304
|
# calcualte the expression only for select muzltiple and fake calculate
|
|
2118
|
-
if
|
|
2305
|
+
if issubclass(node.reference.__class__, (list, OrderedSet)):
|
|
2119
2306
|
if node.expression_reference is None and len(node.reference) == 1:
|
|
2120
2307
|
ref = node.reference[0]
|
|
2121
2308
|
if issubclass(ref.__class__, TriccNodeBaseModel):
|
|
@@ -2123,81 +2310,79 @@ def get_rhombus_terms( node, processed_nodes, get_overall_exp=False, negate=Fals
|
|
|
2123
2310
|
expression = get_activity_end_terms(ref, processed_nodes, process=process)
|
|
2124
2311
|
elif issubclass(ref.__class__, TriccNodeFakeCalculateBase):
|
|
2125
2312
|
expression = get_node_expression(
|
|
2126
|
-
ref,
|
|
2127
|
-
processed_nodes=processed_nodes,
|
|
2128
|
-
get_overall_exp=True,
|
|
2129
|
-
is_prev=True,
|
|
2130
|
-
process=process
|
|
2313
|
+
ref, processed_nodes=processed_nodes, get_overall_exp=True, is_prev=True, process=process
|
|
2131
2314
|
)
|
|
2132
2315
|
else:
|
|
2133
2316
|
expression = ref
|
|
2134
2317
|
elif issubclass(ref.__class__, TriccReference):
|
|
2135
2318
|
expression = ref
|
|
2136
2319
|
else:
|
|
2137
|
-
logger.critical(
|
|
2138
|
-
|
|
2320
|
+
logger.critical(
|
|
2321
|
+
"reference {0} was not found in the previous nodes of node {1}".format(
|
|
2322
|
+
node.reference, node.get_name()
|
|
2323
|
+
)
|
|
2324
|
+
)
|
|
2139
2325
|
exit(1)
|
|
2140
|
-
elif node.expression_reference is not None and node.expression_reference !=
|
|
2326
|
+
elif node.expression_reference is not None and node.expression_reference != "":
|
|
2141
2327
|
if isinstance(node.expression_reference, (TriccOperation, TriccReference, TriccStatic)):
|
|
2142
2328
|
return node.expression_reference
|
|
2143
2329
|
elif isinstance(node.expression_reference, str):
|
|
2144
2330
|
expression = node.expression_reference.format(*get_list_names(node.reference))
|
|
2145
2331
|
else:
|
|
2146
|
-
logger.critical(
|
|
2332
|
+
logger.critical(
|
|
2333
|
+
"expression_reference {0} unsuported type {1}".format(
|
|
2334
|
+
node.expression_reference, node.expression_reference.__class__.__name__
|
|
2335
|
+
)
|
|
2336
|
+
)
|
|
2147
2337
|
exit(1)
|
|
2148
2338
|
|
|
2149
2339
|
else:
|
|
2150
2340
|
logger.warning("missing expression for node {}".format(node.get_name()))
|
|
2151
2341
|
else:
|
|
2152
|
-
logger.critical(
|
|
2342
|
+
logger.critical("reference {0} is not a list {1}".format(node.reference, node.get_name()))
|
|
2153
2343
|
exit(1)
|
|
2154
2344
|
else:
|
|
2155
|
-
logger.critical(
|
|
2345
|
+
logger.critical("reference empty for Rhombis {}".format(node.get_name()))
|
|
2156
2346
|
exit(1)
|
|
2157
2347
|
|
|
2158
2348
|
if expression is not None:
|
|
2159
2349
|
if isinstance(expression, (TriccOperation, TriccStatic)):
|
|
2160
2350
|
return expression
|
|
2161
|
-
elif issubclass(expression.__class__
|
|
2351
|
+
elif issubclass(expression.__class__, TriccNodeCalculateBase):
|
|
2162
2352
|
return TriccOperation(
|
|
2163
2353
|
TriccOperator.CAST_NUMBER,
|
|
2164
2354
|
[
|
|
2165
2355
|
get_node_expression(
|
|
2166
|
-
expression,
|
|
2167
|
-
processed_nodes=processed_nodes,
|
|
2168
|
-
get_overall_exp=True,
|
|
2169
|
-
is_prev=True,
|
|
2170
|
-
process=process
|
|
2356
|
+
expression, processed_nodes=processed_nodes, get_overall_exp=True, is_prev=True, process=process
|
|
2171
2357
|
)
|
|
2172
|
-
]
|
|
2173
|
-
elif issubclass(expression.__class__ , (TriccOperation) ):
|
|
2174
|
-
return expression
|
|
2175
|
-
elif issubclass(expression.__class__ , (TriccNodeDisplayModel, TriccReference)):
|
|
2176
|
-
return TriccOperation(
|
|
2177
|
-
TriccOperator.ISTRUE,
|
|
2178
|
-
[
|
|
2179
|
-
expression
|
|
2180
|
-
]
|
|
2358
|
+
],
|
|
2181
2359
|
)
|
|
2360
|
+
elif issubclass(expression.__class__, (TriccOperation)):
|
|
2361
|
+
return expression
|
|
2362
|
+
elif issubclass(expression.__class__, (TriccNodeDisplayModel, TriccReference)):
|
|
2363
|
+
return TriccOperation(TriccOperator.ISTRUE, [expression])
|
|
2182
2364
|
else:
|
|
2183
2365
|
if left_term is not None and re.search(" (+)|(-)|(or)|(and) ", expression):
|
|
2184
2366
|
expression = "({0}){1}".format(expression, left_term)
|
|
2185
2367
|
else:
|
|
2186
2368
|
expression = "{0}{1}".format(expression, left_term)
|
|
2187
2369
|
else:
|
|
2188
|
-
logger.critical(
|
|
2189
|
-
node.get_name(),
|
|
2190
|
-
|
|
2191
|
-
))
|
|
2370
|
+
logger.critical(
|
|
2371
|
+
"Rhombus reference was not found for node {}, reference {}".format(node.get_name(), node.reference)
|
|
2372
|
+
)
|
|
2192
2373
|
exit(1)
|
|
2193
2374
|
|
|
2194
2375
|
return expression
|
|
2376
|
+
|
|
2377
|
+
|
|
2195
2378
|
# function that generate the calculation terms return by calculate node
|
|
2196
2379
|
# @param node calculate node to assess
|
|
2197
2380
|
# @param processed_nodes list of node already processed, importnat because only processed node could be use
|
|
2198
2381
|
# @param get_overall_exp used when this funciton is called in the evaluation of another calculate
|
|
2199
2382
|
# @param negate use to retriece the negation of a calculation
|
|
2200
|
-
|
|
2383
|
+
|
|
2384
|
+
|
|
2385
|
+
def get_calculation_terms(node, processed_nodes, get_overall_exp=False, negate=False, process=None):
|
|
2201
2386
|
# returns something directly only if the negate is managed
|
|
2202
2387
|
expression = None
|
|
2203
2388
|
if isinstance(node, TriccNodeAdd):
|
|
@@ -2206,22 +2391,25 @@ def get_calculation_terms( node, processed_nodes, get_overall_exp=False, negate=
|
|
|
2206
2391
|
return get_count_terms(node, False, negate, process=process)
|
|
2207
2392
|
elif isinstance(node, TriccNodeRhombus):
|
|
2208
2393
|
return get_rhombus_terms(
|
|
2209
|
-
node,
|
|
2210
|
-
processed_nodes=processed_nodes,
|
|
2211
|
-
get_overall_exp=False,
|
|
2212
|
-
negate=negate,
|
|
2213
|
-
process=process
|
|
2394
|
+
node, processed_nodes=processed_nodes, get_overall_exp=False, negate=negate, process=process
|
|
2214
2395
|
)
|
|
2215
|
-
elif isinstance(node, (
|
|
2396
|
+
elif isinstance(node, (TriccNodeWait)):
|
|
2216
2397
|
# just use to force order of question
|
|
2217
2398
|
expression = None
|
|
2218
|
-
# in case of calulate expression evaluation, we need to get the relevance of the activity
|
|
2399
|
+
# in case of calulate expression evaluation, we need to get the relevance of the activity
|
|
2219
2400
|
# because calculate are not the the activity group
|
|
2220
2401
|
elif isinstance(node, (TriccNodeActivityStart)) and get_overall_exp:
|
|
2221
|
-
expression =
|
|
2402
|
+
expression = get_prev_node_expression(
|
|
2403
|
+
node.activity,
|
|
2404
|
+
processed_nodes=processed_nodes,
|
|
2405
|
+
get_overall_exp=get_overall_exp,
|
|
2406
|
+
negate=negate,
|
|
2407
|
+
process=process,
|
|
2408
|
+
)
|
|
2222
2409
|
elif isinstance(node, (TriccNodeActivityStart, TriccNodeActivityEnd)):
|
|
2223
2410
|
# the group have the relevance for the activity, not needed to replicate it
|
|
2224
|
-
|
|
2411
|
+
# return get_prev_node_expression(node.activity, processed_nodes, get_overall_exp=False, excluded_name=None)
|
|
2412
|
+
expression = None
|
|
2225
2413
|
elif isinstance(node, TriccNodeExclusive):
|
|
2226
2414
|
if len(node.prev_nodes) == 1:
|
|
2227
2415
|
iterator = iter(node.prev_nodes)
|
|
@@ -2236,8 +2424,8 @@ def get_calculation_terms( node, processed_nodes, get_overall_exp=False, negate=
|
|
|
2236
2424
|
get_overall_exp=True,
|
|
2237
2425
|
is_prev=True,
|
|
2238
2426
|
negate=True,
|
|
2239
|
-
process=process
|
|
2240
|
-
|
|
2427
|
+
process=process,
|
|
2428
|
+
)
|
|
2241
2429
|
elif isinstance(node_to_negate, TriccNodeActivity):
|
|
2242
2430
|
return get_node_expression(
|
|
2243
2431
|
node_to_negate,
|
|
@@ -2245,36 +2433,45 @@ def get_calculation_terms( node, processed_nodes, get_overall_exp=False, negate=
|
|
|
2245
2433
|
get_overall_exp=True,
|
|
2246
2434
|
is_prev=True,
|
|
2247
2435
|
negate=True,
|
|
2248
|
-
process=process
|
|
2436
|
+
process=process,
|
|
2249
2437
|
)
|
|
2250
2438
|
else:
|
|
2251
|
-
logger.critical(
|
|
2439
|
+
logger.critical(
|
|
2440
|
+
f"exclusive node {node.get_name()}\
|
|
2252
2441
|
does not depend of a calculate but on\
|
|
2253
|
-
{node_to_negate.__class__}::{node_to_negate.get_name()}"
|
|
2442
|
+
{node_to_negate.__class__}::{node_to_negate.get_name()}"
|
|
2443
|
+
)
|
|
2254
2444
|
|
|
2255
2445
|
else:
|
|
2256
2446
|
logger.critical("exclusive node {} has no ou too much parent".format(node.get_name()))
|
|
2257
|
-
|
|
2447
|
+
|
|
2258
2448
|
if isinstance(node.expression_reference, (TriccOperation, TriccStatic)):
|
|
2259
2449
|
expression = node.expression_reference
|
|
2260
|
-
elif node.reference is not None and node.expression_reference is not None
|
|
2261
|
-
expression = get_prev_node_expression(
|
|
2450
|
+
elif node.reference is not None and node.expression_reference is not None:
|
|
2451
|
+
expression = get_prev_node_expression(
|
|
2452
|
+
node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
|
|
2453
|
+
)
|
|
2262
2454
|
ref_expression = node.expression_reference.format(*[get_export_name(ref) for ref in node.reference])
|
|
2263
|
-
if expression is not None and expression !=
|
|
2264
|
-
expression =
|
|
2455
|
+
if expression is not None and expression != "":
|
|
2456
|
+
expression = and_join([expression, ref_expression])
|
|
2265
2457
|
else:
|
|
2266
2458
|
expression = ref_expression
|
|
2267
2459
|
elif expression is None:
|
|
2268
|
-
expression =
|
|
2269
|
-
|
|
2460
|
+
expression = get_prev_node_expression(
|
|
2461
|
+
node, processed_nodes=processed_nodes, get_overall_exp=get_overall_exp, process=process
|
|
2462
|
+
)
|
|
2463
|
+
|
|
2270
2464
|
# manage the generic negation
|
|
2271
2465
|
if negate:
|
|
2272
|
-
|
|
2466
|
+
|
|
2273
2467
|
return negate_term(expression)
|
|
2274
2468
|
else:
|
|
2275
2469
|
return expression
|
|
2276
|
-
|
|
2470
|
+
|
|
2471
|
+
|
|
2277
2472
|
# Function that add element to array is not None or ''
|
|
2473
|
+
|
|
2474
|
+
|
|
2278
2475
|
def add_sub_expression(array, sub):
|
|
2279
2476
|
if isinstance(sub, (TriccOperation, TriccStatic)):
|
|
2280
2477
|
not_sub = negate_term(sub)
|
|
@@ -2288,62 +2485,146 @@ def add_sub_expression(array, sub):
|
|
|
2288
2485
|
pass
|
|
2289
2486
|
# elif sub is None:
|
|
2290
2487
|
# array.append(TriccStatic(True))
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
2488
|
|
|
2294
2489
|
# function that negate terms
|
|
2490
|
+
|
|
2491
|
+
|
|
2295
2492
|
# @param expression to negate
|
|
2296
|
-
def negate_term(expression):
|
|
2297
|
-
|
|
2298
|
-
return not_clean(expression)
|
|
2299
2493
|
|
|
2300
2494
|
|
|
2495
|
+
def negate_term(expression):
|
|
2496
|
+
|
|
2497
|
+
return not_clean(expression)
|
|
2301
2498
|
|
|
2302
2499
|
|
|
2303
2500
|
# if the node is "required" then we can take the fact that it has value for the next elements
|
|
2304
2501
|
def get_required_node_expression(node):
|
|
2305
|
-
return TriccOperation(
|
|
2306
|
-
operator=TriccOperator.EXISTS,
|
|
2307
|
-
reference=[
|
|
2308
|
-
node
|
|
2309
|
-
]
|
|
2310
|
-
)
|
|
2502
|
+
return TriccOperation(operator=TriccOperator.EXISTS, reference=[node])
|
|
2311
2503
|
|
|
2312
2504
|
|
|
2313
2505
|
# Get a selected option
|
|
2314
2506
|
def get_selected_option_expression(option_node, negate):
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2507
|
+
if isinstance(option_node.select, TriccNodeSelectOne):
|
|
2508
|
+
return get_selected_option_expression_single(option_node, negate)
|
|
2509
|
+
else:
|
|
2510
|
+
return get_selected_option_expression_multiple(option_node, negate)
|
|
2511
|
+
|
|
2512
|
+
|
|
2513
|
+
def get_selected_option_expression_single(option_node, negate):
|
|
2514
|
+
|
|
2515
|
+
if not negate:
|
|
2516
|
+
return TriccOperation(TriccOperator.EQUAL, [option_node.select, option_node])
|
|
2517
|
+
|
|
2518
|
+
|
|
2519
|
+
def get_selected_option_expression_multiple(option_node, negate):
|
|
2520
|
+
|
|
2521
|
+
selected = TriccOperation(TriccOperator.SELECTED, [option_node.select, option_node])
|
|
2522
|
+
|
|
2324
2523
|
if negate:
|
|
2325
2524
|
return TriccOperation(
|
|
2326
2525
|
operator=TriccOperator.AND,
|
|
2327
2526
|
resource=[
|
|
2328
|
-
TriccOperation(
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
),TriccOperation(
|
|
2334
|
-
operator=TriccOperator.NATIVE,
|
|
2335
|
-
resource=[
|
|
2336
|
-
'count-selected',
|
|
2337
|
-
option_node.select
|
|
2338
|
-
]
|
|
2339
|
-
)
|
|
2340
|
-
])
|
|
2341
|
-
|
|
2527
|
+
TriccOperation(operator=TriccOperator.NOT, resource=[selected]),
|
|
2528
|
+
TriccOperation(operator=TriccOperator.ISNOTNULL, resource=[option_node.select]),
|
|
2529
|
+
],
|
|
2530
|
+
)
|
|
2531
|
+
|
|
2342
2532
|
else:
|
|
2343
2533
|
return selected
|
|
2344
2534
|
|
|
2345
2535
|
|
|
2346
|
-
|
|
2536
|
+
def generate_calculate(node, processed_nodes, **kwargs):
|
|
2537
|
+
# For calculations, set calculate in questionOptions
|
|
2538
|
+
# Check if node is ready to be processed (similar to XLS form strategy)
|
|
2539
|
+
if not is_ready_to_process(node, processed_nodes, strict=True):
|
|
2540
|
+
return False
|
|
2541
|
+
|
|
2542
|
+
# Process references to ensure dependencies are handled
|
|
2543
|
+
if not process_reference(
|
|
2544
|
+
node, processed_nodes, {}, replace_reference=True, codesystems=kwargs.get("codesystems", None)
|
|
2545
|
+
):
|
|
2546
|
+
return False
|
|
2547
|
+
|
|
2548
|
+
if node not in processed_nodes:
|
|
2549
|
+
if kwargs.get("warn", True):
|
|
2550
|
+
logger.debug("generation of calculate for node {}".format(node.get_name()))
|
|
2551
|
+
if (
|
|
2552
|
+
hasattr(node, "expression")
|
|
2553
|
+
and (node.expression is None)
|
|
2554
|
+
and issubclass(node.__class__, TriccNodeCalculateBase)
|
|
2555
|
+
):
|
|
2556
|
+
node.expression = get_node_expressions(
|
|
2557
|
+
node, processed_nodes, process=kwargs.get("process", "main ")
|
|
2558
|
+
)
|
|
2559
|
+
# continue walk
|
|
2560
|
+
if issubclass(
|
|
2561
|
+
node.__class__,
|
|
2562
|
+
(
|
|
2563
|
+
TriccNodeDisplayModel,
|
|
2564
|
+
TriccNodeDisplayCalculateBase,
|
|
2565
|
+
TriccNodeEnd,
|
|
2566
|
+
),
|
|
2567
|
+
):
|
|
2568
|
+
set_last_version_false(node, processed_nodes)
|
|
2569
|
+
return True
|
|
2347
2570
|
|
|
2348
2571
|
|
|
2572
|
+
def generate_base(node, processed_nodes, **kwargs):
|
|
2573
|
+
# Generate question for OpenMRS O3 schema
|
|
2574
|
+
# Handle activity nodes by processing their inner content
|
|
2575
|
+
# Check if node is ready to be processed (similar to XLS form strategy)
|
|
2576
|
+
if not is_ready_to_process(node, processed_nodes, strict=False):
|
|
2577
|
+
return False
|
|
2349
2578
|
|
|
2579
|
+
# Process references to ensure dependencies are handled
|
|
2580
|
+
if not process_reference(
|
|
2581
|
+
node, processed_nodes, {}, replace_reference=False, codesystems=kwargs.get("codesystems", None)
|
|
2582
|
+
):
|
|
2583
|
+
return False
|
|
2584
|
+
if node not in processed_nodes:
|
|
2585
|
+
if issubclass(node.__class__, TriccRhombusMixIn) and isinstance(node.reference, str):
|
|
2586
|
+
logger.warning("node {} still using the reference string".format(node.get_name()))
|
|
2587
|
+
if issubclass(node.__class__, TriccNodeInputModel):
|
|
2588
|
+
# we don't overright if define in the diagram
|
|
2589
|
+
if node.constraint is None:
|
|
2590
|
+
if isinstance(node, TriccNodeSelectMultiple):
|
|
2591
|
+
node.constraint = or_join(
|
|
2592
|
+
[
|
|
2593
|
+
TriccOperation(
|
|
2594
|
+
TriccOperator.EQUAL,
|
|
2595
|
+
["$this", TriccStatic("opt_none")],
|
|
2596
|
+
),
|
|
2597
|
+
TriccOperation(
|
|
2598
|
+
TriccOperator.NOT,
|
|
2599
|
+
[
|
|
2600
|
+
TriccOperation(
|
|
2601
|
+
TriccOperator.SELECTED,
|
|
2602
|
+
["$this", TriccStatic("opt_none")],
|
|
2603
|
+
)
|
|
2604
|
+
],
|
|
2605
|
+
),
|
|
2606
|
+
]
|
|
2607
|
+
) # '.=\'opt_none\' or not(selected(.,\'opt_none\'))'
|
|
2608
|
+
node.constraint_message = "**None** cannot be selected together with choice."
|
|
2609
|
+
elif node.tricc_type in (
|
|
2610
|
+
TriccNodeType.integer,
|
|
2611
|
+
TriccNodeType.decimal,
|
|
2612
|
+
):
|
|
2613
|
+
constraints = []
|
|
2614
|
+
constraints_min = ""
|
|
2615
|
+
constraints_max = ""
|
|
2616
|
+
if node.min is not None and node.min != "":
|
|
2617
|
+
constraints.append(TriccOperation(TriccOperator.MORE_OR_EQUAL, ["$this", node.min]))
|
|
2618
|
+
constraints_min = "The minimun value is {0}.".format(node.min)
|
|
2619
|
+
if node.max is not None and node.max != "":
|
|
2620
|
+
constraints.append(TriccOperation(TriccOperator.LESS_OR_EQUAL, ["$this", node.max]))
|
|
2621
|
+
constraints_max = "The maximum value is {0}.".format(node.max)
|
|
2622
|
+
if len(constraints) > 1:
|
|
2623
|
+
node.constraint = TriccOperation(TriccOperator.AND, constraints)
|
|
2624
|
+
node.constraint_message = (constraints_min + " " + constraints_max).strip()
|
|
2625
|
+
elif len(constraints) == 1:
|
|
2626
|
+
node.constraint = constraints[0]
|
|
2627
|
+
node.constraint_message = (constraints_min + " " + constraints_max).strip()
|
|
2628
|
+
# continue walk
|
|
2629
|
+
return True
|
|
2630
|
+
return False
|