tricc-oo 1.5.22__py3-none-any.whl → 1.5.23__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.
Files changed (42) hide show
  1. tests/build.py +13 -23
  2. tests/test_cql.py +37 -108
  3. tests/to_ocl.py +15 -17
  4. tricc_oo/__init__.py +0 -6
  5. tricc_oo/converters/codesystem_to_ocl.py +51 -40
  6. tricc_oo/converters/cql/cqlLexer.py +1 -0
  7. tricc_oo/converters/cql/cqlListener.py +1 -0
  8. tricc_oo/converters/cql/cqlParser.py +1 -0
  9. tricc_oo/converters/cql/cqlVisitor.py +1 -0
  10. tricc_oo/converters/cql_to_operation.py +125 -123
  11. tricc_oo/converters/datadictionnary.py +39 -53
  12. tricc_oo/converters/drawio_type_map.py +143 -61
  13. tricc_oo/converters/tricc_to_xls_form.py +14 -24
  14. tricc_oo/converters/utils.py +3 -3
  15. tricc_oo/converters/xml_to_tricc.py +286 -231
  16. tricc_oo/models/__init__.py +2 -1
  17. tricc_oo/models/base.py +300 -308
  18. tricc_oo/models/calculate.py +63 -49
  19. tricc_oo/models/lang.py +26 -27
  20. tricc_oo/models/ocl.py +146 -161
  21. tricc_oo/models/ordered_set.py +15 -19
  22. tricc_oo/models/tricc.py +144 -88
  23. tricc_oo/parsers/xml.py +15 -30
  24. tricc_oo/serializers/planuml.py +4 -6
  25. tricc_oo/serializers/xls_form.py +81 -135
  26. tricc_oo/strategies/input/base_input_strategy.py +28 -32
  27. tricc_oo/strategies/input/drawio.py +57 -69
  28. tricc_oo/strategies/output/base_output_strategy.py +108 -67
  29. tricc_oo/strategies/output/spice.py +106 -127
  30. tricc_oo/strategies/output/xls_form.py +275 -200
  31. tricc_oo/strategies/output/xlsform_cdss.py +623 -142
  32. tricc_oo/strategies/output/xlsform_cht.py +106 -114
  33. tricc_oo/strategies/output/xlsform_cht_hf.py +13 -24
  34. tricc_oo/visitors/tricc.py +1191 -1021
  35. tricc_oo/visitors/utils.py +16 -16
  36. tricc_oo/visitors/xform_pd.py +91 -89
  37. {tricc_oo-1.5.22.dist-info → tricc_oo-1.5.23.dist-info}/METADATA +3 -1
  38. tricc_oo-1.5.23.dist-info/RECORD +47 -0
  39. tricc_oo-1.5.23.dist-info/licenses/LICENSE +373 -0
  40. tricc_oo-1.5.22.dist-info/RECORD +0 -46
  41. {tricc_oo-1.5.22.dist-info → tricc_oo-1.5.23.dist-info}/WHEEL +0 -0
  42. {tricc_oo-1.5.22.dist-info → tricc_oo-1.5.23.dist-info}/top_level.txt +0 -0
@@ -6,17 +6,31 @@ Strategy to build the skyp logic following the XLSForm way
6
6
  import datetime
7
7
  import logging
8
8
  import os
9
-
9
+ import re
10
10
  import pandas as pd
11
11
 
