openehr 2.0.2 → 2.3.0

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +19 -6
  3. data/lib/openehr/am/archetype/constraint_model.rb +1 -1
  4. data/lib/openehr/aql/engine/contains_resolver.rb +98 -7
  5. data/lib/openehr/aql/engine/dataset.rb +3 -1
  6. data/lib/openehr/aql/engine/predicate_evaluator.rb +70 -3
  7. data/lib/openehr/aql/engine.rb +45 -12
  8. data/lib/openehr/assumed_library_types.rb +20 -17
  9. data/lib/openehr/parser/adl_parser.rb +0 -4
  10. data/lib/openehr/parser/opt_parser.rb +12 -429
  11. data/lib/openehr/parser/xml_archetype_parser.rb +255 -0
  12. data/lib/openehr/parser/xml_constraint_parsing.rb +264 -0
  13. data/lib/openehr/parser/xml_domain_type_parsing.rb +128 -0
  14. data/lib/openehr/parser/xml_primitive_parsing.rb +145 -0
  15. data/lib/openehr/parser.rb +1 -0
  16. data/lib/openehr/rm/common/generic.rb +6 -9
  17. data/lib/openehr/rm/common/resource.rb +0 -1
  18. data/lib/openehr/rm/composition/content/entry.rb +4 -1
  19. data/lib/openehr/rm/data_structures/item_structure/representation.rb +12 -2
  20. data/lib/openehr/rm/data_structures/item_structure.rb +0 -1
  21. data/lib/openehr/rm/data_types/basic.rb +11 -21
  22. data/lib/openehr/rm/data_types/encapsulated.rb +18 -2
  23. data/lib/openehr/rm/data_types/quantity/date_time.rb +203 -28
  24. data/lib/openehr/rm/data_types/quantity.rb +66 -10
  25. data/lib/openehr/rm/data_types/time_specification.rb +101 -27
  26. data/lib/openehr/rm/data_types/uri.rb +0 -8
  27. data/lib/openehr/rm/ehr.rb +6 -6
  28. data/lib/openehr/rm/factory.rb +22 -0
  29. data/lib/openehr/rm/security.rb +3 -1
  30. data/lib/openehr/rm/type_name.rb +0 -1
  31. data/lib/openehr/serializer/adl_serializer.rb +239 -84
  32. data/lib/openehr/serializer/base.rb +2 -0
  33. data/lib/openehr/serializer/rm_json_serializer.rb +0 -1
  34. data/lib/openehr/serializer/xml_serializer.rb +351 -103
  35. data/lib/openehr/version.rb +1 -1
  36. metadata +9 -144
@@ -1,12 +1,19 @@
1
1
  require 'nokogiri'
2
+ require_relative 'xml_constraint_parsing'
3
+ require_relative 'xml_primitive_parsing'
4
+ require_relative 'xml_domain_type_parsing'
2
5
 
3
6
  module OpenEHR
4
7
  module Parser
5
8
  class OPTParser < ::OpenEHR::Parser::Base
9
+ include XMLConstraintParsing
10
+ include XMLPrimitiveParsing
11
+ include XMLDomainTypeParsing
12
+
6
13
  TEMPLATE_LANGUAGE_CODE_PATH =
7
14
  '/template/language/code_string'
8
15
  TEMPLATE_LANGUAGE_TERM_ID_PATH =
9
- '/template/language/terminology_id/value'
16
+ '/template/language/terminology_id/value'
10
17
  TEMPLATE_ID_PATH = '/template/template_id/value'
11
18
  UID_PATH = '/template/uid/value'
12
19
  CONCEPT_PATH = '/template/concept'
@@ -31,18 +38,14 @@ module OpenEHR
31
38
  '/template/description/other_details'
32
39
  DEFINITION_PATH = '/template/definition'
33
40
  OCCURRENCE_PATH = '/occurrences'
34
-
35
- def initialize(filename)
36
- super(filename)
37
- end
38
41
 
39
42
  def parse
40
43
  @opt = Nokogiri::XML::Document.parse(File.open(@filename))
41
44
  @opt.remove_namespaces!
42
-
45
+
43
46
  uid = build_uid
44
47
  defs = definition
45
-
48
+
46
49
  # Create operational template with archetype-compatible parameters
