tricc-oo 1.0.1__py3-none-any.whl → 1.4.15__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 +213 -0
- tests/test_cql.py +197 -0
- tests/to_ocl.py +51 -0
- {tricc → tricc_oo}/__init__.py +3 -1
- tricc_oo/converters/codesystem_to_ocl.py +169 -0
- tricc_oo/converters/cql/cqlLexer.py +822 -0
- tricc_oo/converters/cql/cqlListener.py +1632 -0
- tricc_oo/converters/cql/cqlParser.py +11204 -0
- tricc_oo/converters/cql/cqlVisitor.py +913 -0
- tricc_oo/converters/cql_to_operation.py +402 -0
- tricc_oo/converters/datadictionnary.py +115 -0
- tricc_oo/converters/drawio_type_map.py +222 -0
- tricc_oo/converters/tricc_to_xls_form.py +61 -0
- tricc_oo/converters/utils.py +65 -0
- tricc_oo/converters/xml_to_tricc.py +1003 -0
- tricc_oo/models/__init__.py +4 -0
- tricc_oo/models/base.py +732 -0
- tricc_oo/models/calculate.py +216 -0
- tricc_oo/models/ocl.py +281 -0
- tricc_oo/models/ordered_set.py +125 -0
- tricc_oo/models/tricc.py +418 -0
- tricc_oo/parsers/xml.py +138 -0
- tricc_oo/serializers/__init__.py +0 -0
- tricc_oo/serializers/xls_form.py +745 -0
- tricc_oo/strategies/__init__.py +0 -0
- tricc_oo/strategies/input/__init__.py +0 -0
- tricc_oo/strategies/input/base_input_strategy.py +111 -0
- tricc_oo/strategies/input/drawio.py +317 -0
- tricc_oo/strategies/output/base_output_strategy.py +148 -0
- tricc_oo/strategies/output/spice.py +365 -0
- tricc_oo/strategies/output/xls_form.py +697 -0
- tricc_oo/strategies/output/xlsform_cdss.py +189 -0
- tricc_oo/strategies/output/xlsform_cht.py +200 -0
- tricc_oo/strategies/output/xlsform_cht_hf.py +334 -0
- tricc_oo/visitors/__init__.py +0 -0
- tricc_oo/visitors/tricc.py +2198 -0
- tricc_oo/visitors/utils.py +17 -0
- tricc_oo/visitors/xform_pd.py +264 -0
- tricc_oo-1.4.15.dist-info/METADATA +219 -0
- tricc_oo-1.4.15.dist-info/RECORD +46 -0
- {tricc_oo-1.0.1.dist-info → tricc_oo-1.4.15.dist-info}/WHEEL +1 -1
- tricc_oo-1.4.15.dist-info/top_level.txt +2 -0
- tricc/converters/mc_to_tricc.py +0 -542
- tricc/converters/tricc_to_xls_form.py +0 -553
- tricc/converters/utils.py +0 -44
- tricc/converters/xml_to_tricc.py +0 -740
- tricc/models/tricc.py +0 -1093
- tricc/parsers/xml.py +0 -81
- tricc/serializers/xls_form.py +0 -364
- tricc/strategies/input/base_input_strategy.py +0 -80
- tricc/strategies/input/drawio.py +0 -246
- tricc/strategies/input/medalcreator.py +0 -168
- tricc/strategies/output/base_output_strategy.py +0 -92
- tricc/strategies/output/xls_form.py +0 -194
- tricc/strategies/output/xlsform_cdss.py +0 -46
- tricc/strategies/output/xlsform_cht.py +0 -106
- tricc/visitors/tricc.py +0 -375
- tricc_oo-1.0.1.dist-info/LICENSE +0 -78
- tricc_oo-1.0.1.dist-info/METADATA +0 -229
- tricc_oo-1.0.1.dist-info/RECORD +0 -26
- tricc_oo-1.0.1.dist-info/top_level.txt +0 -2
- venv/bin/vba_extract.py +0 -78
- {tricc → tricc_oo}/converters/__init__.py +0 -0
- {tricc → tricc_oo}/models/lang.py +0 -0
- {tricc/serializers → tricc_oo/parsers}/__init__.py +0 -0
- {tricc → tricc_oo}/serializers/planuml.py +0 -0
tricc/converters/xml_to_tricc.py
DELETED
|
@@ -1,740 +0,0 @@
|
|
|
1
|
-
import base64
|
|
2
|
-
import os
|
|
3
|
-
import re
|
|
4
|
-
from curses.ascii import isalnum, isalpha, isdigit
|
|
5
|
-
|
|
6
|
-
from numpy import isnan
|
|
7
|
-
|
|
8
|
-
from tricc.converters.utils import OPERATION_LIST, clean_name, remove_html
|
|
9
|
-
from tricc.models.tricc import *
|
|
10
|
-
from tricc.parsers.xml import (get_edges_list, get_mxcell,
|
|
11
|
-
get_mxcell_parent_list, get_tricc_type,
|
|
12
|
-
get_tricc_type_list)
|
|
13
|
-
|
|
14
|
-
from tricc.visitors.tricc import *
|
|
15
|
-
|
|
16
|
-
TRICC_YES_LABEL = ['yes', "oui"]
|
|
17
|
-
TRICC_NO_LABEL = ['no', "non"]
|
|
18
|
-
TRICC_FOLOW_LABEL = ['folow', "suivre"]
|
|
19
|
-
NO_LABEL = "NO_LABEL"
|
|
20
|
-
TRICC_LIST_NAME = 'list_{0}'
|
|
21
|
-
import logging
|
|
22
|
-
|
|
23
|
-
logger = logging.getLogger("default")
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def create_activity(diagram, media_path):
|
|
27
|
-
id = diagram.attrib.get('id')
|
|
28
|
-
root = create_root_node(diagram)
|
|
29
|
-
name = diagram.attrib.get('name')
|
|
30
|
-
form_id=diagram.attrib.get('name',None)
|
|
31
|
-
if root is not None:
|
|
32
|
-
activity = TriccNodeActivity(
|
|
33
|
-
root=root,
|
|
34
|
-
name=id,
|
|
35
|
-
id=id,
|
|
36
|
-
label=name,
|
|
37
|
-
form_id=form_id,
|
|
38
|
-
)
|
|
39
|
-
# activity definition is never instanciated
|
|
40
|
-
if isinstance(root, TriccNodeActivityStart):
|
|
41
|
-
activity.instance = 0
|
|
42
|
-
# add the group on the root node
|
|
43
|
-
root.group = activity
|
|
44
|
-
activity.group = activity
|
|
45
|
-
edges = get_edges(diagram)
|
|
46
|
-
if edges and len(edges)>0:
|
|
47
|
-
activity.edges = edges
|
|
48
|
-
nodes = get_nodes(diagram, activity)
|
|
49
|
-
groups = get_groups(diagram, nodes, activity)
|
|
50
|
-
if groups and len(groups)>0:
|
|
51
|
-
activity.groups = groups
|
|
52
|
-
if nodes and len(nodes)>0:
|
|
53
|
-
activity.nodes = nodes
|
|
54
|
-
|
|
55
|
-
process_edges(diagram, media_path, activity, nodes)
|
|
56
|
-
# link back the activity
|
|
57
|
-
activity.root.activity = activity
|
|
58
|
-
manage_dandling_calculate(activity)
|
|
59
|
-
|
|
60
|
-
return activity
|
|
61
|
-
else:
|
|
62
|
-
logger.warning("root not found for page {0}".format(name))
|
|
63
|
-
|
|
64
|
-
def manage_dandling_calculate(activity):
|
|
65
|
-
dandling = {}
|
|
66
|
-
for node in activity.nodes.values():
|
|
67
|
-
prev_nodes = [activity.nodes[n.source] for n in list(filter(lambda x: (x.target == node.id or x.target == node) and (x.source in activity.nodes or x.source in activity.nodes.values()), activity.edges ))]
|
|
68
|
-
if len(prev_nodes) == 0 and issubclass(node.__class__, TriccNodeCalculate):
|
|
69
|
-
dandling[node.id] = node
|
|
70
|
-
if len(dandling)>0:
|
|
71
|
-
activity.calculates+=list(dandling.values())
|
|
72
|
-
#wait = get_activity_wait([activity.root], [activity.root], dandling.values(), edge_only=True)
|
|
73
|
-
#activity.nodes.update(dandling)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def process_edges(diagram, media_path, activity, nodes):
|
|
77
|
-
end_found = False
|
|
78
|
-
for edge in activity.edges:
|
|
79
|
-
# enrich nodes
|
|
80
|
-
if edge.target not in nodes :
|
|
81
|
-
activity.unused_edges.append(edge)
|
|
82
|
-
elif edge.source not in nodes and edge.target in nodes:
|
|
83
|
-
enriched = enrich_node(diagram, media_path, edge, nodes[edge.target])
|
|
84
|
-
if enriched is None:
|
|
85
|
-
activity.unused_edges.append(edge)
|
|
86
|
-
elif isinstance(nodes[edge.target], (TriccNodeActivityEnd, TriccNodeEnd)):
|
|
87
|
-
end_found = True
|
|
88
|
-
if edge.target in nodes and issubclass(nodes[edge.target].__class__, TriccRhombusMixIn) and edge.source != nodes[edge.target].path.id :
|
|
89
|
-
edge.target = nodes[edge.target].path.id
|
|
90
|
-
# modify edge for selectyesNo
|
|
91
|
-
if edge.source in nodes and isinstance(nodes[edge.source], TriccNodeSelectYesNo):
|
|
92
|
-
process_yesno_edge(edge, nodes)
|
|
93
|
-
|
|
94
|
-
# create calculate based on edges label
|
|
95
|
-
elif edge.value is not None:
|
|
96
|
-
label = edge.value.strip()
|
|
97
|
-
processed = False
|
|
98
|
-
calc = None
|
|
99
|
-
if isinstance(nodes[edge.source], TriccNodeRhombus) and label.lower() in TRICC_FOLOW_LABEL:
|
|
100
|
-
edge.source = nodes[edge.source].path.id
|
|
101
|
-
processed = True
|
|
102
|
-
elif label.lower() in (TRICC_YES_LABEL )or label == '':
|
|
103
|
-
# do nothinbg for yes
|
|
104
|
-
processed = True
|
|
105
|
-
elif re.search(r'^\-?[0-9]+([.,][0-9]+)?$', edge.value.strip() ):
|
|
106
|
-
calc = process_factor_edge(edge,nodes)
|
|
107
|
-
elif label.lower() in TRICC_NO_LABEL:
|
|
108
|
-
calc = process_exclusive_edge(edge, nodes)
|
|
109
|
-
else:
|
|
110
|
-
# manage comment
|
|
111
|
-
calc = process_condition_edge(edge,nodes)
|
|
112
|
-
|
|
113
|
-
if calc is not None:
|
|
114
|
-
processed = True
|
|
115
|
-
nodes[calc.id] = calc
|
|
116
|
-
# add edge between calc and
|
|
117
|
-
set_prev_next_node(calc,nodes[edge.target], edge_only=True)
|
|
118
|
-
edge.target = calc.id
|
|
119
|
-
if not processed:
|
|
120
|
-
logger.warning("Edge between {0} and {1} with label '{2}' could not be interpreted: {3}".format(
|
|
121
|
-
nodes[edge.source].get_name(),
|
|
122
|
-
nodes[edge.target].get_name(),
|
|
123
|
-
edge.value.strip(),
|
|
124
|
-
"not management found"))
|
|
125
|
-
if not end_found:
|
|
126
|
-
logger.error("the activity {} has no end node".format(activity.get_name()))
|
|
127
|
-
exit()
|
|
128
|
-
|
|
129
|
-
def get_nodes(diagram, activity):
|
|
130
|
-
nodes = {activity.root.id: activity.root}
|
|
131
|
-
add_note_nodes(nodes, diagram, activity)
|
|
132
|
-
add_calculate_nodes(nodes, diagram, activity)
|
|
133
|
-
add_select_nodes(nodes, diagram, activity)
|
|
134
|
-
add_input_nodes(nodes, diagram, activity)
|
|
135
|
-
add_link_nodes(nodes, diagram, activity)
|
|
136
|
-
get_hybride_node(nodes, diagram, activity)
|
|
137
|
-
new_nodes={}
|
|
138
|
-
node_to_remove=[]
|
|
139
|
-
activity_end_node = None
|
|
140
|
-
end_node = None
|
|
141
|
-
for node in nodes.values():
|
|
142
|
-
# clean name
|
|
143
|
-
if hasattr(node, 'name') and node.name is not None and (node.name.endswith(('_','.'))):
|
|
144
|
-
node.name = node.name + node.id
|
|
145
|
-
if issubclass(node.__class__, TriccRhombusMixIn) and node.path is None:
|
|
146
|
-
# generate rhombuse path
|
|
147
|
-
calc = inject_bridge_path(node,nodes)
|
|
148
|
-
node.path = calc
|
|
149
|
-
new_nodes[calc.id] = calc
|
|
150
|
-
# add the edge between trhombus and its path
|
|
151
|
-
elif isinstance(node, TriccNodeGoTo):
|
|
152
|
-
#find if the node has next nodes, if yes, add a bridge + Rhoimbus
|
|
153
|
-
path = inject_bridge_path(node,nodes)
|
|
154
|
-
new_nodes[path.id] = path
|
|
155
|
-
# action after the activity
|
|
156
|
-
next_nodes_id = [ e.target for e in activity.edges if e.source == node.id]
|
|
157
|
-
if len(next_nodes_id)>0:
|
|
158
|
-
|
|
159
|
-
calc = get_activity_wait([path], [node], next_nodes_id, node, edge_only=True)
|
|
160
|
-
new_nodes[calc.id] = calc
|
|
161
|
-
elif isinstance(node, TriccNodeEnd):
|
|
162
|
-
if not end_node:
|
|
163
|
-
end_node = node
|
|
164
|
-
else:
|
|
165
|
-
merge_node(node,end_node)
|
|
166
|
-
node_to_remove.append(node.id)
|
|
167
|
-
elif isinstance(node, TriccNodeActivityEnd):
|
|
168
|
-
if not activity_end_node:
|
|
169
|
-
activity_end_node = node
|
|
170
|
-
else:
|
|
171
|
-
merge_node(node,activity_end_node)
|
|
172
|
-
node_to_remove.append(node.id)
|
|
173
|
-
|
|
174
|
-
nodes.update(new_nodes)
|
|
175
|
-
|
|
176
|
-
for key in node_to_remove:
|
|
177
|
-
del nodes[key]
|
|
178
|
-
edge_list = activity.edges.copy()
|
|
179
|
-
for edge in edge_list:
|
|
180
|
-
if edge.source in node_to_remove or edge.target in node_to_remove:
|
|
181
|
-
activity.edges.remove(edge)
|
|
182
|
-
|
|
183
|
-
return nodes
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
def create_root_node(diagram):
|
|
187
|
-
node = None
|
|
188
|
-
elm = get_tricc_type(diagram, 'object', TriccNodeType.start)
|
|
189
|
-
if elm is not None:
|
|
190
|
-
node= TriccNodeMainStart(
|
|
191
|
-
id = elm.attrib.get('id'),
|
|
192
|
-
parent= elm.attrib.get('parent'),
|
|
193
|
-
name = 'ms'+diagram.attrib.get('id'),
|
|
194
|
-
label = elm.attrib.get('label'),
|
|
195
|
-
form_id= elm.attrib.get('form_id'),
|
|
196
|
-
process= elm.attrib.get('process')
|
|
197
|
-
)
|
|
198
|
-
else:
|
|
199
|
-
elm = get_tricc_type(diagram, 'object', TriccNodeType.activity_start)
|
|
200
|
-
if elm is not None:
|
|
201
|
-
node = TriccNodeActivityStart(
|
|
202
|
-
id = elm.attrib.get('id'),
|
|
203
|
-
parent= elm.attrib.get('parent'),
|
|
204
|
-
name = 'ma'+diagram.attrib.get('id'),
|
|
205
|
-
label = diagram.attrib.get('name'),
|
|
206
|
-
instance = int(elm.attrib.get('instance') if elm.attrib.get('instance') is not None else 1)
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
return node
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
# converter XML item to object
|
|
213
|
-
|
|
214
|
-
def set_additional_attributes(attribute_names, elm, node):
|
|
215
|
-
if not isinstance(attribute_names, list):
|
|
216
|
-
attribute_names = [attribute_names]
|
|
217
|
-
for attributename in attribute_names:
|
|
218
|
-
attribute = elm.attrib.get(attributename)
|
|
219
|
-
if attribute is not None:
|
|
220
|
-
# input expression can add a condition to either relevance (display) or calculate expression
|
|
221
|
-
if attributename == 'expression_inputs':
|
|
222
|
-
attribute = [attribute]
|
|
223
|
-
elif attributename == 'instance':
|
|
224
|
-
attribute = int(attribute)
|
|
225
|
-
else:
|
|
226
|
-
attribute
|
|
227
|
-
setattr(node, attributename, attribute)
|
|
228
|
-
|
|
229
|
-
def add_note_nodes(nodes, diagram, group):
|
|
230
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.note)
|
|
231
|
-
add_tricc_nodes(nodes, TriccNodeNote, list, group, ['relevance'])
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
def add_select_nodes(nodes, diagram, group=None):
|
|
235
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.select_one)
|
|
236
|
-
add_tricc_select_nodes(diagram, nodes, TriccNodeSelectOne, list, group, ['required','save','filter','constraint','constraint_message'])
|
|
237
|
-
#list = get_tricc_type_list(diagram, 'UserObject', TriccNodeType.select_yesno)
|
|
238
|
-
#add_tricc_nodes(nodes, TriccNodeSelectYesNo, list, ['constraint','save','constraint_message','required'])
|
|
239
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.select_multiple)
|
|
240
|
-
add_tricc_select_nodes(diagram, nodes, TriccNodeSelectMultiple, list, group, ['required','save','filter','constraint','constraint_message'])
|
|
241
|
-
|
|
242
|
-
def add_input_nodes(nodes, diagram, group= None):
|
|
243
|
-
list = get_tricc_type_list(diagram, ['object','UserObject'], TriccNodeType.decimal)
|
|
244
|
-
add_tricc_nodes(nodes, TriccNodeDecimal, list, group, ['min','max', 'constraint','save','constraint_message','required'])
|
|
245
|
-
list = get_tricc_type_list(diagram, ['object','UserObject'], TriccNodeType.integer)
|
|
246
|
-
add_tricc_nodes(nodes, TriccNodeInteger, list, group, ['min','max', 'constraint','save','constraint_message','required'])
|
|
247
|
-
list = get_tricc_type_list(diagram, ['object','UserObject'], TriccNodeType.text)
|
|
248
|
-
add_tricc_nodes(nodes, TriccNodeText, list, group, ['constraint','save','constraint_message','required'])
|
|
249
|
-
list = get_tricc_type_list(diagram, ['object','UserObject'], TriccNodeType.date)
|
|
250
|
-
add_tricc_nodes(nodes, TriccNodeDate, list, group, ['constraint','save','constraint_message','required'])
|
|
251
|
-
|
|
252
|
-
def add_calculate_nodes(nodes, diagram, group=None):
|
|
253
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.calculate)
|
|
254
|
-
add_tricc_nodes(nodes, TriccNodeCalculate, list, group, ['save','expression','help', 'hint'])
|
|
255
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.add)
|
|
256
|
-
add_tricc_nodes(nodes, TriccNodeAdd, list, group, ['save','expression'])
|
|
257
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.count)
|
|
258
|
-
add_tricc_nodes(nodes, TriccNodeCount, list, group, ['save','expression'])
|
|
259
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.rhombus)
|
|
260
|
-
add_tricc_nodes(nodes, TriccNodeRhombus, list, group, ['save','expression'],['reference'])
|
|
261
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.exclusive)
|
|
262
|
-
add_tricc_base_node(nodes, TriccNodeExclusive, list, group)
|
|
263
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.wait)
|
|
264
|
-
add_tricc_nodes(nodes, TriccNodeWait, list, group, ['save','expression'],['reference'])
|
|
265
|
-
def get_hybride_node(nodes, diagram, group=None):
|
|
266
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.not_available)
|
|
267
|
-
add_tricc_hybrid_select_nodes(nodes, TriccNodeSelectNotAvailable, list, group, [])
|
|
268
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.select_yesno)
|
|
269
|
-
add_tricc_hybrid_select_nodes(nodes, TriccNodeSelectYesNo, list, group, ['required','save','filter','constraint','constraint_message'])
|
|
270
|
-
#to do generate option
|
|
271
|
-
|
|
272
|
-
def add_link_nodes(nodes, diagram, group=None):
|
|
273
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.link_out)
|
|
274
|
-
add_tricc_nodes(nodes, TriccNodeLinkOut, list, group, [], ['reference'])
|
|
275
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.link_in)
|
|
276
|
-
add_tricc_nodes(nodes, TriccNodeLinkIn, list, group)
|
|
277
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.goto)
|
|
278
|
-
add_tricc_nodes(nodes, TriccNodeGoTo, list, group,['instance'],['link'])
|
|
279
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.activity_end)
|
|
280
|
-
add_tricc_base_node(nodes, TriccNodeActivityEnd, list, group)
|
|
281
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.end)
|
|
282
|
-
add_tricc_base_node(nodes, TriccNodeEnd, list, group)
|
|
283
|
-
list = get_tricc_type_list(diagram, ['UserObject','object'], TriccNodeType.bridge)
|
|
284
|
-
add_tricc_base_node(nodes, TriccNodeBridge, list, group)
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
def get_select_options(diagram, select_node, nodes):
|
|
289
|
-
options = {}
|
|
290
|
-
i = 0
|
|
291
|
-
list = get_mxcell_parent_list(diagram, select_node.id, TriccNodeType.select_option)
|
|
292
|
-
options_name_list = []
|
|
293
|
-
for elm in list:
|
|
294
|
-
name = elm.attrib.get('name')
|
|
295
|
-
if name in options_name_list and not name.endswith('_'):
|
|
296
|
-
logger.error("Select question {0} have twice the option name {1}"\
|
|
297
|
-
.format(select_node.get_name() ,name))
|
|
298
|
-
else:
|
|
299
|
-
options_name_list.append(name)
|
|
300
|
-
id=elm.attrib.get('id')
|
|
301
|
-
option = TriccNodeSelectOption(
|
|
302
|
-
id = id,
|
|
303
|
-
label = elm.attrib.get('label'),
|
|
304
|
-
name = name,
|
|
305
|
-
select = select_node,
|
|
306
|
-
list_name = select_node.list_name,
|
|
307
|
-
group = select_node.group
|
|
308
|
-
)
|
|
309
|
-
set_additional_attributes(['save'], elm, option)
|
|
310
|
-
options[i]=option
|
|
311
|
-
nodes[id]=option
|
|
312
|
-
i += 1
|
|
313
|
-
if len(list)== 0:
|
|
314
|
-
logger.error("select {} does not have any option".format(select_node.label))
|
|
315
|
-
else:
|
|
316
|
-
return options
|
|
317
|
-
|
|
318
|
-
##TBR START
|
|
319
|
-
|
|
320
|
-
def get_max_version(dict):
|
|
321
|
-
max_version = None
|
|
322
|
-
for id, sim_node in dict.items():
|
|
323
|
-
if max_version is None or max_version.version < sim_node.version :
|
|
324
|
-
max_version = sim_node
|
|
325
|
-
return max_version
|
|
326
|
-
|
|
327
|
-
def get_last_version(dict, name):
|
|
328
|
-
max_version = None
|
|
329
|
-
if name in dict:
|
|
330
|
-
for sim_node in dict[name].values():
|
|
331
|
-
if max_version is None or max_version.path_len < sim_node.path_len :
|
|
332
|
-
max_version = sim_node
|
|
333
|
-
return max_version
|
|
334
|
-
|
|
335
|
-
def process_calculate(node,processed_nodes, stashed_nodes, calculates, used_calculates, warn = False, **kwargs ):
|
|
336
|
-
# used_calculates dict[name, Dict[id, node]]
|
|
337
|
-
# processed_nodes Dict[id, node]
|
|
338
|
-
# calculates dict[name, Dict[id, node]]
|
|
339
|
-
if node not in processed_nodes:
|
|
340
|
-
# generate condition
|
|
341
|
-
if is_ready_to_process(node, processed_nodes,False) and process_reference(node, calculates,used_calculates,processed_nodes,warn = warn):
|
|
342
|
-
if is_rhombus_ready_to_process(node,processed_nodes):
|
|
343
|
-
generate_calculates(node,calculates, used_calculates,processed_nodes)
|
|
344
|
-
if issubclass(node.__class__, (TriccNodeDisplayCalculateBase )) and node.name is not None:
|
|
345
|
-
# generate the calc node version by looking in the processed calculate
|
|
346
|
-
last_calc = get_last_version(calculates, node.name)
|
|
347
|
-
# get max version used
|
|
348
|
-
#last_used_version = get_max_named_version(used_calculates, node.name)
|
|
349
|
-
last_used_calc = get_last_version(used_calculates, node.name)
|
|
350
|
-
# add calculate is added after the version collection so it is 0 in case there is no calc found
|
|
351
|
-
add_calculate(calculates,node)
|
|
352
|
-
# merge is there is unused version ->
|
|
353
|
-
# current node not yet in the list so 1 item is enough
|
|
354
|
-
if last_calc is not None:
|
|
355
|
-
if last_used_calc is None or last_calc.path_len > last_used_calc.path_len:
|
|
356
|
-
node.version = last_calc.version + 1
|
|
357
|
-
node_to_delete = merge_calculate(node, calculates[node.name],last_used_calc)
|
|
358
|
-
if node_to_delete is not None:
|
|
359
|
-
for d_node in node_to_delete:
|
|
360
|
-
del calculates[d_node.name][d_node.id]
|
|
361
|
-
|
|
362
|
-
if d_node.name in used_calculates:
|
|
363
|
-
if d_node.id in used_calculates[d_node.name]:
|
|
364
|
-
logger.error("node {} used but deleted".format(d_node.get_name()))
|
|
365
|
-
if d_node.id in d_node.activity.nodes:
|
|
366
|
-
# mostly for end nodes
|
|
367
|
-
if isinstance(d_node,(TriccNodeEnd,TriccNodeActivityEnd)):
|
|
368
|
-
del d_node.activity.nodes[d_node.id]
|
|
369
|
-
if d_node in stashed_nodes:
|
|
370
|
-
logger.error("node {} not porcessed but deleted".format(d_node.get_name()))
|
|
371
|
-
# chaining the calculate, this is needed each time there is a last used version
|
|
372
|
-
if last_used_calc is not None :
|
|
373
|
-
logger.debug("set last to false for node {} and add its link it to next one".format(last_used_calc.get_name()))
|
|
374
|
-
set_prev_next_node(last_used_calc,node)
|
|
375
|
-
last_used_calc.last = False
|
|
376
|
-
update_calc_version(calculates,node.name)
|
|
377
|
-
#if hasattr(node, 'next_nodes'):
|
|
378
|
-
#node.next_nodes=reorder_node_list(node.next_nodes, node.group)
|
|
379
|
-
return True
|
|
380
|
-
# not ready to process or already processed
|
|
381
|
-
|
|
382
|
-
return False
|
|
383
|
-
|
|
384
|
-
def update_calc_version(calculates,name):
|
|
385
|
-
if name in calculates and len(calculates[name])>1:
|
|
386
|
-
ordered_list = sorted(list(calculates[name].values()), key=lambda x:x.path_len)
|
|
387
|
-
i = 1
|
|
388
|
-
len_max=len(calculates[name])
|
|
389
|
-
for elm in ordered_list:
|
|
390
|
-
elm.version=i
|
|
391
|
-
elm.last= (i == len_max)
|
|
392
|
-
i+=1
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
def get_max_named_version(calculates,name):
|
|
396
|
-
max = 0
|
|
397
|
-
if name in calculates:
|
|
398
|
-
for node in calculates[name].values():
|
|
399
|
-
if node.version > max:
|
|
400
|
-
max = node.version
|
|
401
|
-
return max
|
|
402
|
-
|
|
403
|
-
def get_count_node(node):
|
|
404
|
-
count_id = generate_id()
|
|
405
|
-
count_name = "cnt_"+count_id
|
|
406
|
-
return TriccNodeCount(
|
|
407
|
-
id = count_id,
|
|
408
|
-
group = node.group,
|
|
409
|
-
activity = node.activity,
|
|
410
|
-
label = "count: "+node.get_name(),
|
|
411
|
-
name = count_name,
|
|
412
|
-
path_len=node.path_len
|
|
413
|
-
)
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
def inject_bridge_path(node, nodes):
|
|
417
|
-
calc_id = generate_id()
|
|
418
|
-
calc_name = "path_"+calc_id
|
|
419
|
-
data = {
|
|
420
|
-
'id': calc_id,
|
|
421
|
-
'group': node.group,
|
|
422
|
-
'activity': node.activity,
|
|
423
|
-
'label': "path: " + node.get_name(),
|
|
424
|
-
'name': calc_name,
|
|
425
|
-
'path_len': node.path_len
|
|
426
|
-
}
|
|
427
|
-
prev_nodes = [nodes[n.source] for n in list(filter(lambda x: (x.target == node.id or x.target == node) and x.source in nodes ,node.activity.edges ))]
|
|
428
|
-
if sum([0 if issubclass(n.__class__, (TriccNodeDisplayCalculateBase, TriccNodeRhombus)) else 1 for n in prev_nodes])>0 : #and len(node.prev_nodes)>1:
|
|
429
|
-
calc= TriccNodeDisplayBridge( **data)
|
|
430
|
-
else:
|
|
431
|
-
calc = TriccNodeBridge( **data)
|
|
432
|
-
|
|
433
|
-
for e in node.activity.edges:
|
|
434
|
-
if e.target == node.id:
|
|
435
|
-
e.target = calc.id
|
|
436
|
-
|
|
437
|
-
# add edge between bridge and node
|
|
438
|
-
set_prev_next_node(calc,node,edge_only=True)
|
|
439
|
-
|
|
440
|
-
node.path_len += 1
|
|
441
|
-
return calc
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
def enrich_node(diagram, media_path, edge, node):
|
|
446
|
-
if edge.target == node.id:
|
|
447
|
-
# get node and process type
|
|
448
|
-
type, message = get_message(diagram, edge.source)
|
|
449
|
-
if type is not None:
|
|
450
|
-
if type in (TriccNodeType.start, TriccNodeType.activity_start):
|
|
451
|
-
return True
|
|
452
|
-
elif hasattr(node, type):
|
|
453
|
-
if message is not None:
|
|
454
|
-
setattr(node,type,message)
|
|
455
|
-
return True
|
|
456
|
-
else:
|
|
457
|
-
logger.warning("A attribute box of type {0} and value {1} is attached to an object not compatible {2}".format(type, message, node.get_name()))
|
|
458
|
-
else:
|
|
459
|
-
image = get_image(diagram, media_path, edge.source )
|
|
460
|
-
if image is not None :
|
|
461
|
-
if hasattr(node, 'image'):
|
|
462
|
-
node.image = image
|
|
463
|
-
return image
|
|
464
|
-
else:
|
|
465
|
-
print('image not supported for {} '.format(node.get_name()))
|
|
466
|
-
|
|
467
|
-
def add_tricc_hybrid_select_nodes(nodes, type, list, group, attributes):
|
|
468
|
-
for elm in list:
|
|
469
|
-
id = elm.attrib.get('id')
|
|
470
|
-
label = elm.attrib.get('label')
|
|
471
|
-
name = elm.attrib.get('name')
|
|
472
|
-
if name is None:
|
|
473
|
-
name = elm.attrib.get('id')
|
|
474
|
-
node = type(
|
|
475
|
-
id=id,
|
|
476
|
-
parent= elm.attrib.get('parent'),
|
|
477
|
-
label = label if type != TriccNodeSelectNotAvailable else NO_LABEL,
|
|
478
|
-
name = name,
|
|
479
|
-
required=True,
|
|
480
|
-
group = group,
|
|
481
|
-
activity = group,
|
|
482
|
-
list_name = 'yes_no' if type == TriccNodeSelectYesNo else TRICC_LIST_NAME.format(id)
|
|
483
|
-
)
|
|
484
|
-
if type == TriccNodeSelectNotAvailable:
|
|
485
|
-
node.options = get_select_not_available_options(node, group, label)
|
|
486
|
-
nodes[node.options[0].id]=node.options[0]
|
|
487
|
-
elif type == TriccNodeSelectYesNo:
|
|
488
|
-
node.options = get_select_yes_no_options(node, group)
|
|
489
|
-
nodes[node.options[0].id]=node.options[0]
|
|
490
|
-
nodes[node.options[1].id]=node.options[1]
|
|
491
|
-
set_additional_attributes(attributes, elm, node)
|
|
492
|
-
nodes[id]=node
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
def add_tricc_select_nodes(diagram, nodes, type, list, group, attributes):
|
|
496
|
-
for elm in list:
|
|
497
|
-
id = elm.attrib.get('id')
|
|
498
|
-
node = type(
|
|
499
|
-
id = id,
|
|
500
|
-
parent= elm.attrib.get('parent'),
|
|
501
|
-
label = elm.attrib.get('label'),
|
|
502
|
-
name = elm.attrib.get('name'),
|
|
503
|
-
required=True,
|
|
504
|
-
group = group,
|
|
505
|
-
activity = group,
|
|
506
|
-
list_name = TRICC_LIST_NAME.format(id)
|
|
507
|
-
)
|
|
508
|
-
node.options = get_select_options(diagram, node, nodes)
|
|
509
|
-
set_additional_attributes(attributes, elm, node)
|
|
510
|
-
|
|
511
|
-
nodes[id]=node
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
def add_tricc_nodes(nodes, type, list, group, attributes = [], mandatory_attributes = []):
|
|
516
|
-
mandatory_attributes += ['label','name']
|
|
517
|
-
add_tricc_base_node(nodes, type, list, group, attributes, mandatory_attributes)
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
def add_tricc_base_node(nodes, type, list, group, attributes = [], mandatory_attributes = []):
|
|
521
|
-
for elm in list:
|
|
522
|
-
id = elm.attrib.get('id')
|
|
523
|
-
parent= elm.attrib.get('parent')
|
|
524
|
-
node = type(
|
|
525
|
-
id = id,
|
|
526
|
-
parent= parent,
|
|
527
|
-
group = group,
|
|
528
|
-
activity = group,
|
|
529
|
-
**set_mandatory_attribute(elm, mandatory_attributes, group.name)
|
|
530
|
-
)
|
|
531
|
-
set_additional_attributes(attributes, elm, node)
|
|
532
|
-
nodes[id]=node
|
|
533
|
-
|
|
534
|
-
def set_mandatory_attribute(elm, mandatory_attributes, groupname = None):
|
|
535
|
-
param = {}
|
|
536
|
-
for attributes in mandatory_attributes:
|
|
537
|
-
attribute_value = elm.attrib.get(attributes)
|
|
538
|
-
if attribute_value is None:
|
|
539
|
-
if elm.attrib.get('label')is not None:
|
|
540
|
-
display_name = elm.attrib.get('label')
|
|
541
|
-
elif elm.attrib.get('name')is not None:
|
|
542
|
-
display_name = elm.attrib.get('name')
|
|
543
|
-
else:
|
|
544
|
-
display_name = elm.attrib.get('id')
|
|
545
|
-
logger.error("the attibute {} is mandatory but not found in {} within group {}".format(attributes, display_name, groupname if groupname is not None else ''))
|
|
546
|
-
if mandatory_attributes == "source":
|
|
547
|
-
if elm.attrib.get('target') is not None:
|
|
548
|
-
logger.error("the attibute target is ".format(elm.attrib.get('target')))
|
|
549
|
-
elif mandatory_attributes == "target":
|
|
550
|
-
if elm.attrib.get('source') is not None:
|
|
551
|
-
logger.error("the attibute target is ".format(elm.attrib.get('source')))
|
|
552
|
-
exit()
|
|
553
|
-
if attributes == 'link':
|
|
554
|
-
param[attributes] = clean_link(attribute_value)
|
|
555
|
-
elif attributes in ('parent','id', 'source', 'target'):
|
|
556
|
-
param[attributes]=attribute_value
|
|
557
|
-
elif attribute_value is not None:
|
|
558
|
-
param[attributes]=remove_html(attribute_value.strip())
|
|
559
|
-
return param
|
|
560
|
-
|
|
561
|
-
def clean_link(link):
|
|
562
|
-
# link have the format "data:page/id,DiagramID"
|
|
563
|
-
link_parts = link.split(',')
|
|
564
|
-
if link_parts[0] == 'data:page/id' and len(link_parts)==2:
|
|
565
|
-
return link_parts[1]
|
|
566
|
-
|
|
567
|
-
def get_groups(diagram, nodes, parent_group):
|
|
568
|
-
groups = {}
|
|
569
|
-
list=get_tricc_type_list(diagram, 'object', TriccNodeType.page )
|
|
570
|
-
for elm in list:
|
|
571
|
-
add_group(elm, diagram, nodes, groups,parent_group)
|
|
572
|
-
return groups
|
|
573
|
-
|
|
574
|
-
def add_group(elm, diagram, nodes, groups, parent_group):
|
|
575
|
-
id = elm.attrib.get('id')
|
|
576
|
-
if id not in groups:
|
|
577
|
-
group = TriccGroup(
|
|
578
|
-
name = elm.attrib.get('name'),
|
|
579
|
-
label = elm.attrib.get('label'),
|
|
580
|
-
id = id,
|
|
581
|
-
group = parent_group
|
|
582
|
-
)
|
|
583
|
-
# get elememt witn parent = id and tricc_type defiend
|
|
584
|
-
list_child = get_tricc_type_list(diagram, ['object','UserObject'], tricc_type=None, parent_id = id)
|
|
585
|
-
add_group_to_child(group, diagram,list_child, nodes, groups, parent_group)
|
|
586
|
-
if group is not None:
|
|
587
|
-
groups[group.id] = group
|
|
588
|
-
return group
|
|
589
|
-
|
|
590
|
-
def add_group_to_child(group, diagram,list_child, nodes, groups, parent_group):
|
|
591
|
-
for child_elm in list_child:
|
|
592
|
-
if child_elm.attrib.get('tricc_type') == TriccNodeType.container_hint_media:
|
|
593
|
-
list_sub_child = get_tricc_type_list(diagram, ['object','UserObject'], tricc_type=None, parent_id =child_elm.attrib.get('id') )
|
|
594
|
-
add_group_to_child(group, diagram,list_sub_child, nodes, groups, parent_group )
|
|
595
|
-
elif child_elm.attrib.get('tricc_type') == TriccNodeType.page:
|
|
596
|
-
child_group_id = child_elm.attrib.get('id')
|
|
597
|
-
if not child_group_id in groups:
|
|
598
|
-
child_group = add_group(child_elm, diagram, nodes, groups, group)
|
|
599
|
-
else:
|
|
600
|
-
child_group = groups[child_group_id]
|
|
601
|
-
child_group.group = group
|
|
602
|
-
else:
|
|
603
|
-
child_id=child_elm.attrib.get('id')
|
|
604
|
-
if child_id is not None and child_id in nodes:
|
|
605
|
-
nodes[child_id].group = group
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
def get_image(diagram, path, id, image_name = None ):
|
|
609
|
-
elm = get_mxcell(diagram, id)
|
|
610
|
-
if elm is not None:
|
|
611
|
-
style=elm.attrib.get('style')
|
|
612
|
-
if image_name is None:
|
|
613
|
-
image_name = id
|
|
614
|
-
file_name = add_image_from_style(style, path, image_name)
|
|
615
|
-
if file_name is not None:
|
|
616
|
-
return file_name
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
def add_image_from_style(style,path, image_name):
|
|
620
|
-
image_attrib = None
|
|
621
|
-
if style is not None and 'image=data:image/' in style:
|
|
622
|
-
image_attrib = style.split('image=data:image/')
|
|
623
|
-
if image_attrib is not None and len(image_attrib)==2:
|
|
624
|
-
image_parts = image_attrib[1].split(',')
|
|
625
|
-
if len(image_parts) == 2:
|
|
626
|
-
payload = image_parts[1][:-1]
|
|
627
|
-
path = os.path.join(path, 'images')
|
|
628
|
-
file_name = os.path.join(path , image_name+ '.' + image_parts[0])
|
|
629
|
-
if not(os.path.isdir(path)): # check if it exists, because if it does, error will be raised
|
|
630
|
-
# (later change to make folder complaint to CHT)
|
|
631
|
-
os.makedirs(path, exist_ok = True)
|
|
632
|
-
with open(file_name , "wb") as fh:
|
|
633
|
-
fh.write(base64.decodebytes(payload.encode('ascii')))
|
|
634
|
-
return os.path.basename(file_name)
|
|
635
|
-
|
|
636
|
-
def get_contained_main_node(diagram, id):
|
|
637
|
-
list = get_mxcell_parent_list(diagram, id, media_nodes)
|
|
638
|
-
if isinstance(list, List) and len(list)>0:
|
|
639
|
-
#use only the first one
|
|
640
|
-
return list[0]
|
|
641
|
-
|
|
642
|
-
def get_message(diagram, id):
|
|
643
|
-
elm = get_mxcell(diagram, id)
|
|
644
|
-
if elm is not None:
|
|
645
|
-
type = elm.attrib.get('odk_type')
|
|
646
|
-
if type is not None:
|
|
647
|
-
if type.endswith("-message"):
|
|
648
|
-
type = type[:-8]
|
|
649
|
-
return type, elm.attrib.get('label')
|
|
650
|
-
#use only the first one
|
|
651
|
-
return None, None
|
|
652
|
-
|
|
653
|
-
def get_edges( diagram):
|
|
654
|
-
edges = []
|
|
655
|
-
list = get_edges_list(diagram)
|
|
656
|
-
for elm in list:
|
|
657
|
-
id = elm.attrib.get('id')
|
|
658
|
-
edge = TriccEdge(
|
|
659
|
-
id = id,
|
|
660
|
-
**set_mandatory_attribute(elm, ['source' , 'parent', 'target'], diagram.attrib.get('name'))
|
|
661
|
-
)
|
|
662
|
-
set_additional_attributes(['value'], elm, edge)
|
|
663
|
-
if edge.value is not None:
|
|
664
|
-
edge.value = remove_html(edge.value)
|
|
665
|
-
edges.append(edge)
|
|
666
|
-
return edges
|
|
667
|
-
|
|
668
|
-
## Process edges
|
|
669
|
-
|
|
670
|
-
def process_factor_edge(edge,nodes):
|
|
671
|
-
factor = edge.value.strip()
|
|
672
|
-
if factor != 1:
|
|
673
|
-
return TriccNodeCalculate(
|
|
674
|
-
id = edge.id,
|
|
675
|
-
expression_reference = "number(${{{}}}) * {}".format('', factor),
|
|
676
|
-
reference = [nodes[edge.source]],
|
|
677
|
-
activity = nodes[edge.source].activity,
|
|
678
|
-
group = nodes[edge.source].group,
|
|
679
|
-
label= "factor {}".format(factor)
|
|
680
|
-
)
|
|
681
|
-
return None
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
def process_condition_edge(edge,nodes):
|
|
685
|
-
label = edge.value.strip()
|
|
686
|
-
for op in OPERATION_LIST:
|
|
687
|
-
if op in label:
|
|
688
|
-
# insert rhombus
|
|
689
|
-
return TriccNodeRhombus(
|
|
690
|
-
id = edge.id,
|
|
691
|
-
reference = [nodes[edge.source]],
|
|
692
|
-
path = nodes[edge.source],
|
|
693
|
-
activity = nodes[edge.source].activity,
|
|
694
|
-
group = nodes[edge.source].group,
|
|
695
|
-
label= label
|
|
696
|
-
)
|
|
697
|
-
def process_exclusive_edge(edge, nodes):
|
|
698
|
-
error = None
|
|
699
|
-
if issubclass(nodes[edge.source].__class__, TriccNodeCalculateBase):
|
|
700
|
-
# insert Negate
|
|
701
|
-
if not isinstance(nodes[edge.target], TriccNodeExclusive) or not isinstance(nodes[edge.source], TriccNodeExclusive):
|
|
702
|
-
return TriccNodeExclusive(
|
|
703
|
-
id = edge.id,
|
|
704
|
-
activity = nodes[edge.target].activity,
|
|
705
|
-
group = nodes[edge.target].group
|
|
706
|
-
)
|
|
707
|
-
else:
|
|
708
|
-
error = "No after or before a exclusice/negate node"
|
|
709
|
-
else:
|
|
710
|
-
error = "label not after a yesno nor a calculate"
|
|
711
|
-
if error is not None:
|
|
712
|
-
logger.warning("Edge between {0} and {1} with label '{2}' could not be interpreted: {3}".format(
|
|
713
|
-
nodes[edge.source].get_name(),
|
|
714
|
-
nodes[edge.target].get_name(),
|
|
715
|
-
edge.value.strip(),
|
|
716
|
-
error
|
|
717
|
-
))
|
|
718
|
-
return None
|
|
719
|
-
|
|
720
|
-
def process_yesno_edge(edge, nodes):
|
|
721
|
-
if edge.value is None:
|
|
722
|
-
logger.error("yesNo {} node with labelless edges".format(nodes[edge.source].get_name()))
|
|
723
|
-
exit()
|
|
724
|
-
label = edge.value.strip().lower()
|
|
725
|
-
yes_option = None
|
|
726
|
-
no_option = None
|
|
727
|
-
for option in nodes[edge.source].options.values():
|
|
728
|
-
if option.name == '1':
|
|
729
|
-
yes_option = option
|
|
730
|
-
else:
|
|
731
|
-
no_option = option
|
|
732
|
-
if label.lower() in TRICC_FOLOW_LABEL:
|
|
733
|
-
pass
|
|
734
|
-
elif label.lower() in TRICC_YES_LABEL:
|
|
735
|
-
edge.source = yes_option.id
|
|
736
|
-
elif label.lower() in TRICC_NO_LABEL:
|
|
737
|
-
edge.source = no_option.id
|
|
738
|
-
else:
|
|
739
|
-
logger.warning("edge {0} is coming from select {1}".format(edge.id, nodes[edge.source].get_name()))
|
|
740
|
-
|