12
- from tricc_oo.converters.tricc_to_xls_form import *
12
+ from tricc_oo.converters.utils import clean_name
13
+ from tricc_oo.models.base import (
14
+ TriccOperator,
15
+ TriccOperation, TriccStatic, TriccReference, TriccNodeType, or_join
16
+ )
17
+ from tricc_oo.models.ordered_set import OrderedSet
18
+ from tricc_oo.models.calculate import (
19
+ TriccNodeEnd,
20
+ TriccNodeDisplayCalculateBase,
21
+ TriccRhombusMixIn,
13
22
 
14
- from tricc_oo.models import (
15
- TriccNodeActivity,
16
- TriccGroup,
17
- TriccOperation,
18
- TriccOperator
19
23
  )
24
+ from tricc_oo.models.tricc import (
25
+ TriccNodeCalculateBase,
26
+ TriccNodeBaseModel,
27
+ TriccNodeSelectMultiple,
28
+ TriccNodeSelectOption,
29
+ TriccNodeInputModel,
30
+ TriccNodeDisplayModel
31
+ )
32
+ from tricc_oo.converters.tricc_to_xls_form import get_export_name
33
+
20
34
  from tricc_oo.models.lang import SingletonLangClass
21
35
 
22
36
  from tricc_oo.visitors.tricc import (
@@ -27,7 +41,7 @@ from tricc_oo.visitors.tricc import (
27
41
  get_node_expressions,
28
42
  TRICC_TRUE_VALUE,
29
43
  TRICC_FALSE_VALUE,
30
- set_last_version_false
44
+ set_last_version_false,
31
45
  )
32
46
  from tricc_oo.serializers.xls_form import (
33
47
  CHOICE_MAP,
@@ -35,14 +49,13 @@ from tricc_oo.serializers.xls_form import (
35
49
  end_group,
36
50
  generate_xls_form_export,
37
51
  start_group,
38
- BOOLEAN_MAP
52
+ BOOLEAN_MAP,
39
53
  )
40
54
  from tricc_oo.strategies.output.base_output_strategy import BaseOutPutStrategy
41
55
 
42
56
  logger = logging.getLogger("default")
43
57
 
44
58
 
45
-
46
59
  """
47
60
  The XLSForm strategy is a strategy that will generate the XLSForm logic
48
61
  The XLSForm logic is a logic that is based on the XLSForm format
@@ -61,7 +74,7 @@ logger = logging.getLogger("default")
61
74
  check_stashed_loop
62
75
  generate_xls_form_export
63
76
  generate_xls_form_export
64
-
77
+
65
78
  """
66
79
  langs = SingletonLangClass()
67
80
 
@@ -73,25 +86,25 @@ OPERATOR_COALESCE_FALLBACK = {
73
86
  TriccOperator.MORE: -2147483648,
74
87
  TriccOperator.MORE_OR_EQUAL: -2147483648,
75
88
  TriccOperator.LESS: 2147483647,
76
- TriccOperator.LESS_OR_EQUAL: 2147483647
89
+ TriccOperator.LESS_OR_EQUAL: 2147483647,
77
90
  }
78
91
 
92
+
79
93
  class XLSFormStrategy(BaseOutPutStrategy):
80
- pd.set_option('display.max_colwidth', None)
94
+ pd.set_option("display.max_colwidth", None)
81
95
  df_survey = pd.DataFrame(columns=SURVEY_MAP.keys())
82
96
  df_calculate = pd.DataFrame(columns=SURVEY_MAP.keys())
83
97
  df_choice = pd.DataFrame(columns=CHOICE_MAP.keys())
84
98
  calculates = {}
85
99
  # add save nodes and merge nodes
86
100
 
87
-
88
- def clean_coalesce(self, expression):
101
+ def clean_coalesce(self, expression):
89
102
  if re.match(r"^coalesce\(\${[^}]+},''\)$", str(expression)):
90
103
  return str(expression[9:-4])
91
104
  return str(expression)
92
105
 
93
106
  def generate_base(self, node, **kwargs):
94
- return self.generate_xls_form_condition(node, **kwargs)
107
+ return self.generate_xls_form_condition(node, **kwargs)
95
108
 
96
109
  def generate_relevance(self, node, **kwargs):
97
110
  return self.generate_xls_form_relevance(node, **kwargs)
@@ -112,13 +125,12 @@ class XLSFormStrategy(BaseOutPutStrategy):
112
125
  "df_survey": self.df_survey,
113
126
  "df_choice": self.df_choice,
114
127
  "df_calculate": self.df_calculate,
115
- "calculates": self.calculates
128
+ "calculates": self.calculates,
116
129
  }
117
130
 
118
131
  def generate_export(self, node, **kwargs):
119
132
  return generate_xls_form_export(self, node, **kwargs)
120
133
 
121
-
122
134
  def export(self, start_pages, version):
123
135
  if start_pages["main"].root.form_id is not None:
124
136
  form_id = str(start_pages["main"].root.form_id)
@@ -128,7 +140,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
128
140
  title = start_pages["main"].root.label
129
141
  file_name = form_id + ".xlsx"
130
142
  # make a 'settings' tab
131
- now = datetime.datetime.now()
143
+ datetime.datetime.now()
132
144
  indx = [[1]]
133
145
 
134
146
  settings = {
@@ -148,8 +160,8 @@ class XLSFormStrategy(BaseOutPutStrategy):
148
160
 
149
161
  # create a Pandas Excel writer using XlsxWriter as the engine
150
162
  writer = pd.ExcelWriter(newpath, engine="xlsxwriter")
151
- if len(self.df_survey[self.df_survey['name'] == 'version'] ):
152
- self.df_survey.loc[ self.df_survey['name'] == 'version', 'label'] = f"v{version}"
163
+ if len(self.df_survey[self.df_survey["name"] == "version"]):
164
+ self.df_survey.loc[self.df_survey["name"] == "version", "label"] = f"v{version}"
153
165
  self.df_survey.to_excel(writer, sheet_name="survey", index=False)
154
166
  self.df_choice.to_excel(writer, sheet_name="choices", index=False)
155
167
  df_settings.to_excel(writer, sheet_name="settings", index=False)
@@ -175,9 +187,16 @@ class XLSFormStrategy(BaseOutPutStrategy):
175
187
  cur_group = activity
176
188
  groups[activity.id] = 0
177
189
  path_len = 0
178
- process = ['main']
190
+ process = ["main"]
179
191
  # keep the vesrions on the group id, max version
180
- start_group(self, cur_group=cur_group, groups=groups, processed_nodes=processed_nodes, process=process, **self.get_kwargs())
192
+ start_group(
193
+ self,
194
+ cur_group=cur_group,
195
+ groups=groups,
196
+ processed_nodes=processed_nodes,
197
+ process=process,
198
+ **self.get_kwargs(),
199
+ )
181
200
  walktrhough_tricc_node_processed_stached(
182
201
  activity.root,
183
202
  self.generate_export,
@@ -187,14 +206,14 @@ class XLSFormStrategy(BaseOutPutStrategy):
187
206
  cur_group=activity.root.group,
188
207
  process=process,
189
208
  recursive=False,
190
- **self.get_kwargs()
209
+ **self.get_kwargs(),
191
210
  )
192
211
  end_group(self, cur_group=activity, groups=groups, **self.get_kwargs())
193
212
  # we save the survey data frame
194
213
  df_survey_final = pd.DataFrame(columns=SURVEY_MAP.keys())
195
214
  if len(self.df_survey) > (2 + skip_header):
196
215
  df_survey_final = self.df_survey
197
- ## MANAGE STASHED NODES
216
+ # MANAGE STASHED NODES
198
217
  prev_stashed_nodes = stashed_nodes.copy()
199
218
  loop_count = 0
200
219
  len_prev_processed_nodes = 0
@@ -214,9 +233,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
214
233
  # while len(stashed_nodes)>0 and isinstance(s_node,TriccGroup):
215
234
  # s_node = stashed_nodes.pop()
216
235
  if s_node.group is None:
217
- logger.critical(
218
- "ERROR group is none for node {}".format(s_node.get_name())
219
- )
236
+ logger.critical("ERROR group is none for node {}".format(s_node.get_name()))
220
237
  start_group(
221
238
  self,
222
239
  cur_group=s_node.group,
@@ -224,7 +241,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
224
241
  processed_nodes=processed_nodes,
225
242
  process=process,
226
243
  relevance=True,
227
- **self.get_kwargs()
244
+ **self.get_kwargs(),
228
245
  )
229
246
  # arrange empty group
230
247
  walktrhough_tricc_node_processed_stached(
@@ -236,8 +253,8 @@ class XLSFormStrategy(BaseOutPutStrategy):
236
253
  groups=groups,
237
254
  cur_group=s_node.group,
238
255
  recursive=False,
239
- process = process,
240
- **self.get_kwargs()
256
+ process=process,
257
+ **self.get_kwargs(),
241
258
  )
242
259
  # add end group if new node where added OR if the previous end group was removed
243
260
  end_group(self, cur_group=s_node.group, groups=groups, **self.get_kwargs())
@@ -254,13 +271,9 @@ class XLSFormStrategy(BaseOutPutStrategy):
254
271
  )
255
272
  )
256
273
  if len(df_survey_final):
257
- df_survey_final.drop(
258
- index=df_survey_final.index[-1], axis=0, inplace=True
259
- )
260
- self.df_survey = self.df_survey[(1 + skip_header) :]
261
- df_survey_final = pd.concat(
262
- [df_survey_final, self.df_survey], ignore_index=True
263
- )
274
+ df_survey_final.drop(index=df_survey_final.index[-1], axis=0, inplace=True)
275
+ self.df_survey = self.df_survey[(1 + skip_header):]
276
+ df_survey_final = pd.concat([df_survey_final, self.df_survey], ignore_index=True)
264
277
 
265
278
  else:
266
279
  logger.debug(
@@ -271,9 +284,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
271
284
  s_node.group.instance,
272
285
  )
273
286
  )
