tricc-oo 1.5.13__py3-none-any.whl → 1.6.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tests/build.py +20 -28
- tests/test_build.py +260 -0
- tests/test_cql.py +48 -109
- tests/to_ocl.py +15 -17
- tricc_oo/__init__.py +0 -6
- tricc_oo/converters/codesystem_to_ocl.py +51 -40
- tricc_oo/converters/cql/cqlLexer.py +1 -0
- tricc_oo/converters/cql/cqlListener.py +1 -0
- tricc_oo/converters/cql/cqlParser.py +1 -0
- tricc_oo/converters/cql/cqlVisitor.py +1 -0
- tricc_oo/converters/cql_to_operation.py +129 -123
- tricc_oo/converters/datadictionnary.py +45 -54
- tricc_oo/converters/drawio_type_map.py +146 -65
- tricc_oo/converters/tricc_to_xls_form.py +58 -28
- tricc_oo/converters/utils.py +4 -4
- tricc_oo/converters/xml_to_tricc.py +296 -235
- tricc_oo/models/__init__.py +2 -1
- tricc_oo/models/base.py +333 -305
- tricc_oo/models/calculate.py +66 -51
- tricc_oo/models/lang.py +26 -27
- tricc_oo/models/ocl.py +146 -161
- tricc_oo/models/ordered_set.py +15 -19
- tricc_oo/models/tricc.py +149 -89
- tricc_oo/parsers/xml.py +15 -30
- tricc_oo/serializers/planuml.py +4 -6
- tricc_oo/serializers/xls_form.py +110 -153
- tricc_oo/strategies/input/base_input_strategy.py +28 -32
- tricc_oo/strategies/input/drawio.py +59 -71
- tricc_oo/strategies/output/base_output_strategy.py +151 -65
- tricc_oo/strategies/output/dhis2_form.py +908 -0
- tricc_oo/strategies/output/fhir_form.py +377 -0
- tricc_oo/strategies/output/html_form.py +224 -0
- tricc_oo/strategies/output/openmrs_form.py +694 -0
- tricc_oo/strategies/output/spice.py +106 -127
- tricc_oo/strategies/output/xls_form.py +322 -244
- tricc_oo/strategies/output/xlsform_cdss.py +627 -142
- tricc_oo/strategies/output/xlsform_cht.py +252 -125
- tricc_oo/strategies/output/xlsform_cht_hf.py +13 -24
- tricc_oo/visitors/tricc.py +1424 -1033
- tricc_oo/visitors/utils.py +16 -16
- tricc_oo/visitors/xform_pd.py +91 -89
- {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/METADATA +128 -84
- tricc_oo-1.6.8.dist-info/RECORD +52 -0
- tricc_oo-1.6.8.dist-info/licenses/LICENSE +373 -0
- {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/top_level.txt +0 -0
- tricc_oo-1.5.13.dist-info/RECORD +0 -46
- {tricc_oo-1.5.13.dist-info → tricc_oo-1.6.8.dist-info}/WHEEL +0 -0
tricc_oo/models/tricc.py
CHANGED
|
@@ -1,24 +1,32 @@
|
|
|
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
|
+
TRICC_TRUE_VALUE = "true"
|
|
19
|
+
TRICC_FALSE_VALUE = "false"
|
|
20
|
+
|
|
14
21
|
|
|
15
22
|
class TriccNodeCalculateBase(TriccNodeBaseModel):
|
|
16
|
-
#input: Dict[TriccOperation, TriccNodeBaseModel] = {}
|
|
17
|
-
reference: Union[List[Union[TriccNodeBaseModel,TriccStatic]], Expression, TriccStatic] = None
|
|
23
|
+
# input: Dict[TriccOperation, TriccNodeBaseModel] = {}
|
|
24
|
+
reference: Union[List[Union[TriccNodeBaseModel, TriccStatic]], Expression, TriccStatic] = None
|
|
18
25
|
expression_reference: Union[str, TriccOperation] = None
|
|
19
26
|
last: bool = None
|
|
20
|
-
datatype: str =
|
|
27
|
+
datatype: str = "boolean"
|
|
21
28
|
priority: Union[float, int, None] = None
|
|
29
|
+
|
|
22
30
|
# to use the enum value of the TriccNodeType
|
|
23
31
|
class Config:
|
|
24
32
|
use_enum_values = True # <--
|
|
@@ -26,11 +34,18 @@ class TriccNodeCalculateBase(TriccNodeBaseModel):
|
|
|
26
34
|
def make_instance(self, instance_nb, activity, **kwargs):
|
|
27
35
|
# shallow copy
|
|
28
36
|
instance = super().make_instance(instance_nb, activity=activity)
|
|
29
|
-
#input = {}
|
|
30
|
-
#instance.input = input
|
|
31
|
-
|
|
37
|
+
# input = {}
|
|
38
|
+
# instance.input = input
|
|
39
|
+
self.expression.copy() if self.expression is not None else None
|
|
32
40
|
if self.reference:
|
|
33
|
-
instance.reference = [
|
|
41
|
+
instance.reference = [
|
|
42
|
+
(
|
|
43
|
+
e.copy()
|
|
44
|
+
if isinstance(e, (TriccReference, TriccOperation))
|
|
45
|
+
else (TriccReference(e.name) if hasattr(e, "name") else e)
|
|
46
|
+
)
|
|
47
|
+
for e in self.reference
|
|
48
|
+
]
|
|
34
49
|
else:
|
|
35
50
|
instance.reference = None
|
|
36
51
|
if instance.base_instance != self:
|
|
@@ -38,14 +53,13 @@ class TriccNodeCalculateBase(TriccNodeBaseModel):
|
|
|
38
53
|
return instance
|
|
39
54
|
|
|
40
55
|
def __init__(self, **data):
|
|
41
|
-
if
|
|
42
|
-
data[
|
|
56
|
+
if "name" not in data:
|
|
57
|
+
data["name"] = get_rand_name(data.get("id", None))
|
|
43
58
|
super().__init__(**data)
|
|
44
|
-
|
|
45
|
-
|
|
59
|
+
|
|
46
60
|
def append(self, elm):
|
|
47
61
|
self.reference.append(elm)
|
|
48
|
-
|
|
62
|
+
|
|
49
63
|
def get_references(self):
|
|
50
64
|
if isinstance(self.reference, set):
|
|
51
65
|
return self.reference
|
|
@@ -55,10 +69,11 @@ class TriccNodeCalculateBase(TriccNodeBaseModel):
|
|
|
55
69
|
return self.expression_reference.get_references()
|
|
56
70
|
elif isinstance(self.reference, TriccOperation):
|
|
57
71
|
return self.reference.get_references()
|
|
58
|
-
|
|
72
|
+
|
|
59
73
|
elif self.reference:
|
|
60
74
|
return self.reference
|
|
61
75
|
logger.critical("Cannot get reference from a sting")
|
|
76
|
+
|
|
62
77
|
def __str__(self):
|
|
63
78
|
return self.get_name()
|
|
64
79
|
|
|
@@ -75,29 +90,29 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
75
90
|
nodes: Dict[str, TriccNodeBaseModel] = {}
|
|
76
91
|
# groups
|
|
77
92
|
groups: Dict[str, TriccGroup] = {}
|
|
78
|
-
# save the instance on the base activity
|
|
93
|
+
# save the instance on the base activity
|
|
79
94
|
instances: Dict[int, TriccNodeBaseModel] = {}
|
|
80
95
|
relevance: Optional[Union[Expression, TriccOperation]] = None
|
|
81
|
-
#caclulate that are not part of the any skip logic:
|
|
96
|
+
# caclulate that are not part of the any skip logic:
|
|
82
97
|
# - inputs
|
|
83
98
|
# - dangling calculate
|
|
84
99
|
# - case definition
|
|
85
100
|
calculates: List[TriccNodeCalculateBase] = []
|
|
86
101
|
applicability: Optional[Union[Expression, TriccOperation]] = None
|
|
87
102
|
|
|
88
|
-
# redefine
|
|
103
|
+
# redefine
|
|
89
104
|
def make_instance(self, instance_nb=None, **kwargs):
|
|
90
105
|
from tricc_oo.models.calculate import (
|
|
91
106
|
TriccNodeDisplayBridge,
|
|
92
107
|
TriccNodeBridge,
|
|
93
|
-
|
|
94
108
|
)
|
|
109
|
+
|
|
95
110
|
# shallow copy
|
|
96
111
|
if instance_nb in self.instances:
|
|
97
112
|
return self.instances[instance_nb]
|
|
98
113
|
else:
|
|
99
114
|
instance = super().make_instance(instance_nb, activity=None)
|
|
100
|
-
base_instance =
|
|
115
|
+
base_instance = self.base_instance or self
|
|
101
116
|
instance.base_instance = base_instance
|
|
102
117
|
# instance.base_instance = self
|
|
103
118
|
# we duplicate all the related nodes (not the calculate, duplication is manage in calculate version code)
|
|
@@ -119,15 +134,36 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
119
134
|
instance.edges.append(edge.make_instance(instance_nb, activity=instance))
|
|
120
135
|
instance.update_nodes(self.root)
|
|
121
136
|
# we walk throught the nodes and replace them when ready
|
|
122
|
-
for node in list(
|
|
137
|
+
for node in list(
|
|
138
|
+
filter(
|
|
139
|
+
lambda p_node: isinstance(p_node, (TriccNodeDisplayBridge, TriccNodeBridge)),
|
|
140
|
+
list(self.nodes.values()),
|
|
141
|
+
)
|
|
142
|
+
):
|
|
123
143
|
instance.update_nodes(node)
|
|
124
|
-
for node in list(
|
|
144
|
+
for node in list(
|
|
145
|
+
filter(
|
|
146
|
+
lambda p_node: p_node != self.root
|
|
147
|
+
and not isinstance(p_node, (TriccNodeDisplayBridge, TriccNodeBridge)),
|
|
148
|
+
list(self.nodes.values()),
|
|
149
|
+
)
|
|
150
|
+
):
|
|
125
151
|
instance_node = instance.update_nodes(node)
|
|
126
152
|
if node in self.calculates and instance_node:
|
|
127
153
|
instance.calculates.append(instance_node)
|
|
128
|
-
# update parents
|
|
129
|
-
for node in list(
|
|
130
|
-
|
|
154
|
+
# update parents
|
|
155
|
+
for node in list(
|
|
156
|
+
filter(
|
|
157
|
+
lambda p_node: getattr(p_node, "parent", None) is not None,
|
|
158
|
+
list(instance.nodes.values()),
|
|
159
|
+
)
|
|
160
|
+
):
|
|
161
|
+
new_parent = list(
|
|
162
|
+
filter(
|
|
163
|
+
lambda p_node: p_node.base_instance == node.parent,
|
|
164
|
+
list(instance.nodes.values()),
|
|
165
|
+
)
|
|
166
|
+
)
|
|
131
167
|
if new_parent:
|
|
132
168
|
node.parent = new_parent[0]
|
|
133
169
|
else:
|
|
@@ -148,7 +184,7 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
148
184
|
instance_group.group == self
|
|
149
185
|
|
|
150
186
|
def update_groups(self, group):
|
|
151
|
-
# create new group
|
|
187
|
+
# create new group
|
|
152
188
|
instance_group = group.make_instance(self.instance, activity=self)
|
|
153
189
|
# update the group in all activity
|
|
154
190
|
for node in list(self.nodes.values()):
|
|
@@ -158,18 +194,20 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
158
194
|
|
|
159
195
|
def update_nodes(self, node_origin):
|
|
160
196
|
from tricc_oo.models.calculate import (
|
|
161
|
-
TriccNodeEnd,
|
|
162
197
|
TriccNodeActivityStart,
|
|
163
|
-
TriccNodeMainStart,
|
|
164
198
|
TriccNodeActivityEnd,
|
|
165
|
-
TriccRhombusMixIn
|
|
199
|
+
TriccRhombusMixIn,
|
|
166
200
|
)
|
|
201
|
+
|
|
167
202
|
updated_edges = 0
|
|
168
203
|
node_instance = None
|
|
169
204
|
if not isinstance(node_origin, TriccNodeSelectOption):
|
|
170
205
|
# do not perpetuate the instance number in the underlying activities
|
|
171
206
|
if isinstance(node_origin, TriccNodeActivity):
|
|
172
|
-
node_instance = node_origin.make_instance(
|
|
207
|
+
node_instance = node_origin.make_instance(
|
|
208
|
+
node_origin.instance if node_origin.instance < 100 else 0,
|
|
209
|
+
activity=self,
|
|
210
|
+
)
|
|
173
211
|
else:
|
|
174
212
|
node_instance = node_origin.make_instance(self.instance, activity=self)
|
|
175
213
|
self.nodes[node_instance.id] = node_instance
|
|
@@ -185,13 +223,16 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
185
223
|
for n in node_instance.activity.nodes.values():
|
|
186
224
|
if n.base_instance.id == old_path.id:
|
|
187
225
|
node_instance.path = n
|
|
188
|
-
# test next_nodes to check that the instance has already prev/next
|
|
226
|
+
# test next_nodes to check that the instance has already prev/next
|
|
189
227
|
if node_instance.path is None and node_instance.next_nodes:
|
|
190
228
|
logger.critical("new path not found")
|
|
191
229
|
elif len(node_instance.prev_nodes) == 1:
|
|
192
|
-
|
|
193
|
-
elif not (
|
|
194
|
-
|
|
230
|
+
node_origin.path = list(node_instance.prev_nodes)[0]
|
|
231
|
+
elif not (
|
|
232
|
+
len(node_instance.reference) == 1
|
|
233
|
+
and issubclass(node_instance.reference[0].__class__, TriccNodeInputModel)
|
|
234
|
+
):
|
|
235
|
+
logger.warning("Rhombus without a path")
|
|
195
236
|
exit(1)
|
|
196
237
|
# generate options
|
|
197
238
|
elif issubclass(node_instance.__class__, TriccNodeSelect):
|
|
@@ -199,19 +240,27 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
199
240
|
updated_edges += self.update_edges(node_origin.options[key], option_instance)
|
|
200
241
|
updated_edges += self.update_edges(node_origin, node_instance)
|
|
201
242
|
if updated_edges == 0:
|
|
202
|
-
node_edge = list(
|
|
203
|
-
|
|
243
|
+
node_edge = list(
|
|
244
|
+
filter(
|
|
245
|
+
lambda x: (x.source == node_instance.id or x.source == node_instance),
|
|
246
|
+
node_instance.activity.edges,
|
|
247
|
+
)
|
|
248
|
+
)
|
|
204
249
|
if len(node_edge) == 0 and not issubclass(node_origin.__class__, TriccNodeCalculateBase):
|
|
205
|
-
logger.warning(
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
250
|
+
logger.warning(
|
|
251
|
+
"no edge was updated for node {}::{}::{}::{}".format(
|
|
252
|
+
node_instance.activity.get_name(),
|
|
253
|
+
node_instance.__class__,
|
|
254
|
+
node_instance.get_name(),
|
|
255
|
+
node_instance.instance,
|
|
256
|
+
)
|
|
257
|
+
)
|
|
209
258
|
return node_instance
|
|
210
259
|
|
|
211
260
|
def update_edges(self, node_origin, node_instance):
|
|
212
261
|
updates = 0
|
|
213
|
-
|
|
214
|
-
for edge in self.edges:
|
|
262
|
+
|
|
263
|
+
for edge in self.edges:
|
|
215
264
|
if edge.source == node_origin.id or edge.source == node_origin:
|
|
216
265
|
edge.source = node_instance.id
|
|
217
266
|
updates += 1
|
|
@@ -225,9 +274,14 @@ class TriccNodeActivity(TriccNodeBaseModel):
|
|
|
225
274
|
TriccNodeEnd,
|
|
226
275
|
TriccNodeActivityEnd,
|
|
227
276
|
)
|
|
228
|
-
return list(filter(lambda x: isinstance(x, (TriccNodeActivityEnd)) or (isinstance(x, (TriccNodeEnd)) and isinstance(self.root, TriccNodeMainStart )), self.nodes.values()))
|
|
229
|
-
|
|
230
277
|
|
|
278
|
+
return list(
|
|
279
|
+
filter(
|
|
280
|
+
lambda x: isinstance(x, (TriccNodeActivityEnd))
|
|
281
|
+
or (isinstance(x, (TriccNodeEnd)) and isinstance(self.root, TriccNodeMainStart)),
|
|
282
|
+
self.nodes.values(),
|
|
283
|
+
)
|
|
284
|
+
)
|
|
231
285
|
|
|
232
286
|
|
|
233
287
|
class TriccNodeDisplayModel(TriccNodeBaseModel):
|
|
@@ -237,6 +291,8 @@ class TriccNodeDisplayModel(TriccNodeBaseModel):
|
|
|
237
291
|
help: Optional[Union[str, TriccNodeBaseModel]] = None
|
|
238
292
|
group: Optional[Union[TriccGroup, TriccNodeActivity]] = None
|
|
239
293
|
relevance: Optional[Union[Expression, TriccOperation]] = None
|
|
294
|
+
default: Optional[Union[Expression, TriccOperation, TriccReference, TriccStatic]] = None
|
|
295
|
+
trigger: Optional[Union[Expression, TriccOperation, TriccReference]] = None
|
|
240
296
|
priority: Union[float, int, None] = None
|
|
241
297
|
|
|
242
298
|
# to use the enum value of the TriccNodeType
|
|
@@ -244,18 +300,19 @@ class TriccNodeDisplayModel(TriccNodeBaseModel):
|
|
|
244
300
|
|
|
245
301
|
class TriccNodeNote(TriccNodeDisplayModel):
|
|
246
302
|
tricc_type: TriccNodeType = TriccNodeType.note
|
|
247
|
-
datatype: str =
|
|
303
|
+
datatype: str = "string"
|
|
304
|
+
|
|
248
305
|
|
|
249
306
|
class TriccNodeInputModel(TriccNodeDisplayModel):
|
|
250
|
-
required: Optional[Union[Expression, TriccOperation, TriccStatic]] =
|
|
251
|
-
constraint_message: Optional[Union[str, Dict[str,str]]] = None
|
|
307
|
+
required: Optional[Union[Expression, TriccOperation, TriccStatic]] = "1"
|
|
308
|
+
constraint_message: Optional[Union[str, Dict[str, str]]] = None
|
|
252
309
|
constraint: Optional[Expression] = None
|
|
253
|
-
save: Optional[str] = None
|
|
310
|
+
save: Optional[str] = None # contribute to another calculate
|
|
254
311
|
|
|
255
312
|
|
|
256
313
|
class TriccNodeDate(TriccNodeInputModel):
|
|
257
314
|
tricc_type: TriccNodeType = TriccNodeType.date
|
|
258
|
-
datatype: str =
|
|
315
|
+
datatype: str = "date"
|
|
259
316
|
|
|
260
317
|
|
|
261
318
|
class TriccNodeMainStart(TriccNodeBaseModel):
|
|
@@ -263,25 +320,25 @@ class TriccNodeMainStart(TriccNodeBaseModel):
|
|
|
263
320
|
form_id: Optional[str] = None
|
|
264
321
|
process: Optional[str] = None
|
|
265
322
|
relevance: Optional[Union[Expression, TriccOperation]] = None
|
|
266
|
-
datatype: str =
|
|
323
|
+
datatype: str = "boolean"
|
|
267
324
|
|
|
268
325
|
|
|
269
326
|
class TriccNodeLinkIn(TriccNodeBaseModel):
|
|
270
327
|
tricc_type: TriccNodeType = TriccNodeType.link_in
|
|
271
|
-
datatype: str =
|
|
328
|
+
datatype: str = "n/a"
|
|
272
329
|
|
|
273
330
|
|
|
274
331
|
class TriccNodeLinkOut(TriccNodeBaseModel):
|
|
275
332
|
tricc_type: TriccNodeType = TriccNodeType.link_out
|
|
276
333
|
reference: Optional[Union[TriccNodeLinkIn, triccId]] = None
|
|
277
334
|
# no need to copy
|
|
278
|
-
datatype: str =
|
|
335
|
+
datatype: str = "n/a"
|
|
279
336
|
|
|
280
337
|
|
|
281
338
|
class TriccNodeGoTo(TriccNodeBaseModel):
|
|
282
339
|
tricc_type: TriccNodeType = TriccNodeType.goto
|
|
283
340
|
link: Union[TriccNodeActivity, triccId]
|
|
284
|
-
datatype: str =
|
|
341
|
+
datatype: str = "n/a"
|
|
285
342
|
instance: int = 1
|
|
286
343
|
|
|
287
344
|
# no need ot copy
|
|
@@ -295,16 +352,16 @@ class TriccNodeGoTo(TriccNodeBaseModel):
|
|
|
295
352
|
|
|
296
353
|
class TriccNodeSelectOption(TriccNodeDisplayModel):
|
|
297
354
|
tricc_type: TriccNodeType = TriccNodeType.select_option
|
|
298
|
-
label: Union[str, Dict[str,str]]
|
|
355
|
+
label: Union[str, Dict[str, str]]
|
|
299
356
|
save: Optional[str] = None
|
|
300
357
|
select: TriccNodeInputModel
|
|
301
358
|
list_name: str
|
|
359
|
+
|
|
302
360
|
def get_datatype(self):
|
|
303
361
|
if self.name.isnumeric():
|
|
304
|
-
return
|
|
362
|
+
return "number"
|
|
305
363
|
else:
|
|
306
|
-
return
|
|
307
|
-
|
|
364
|
+
return "string"
|
|
308
365
|
|
|
309
366
|
def make_instance(self, instance_nb, activity, select, **kwargs):
|
|
310
367
|
# shallow copy
|
|
@@ -322,15 +379,16 @@ class TriccNodeSelect(TriccNodeInputModel):
|
|
|
322
379
|
filter: Optional[str] = None
|
|
323
380
|
options: Dict[int, TriccNodeSelectOption] = {}
|
|
324
381
|
list_name: str
|
|
382
|
+
|
|
325
383
|
def get_datatype(self):
|
|
326
384
|
rtype = set()
|
|
327
|
-
for k,o in self.options.items():
|
|
385
|
+
for k, o in self.options.items():
|
|
328
386
|
rtype.add(o.get_datatype())
|
|
329
|
-
if len(rtype)>1:
|
|
330
|
-
return
|
|
387
|
+
if len(rtype) > 1:
|
|
388
|
+
return "mixed"
|
|
331
389
|
else:
|
|
332
390
|
return rtype.pop()
|
|
333
|
-
|
|
391
|
+
|
|
334
392
|
def make_instance(self, instance_nb, activity, **kwargs):
|
|
335
393
|
# shallow copy, no copy of filter and list_name
|
|
336
394
|
instance = super().make_instance(instance_nb, activity=activity)
|
|
@@ -347,13 +405,15 @@ class TriccNodeSelectOne(TriccNodeSelect):
|
|
|
347
405
|
class TriccNodeSelectYesNo(TriccNodeSelectOne):
|
|
348
406
|
pass
|
|
349
407
|
|
|
350
|
-
|
|
408
|
+
|
|
409
|
+
class TriccNodeAcceptDiagnostic(TriccNodeSelectYesNo):
|
|
351
410
|
severity: Optional[str] = None
|
|
352
411
|
priority: Union[float, int, None] = None
|
|
353
412
|
|
|
354
413
|
|
|
355
414
|
class TriccParentMixIn(BaseModel):
|
|
356
|
-
parent: Optional[TriccNodeBaseModel]
|
|
415
|
+
parent: Optional[TriccNodeBaseModel] = None
|
|
416
|
+
|
|
357
417
|
|
|
358
418
|
# options: List[TriccNodeSelectOption] = [TriccNodeSelectOption(label='Yes', name='yes'),
|
|
359
419
|
# TriccNodeSelectOption(label='No', name='no')]
|
|
@@ -368,7 +428,7 @@ class TriccNodeSelectMultiple(TriccNodeSelect):
|
|
|
368
428
|
class TriccNodeNumber(TriccNodeInputModel):
|
|
369
429
|
min: Optional[float] = None
|
|
370
430
|
max: Optional[float] = None
|
|
371
|
-
datatype
|
|
431
|
+
datatype: str = "number"
|
|
372
432
|
# no need to copy min max in make isntance
|
|
373
433
|
|
|
374
434
|
|
|
@@ -376,48 +436,48 @@ class TriccNodeDecimal(TriccNodeNumber):
|
|
|
376
436
|
tricc_type: TriccNodeType = TriccNodeType.decimal
|
|
377
437
|
|
|
378
438
|
|
|
379
|
-
|
|
380
439
|
class TriccNodeInteger(TriccNodeNumber):
|
|
381
440
|
tricc_type: TriccNodeType = TriccNodeType.integer
|
|
382
441
|
|
|
383
442
|
|
|
384
443
|
class TriccNodeText(TriccNodeInputModel):
|
|
385
444
|
tricc_type: TriccNodeType = TriccNodeType.text
|
|
386
|
-
datatype
|
|
445
|
+
datatype: str = "string"
|
|
387
446
|
|
|
388
447
|
|
|
389
448
|
class TriccNodeMoreInfo(TriccNodeInputModel, TriccParentMixIn):
|
|
390
449
|
tricc_type: TriccNodeType = TriccNodeType.help
|
|
391
|
-
datatype
|
|
450
|
+
datatype: str = "n/a"
|
|
451
|
+
|
|
392
452
|
|
|
393
|
-
|
|
394
|
-
|
|
395
453
|
class TriccProject(BaseModel):
|
|
396
454
|
title: str = "My project"
|
|
397
455
|
description: str = ""
|
|
398
456
|
lang_code: str = "en"
|
|
399
457
|
# abstract graph / Scheduling
|
|
400
|
-
#abs_graph: MultiDiGraph = MultiDiGraph()
|
|
401
|
-
#abs_graph_process_start: Dict = {}
|
|
458
|
+
# abs_graph: MultiDiGraph = MultiDiGraph()
|
|
459
|
+
# abs_graph_process_start: Dict = {}
|
|
402
460
|
# implementation graph
|
|
403
|
-
#impl_graph: MultiDiGraph = MultiDiGraph()
|
|
404
|
-
#impl_graph_process_start: Dict = {}
|
|
461
|
+
# impl_graph: MultiDiGraph = MultiDiGraph()
|
|
462
|
+
# impl_graph_process_start: Dict = {}
|
|
405
463
|
# authored graph
|
|
406
|
-
#graph: MultiDiGraph = MultiDiGraph()
|
|
407
|
-
#graph_process_start: Dict = {}
|
|
464
|
+
# graph: MultiDiGraph = MultiDiGraph()
|
|
465
|
+
# graph_process_start: Dict = {}
|
|
408
466
|
# list of context:
|
|
409
|
-
pages: Dict[str, TriccNodeActivity]= {}
|
|
467
|
+
pages: Dict[str, TriccNodeActivity] = {}
|
|
410
468
|
start_pages: Dict[str, TriccNodeActivity] = {}
|
|
411
|
-
images: List[Dict[str,str]] = []
|
|
412
|
-
contexts
|
|
469
|
+
images: List[Dict[str, str]] = []
|
|
470
|
+
contexts: Set[triccName] = set()
|
|
471
|
+
|
|
413
472
|
# TODO manage trad properly
|
|
414
473
|
def get_keyword_trad(keyword):
|
|
415
474
|
return keyword
|
|
475
|
+
|
|
416
476
|
# dict of code_system_id: codesystem
|
|
417
477
|
code_systems: Dict[str, CodeSystem] = {}
|
|
418
478
|
# dict of valueset_id: valueset
|
|
419
479
|
value_sets: Dict[str, ValueSet] = {}
|
|
420
|
-
|
|
421
|
-
#class Config:
|
|
422
|
-
|
|
423
|
-
# arbitrary_types_allowed = True
|
|
480
|
+
|
|
481
|
+
# class Config:
|
|
482
|
+
# Allow arbitrary types for validation
|
|
483
|
+
# 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
|