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/models/tricc.py
CHANGED
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import random
|
|
5
|
-
import string
|
|
6
|
-
from enum import Enum, auto
|
|
7
|
-
from typing import Dict, ForwardRef, List, Optional, Union
|
|
3
|
+
from typing import Dict, List, Optional, Union, Set
|
|
8
4
|
from fhir.resources.codesystem import CodeSystem
|
|
9
5
|
from fhir.resources.valueset import ValueSet
|
|
10
|
-
from pydantic import BaseModel
|
|
11
|
-
from
|
|
12
|
-
from .base import
|
|
13
|
-
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
from tricc_oo.converters.utils import get_rand_name
|
|
8
|
+
from tricc_oo.models.base import (
|
|
9
|
+
TriccNodeBaseModel, Expression, TriccOperation,
|
|
10
|
+
TriccStatic, TriccReference, TriccNodeType, TriccGroup, triccName,
|
|
11
|
+
TriccEdge, b64, triccId
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
14
19
|
|
|
15
20
|
class TriccNodeCalculateBase(TriccNodeBaseModel):
|
|
16
|
-
#input: Dict[TriccOperation, TriccNodeBaseModel] = {}
|
|
17
|
-
reference: Union[List[Union[TriccNodeBaseModel,TriccStatic]], Expression, TriccStatic] = None
|
|
21
|
+
# input: Dict[TriccOperation, TriccNodeBaseModel] = {}
|
|
22
|
+
reference: Union[List[Union[TriccNodeBaseModel, TriccStatic]], Expression, TriccStatic] = None
|
|
18
23
|
expression_reference: Union[str, TriccOperation] = None
|
|
19
24
|
last: bool = None
|
|
20
|
-
datatype: str =
|
|
25
|
+
datatype: str = "boolean"
|
|
21
26
|
priority: Union[float, int, None] = None
|
|
27
|
+
|
|
22
28
|
# to use the enum value of the TriccNodeType
|
|
23
29
|
class Config:
|
|
24
30
|
use_enum_values = True # <--
|
|
@@ -26,11 +32,18 @@ class TriccNodeCalculateBase(TriccNodeBaseModel):
|
|
|
26
32
|
def make_instance(self, instance_nb, activity, **kwargs):
|
|
27
33
|
# shallow copy
|
|
28
34
|
instance = super().make_instance(instance_nb, activity=activity)
|
|
29
|
-
#input = {}
|
|
30
|
-
#instance.input = input
|
|
31
|
-
|
|
35
|
+
# input = {}
|
|
36
|
+
# instance.input = input
|
|
37
|
+
self.expression.copy() if self.expression is not None else None
|
|
32
38
|
if self.reference:
|
|
33
|
-
instance.reference = [
|
|
39
|
+
instance.reference = [
|
|
40
|
+
(
|
|
41
|
+
e.copy()
|
|
42
|
+
if isinstance(e, (TriccReference, TriccOperation))
|
|
43
|
+
else (TriccReference(e.name) if hasattr(e, "name") else e)
|
|
44
|
+
)
|
|
45
|
+
for e in self.reference
|
|
46
|
+
]
|
|
34
47
|
else:
|
|
35
48
|
instance.reference = None
|
|
36
49
|
if instance.base_instance != self:
|
|
@@ -38,14 +51,13 @@ class TriccNodeCalculateBase(TriccNodeBaseModel):
|
|
|
38
51
|
return instance
|
|
39
52
|
|
|
40
53
|
def __init__(self, **data):
|
|
41
|
-
if
|
|
42
|
-
data[
|
|
54
|
+
if "name" not in data:
|
|
55
|
+
data["name"] = get_rand_name(data.get("id", None))
|
|
43
56
|
super().__init__(**data)
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
|
|
46
58
|
def append(self, elm):
|
|
47
59
|
self.reference.append(elm)
|
|
48
|
-
|
|
60
|
+
|
|
49
61
|
def get_references(self):
|
|
50
62
|
if isinstance(self.reference, set):
|
|
51
63
|
return self.reference
|
|
@@ -55,10 +67,11 @@ class TriccNodeCalculateBase(TriccNodeBaseModel):
|
|
|
55
67
|
return self.expression_reference.get_references()
|
|
56
68
|
elif isinstance(self.reference, TriccOperation):
|
|
57
69
|
return self.reference.get_references()
|
|
58
|
-
|
|
70
|
+
|
|
59
71
|
elif self.reference:
|
|
60
72
|
return self.reference
|
|
61
73
|
logger.critical("Cannot get reference from a sting")
|
|
74
|
+
|
|
62
75
|
def __str__(self):
|
|
63
76
|
return self.get_name()
|
|
64
77
|
|
|
@@ -75,29 +88,29 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
75
88
|
nodes: Dict[str, TriccNodeBaseModel] = {}
|
|
76
89
|
# groups
|
|
77
90
|
groups: Dict[str, TriccGroup] = {}
|
|
78
|
-
# save the instance on the base activity
|
|
91
|
+
# save the instance on the base activity
|
|
79
92
|
instances: Dict[int, TriccNodeBaseModel] = {}
|
|
80
93
|
relevance: Optional[Union[Expression, TriccOperation]] = None
|
|
81
|
-
#caclulate that are not part of the any skip logic:
|
|
94
|
+
# caclulate that are not part of the any skip logic:
|
|
82
95
|
# - inputs
|
|
83
96
|
# - dangling calculate
|
|
84
97
|
# - case definition
|
|
85
98
|
calculates: List[TriccNodeCalculateBase] = []
|
|
86
99
|
applicability: Optional[Union[Expression, TriccOperation]] = None
|
|
87
100
|
|
|
88
|
-
# redefine
|
|
101
|
+
# redefine
|
|
89
102
|
def make_instance(self, instance_nb=None, **kwargs):
|
|
90
103
|
from tricc_oo.models.calculate import (
|
|
91
104
|
TriccNodeDisplayBridge,
|
|
92
105
|
TriccNodeBridge,
|
|
93
|
-
|
|
94
106
|
)
|
|
107
|
+
|
|
95
108
|
# shallow copy
|
|
96
109
|
if instance_nb in self.instances:
|
|
97
110
|
return self.instances[instance_nb]
|
|
98
111
|
else:
|
|
99
112
|
instance = super().make_instance(instance_nb, activity=None)
|
|
100
|
-
base_instance =
|
|
113
|
+
base_instance = self.base_instance or self
|
|
101
114
|
instance.base_instance = base_instance
|
|
102
115
|
# instance.base_instance = self
|
|
103
116
|
# we duplicate all the related nodes (not the calculate, duplication is manage in calculate version code)
|
|
@@ -119,15 +132,36 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
119
132
|
instance.edges.append(edge.make_instance(instance_nb, activity=instance))
|
|
120
133
|
instance.update_nodes(self.root)
|
|
121
134
|
# we walk throught the nodes and replace them when ready
|
|
122
|
-
for node in list(
|
|
135
|
+
for node in list(
|
|
136
|
+
filter(
|
|
137
|
+
lambda p_node: isinstance(p_node, (TriccNodeDisplayBridge, TriccNodeBridge)),
|
|
138
|
+
list(self.nodes.values()),
|
|
139
|
+
)
|
|
140
|
+
):
|
|
123
141
|
instance.update_nodes(node)
|
|
124
|
-
for node in list(
|
|
142
|
+
for node in list(
|
|
143
|
+
filter(
|
|
144
|
+
lambda p_node: p_node != self.root
|
|
145
|
+
and not isinstance(p_node, (TriccNodeDisplayBridge, TriccNodeBridge)),
|
|
146
|
+
list(self.nodes.values()),
|
|
147
|
+
)
|
|
148
|
+
):
|
|
125
149
|
instance_node = instance.update_nodes(node)
|
|
126
150
|
if node in self.calculates and instance_node:
|
|
127
151
|
instance.calculates.append(instance_node)
|
|
128
|
-
# update parents
|
|
129
|
-
for node in list(
|
|
130
|
-
|
|
152
|
+
# update parents
|
|
153
|
+
for node in list(
|
|
154
|
+
filter(
|
|
155
|
+
lambda p_node: getattr(p_node, "parent", None) is not None,
|
|
156
|
+
list(instance.nodes.values()),
|
|
157
|
+
)
|
|
158
|
+
):
|
|
159
|
+
new_parent = list(
|
|
160
|
+
filter(
|
|
161
|
+
lambda p_node: p_node.base_instance == node.parent,
|
|
162
|
+
list(instance.nodes.values()),
|
|
163
|
+
)
|
|
164
|
+
)
|
|
131
165
|
if new_parent:
|
|
132
166
|
node.parent = new_parent[0]
|
|
133
167
|
else:
|
|
@@ -148,7 +182,7 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
148
182
|
instance_group.group == self
|
|
149
183
|
|
|
150
184
|
def update_groups(self, group):
|
|
151
|
-
# create new group
|
|
185
|
+
# create new group
|
|
152
186
|
instance_group = group.make_instance(self.instance, activity=self)
|
|
153
187
|
# update the group in all activity
|
|
154
188
|
for node in list(self.nodes.values()):
|
|
@@ -158,18 +192,20 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
158
192
|
|
|
159
193
|
def update_nodes(self, node_origin):
|
|
160
194
|
from tricc_oo.models.calculate import (
|
|
161
|
-
TriccNodeEnd,
|
|
162
195
|
TriccNodeActivityStart,
|
|
163
|
-
TriccNodeMainStart,
|
|
164
196
|
TriccNodeActivityEnd,
|
|
165
|
-
TriccRhombusMixIn
|
|
197
|
+
TriccRhombusMixIn,
|
|
166
198
|
)
|
|
199
|
+
|
|
167
200
|
updated_edges = 0
|
|
168
201
|
node_instance = None
|
|
169
202
|
if not isinstance(node_origin, TriccNodeSelectOption):
|
|
170
203
|
# do not perpetuate the instance number in the underlying activities
|
|
171
204
|
if isinstance(node_origin, TriccNodeActivity):
|
|
172
|
-
node_instance = node_origin.make_instance(
|
|
205
|
+
node_instance = node_origin.make_instance(
|
|
206
|
+
node_origin.instance if node_origin.instance < 100 else 0,
|
|
207
|
+
activity=self,
|
|
208
|
+
)
|
|
173
209
|
else:
|
|
174
210
|
node_instance = node_origin.make_instance(self.instance, activity=self)
|
|
175
211
|
self.nodes[node_instance.id] = node_instance
|
|
@@ -185,13 +221,16 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
185
221
|
for n in node_instance.activity.nodes.values():
|
|
186
222
|
if n.base_instance.id == old_path.id:
|
|
187
223
|
node_instance.path = n
|
|
188
|
-
# test next_nodes to check that the instance has already prev/next
|
|
224
|
+
# test next_nodes to check that the instance has already prev/next
|
|
189
225
|
if node_instance.path is None and node_instance.next_nodes:
|
|
190
226
|
logger.critical("new path not found")
|
|
191
227
|
elif len(node_instance.prev_nodes) == 1:
|
|
192
|
-
|
|
193
|
-
elif not (
|
|
194
|
-
|
|
228
|
+
node_origin.path = list(node_instance.prev_nodes)[0]
|
|
229
|
+
elif not (
|
|
230
|
+
len(node_instance.reference) == 1
|
|
231
|
+
and issubclass(node_instance.reference[0].__class__, TriccNodeInputModel)
|
|
232
|
+
):
|
|
233
|
+
logger.warning("Rhombus without a path")
|
|
195
234
|
exit(1)
|
|
196
235
|
# generate options
|
|
197
236
|
elif issubclass(node_instance.__class__, TriccNodeSelect):
|
|
@@ -199,19 +238,27 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
199
238
|
updated_edges += self.update_edges(node_origin.options[key], option_instance)
|
|
200
239
|
updated_edges += self.update_edges(node_origin, node_instance)
|
|
201
240
|
if updated_edges == 0:
|
|
202
|
-
node_edge = list(
|
|
203
|
-
|
|
241
|
+
node_edge = list(
|
|
242
|
+
filter(
|
|
243
|
+
lambda x: (x.source == node_instance.id or x.source == node_instance),
|
|
244
|
+
node_instance.activity.edges,
|
|
245
|
+
)
|
|
246
|
+
)
|
|
204
247
|
if len(node_edge) == 0 and not issubclass(node_origin.__class__, TriccNodeCalculateBase):
|
|
205
|
-
logger.warning(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
248
|
+
logger.warning(
|
|
249
|
+
"no edge was updated for node {}::{}::{}::{}".format(
|
|
250
|
+
node_instance.activity.get_name(),
|
|
251
|
+
node_instance.__class__,
|
|
252
|
+
node_instance.get_name(),
|
|
253
|
+
node_instance.instance,
|
|
254
|
+
)
|
|
255
|
+
)
|
|
209
256
|
return node_instance
|
|
210
257
|
|
|
211
258
|
def update_edges(self, node_origin, node_instance):
|
|
212
259
|
updates = 0
|
|
213
|
-
|
|
214
|
-
for edge in self.edges:
|
|
260
|
+
|
|
261
|
+
for edge in self.edges:
|
|
215
262
|
if edge.source == node_origin.id or edge.source == node_origin:
|
|
216
263
|
edge.source = node_instance.id
|
|
217
264
|
updates += 1
|
|
@@ -225,9 +272,14 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
225
272
|
TriccNodeEnd,
|
|
226
273
|
TriccNodeActivityEnd,
|
|
227
274
|
)
|
|
228
|
-
return list(filter(lambda x: isinstance(x, (TriccNodeActivityEnd)) or (isinstance(x, (TriccNodeEnd)) and isinstance(self.root, TriccNodeMainStart )), self.nodes.values()))
|
|
229
|
-
|
|
230
275
|
|
|
276
|
+
return list(
|
|
277
|
+
filter(
|
|
278
|
+
lambda x: isinstance(x, (TriccNodeActivityEnd))
|
|
279
|
+
or (isinstance(x, (TriccNodeEnd)) and isinstance(self.root, TriccNodeMainStart)),
|
|
280
|
+
self.nodes.values(),
|
|
281
|
+
)
|
|
282
|
+
)
|
|
231
283
|
|
|
232
284
|
|
|
233
285
|
class TriccNodeDisplayModel(TriccNodeBaseModel):
|
|
@@ -246,18 +298,19 @@ class TriccNodeDisplayModel(TriccNodeBaseModel):
|
|
|
246
298
|
|
|
247
299
|
class TriccNodeNote(TriccNodeDisplayModel):
|
|
248
300
|
tricc_type: TriccNodeType = TriccNodeType.note
|
|
249
|
-
datatype: str =
|
|
301
|
+
datatype: str = "string"
|
|
302
|
+
|
|
250
303
|
|
|
251
304
|
class TriccNodeInputModel(TriccNodeDisplayModel):
|
|
252
|
-
required: Optional[Union[Expression, TriccOperation, TriccStatic]] =
|
|
253
|
-
constraint_message: Optional[Union[str, Dict[str,str]]] = None
|
|
305
|
+
required: Optional[Union[Expression, TriccOperation, TriccStatic]] = "1"
|
|
306
|
+
constraint_message: Optional[Union[str, Dict[str, str]]] = None
|
|
254
307
|
constraint: Optional[Expression] = None
|
|
255
|
-
save: Optional[str] = None
|
|
308
|
+
save: Optional[str] = None # contribute to another calculate
|
|
256
309
|
|
|
257
310
|
|
|
258
311
|
class TriccNodeDate(TriccNodeInputModel):
|
|
259
312
|
tricc_type: TriccNodeType = TriccNodeType.date
|
|
260
|
-
datatype: str =
|
|
313
|
+
datatype: str = "date"
|
|
261
314
|
|
|
262
315
|
|
|
263
316
|
class TriccNodeMainStart(TriccNodeBaseModel):
|
|
@@ -265,25 +318,25 @@ class TriccNodeMainStart(TriccNodeBaseModel):
|
|
|
265
318
|
form_id: Optional[str] = None
|
|
266
319
|
process: Optional[str] = None
|
|
267
320
|
relevance: Optional[Union[Expression, TriccOperation]] = None
|
|
268
|
-
datatype: str =
|
|
321
|
+
datatype: str = "boolean"
|
|
269
322
|
|
|
270
323
|
|
|
271
324
|
class TriccNodeLinkIn(TriccNodeBaseModel):
|
|
272
325
|
tricc_type: TriccNodeType = TriccNodeType.link_in
|
|
273
|
-
datatype: str =
|
|
326
|
+
datatype: str = "n/a"
|
|
274
327
|
|
|
275
328
|
|
|
276
329
|
class TriccNodeLinkOut(TriccNodeBaseModel):
|
|
277
330
|
tricc_type: TriccNodeType = TriccNodeType.link_out
|
|
278
331
|
reference: Optional[Union[TriccNodeLinkIn, triccId]] = None
|
|
279
332
|
# no need to copy
|
|
280
|
-
datatype: str =
|
|
333
|
+
datatype: str = "n/a"
|
|
281
334
|
|
|
282
335
|
|
|
283
336
|
class TriccNodeGoTo(TriccNodeBaseModel):
|
|
284
337
|
tricc_type: TriccNodeType = TriccNodeType.goto
|
|
285
338
|
link: Union[TriccNodeActivity, triccId]
|
|
286
|
-
datatype: str =
|
|
339
|
+
datatype: str = "n/a"
|
|
287
340
|
instance: int = 1
|
|
288
341
|
|
|
289
342
|
# no need ot copy
|
|
@@ -297,16 +350,16 @@ class TriccNodeGoTo(TriccNodeBaseModel):
|
|
|
297
350
|
|
|
298
351
|
class TriccNodeSelectOption(TriccNodeDisplayModel):
|
|
299
352
|
tricc_type: TriccNodeType = TriccNodeType.select_option
|
|
300
|
-
label: Union[str, Dict[str,str]]
|
|
353
|
+
label: Union[str, Dict[str, str]]
|
|
301
354
|
save: Optional[str] = None
|
|
302
355
|
select: TriccNodeInputModel
|
|
303
356
|
list_name: str
|
|
357
|
+
|
|
304
358
|
def get_datatype(self):
|
|
305
359
|
if self.name.isnumeric():
|
|
306
|
-
return
|
|
360
|
+
return "number"
|
|
307
361
|
else:
|
|
308
|
-
return
|
|
309
|
-
|
|
362
|
+
return "string"
|
|
310
363
|
|
|
311
364
|
def make_instance(self, instance_nb, activity, select, **kwargs):
|
|
312
365
|
# shallow copy
|
|
@@ -324,15 +377,16 @@ class TriccNodeSelect(TriccNodeInputModel):
|
|
|
324
377
|
filter: Optional[str] = None
|
|
325
378
|
options: Dict[int, TriccNodeSelectOption] = {}
|
|
326
379
|
list_name: str
|
|
380
|
+
|
|
327
381
|
def get_datatype(self):
|
|
328
382
|
rtype = set()
|
|
329
|
-
for k,o in self.options.items():
|
|
383
|
+
for k, o in self.options.items():
|
|
330
384
|
rtype.add(o.get_datatype())
|
|
331
|
-
if len(rtype)>1:
|
|
332
|
-
return
|
|
385
|
+
if len(rtype) > 1:
|
|
386
|
+
return "mixed"
|
|
333
387
|
else:
|
|
334
388
|
return rtype.pop()
|
|
335
|
-
|
|
389
|
+
|
|
336
390
|
def make_instance(self, instance_nb, activity, **kwargs):
|
|
337
391
|
# shallow copy, no copy of filter and list_name
|
|
338
392
|
instance = super().make_instance(instance_nb, activity=activity)
|
|
@@ -349,13 +403,15 @@ class TriccNodeSelectOne(TriccNodeSelect):
|
|
|
349
403
|
class TriccNodeSelectYesNo(TriccNodeSelectOne):
|
|
350
404
|
pass
|
|
351
405
|
|
|
352
|
-
|
|
406
|
+
|
|
407
|
+
class TriccNodeAcceptDiagnostic(TriccNodeSelectYesNo):
|
|
353
408
|
severity: Optional[str] = None
|
|
354
409
|
priority: Union[float, int, None] = None
|
|
355
410
|
|
|
356
411
|
|
|
357
412
|
class TriccParentMixIn(BaseModel):
|
|
358
|
-
parent: Optional[TriccNodeBaseModel]
|
|
413
|
+
parent: Optional[TriccNodeBaseModel] = None
|
|
414
|
+
|
|
359
415
|
|
|
360
416
|
# options: List[TriccNodeSelectOption] = [TriccNodeSelectOption(label='Yes', name='yes'),
|
|
361
417
|
# TriccNodeSelectOption(label='No', name='no')]
|
|
@@ -370,7 +426,7 @@ class TriccNodeSelectMultiple(TriccNodeSelect):
|
|
|
370
426
|
class TriccNodeNumber(TriccNodeInputModel):
|
|
371
427
|
min: Optional[float] = None
|
|
372
428
|
max: Optional[float] = None
|
|
373
|
-
datatype
|
|
429
|
+
datatype: str = "number"
|
|
374
430
|
# no need to copy min max in make isntance
|
|
375
431
|
|
|
376
432
|
|
|
@@ -378,48 +434,48 @@ class TriccNodeDecimal(TriccNodeNumber):
|
|
|
378
434
|
tricc_type: TriccNodeType = TriccNodeType.decimal
|
|
379
435
|
|
|
380
436
|
|
|
381
|
-
|
|
382
437
|
class TriccNodeInteger(TriccNodeNumber):
|
|
383
438
|
tricc_type: TriccNodeType = TriccNodeType.integer
|
|
384
439
|
|
|
385
440
|
|
|
386
441
|
class TriccNodeText(TriccNodeInputModel):
|
|
387
442
|
tricc_type: TriccNodeType = TriccNodeType.text
|
|
388
|
-
datatype
|
|
443
|
+
datatype: str = "string"
|
|
389
444
|
|
|
390
445
|
|
|
391
446
|
class TriccNodeMoreInfo(TriccNodeInputModel, TriccParentMixIn):
|
|
392
447
|
tricc_type: TriccNodeType = TriccNodeType.help
|
|
393
|
-
datatype
|
|
448
|
+
datatype: str = "n/a"
|
|
449
|
+
|
|
394
450
|
|
|
395
|
-
|
|
396
|
-
|
|
397
451
|
class TriccProject(BaseModel):
|
|
398
452
|
title: str = "My project"
|
|
399
453
|
description: str = ""
|
|
400
454
|
lang_code: str = "en"
|
|
401
455
|
# abstract graph / Scheduling
|
|
402
|
-
#abs_graph: MultiDiGraph = MultiDiGraph()
|
|
403
|
-
#abs_graph_process_start: Dict = {}
|
|
456
|
+
# abs_graph: MultiDiGraph = MultiDiGraph()
|
|
457
|
+
# abs_graph_process_start: Dict = {}
|
|
404
458
|
# implementation graph
|
|
405
|
-
#impl_graph: MultiDiGraph = MultiDiGraph()
|
|
406
|
-
#impl_graph_process_start: Dict = {}
|
|
459
|
+
# impl_graph: MultiDiGraph = MultiDiGraph()
|
|
460
|
+
# impl_graph_process_start: Dict = {}
|
|
407
461
|
# authored graph
|
|
408
|
-
#graph: MultiDiGraph = MultiDiGraph()
|
|
409
|
-
#graph_process_start: Dict = {}
|
|
462
|
+
# graph: MultiDiGraph = MultiDiGraph()
|
|
463
|
+
# graph_process_start: Dict = {}
|
|
410
464
|
# list of context:
|
|
411
|
-
pages: Dict[str, TriccNodeActivity]= {}
|
|
465
|
+
pages: Dict[str, TriccNodeActivity] = {}
|
|
412
466
|
start_pages: Dict[str, TriccNodeActivity] = {}
|
|
413
|
-
images: List[Dict[str,str]] = []
|
|
414
|
-
contexts
|
|
467
|
+
images: List[Dict[str, str]] = []
|
|
468
|
+
contexts: Set[triccName] = set()
|
|
469
|
+
|
|
415
470
|
# TODO manage trad properly
|
|
416
471
|
def get_keyword_trad(keyword):
|
|
417
472
|
return keyword
|
|
473
|
+
|
|
418
474
|
# dict of code_system_id: codesystem
|
|
419
475
|
code_systems: Dict[str, CodeSystem] = {}
|
|
420
476
|
# dict of valueset_id: valueset
|
|
421
477
|
value_sets: Dict[str, ValueSet] = {}
|
|
422
|
-
|
|
423
|
-
#class Config:
|
|
424
|
-
|
|
425
|
-
# arbitrary_types_allowed = True
|
|
478
|
+
|
|
479
|
+
# class Config:
|
|
480
|
+
# Allow arbitrary types for validation
|
|
481
|
+
# arbitrary_types_allowed = True
|
tricc_oo/parsers/xml.py
CHANGED
|
@@ -7,7 +7,7 @@ type_name = "odk_type"
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def read_drawio(file_content):
|
|
10
|
-
if file_content.startswith(
|
|
10
|
+
if file_content.startswith("<mxfile host"):
|
|
11
11
|
file_content = "<?xml version='1.0' encoding='utf-8'?>\n" + file_content
|
|
12
12
|
file_content = bytes(bytearray(file_content, encoding="utf-8"))
|
|
13
13
|
root = etree.fromstring(file_content)
|
|
@@ -24,9 +24,7 @@ def read_drawio(file_content):
|
|
|
24
24
|
|
|
25
25
|
def get_container_media(diagram, container_id):
|
|
26
26
|
# get the edge
|
|
27
|
-
return diagram.find(
|
|
28
|
-
f".//object[@{type_name}='container_hint_media' and @id='{container_id}']"
|
|
29
|
-
)
|
|
27
|
+
return diagram.find(f".//object[@{type_name}='container_hint_media' and @id='{container_id}']")
|
|
30
28
|
# get the image node
|
|
31
29
|
|
|
32
30
|
|
|
@@ -57,16 +55,13 @@ def get_tricc_type_list(diagram, node_type, tricc_type=None, parent_id=None):
|
|
|
57
55
|
return get_child_through_mxcell(diagram, type_name, node_type, parent_suffix, tricc_type)
|
|
58
56
|
|
|
59
57
|
else:
|
|
60
|
-
child = list(
|
|
61
|
-
diagram.findall(
|
|
62
|
-
f'.//{node_type}[@{type_name}="{tricc_type}"]{parent_suffix}'
|
|
63
|
-
)
|
|
64
|
-
)
|
|
58
|
+
child = list(diagram.findall(f'.//{node_type}[@{type_name}="{tricc_type}"]{parent_suffix}'))
|
|
65
59
|
if child:
|
|
66
60
|
return child
|
|
67
61
|
else:
|
|
68
62
|
return get_child_through_mxcell(diagram, type_name, node_type, parent_suffix, tricc_type)
|
|
69
63
|
|
|
64
|
+
|
|
70
65
|
def get_child_through_mxcell(diagram, type_name, node_type, parent_suffix, tricc_type):
|
|
71
66
|
child = []
|
|
72
67
|
# try with mxCell
|
|
@@ -74,19 +69,17 @@ def get_child_through_mxcell(diagram, type_name, node_type, parent_suffix, tricc
|
|
|
74
69
|
for s in sub:
|
|
75
70
|
obj = s.getparent()
|
|
76
71
|
if (
|
|
77
|
-
obj.tag == node_type
|
|
72
|
+
obj.tag == node_type
|
|
78
73
|
and type_name in obj.attrib
|
|
79
|
-
and (
|
|
80
|
-
not tricc_type
|
|
81
|
-
or tricc_type == obj.attrib.get(type_name, None)
|
|
82
|
-
)
|
|
74
|
+
and (not tricc_type or tricc_type == obj.attrib.get(type_name, None))
|
|
83
75
|
):
|
|
84
76
|
child.append(obj)
|
|
85
77
|
return child
|
|
86
78
|
|
|
87
|
-
|
|
79
|
+
|
|
88
80
|
# end def
|
|
89
81
|
|
|
82
|
+
|
|
90
83
|
def get_mxcell_parent_list(diagram, select_id, tricc_type=None, attrib=None):
|
|
91
84
|
# get the mxcels
|
|
92
85
|
if tricc_type is None:
|
|
@@ -100,9 +93,7 @@ def get_mxcell_parent_list(diagram, select_id, tricc_type=None, attrib=None):
|
|
|
100
93
|
result += get_mxcell_parent_list(diagram, select_id, type)
|
|
101
94
|
return result
|
|
102
95
|
else:
|
|
103
|
-
return diagram.findall(
|
|
104
|
-
f".//mxCell[@parent='{select_id}']/..[@{type_name}='{tricc_type}']"
|
|
105
|
-
)
|
|
96
|
+
return diagram.findall(f".//mxCell[@parent='{select_id}']/..[@{type_name}='{tricc_type}']")
|
|
106
97
|
|
|
107
98
|
|
|
108
99
|
def get_elm(diagram, id):
|
|
@@ -110,8 +101,8 @@ def get_elm(diagram, id):
|
|
|
110
101
|
|
|
111
102
|
|
|
112
103
|
def get_mxcell(diagram, id):
|
|
113
|
-
elm =
|
|
114
|
-
if elm.tag ==
|
|
104
|
+
elm = diagram.find(f".//*[@id='{id}']")
|
|
105
|
+
if elm.tag == "mxCell":
|
|
115
106
|
return elm
|
|
116
107
|
else:
|
|
117
108
|
return diagram.find(f".//*[@id='{id}']/mxCell")
|
|
@@ -119,13 +110,9 @@ def get_mxcell(diagram, id):
|
|
|
119
110
|
|
|
120
111
|
def get_edges_list(diagram):
|
|
121
112
|
# return list(diagram.findall('.//mxCell[@edge][@source][@target]'))
|
|
122
|
-
# to ensure source and target one can use this xpath above
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
diagram.findall(".//mxCell[@edge][@source]")
|
|
126
|
-
+ diagram.findall(".//mxCell[@edge][@target]")
|
|
127
|
-
)
|
|
128
|
-
)
|
|
113
|
+
# to ensure source and target one can use this xpath above
|
|
114
|
+
# but better trigger a pydantic error if source/target are missing
|
|
115
|
+
return list(set(diagram.findall(".//mxCell[@edge][@source]") + diagram.findall(".//mxCell[@edge][@target]")))
|
|
129
116
|
|
|
130
117
|
|
|
131
118
|
def get_select_option_image(diagram, select_option_id):
|
|
@@ -133,6 +120,4 @@ def get_select_option_image(diagram, select_option_id):
|
|
|
133
120
|
edge = diagram.find(f".//mxCell[@edge and @target='{select_option_id}']")
|
|
134
121
|
# get the image node
|
|
135
122
|
if edge is not None and edge.attrib.get("source") is not None:
|
|
136
|
-
return diagram.find(
|
|
137
|
-
f".//mxCell[@id='{edge.attrib.get('source')}' and not(@{type_name}) and not(@edge)]"
|
|
138
|
-
)
|
|
123
|
+
return diagram.find(f".//mxCell[@id='{edge.attrib.get('source')}' and not(@{type_name}) and not(@edge)]")
|
tricc_oo/serializers/planuml.py
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
# we should not use the logger
|
|
2
2
|
import logging
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
plantuml = logging.getLogger("plantuml")
|
|
5
|
+
|
|
4
6
|
|
|
5
7
|
def print_plantuml(start_page):
|
|
6
|
-
|
|
7
|
-
pass
|
|
8
|
-
# plantuml.info("{0} -> {1}: 'from {2}'".format(page.id.replace('-',''), next_page.id.replace('-',''), node.label) )
|
|
9
|
-
# plantuml.info('{0}[label="{1}"]'.format(next_page.id.replace('-',''),next_page.label ))
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
pass
|