274
- df_survey_final = pd.concat(
275
- [df_survey_final, self.df_survey], ignore_index=True
276
- )
287
+ df_survey_final = pd.concat([df_survey_final, self.df_survey], ignore_index=True)
277
288
  cur_group = s_node.group
278
289
 
279
290
  # add the calulate
@@ -282,20 +293,15 @@ class XLSFormStrategy(BaseOutPutStrategy):
282
293
  self.df_survey.reset_index(drop=True, inplace=True)
283
294
  self.df_calculate.reset_index(drop=True, inplace=True)
284
295
  self.df_calculate = self.df_calculate.drop(df_empty_calc.index)
285
- self.df_survey = pd.concat(
286
- [df_survey_final, self.df_calculate], ignore_index=True
287
- )
288
- df_duplicate = self.df_calculate[
289
- self.df_calculate.duplicated(subset=["calculation"], keep="first")
290
- ]
296
+ self.df_survey = pd.concat([df_survey_final, self.df_calculate], ignore_index=True)
297
+ df_duplicate = self.df_calculate[self.df_calculate.duplicated(subset=["calculation"], keep="first")]
291
298
  # self.df_survey=self.df_survey.drop_duplicates(subset=['name'])
292
299
  for index, drop_calc in df_duplicate.iterrows():
293
300
  # remove the duplicate
294
301
  replace_name = False
295
302
  # find the actual calcualte
296
303
  similar_calc = self.df_survey[
297
- (drop_calc["calculation"] == self.df_survey["calculation"])
298
- & (self.df_survey["type"] == "calculate")
304
+ (drop_calc["calculation"] == self.df_survey["calculation"]) & (self.df_survey["type"] == "calculate")
299
305
  ]
300
306
  same_calc = self.df_survey[self.df_survey["name"] == drop_calc["name"]]
301
307
  if len(same_calc) > 1:
@@ -324,165 +330,193 @@ class XLSFormStrategy(BaseOutPutStrategy):
324
330
  )
325
331
  else:
326
332
  logger.critical(
327
- "duplicate reference not found for calculation: {}".format(
328
- drop_calc["calculation"]
329
- )
333
+ "duplicate reference not found for calculation: {}".format(drop_calc["calculation"])
330
334
  )
331
335
  for index, empty_calc in df_empty_calc.iterrows():
332
336
  self.df_survey.replace("${" + empty_calc["name"] + "}", "1", regex=True)
333
337
 
334
338
  # TODO try to reinject calc to reduce complexity
335
- for i, c in self.df_calculate[
336
- ~self.df_calculate["name"].isin(self.df_survey["name"])
337
- ].iterrows():
339
+ for i, c in self.df_calculate[~self.df_calculate["name"].isin(self.df_survey["name"])].iterrows():
338
340
  real_calc = re.find(r"^number\((.+)\)$", c["calculation"])
339
341
  if real_calc is not None and real_calc != "":