47
50
  OpenEHR::AM::Template::OperationalTemplate.new(
48
51
  uid: uid,
@@ -123,7 +126,7 @@ module OpenEHR
123
126
  # Create a basic ontology for the template using the main concept
124
127
  concept_code = 'at0000'
125
128
  original_lang = language
126
-
129
+
127
130
  term_definitions = {
128
131
  original_lang.code_string => [
129
132
  OpenEHR::AM::Archetype::Terminology::ArchetypeTerm.new(
@@ -135,7 +138,7 @@ module OpenEHR
135
138
  )
136
139
  ]
137
140
  }
138
-
141
+
139
142
  OpenEHR::AM::Archetype::Terminology::ArchetypeTerminology.new(
140
143
  concept_code: concept_code,
141
144
  original_language: original_lang,
@@ -164,418 +167,6 @@ module OpenEHR
164
167
  { language.code_string => term_items }
165
168
  end
166
169
 
167
- def c_archetype_root(xml, node = Node.new)
168
- rm_type_name = text_on_path(xml, './rm_type_name')
169
- id = text_on_path(xml, './node_id')
170
- node.id = id unless id.nil? or id.empty?
171
- occurrences = occurrences(xml.xpath('./occurrences'))
172
- archetype_id = OpenEHR::RM::Support::Identification::ArchetypeID.new(value: text_on_path(xml, './archetype_id/value'))
173
- if node.root? or node.id.nil?
174
- node.path = "/"
175
- # else
176
- # node.path += "/" #"/[#{archetype_id.value}]"
177
- end
178
- component_terminologies(archetype_id, xml)
179
- OpenEHR::AM::Archetype::ConstraintModel::CArchetypeRoot.new(rm_type_name: rm_type_name, node_id: node.id, path: node.path, occurrences: occurrences, archetype_id: archetype_id, attributes: attributes(xml.xpath('./attributes'), node))
180
- end
181
-
182
- def c_complex_object(xml, node)
183
- rm_type_name = xml.xpath('./rm_type_name').text
184
- node_id = xml.xpath('./node_id').text
185
- unless node_id.nil? or node_id.empty?
186
- node.id = node_id
187
- node.path = "#{node.path}[#{node.id}]"
188
- end
189
- OpenEHR::AM::Archetype::ConstraintModel::CComplexObject.new(rm_type_name: rm_type_name, node_id: node.id, path: node.path, occurrences: occurrences(xml.xpath('./occurrences')), attributes: attributes(xml.xpath('./attributes'), node))
190
- end
191
-
192
- def attributes(attributes_xml, node)
193
- attributes_xml.map do |attr|
194
- rm_attribute_name = attr.at('rm_attribute_name').text
195
- if node.root?
196
- path = "/#{rm_attribute_name}"
197
- # elsif node.id
198
- # path = "#{node.path}[#{node.id}]/#{rm_attribute_name}"
199
- else
200
- path = "#{node.path}/#{rm_attribute_name}"
201
- end
202
- child_node = Node.new(node)
203
- child_node.path = path
204
- child_node.id = node.id
205
- send attr.attributes['type'].text.downcase, attr, child_node
206
- end
207
- end
208
-
209
- def children(children_xml, node)
210
- children_xml.map do |child|
211
- send child.attributes['type'].text.downcase, child, node
212
- end
213
- end
214
-
215
- def c_single_attribute(attr_xml, node)
216
- rm_attribute_name = attr_xml.at('rm_attribute_name').text
217
- existence = occurrences(attr_xml.at('existence'))
218
- OpenEHR::AM::Archetype::ConstraintModel::CSingleAttribute.new(rm_attribute_name: rm_attribute_name, existence: existence, path: node.path, children: children(attr_xml.xpath('./children'), node))
219
- end
220
-
221
- def c_multiple_attribute(attr_xml, node)
222
- rm_attribute_name = attr_xml.at('rm_attribute_name').text
223
- existence = occurrences(attr_xml.at('existence'))
224
- OpenEHR::AM::Archetype::ConstraintModel::CMultipleAttribute.new(rm_attribute_name: rm_attribute_name, existence: existence, path: node.path, cardinality: cardinality(attr_xml), children: children(attr_xml.xpath('./children'), node))
225
- end
226
-
227
- def c_code_phrase(attr_xml, node)
228
- terminology_id_node = attr_xml.at('terminology_id/value')
229
- terminology_id = terminology_id_node ? OpenEHR::RM::Support::Identification::TerminologyID.new(value: terminology_id_node.text.strip) : nil
230
-
231
- code_list_nodes = attr_xml.xpath('code_list')
232
- code_list = code_list_nodes.map { |code_node| code_node.text.strip }
233
- code_list = [code_list.first] if code_list.size == 1 && code_list.first.empty?
234
-
235
- occurrences_node = attr_xml.at('occurrences')
236
- occurrences_obj = occurrences_node ? occurrences(occurrences_node) : nil
237
-
238
- OpenEHR::AM::OpenEHRProfile::DataTypes::Text::CCodePhrase.new(
239
- terminology_id: terminology_id,
240
- code_list: code_list,
241
- path: node.path,
242
- occurrences: occurrences_obj,
243
- rm_type_name: 'CODE_PHRASE'
244
- )
245
- end
246
-
247
- def archetype_slot(attr_xml,node)
248
- path = node.path
249
- node.id = attr_xml.at('node_id').text
250
- rm_type_name = attr_xml.at('rm_type_name').text
251
- occurrences = occurrences(attr_xml.at('occurrences'))
252
- includes_leaf = attr_xml.at('includes')
253
- includes = assertions(includes_leaf.children, node) if includes_leaf
254
- excludes_leaf = attr_xml.at('excludes')
255
- excludes = assertions(excludes_leaf.children, node) if excludes_leaf
256
- OpenEHR::AM::Archetype::ConstraintModel::ArchetypeSlot.new(path: path, node_id: node.id, rm_type_name: rm_type_name, occurrences: occurrences, includes: includes, excludes: excludes)
257
- end
258
-
259
- def occurrences(occurrence_xml)
260
- return nil if occurrence_xml.nil?
261
-
262
- lower_node = occurrence_xml.at('lower')
263
- upper_node = occurrence_xml.at('upper')
264
- lower_included_node = occurrence_xml.at('lower_included')
265
- upper_included_node = occurrence_xml.at('upper_included')
266
- lower_unbounded_node = occurrence_xml.at('lower_unbounded')
267
- upper_unbounded_node = occurrence_xml.at('upper_unbounded')
268
-
269
- lower = lower_node ? lower_node.text.to_i : nil
270
- upper = upper_node ? upper_node.text.to_i : nil
271
- lower_included = lower_included_node ? to_bool(lower_included_node.text) : (lower.nil? ? nil : true)
272
- upper_included = upper_included_node ? to_bool(upper_included_node.text) : (upper.nil? ? nil : true)
273
- lower_unbounded = lower_unbounded_node ? to_bool(lower_unbounded_node.text) : false
274
- upper_unbounded = upper_unbounded_node ? to_bool(upper_unbounded_node.text) : false
275
-
276
- # An occurrences element with none of its children present carries no
277
- # constraint at all; Interval requires at least one bound, so treat
278
- # this as "no occurrences data" rather than raising.
279
- return nil if lower.nil? && upper.nil? && !lower_unbounded && !upper_unbounded
280
-
281
- # Handle unbounded intervals properly
282
- if upper_unbounded || upper.nil?
283
- upper = nil
284
- upper_included = nil
285
- end
286
-
287
- if lower_unbounded || lower.nil?
288
- lower = nil
289
- lower_included = nil
290
- end
291
-
292
- OpenEHR::AssumedLibraryTypes::Interval.new(
293
- lower: lower,
294
- upper: upper,
295
- lower_included: lower_included,
296
- upper_included: upper_included
297
- )
298
- end
299
-
300
- def cardinality(xml)
301
- return nil if xml.nil?
302
-
303
- order_node = xml.at('is_ordered')
304
- unique_node = xml.at('is_unique')
305
- interval_node = xml.at('interval')
306
-
307
- # No cardinality sub-elements at all means no cardinality data.
308
- return nil if order_node.nil? && unique_node.nil? && interval_node.nil?
309
-
310
- order = order_node ? to_bool(order_node.text) : false
311
- unique = unique_node ? to_bool(unique_node.text) : false
312
- interval = interval_node ? occurrences(interval_node) : nil
313
-
314
- OpenEHR::AM::Archetype::ConstraintModel::Cardinality.new(
315
- is_ordered: order,
316
- is_unique: unique,
317
- interval: interval
318
- )
319
- end
320
-
321
- def archetype_internal_ref(attr_xml, node)
322
- rm_type_name = attr_xml.at('rm_type_name').text
323
- target_path = attr_xml.at('target_path').text
324
- occurrences = occurrences(attr_xml.at('occurrences'))
325
- OpenEHR::AM::Archetype::ConstraintModel::ArchetypeInternalRef.new(rm_type_name: rm_type_name, occurrences: occurrences, target_path: target_path)
326
- end
327
-
328
- # No .opt fixture in this gem's corpus uses a C_DV_STATE (state
329
- # machine) constraint, so its actual OPT XML shape is unverified;
330
- # raising a clear, documented error here is safer than guessing
331
- # at element names and risking a silently wrong StateMachine.
332
- def c_dv_state(_attr_xml, _node)
333
- raise NotImplementedError, 'OPTParser does not yet support C_DV_STATE (state machine) constraints'
334
- end
335
-
336
- def constraint_ref(attr_xml, node)
337
- rm_type_name = attr_xml.at('rm_type_name').text
338
- reference = attr_xml.at('reference').text
339
- occurrences = occurrences(attr_xml.at('occurrences'))
340
- OpenEHR::AM::Archetype::ConstraintModel::ConstraintRef.new(rm_type_name: rm_type_name, occurrences: occurrences, reference: reference)
341
- end
342
-
343
- def assertions(attr_xml, node)
344
- string_expression = attr_xml.at('string_expression')
345
- string_expression = string_expression.nil? ? nil : string_expression.text
346
- expression_leaf = attr_xml.at 'expression'
347
- expression = send expression_leaf.attributes['type'].text.downcase, expression_leaf
348
- [OpenEHR::AM::Archetype::Assertion::Assertion.new(expression: expression, string_expression: string_expression)]
349
- end
350
-
351
- def expr_binary_operator(attr_xml)
352
- type = attr_xml.at('type').text
353
- operator = OpenEHR::AM::Archetype::Assertion::OperatorKind.new(value: attr_xml.at('operator').text.to_i)
354
-
355
- precedence_overridden = attr_xml.at('precedence_overridden').text == 'true' ? true : false
356
- right_operand_leaf = attr_xml.at 'right_operand'
357
- right_operand = send right_operand_leaf.attributes['type'].text.downcase, right_operand_leaf
358
- left_operand_leaf = attr_xml.at 'left_operand'
359
- left_operand = send left_operand_leaf.attributes['type'].text.downcase, left_operand_leaf
360
- OpenEHR::AM::Archetype::Assertion::ExprBinaryOperator.new(type: type, operator: operator, precedence_overridden: precedence_overridden, right_operand: right_operand, left_operand: left_operand)
361
- end
362
-
363
- def expr_leaf(attr_xml)
364
- type = attr_xml.at('type').text
365
- item_leaf = attr_xml.at('item')
366
- item = send type.downcase, item_leaf
367
- reference_type = attr_xml.at('reference_type').text
368
- OpenEHR::AM::Archetype::Assertion::ExprLeaf.new(type: type, item: item, reference_type: reference_type)
369
- end
370
-
371
- def c_primitive_object(attr_xml, node)
372
- rm_type_name = attr_xml.at('rm_type_name').text
373
- occurrences = occurrences(attr_xml.at('occurrences'))
374
- item = send attr_xml.at('item')['type'].downcase, attr_xml.at('item')
375
- OpenEHR::AM::Archetype::ConstraintModel::CPrimitiveObject.new(rm_type_name: rm_type_name, occurrences: occurrences, node_id: node.id, item: item)
376
- end
377
-
378
- def c_string(attr_xml)
379
- if attr_xml.at('pattern')
380
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CString.new(pattern: attr_xml.at('pattern').text)
381
- else
382
- list = attr_xml.xpath('.//list').map do |str|
383
- str.text
384
- end
385
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CString.new(list: list)
386
- end
387
- end
388
-
389
- def c_dv_quantity(attr_xml, node)
390
- rm_type_name = attr_xml.at('rm_type_name').text
391
- occurrences = occurrences(attr_xml.at('occurrences'))
392
- property = property_code_phrase(attr_xml.at('property'))
393
- list = attr_xml.xpath('.//list').map do |element|
394
- units = element.at('units').text if element.at('units')
395
- magnitude = occurrences(element.at('magnitude')) if element.at('magnitude')
396
- precision = occurrences(element.at('precision')) if element.at('precision')
397
- OpenEHR::AM::OpenEHRProfile::DataTypes::Quantity::CQuantityItem.new(magnitude: magnitude, precision: precision, units: units)
398
- end
399
- OpenEHR::AM::OpenEHRProfile::DataTypes::Quantity::CDvQuantity.new(rm_type_name: rm_type_name, occurrences: occurrences, list: list, property: property)
400
- end
401
-
402
- # The <property> element is optional in real templates; return nil rather
403
- # than dereferencing missing terminology/code nodes.
404
- def property_code_phrase(property_xml)
405
- return nil if property_xml.nil?
406
- terminology_node = property_xml.at('terminology_id/value')
407
- code_node = property_xml.at('code_string')
408
- return nil if terminology_node.nil? || code_node.nil?
409
- terminology_id = OpenEHR::RM::Support::Identification::TerminologyID.new(value: terminology_node.text)
410
- OpenEHR::RM::DataTypes::Text::CodePhrase.new(terminology_id: terminology_id, code_string: code_node.text)
411
- end
412
-
413
- def c_dv_ordinal(attr_xml, node)
414
- rm_type_name = attr_xml.at('rm_type_name').text
415
- occurrences = occurrences(attr_xml.at('occurrences'))
416
- list = attr_xml.xpath('list').map { |element| dv_ordinal_item(element) }.compact
417
- OpenEHR::AM::OpenEHRProfile::DataTypes::Quantity::CDvOrdinal.new(rm_type_name: rm_type_name, occurrences: occurrences, list: list)
418
- end
419
-
420
- # DV_ORDINAL.symbol is spec'd as DV_CODED_TEXT; the OPT XML only
421
- # carries a defining_code (terminology_id + code_string), so the
422
- # DvCodedText's own value is set to that same code_string (there
423
- # is no separate display text in this element).
424
- def dv_ordinal_item(element)
425
- value_node = element.at('value')
426
- return nil unless value_node && !value_node.text.empty?
427
-
428
- code_phrase = property_code_phrase(element.at('symbol/defining_code'))
429
- return nil if code_phrase.nil?
430
-
431
- symbol = OpenEHR::RM::DataTypes::Text::DvCodedText.new(value: code_phrase.code_string, defining_code: code_phrase)
432
- OpenEHR::RM::DataTypes::Quantity::DvOrdinal.new(value: value_node.text.to_i, symbol: symbol)
433
- end
434
-
435
- def c_dv_scale(attr_xml, node)
436
- rm_type_name = attr_xml.at('rm_type_name').text
437
- occurrences = occurrences(attr_xml.at('occurrences'))
438
- list = attr_xml.xpath('list').map { |element| dv_scale_item(element) }.compact
439
- OpenEHR::AM::OpenEHRProfile::DataTypes::Quantity::CDvScale.new(rm_type_name: rm_type_name, occurrences: occurrences, list: list)
440
- end
441
-
442
- # Same XML shape as C_DV_ORDINAL's list items, but DV_SCALE.value
443
- # is Real rather than Integer.
444
- def dv_scale_item(element)
445
- value_node = element.at('value')
446
- return nil unless value_node && !value_node.text.empty?
447
-
448
- code_phrase = property_code_phrase(element.at('symbol/defining_code'))
449
- return nil if code_phrase.nil?
450
-
451
- symbol = OpenEHR::RM::DataTypes::Text::DvCodedText.new(value: code_phrase.code_string, defining_code: code_phrase)
452
- OpenEHR::RM::DataTypes::Quantity::DvScale.new(value: value_node.text.to_f, symbol: symbol)
453
- end
454
-
455
- def c_date(xml)
456
- pattern = xml.at('pattern')
457
- range = xml.at('range')
458
- if pattern
459
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDate.new(pattern: pattern.text)
460
- elsif range
461
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDate.new(range: occurrences(range))
462
- else
463
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDate.new
464
- end
465
- end
466
-
467
- def c_date_time(xml)
468
- pattern = xml.at('pattern')
469
- range = xml.at('range')
470
- if pattern
471
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDateTime.new(pattern: pattern.text)
472
- elsif range
473
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDateTime.new(range: occurrences(range))
474
- else
475
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDateTime.new
476
- end
477
- end
478
-
479
- def c_integer(xml)
480
- range = xml.at('range')
481
- list = xml.xpath('list')
482
- if range
483
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CInteger.new(range: occurrences(range))
484
- elsif !list.empty?
485
- list_values = list.map { |item| item.text.to_i }
486
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CInteger.new(list: list_values)
487
- else
488
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CInteger.new
489
- end
490
- end
491
-
492
- def c_real(xml)
493
- range = xml.at('range')
494
- list = xml.xpath('list')
495
- if range
496
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CReal.new(range: occurrences(range))
497
- elsif !list.empty?
498
- list_values = list.map { |item| item.text.to_f }
499
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CReal.new(list: list_values)
500
- else
501
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CReal.new
502
- end
503
- end
504
-
505
- def c_duration(xml)
506
- pattern = xml.at('pattern')
507
- range_xml = xml.at('range')
508
- list = xml.xpath('list')
509
- if pattern
510
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDuration.new(pattern: pattern.text)
511
- elsif range_xml
512
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDuration.new(range: duration_range(range_xml))
513
- elsif !list.empty?
514
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDuration.new(list: list.map(&:text))
515
- else
516
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CDuration.new
517
- end
518
- end
519
-
520
- # A C_DURATION range's bounds are ISO8601 duration strings (e.g.
521
- # PT24H), not plain numbers, so occurrences() (built for numeric
522
- # Interval bounds) doesn't apply here; wrap each bound as a
523
- # DV_DURATION instead, matching what CDuration#valid_value?
524
- # already expects its range bounds to be.
525
- def duration_range(range_xml)
526
- lower = duration_bound(range_xml.at('lower'), range_xml.at('lower_unbounded'))
527
- upper = duration_bound(range_xml.at('upper'), range_xml.at('upper_unbounded'))
528
- return nil if lower.nil? && upper.nil?
529
-
530
- OpenEHR::AssumedLibraryTypes::Interval.new(
531
- lower: lower, upper: upper,
532
- lower_included: lower.nil? ? nil : bool_node(range_xml.at('lower_included'), true),
533
- upper_included: upper.nil? ? nil : bool_node(range_xml.at('upper_included'), true))
534
- end
535
-
536
- def duration_bound(value_node, unbounded_node)
537
- return nil if bool_node(unbounded_node, false)
538
- return nil if value_node.nil? || value_node.text.empty?
539
-
540
- OpenEHR::RM::DataTypes::Quantity::DateTime::DvDuration.new(value: value_node.text)
541
- end
542
-
543
- def bool_node(node, default)
544
- node ? to_bool(node.text) : default
545
- end
546
-
547
- def c_time(xml)
548
- pattern = xml.at('pattern')
549
- range = xml.at('range')
550
- if pattern
551
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CTime.new(pattern: pattern.text)
552
- elsif range
553
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CTime.new(range: occurrences(range))
554
- else
555
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CTime.new
556
- end
557
- end
558
-
559
- def c_boolean(xml)
560
- true_valid = xml.at('true_valid')
561
- false_valid = xml.at('false_valid')
562
- assumed_value = xml.at('assumed_value')
563
-
564
- true_valid_value = true_valid ? to_bool(true_valid.text) : nil
565
- false_valid_value = false_valid ? to_bool(false_valid.text) : nil
566
- assumed_value_value = assumed_value ? to_bool(assumed_value.text) : nil
567
-
568
- OpenEHR::AM::Archetype::ConstraintModel::Primitive::CBoolean.new(
569
- true_valid: true_valid_value,
570
- false_valid: false_valid_value,
571
- assumed_value: assumed_value_value
572
- )
573
- end
574
-
575
- def string(attr_xml)
576
- attr_xml.text
577
- end
578
-
579
170
  def empty_then_nil(val)
580
171
  if val.empty?
581
172
  return nil
@@ -587,14 +178,6 @@ module OpenEHR
587
178
  def text_on_path(xml, path)
588
179
  xml.xpath(path).text
589
180
  end
590
-
591
- def to_bool(str)
592
- return nil if str.nil?
593
- str = str.text if str.respond_to?(:text)
594
- return true if /true/i =~ str.to_s
595
- return false if /false/i =~ str.to_s
596
- nil
597
- end
598
181
  end
599
182
  end
600
183
  end