340
- self.df_survey[~self.df_survey["name"] == c["name"]].replace(
341
- real_calc, "${" + c["name"] + "}"
342
- )
343
-
344
- df_duplicate = self.df_survey[
345
- self.df_survey.duplicated(subset=["name"], keep="first")
346
- ]
347
- for index, duplicate in df_duplicate.iterrows():
342
+ self.df_survey[~self.df_survey["name"] == c["name"]].replace(real_calc, "${" + c["name"] + "}")
343
+
344
+ df_duplicate = self.df_survey[self.df_survey.duplicated(subset=["name"], keep="first")]
345
+ for index, duplicate in df_duplicate.iterrows():
348
346
  logger.critical(f"duplicate survey name: {duplicate['name']}")
349
347
  self.df_survey.reset_index(drop=True, inplace=True)
350
348
  return processed_nodes
351
349
 
352
350
  def get_tricc_operation_expression(self, operation):
353
351
  ref_expressions = []
354
- if not hasattr(operation, 'reference'):
355
- return self.get_tricc_operation_operand(operation)
356
-
357
- operator = getattr(operation, 'operator', '')
358
- coalesce_fallback = OPERATOR_COALESCE_FALLBACK[operator] if operator in OPERATOR_COALESCE_FALLBACK else "''"
352
+ if not hasattr(operation, "reference"):
353
+ return self.get_tricc_operation_operand(operation)
354
+
355
+ operator = getattr(operation, "operator", "")
356
+ coalesce_fallback = OPERATOR_COALESCE_FALLBACK[operator] if operator in OPERATOR_COALESCE_FALLBACK else "''"
359
357
  for r in operation.reference:
360
358
  if isinstance(r, list):
361
359
  r_expr = [
362
- self.get_tricc_operation_expression(sr) if isinstance(sr, TriccOperation)
363
- else self.get_tricc_operation_operand(sr,coalesce_fallback)
360
+ (
361
+ self.get_tricc_operation_expression(sr)
362
+ if isinstance(sr, TriccOperation)
363
+ else self.get_tricc_operation_operand(sr, coalesce_fallback)
364
+ )
364
365
  for sr in r
365
366
  ]
366
367
  elif isinstance(r, TriccOperation):
367
368
  r_expr = self.get_tricc_operation_expression(r)
368
369
  else:
369
- r_expr = self.get_tricc_operation_operand(r,coalesce_fallback)
370
+ r_expr = self.get_tricc_operation_operand(r, coalesce_fallback)
370
371
  if isinstance(r_expr, TriccReference):
371
- r_expr = self.get_tricc_operation_operand(r_expr,coalesce_fallback)
372
+ r_expr = self.get_tricc_operation_operand(r_expr, coalesce_fallback)
372
373
  ref_expressions.append(r_expr)
373
-
374
+
374
375
  # build lower level
375
- if hasattr(self,f"tricc_operation_{operation.operator}"):
376
- callable = getattr(self,f"tricc_operation_{operation.operator}")
377
- return callable(ref_expressions)
376
+ if hasattr(self, f"tricc_operation_{operation.operator}"):
377
+ callable = getattr(self, f"tricc_operation_{operation.operator}")
378
+ return callable(ref_expressions)
378
379
  else:
379
- raise NotImplementedError(f"This type of opreation '{operation.operator}' is not supported in this strategy")
380
-
380
+ raise NotImplementedError(
381
+ f"This type of opreation '{operation.operator}' is not supported in this strategy"
382
+ )
383
+
384
+ def tricc_operation_count(self, ref_expressions):
385
+ return f"count-selected({self.clean_coalesce(ref_expressions[0])})"
386
+
381
387
  def tricc_operation_multiplied(self, ref_expressions):
382
- return '*'.join(ref_expressions)
388
+ return "*".join(ref_expressions)
389
+
383
390
  def tricc_operation_divided(self, ref_expressions):
384
391
  return f"{ref_expressions[0]} div {ref_expressions[1]}"
392
+
385
393
  def tricc_operation_modulo(self, ref_expressions):
386
394
  return f"{ref_expressions[0]} mod {ref_expressions[1]}"
395
+
387
396
  def tricc_operation_coalesce(self, ref_expressions):
388
397
  return f"coalesce({','.join(map(self.clean_coalesce, ref_expressions))})"
398
+
389
399
  def tricc_operation_module(self, ref_expressions):
390
400
  return f"{ref_expressions[0]} mod {ref_expressions[1]}"
401
+
391
402
  def tricc_operation_minus(self, ref_expressions):
392
- if len(ref_expressions)>1:
393
- return ' - '.join(map(str,ref_expressions))
394
- elif len(ref_expressions)==1:
395
- return f'-{ref_expressions[0]}'
403
+ if len(ref_expressions) > 1:
404
+ return " - ".join(map(str, ref_expressions))
405
+ elif len(ref_expressions) == 1:
406
+ return f"-{ref_expressions[0]}"
407
+
396
408
  def tricc_operation_plus(self, ref_expressions):
397
- return ' + '.join(ref_expressions)
409
+ return " + ".join(ref_expressions)
410
+
398
411
  def tricc_operation_not(self, ref_expressions):
399
412
  return f"not({ref_expressions[0]})"
413
+
400
414
  def tricc_operation_and(self, ref_expressions):
401
415
  if len(ref_expressions) == 1:
402
416
  return ref_expressions[0]
403
- if len(ref_expressions)>1:
404
- ref_expressions = [f"({r})" if isinstance(r, str) and any(op in r for op in [' or ',' + ',' - '])else r for r in ref_expressions]
405
- return ' and '.join(map(str, ref_expressions))
417
+ if len(ref_expressions) > 1:
418
+ ref_expressions = [
419
+ (f"({r})" if isinstance(r, str) and any(op in r for op in [" or ", " + ", " - "]) else r)
420
+ for r in ref_expressions
421
+ ]
422
+ return " and ".join(map(str, ref_expressions))
406
423
  else:
407
- return '1'
424
+ return "1"
408
425
 
409
426
  def tricc_operation_or(self, ref_expressions):
410
427
  if len(ref_expressions) == 1:
411
428
  return ref_expressions[0]
412
- if len(ref_expressions)>1:
413
- ref_expressions = [f"({r})" if isinstance(r, str) and any(op in r for op in [' and ',' + ',' - ']) else r for r in ref_expressions]
414
- return ' or '.join(map(str, ref_expressions))
429
+ if len(ref_expressions) > 1:
430
+ ref_expressions = [
431
+ (f"({r})" if isinstance(r, str) and any(op in r for op in [" and ", " + ", " - "]) else r)
432
+ for r in ref_expressions
433
+ ]
434
+ return " or ".join(map(str, ref_expressions))
415
435
  else:
416
- return '1'
417
-
418
-
436
+ return "1"
419
437
 
420
438
  def tricc_operation_native(self, ref_expressions):
421
- if len(ref_expressions)>0:
422
- if ref_expressions[0] =='GetChoiceName':
423
- return f"jr:choice-name({self.clean_coalesce(ref_expressions[1])}, '{self.clean_coalesce(ref_expressions[2])}')"
424
- elif ref_expressions[0] =='GetFacilityParam':
425
- return '0'
426
- #return f"jr:choice-name({','.join(ref_expressions[1:])})"
427
- else:
439
+ if len(ref_expressions) > 0:
440
+ if ref_expressions[0] == "GetChoiceName":
441
+ return f"""jr:choice-name({
442
+ self.clean_coalesce(ref_expressions[1])
443
+ }, '{
444
+ self.clean_coalesce(ref_expressions[2])
445
+ }')"""
446
+ elif ref_expressions[0] == "GetFacilityParam":
447
+ return "0"
448
+ # return f"jr:choice-name({','.join(ref_expressions[1:])})"
449
+ else:
428
450
  return f"{ref_expressions[0]}({','.join(ref_expressions[1:])})"
429
-
451
+
430
452
  def tricc_operation_istrue(self, ref_expressions):
431
453
  if str(BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]).isnumeric():
432
454
  return f"{ref_expressions[0]}>={BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]}"
433
455
  else:
434
456
  return f"{ref_expressions[0]}={BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]}"
457
+
435
458
  def tricc_operation_isfalse(self, ref_expressions):
436
459
  if str(BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]).isnumeric():
437
460
  return f"{ref_expressions[0]}={BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]}"
438
461
  else:
439
462
  return f"{ref_expressions[0]}={BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]}"
463
+
440
464
  def tricc_operation_parenthesis(self, ref_expressions):
441
465
  return f"({ref_expressions[0]})"
466
+
442
467
  def tricc_operation_selected(self, ref_expressions):
443
468
  parts = []
444
469
  for s in ref_expressions[1:]:
445
470
  # for option with numeric value
446
- cleaned_s = s if isinstance(s, str) else '\''+str(s)+'\''
471
+ cleaned_s = s if isinstance(s, str) else "'" + str(s) + "'"
447
472
  parts.append(f"selected({self.clean_coalesce(ref_expressions[0])}, {cleaned_s})")
448
473
  if len(parts) == 1:
449
474
  return parts[0]
450
475
  else:
451
476
  return self.tricc_operation_or(parts)
477
+
452
478
  def tricc_operation_more_or_equal(self, ref_expressions):
453
479
  return f"{ref_expressions[0]}>={ref_expressions[1]}"
480
+
454
481
  def tricc_operation_less_or_equal(self, ref_expressions):
455
482
  return f"{ref_expressions[0]}<={ref_expressions[1]}"
483
+
456
484
  def tricc_operation_more(self, ref_expressions):
457
485
  return f"{ref_expressions[0]}>{ref_expressions[1]}"
486
+
458
487
  def tricc_operation_less(self, ref_expressions):
459
488
  return f"{ref_expressions[0]}<{ref_expressions[1]}"
489
+
460
490
  def tricc_operation_between(self, ref_expressions):
461
- return f"{ref_expressions[0]}>={ref_expressions[1]} and {ref_expressions[0]} < {ref_expressions[2]}"
491
+ return f"{ref_expressions[0]}>={ref_expressions[1]} and {ref_expressions[0]} < {ref_expressions[2]}"
492
+
462
493
  def tricc_operation_equal(self, ref_expressions):
463
494
  return f"{ref_expressions[0]}={ref_expressions[1]}"
495
+
464
496
  def tricc_operation_not_equal(self, ref_expressions):
465
497
  return f"{ref_expressions[0]}!={ref_expressions[1]}"
498
+
466
499
  def tricc_operation_isnull(self, ref_expressions):
467
500
  return f"{ref_expressions[0]}=''"
501
+
468
502
  def tricc_operation_isnotnull(self, ref_expressions):
469
503
  return f"{ref_expressions[0]}!=''"
470
-
504
+
471
505
  def tricc_operation_isnottrue(self, ref_expressions):
472
506
  if str(BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]).isnumeric():
473
507
  return f"{ref_expressions[0]}<{BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]}"
474
508
  else:
475
509
  return f"{ref_expressions[0]}!={BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]}"
510
+
476
511
  def tricc_operation_isnotfalse(self, ref_expressions):
477
512
  if str(BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]).isnumeric():
478
513
  return f"{ref_expressions[0]}>{BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]}"
479
514
  else:
480
515
  return f"{ref_expressions[0]}!={BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]}"
516
+
481
517
  def tricc_operation_notexist(self, ref_expressions):
482
518
  return f"{ref_expressions[0]}=''"
483
519
 
484
-
485
-
486
520
  def tricc_operation_case(self, ref_expressions):
487
521
  ifs = 0
488
522
  parts = []
@@ -496,143 +530,175 @@ class XLSFormStrategy(BaseOutPutStrategy):
496
530
  else:
497
531
  else_found = True
498
532
  parts.append(ref_expressions[i])
499
- #join the if
500
- exp = ','.join(map(str,parts))
533
+ # join the if
534
+ exp = ",".join(map(str, parts))
501
535
  # in case there is no default put ''
502
536
  if not else_found:
503
537
  exp += ",''"
504
- #add the closing )
538
+ # add the closing )
505
539
  for i in range(ifs):
506
540
  exp += ")"
507
541
  return exp
508
-
542
+
509
543
  def tricc_operation_ifs(self, ref_expressions):
510
544
  ifs = 0
511
545
  parts = []
512
546
  else_found = False
513
547
  for i in range(int(len(ref_expressions[1:]))):
514
- if isinstance(ref_expressions[i+1], list):
548
+ if isinstance(ref_expressions[i + 1], list):
515
549
  parts.append(f"if({ref_expressions[0]}={ref_expressions[i+1][0]},{ref_expressions[i+1][1]}")
516
550
  ifs += 1
517
551
  else:
518
552
  else_found = True
519
- parts.append(ref_expressions[i+1])
520
- #join the if
521
- exp = ','.join(parts)
553
+ parts.append(ref_expressions[i + 1])
554
+ # join the if
555
+ exp = ",".join(parts)
522
556
  # in case there is no default put ''
523
557
  if not else_found:
524
558
  exp += ",''"
525
- #add the closing )
559
+ # add the closing )
526
560
  for i in range(ifs):
527
561
  exp += ")"
528
562
  return exp
529
-
563
+
530
564
  def tricc_operation_if(self, ref_expressions):
531
565
  return f"if({ref_expressions[0]},{ref_expressions[1]},{ref_expressions[2]})"
532
-
566
+
533
567
  def tricc_operation_contains(self, ref_expressions):
534
568
  return f"contains('{self.clean_coalesce(ref_expressions[0])}', '{self.clean_coalesce(ref_expressions[1])}')"
535
-
569
+
536
570
  def tricc_operation_exists(self, ref_expressions):
537
571
  parts = []
538
572
  for ref in ref_expressions:
539
573
  parts.append(self.tricc_operation_not_equal([self.tricc_operation_coalesce([ref, "''"]), "''"]))
540
574
  return self.tricc_operation_and(parts)
541
-
575
+
542
576
  def tricc_operation_cast_number(self, ref_expressions):
543
- if isinstance(ref_expressions[0], (int, float,)):
577
+ if isinstance(
578
+ ref_expressions[0],
579
+ (
580
+ int,
581
+ float,
582
+ ),
583
+ ):
544
584
  return f"{ref_expressions[0]}"
545
- elif not ref_expressions or ref_expressions[0] == '':
585
+ elif not ref_expressions or ref_expressions[0] == "":
546
586
  logger.warning("empty cast number")
547
- return '0'
548
- elif ref_expressions[0] == 'true' or ref_expressions[0] is True or ref_expressions[0] == BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]:
587
+ return "0"
588
+ elif (
589
+ ref_expressions[0] == "true"
590
+ or ref_expressions[0] is True
591
+ or ref_expressions[0] == BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]
592
+ ):
549
593
  return 1
550
- elif ref_expressions[0] == 'false' or ref_expressions[0] is False or ref_expressions[0] == BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]:
594
+ elif (
595
+ ref_expressions[0] == "false"
596
+ or ref_expressions[0] is False
597
+ or ref_expressions[0] == BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]
598
+ ):
551
599
  return 0
552
600
  else:
553
601
  return f"number({ref_expressions[0]})"
554
-
602
+
555
603
  def tricc_operation_cast_integer(self, ref_expressions):
556
- if isinstance(ref_expressions[0], (int, float,)):
604
+ if isinstance(
605
+ ref_expressions[0],
606
+ (
607
+ int,
608
+ float,
609
+ ),
610
+ ):
557
611
  return f"{ref_expressions[0]}"
558
- elif not ref_expressions or ref_expressions[0] == '':
612
+ elif not ref_expressions or ref_expressions[0] == "":
559
613
  logger.warning("empty cast number")
560
- return '0'
561
- elif ref_expressions[0] == 'true' or ref_expressions[0] is True or ref_expressions[0] == BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]:
614
+ return "0"
615
+ elif (
616
+ ref_expressions[0] == "true"
617
+ or ref_expressions[0] is True
618
+ or ref_expressions[0] == BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]
619
+ ):
562
620
  return 1
563
- elif ref_expressions[0] == 'false' or ref_expressions[0] is False or ref_expressions[0] == BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]:
621
+ elif (
622
+ ref_expressions[0] == "false"
623
+ or ref_expressions[0] is False
624
+ or ref_expressions[0] == BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]
625
+ ):
564
626
  return 0
565
627
  else:
566
- return f"int({ref_expressions[0]})"
628
+ return f"int({ref_expressions[0]})"
629
+
567
630
  def tricc_operation_zscore(self, ref_expressions):
568
631
  y, ll, m, s = self.get_zscore_params(ref_expressions)
569
632
  # return ((Math.pow((y / m), l) - 1) / (s * l));
570
633
  return f"(pow({y} div ({m}), {ll}) -1) div (({s}) div ({ll}))"
571
-
634
+
572
635
  def tricc_operation_datetime_to_decimal(self, ref_expressions):
573
636
  return f"decimal-date-time({ref_expressions[0]})"
574
-
637
+
575
638
  def tricc_operation_round(self, ref_expressions):
576
639
  return f"round({ref_expressions[0]})"
577
-
578
-
579
-
640
+
580
641
  def tricc_operation_izscore(self, ref_expressions):
581
642
  z, ll, m, s = self.get_zscore_params(ref_expressions)
582
643
  # return (m * (z*s*l-1)^(1/l));
583
644
  return f"pow({m} * ({z} * {s} * {ll} -1), 1 div {ll})"
584
-
645
+
585
646
  def get_zscore_params(self, ref_expressions):
586
647
  table = ref_expressions[0]
587
648
  sex = clean_name(ref_expressions[1])
588
649
  x = clean_name(ref_expressions[2])
589
650
  yz = clean_name(ref_expressions[3])
590
- ll = (
591
- f"number(instance({table})/root/item[sex={sex} and x_max>"
592
- + x
593
- + " and x_min<="
594
- + x
595
- + "]/l)"
596
- )
597
- m = (
598
- f"number(instance({table})/root/item[sex={sex} and x_max>"
599
- + x
600
- + " and x_min<="
601
- + x
602
- + "]/m)"
603
- )
604
- s = (
605
- f"number(instance({table})/root/item[sex={sex} and x_max>"
606
- + x
607
- + " and x_min<="
608
- + x
609
- + "]/s)"
610
- )
611
- return yz, ll, m, s
612
-
613
-
614
-
651
+ ll = f"number(instance({table})/root/item[sex={sex} and x_max>" + x + " and x_min<=" + x + "]/l)"
652
+ m = f"number(instance({table})/root/item[sex={sex} and x_max>" + x + " and x_min<=" + x + "]/m)"
653
+ s = f"number(instance({table})/root/item[sex={sex} and x_max>" + x + " and x_min<=" + x + "]/s)"
654
+ return yz, ll, m, s
655
+
615
656
  # function update the calcualte in the XLSFORM format
616
657
  # @param left part
617
- # @param right part
658
+ # @param right part
618
659
  def generate_xls_form_calculate(self, node, processed_nodes, stashed_nodes, calculates, **kwargs):
619
- if is_ready_to_process(node, processed_nodes, strict=False) and process_reference(node, processed_nodes, calculates, replace_reference=False, codesystems= kwargs.get('codesystems', None)):
660
+ if is_ready_to_process(node, processed_nodes, strict=False) and process_reference(
661
+ node,
662
+ processed_nodes,
663
+ calculates,
664
+ replace_reference=False,
665
+ codesystems=kwargs.get("codesystems", None),
666
+ ):
620
667
  if node not in processed_nodes:
621
- if kwargs.get('warn', True):
668
+ if kwargs.get("warn", True):
622
669
  logger.debug("generation of calculate for node {}".format(node.get_name()))
623
- if hasattr(node, 'expression') and (node.expression is None) and issubclass(node.__class__,TriccNodeCalculateBase):
624
- node.expression = get_node_expressions(node, processed_nodes, process=kwargs.get('process', 'main '))
670
+ if (
671
+ hasattr(node, "expression")
672
+ and (node.expression is None)
673
+ and issubclass(node.__class__, TriccNodeCalculateBase)
674
+ ):
675
+ node.expression = get_node_expressions(
676
+ node, processed_nodes, process=kwargs.get("process", "main ")
677
+ )
625
678
  # continue walk
626
- if issubclass(node.__class__, (TriccNodeDisplayModel, TriccNodeDisplayCalculateBase, TriccNodeEnd)):
627
- last_version = set_last_version_false(node, processed_nodes)
679
+ if issubclass(
680
+ node.__class__,
681
+ (
682
+ TriccNodeDisplayModel,
683
+ TriccNodeDisplayCalculateBase,
684
+ TriccNodeEnd,
685
+ ),
686
+ ):
687
+ set_last_version_false(node, processed_nodes)
628
688
  return True
629
689
  return False
630
-
690
+
631
691
  # function update the select node in the XLSFORM format
632
692
  # @param left part
633
693
  # @param right part
634
694
  def generate_xls_form_condition(self, node, processed_nodes, stashed_nodes, calculates, **kwargs):
635
- if is_ready_to_process(node, processed_nodes, strict=False) and process_reference(node, processed_nodes, calculates, replace_reference=False, codesystems= kwargs.get('codesystems', None)):
695
+ if is_ready_to_process(node, processed_nodes, strict=False) and process_reference(
696
+ node,
697
+ processed_nodes,
698
+ calculates,
699
+ replace_reference=False,
700
+ codesystems=kwargs.get("codesystems", None),
701
+ ):
636
702
  if node not in processed_nodes:
637
703
  if issubclass(node.__class__, TriccRhombusMixIn) and isinstance(node.reference, str):
638
704
  logger.warning("node {} still using the reference string".format(node.get_name()))
@@ -642,46 +708,55 @@ class XLSFormStrategy(BaseOutPutStrategy):
642
708
  if isinstance(node, TriccNodeSelectMultiple):
643
709
  node.constraint = or_join(
644
710
  [
645
- TriccOperation(TriccOperator.EQUAL, ['$this', TriccStatic('opt_none')]),
646
- TriccOperation(TriccOperator.NOT, [
647
- TriccOperation(TriccOperator.SELECTED,
648
- [
649
- '$this', TriccStatic('opt_none')
650
- ])
651
- ])
652
- ]
653
- )#'.=\'opt_none\' or not(selected(.,\'opt_none\'))'
654
- node.constraint_message = '**None** cannot be selected together with choice.'
655
- elif node.tricc_type in (TriccNodeType.integer, TriccNodeType.decimal):
711
+ TriccOperation(
712
+ TriccOperator.EQUAL,
713
+ ["$this", TriccStatic("opt_none")],
714
+ ),
715
+ TriccOperation(
716
+ TriccOperator.NOT,
717
+ [
718
+ TriccOperation(
719
+ TriccOperator.SELECTED,
720
+ ["$this", TriccStatic("opt_none")],
721
+ )
722
+ ],
723
+ ),
724
+ ]
725
+ ) # '.=\'opt_none\' or not(selected(.,\'opt_none\'))'
726
+ node.constraint_message = "**None** cannot be selected together with choice."
727
+ elif node.tricc_type in (
728
+ TriccNodeType.integer,
729
+ TriccNodeType.decimal,
730
+ ):
656
731
  constraints = []
657
- constraints_min = ''
658
- constraints_max = ''
659
- if node.min is not None and node.min != '':
660
- constraints.append(TriccOperation(TriccOperator.MORE_OR_EQUAL, ['$this', node.min]))
661
- constraints_min= "The minimun value is {0}.".format(node.min)
662
- if node.max is not None and node.max != '':
663
- constraints.append(TriccOperation(TriccOperator.LESS_OR_EQUAL, ['$this', node.max]))
664
- constraints_max="The maximum value is {0}.".format(node.max)
732
+ constraints_min = ""
733
+ constraints_max = ""
734
+ if node.min is not None and node.min != "":
735
+ constraints.append(TriccOperation(TriccOperator.MORE_OR_EQUAL, ["$this", node.min]))
736
+ constraints_min = "The minimun value is {0}.".format(node.min)
737
+ if node.max is not None and node.max != "":
738
+ constraints.append(TriccOperation(TriccOperator.LESS_OR_EQUAL, ["$this", node.max]))
739
+ constraints_max = "The maximum value is {0}.".format(node.max)
665
740
  if len(constraints) > 1:
666
741
  node.constraint = TriccOperation(TriccOperator.AND, constraints)
667
- node.constraint_message = (constraints_min + " " + constraints_max).strip()
742
+ node.constraint_message = (constraints_min + " " + constraints_max).strip()
668
743
  elif len(constraints) == 1:
669
744
  node.constraint = constraints[0]
670
- node.constraint_message = (constraints_min + " " + constraints_max).strip()
745
+ node.constraint_message = (constraints_min + " " + constraints_max).strip()
671
746
  # continue walk
672
747
  return True
673
748
  return False
674
749
 
675
750
  # function transform an object to XLSFORM value
676
- # @param r reference to be translated
677
- def get_tricc_operation_operand(self,r, coalesce_fallback="''"):
751
+ # @param r reference to be translated
752
+ def get_tricc_operation_operand(self, r, coalesce_fallback="''"):
678
753
  if isinstance(r, TriccOperation):
679
- return self.get_tricc_operation_expression(r)
754
+ return self.get_tricc_operation_expression(r)
680
755
  elif isinstance(r, TriccReference):
681
756
  logger.warning(f"reference `{r.value}` still used in a calculate")
682
- return f"${{{get_export_name(r.value)}}}"
757
+ return f"${{{get_export_name(r.value)}}}"
683
758
  elif isinstance(r, TriccStatic):
684
- if isinstance(r.value, bool) :#or r.value in ('true', 'false')
759
+ if isinstance(r.value, bool): # or r.value in ('true', 'false')
685
760
  return BOOLEAN_MAP[str(TRICC_TRUE_VALUE)] if r.value else BOOLEAN_MAP[str(TRICC_FALSE_VALUE)]
686
761
  if r.value == TRICC_TRUE_VALUE:
687
762
  return BOOLEAN_MAP[str(TRICC_TRUE_VALUE)]
@@ -692,7 +767,7 @@ class XLSFormStrategy(BaseOutPutStrategy):
692
767
  else:
693
768
  return str(r.value)
694
769
  elif isinstance(r, str):
695
- return f"{r}"
770
+ return f"{r}"
696
771
  elif isinstance(r, (int, float)):
697
772
  return str(r)
698
773
  elif isinstance(r, TriccNodeSelectOption):
@@ -706,4 +781,4 @@ class XLSFormStrategy(BaseOutPutStrategy):
706
781
  raise NotImplementedError(f"This type of node {r.__class__} is not supported within an operation")
707
782
 
708
783
  def tricc_operation_concatenate(self, ref_expressions):
709
- return f"concat({','.join(ref_expressions)})"
784
+ return f"concat({','.join(ref_expressions)})"