openehr 1.3.0 → 2.0.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.
- checksums.yaml +4 -4
- data/README.rdoc +93 -12
- data/lib/openehr/am/archetype/constraint_model/primitive.rb +204 -6
- data/lib/openehr/am/archetype/constraint_model.rb +228 -4
- data/lib/openehr/am/archetype/ontology.rb +2 -2
- data/lib/openehr/am/archetype.rb +101 -2
- data/lib/openehr/am/openehr_profile/data_types/basic.rb +28 -0
- data/lib/openehr/am/openehr_profile/data_types/quantity.rb +88 -0
- data/lib/openehr/am/openehr_profile/data_types/text.rb +23 -0
- data/lib/openehr/am/template.rb +25 -3
- data/lib/openehr/aql/engine/binding.rb +13 -0
- data/lib/openehr/aql/engine/contains_resolver.rb +161 -0
- data/lib/openehr/aql/engine/dataset.rb +122 -0
- data/lib/openehr/aql/engine/path_evaluator.rb +137 -0
- data/lib/openehr/aql/engine/predicate_evaluator.rb +65 -0
- data/lib/openehr/aql/engine.rb +119 -0
- data/lib/openehr/aql/errors.rb +27 -0
- data/lib/openehr/aql/lexer.rb +295 -0
- data/lib/openehr/aql/model/containment.rb +45 -0
- data/lib/openehr/aql/model/from_clause.rb +35 -0
- data/lib/openehr/aql/model/function_call.rb +56 -0
- data/lib/openehr/aql/model/identified_path.rb +20 -0
- data/lib/openehr/aql/model/literal.rb +15 -0
- data/lib/openehr/aql/model/object_path.rb +34 -0
- data/lib/openehr/aql/model/order_by_and_limit.rb +50 -0
- data/lib/openehr/aql/model/predicate.rb +84 -0
- data/lib/openehr/aql/model/query.rb +24 -0
- data/lib/openehr/aql/model/select_clause.rb +29 -0
- data/lib/openehr/aql/model/where_clause.rb +105 -0
- data/lib/openehr/aql/model.rb +14 -0
- data/lib/openehr/aql/parser.rb +484 -0
- data/lib/openehr/aql/result_set.rb +54 -0
- data/lib/openehr/aql.rb +28 -0
- data/lib/openehr/assumed_library_types.rb +68 -17
- data/lib/openehr/parser/adl_grammar.tt +29 -13
- data/lib/openehr/parser/adl_parser.rb +18 -4
- data/lib/openehr/parser/archetype_validator.rb +126 -0
- data/lib/openehr/parser/exception.rb +13 -0
- data/lib/openehr/parser/opt_parser.rb +162 -9
- data/lib/openehr/parser.rb +2 -0
- data/lib/openehr/path.rb +195 -0
- data/lib/openehr/rm/common/archetyped.rb +116 -6
- data/lib/openehr/rm/common/change_control.rb +3 -8
- data/lib/openehr/rm/common/directory.rb +4 -0
- data/lib/openehr/rm/common/generic.rb +24 -10
- data/lib/openehr/rm/composition/content/entry.rb +24 -5
- data/lib/openehr/rm/composition/content/navigation.rb +2 -1
- data/lib/openehr/rm/composition.rb +19 -2
- data/lib/openehr/rm/data_structures/history.rb +3 -0
- data/lib/openehr/rm/data_structures/item_structure/representation.rb +13 -9
- data/lib/openehr/rm/data_structures/item_structure.rb +28 -15
- data/lib/openehr/rm/data_types/encapsulated.rb +23 -3
- data/lib/openehr/rm/data_types/quantity/date_time.rb +9 -1
- data/lib/openehr/rm/data_types/quantity.rb +66 -14
- data/lib/openehr/rm/data_types/text.rb +8 -0
- data/lib/openehr/rm/data_types/time_specification.rb +5 -4
- data/lib/openehr/rm/demographic.rb +4 -3
- data/lib/openehr/rm/ehr.rb +20 -1
- data/lib/openehr/rm/factory.rb +234 -6
- data/lib/openehr/rm/integration.rb +1 -0
- data/lib/openehr/rm/support/identification.rb +37 -8
- data/lib/openehr/rm/support/measurement.rb +32 -0
- data/lib/openehr/rm/type_name.rb +90 -0
- data/lib/openehr/rm.rb +3 -0
- data/lib/openehr/serializer/adl_serializer.rb +335 -0
- data/lib/openehr/serializer/base.rb +20 -0
- data/lib/openehr/serializer/opt_serializer.rb +49 -0
- data/lib/openehr/serializer/rm_json_serializer.rb +62 -0
- data/lib/openehr/serializer/xml_serializer.rb +260 -0
- data/lib/openehr/serializer.rb +5 -291
- data/lib/openehr/terminology_service.rb +44 -0
- data/lib/openehr/version.rb +1 -1
- data/lib/openehr.rb +5 -2
- metadata +35 -7
- data/lib/openehr/parser/validator.rb +0 -18
- data/lib/openehr/parser/xml_parser.rb +0 -13
- data/lib/openehr/rm/data_types/charset_extract.rb +0 -24
- data/lib/openehr/writer.rb +0 -12
data/lib/openehr/rm/factory.rb
CHANGED
|
@@ -80,12 +80,6 @@ module OpenEHR
|
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
class TermMappingFactory
|
|
84
|
-
def self.create(*param)
|
|
85
|
-
OpenEHR::RM::DataTypes::Text::TermMapping.new(*param)
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
83
|
class CodePhraseFactory
|
|
90
84
|
def self.create(*param)
|
|
91
85
|
OpenEHR::RM::DataTypes::Text::CodePhrase.new(*param)
|
|
@@ -128,6 +122,12 @@ module OpenEHR
|
|
|
128
122
|
end
|
|
129
123
|
end
|
|
130
124
|
|
|
125
|
+
class DvScaleFactory
|
|
126
|
+
def self.create(*param)
|
|
127
|
+
OpenEHR::RM::DataTypes::Quantity::DvScale.new(*param)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
131
|
class DvQuantifiedFactory
|
|
132
132
|
def self.create(*param)
|
|
133
133
|
DataTypes::Quantity::DvQuantified.new(*param)
|
|
@@ -296,6 +296,234 @@ module OpenEHR
|
|
|
296
296
|
end
|
|
297
297
|
end
|
|
298
298
|
|
|
299
|
+
class ElementFactory
|
|
300
|
+
def self.create(param)
|
|
301
|
+
DataStructures::ItemStructure::Representation::Element.new(param)
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
class ItemTreeFactory
|
|
306
|
+
def self.create(param)
|
|
307
|
+
DataStructures::ItemStructure::ItemTree.new(param)
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
class ItemListFactory
|
|
312
|
+
def self.create(param)
|
|
313
|
+
DataStructures::ItemStructure::ItemList.new(param)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
class ItemSingleFactory
|
|
318
|
+
def self.create(param)
|
|
319
|
+
DataStructures::ItemStructure::ItemSingle.new(param)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
class ItemTableFactory
|
|
324
|
+
def self.create(param)
|
|
325
|
+
DataStructures::ItemStructure::ItemTable.new(param)
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
class HistoryFactory
|
|
330
|
+
def self.create(param)
|
|
331
|
+
DataStructures::History::History.new(param)
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
class EventFactory
|
|
336
|
+
def self.create(param)
|
|
337
|
+
DataStructures::History::Event.new(param)
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
class PointEventFactory
|
|
342
|
+
def self.create(param)
|
|
343
|
+
DataStructures::History::PointEvent.new(param)
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
class IntervalEventFactory
|
|
348
|
+
def self.create(param)
|
|
349
|
+
DataStructures::History::IntervalEvent.new(param)
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
class EvaluationFactory
|
|
354
|
+
def self.create(param)
|
|
355
|
+
Composition::Content::Entry::Evaluation.new(param)
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
class InstructionFactory
|
|
360
|
+
def self.create(param)
|
|
361
|
+
Composition::Content::Entry::Instruction.new(param)
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
class ActionFactory
|
|
366
|
+
def self.create(param)
|
|
367
|
+
Composition::Content::Entry::Action.new(param)
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
class ActivityFactory
|
|
372
|
+
def self.create(param)
|
|
373
|
+
Composition::Content::Entry::Activity.new(param)
|
|
374
|
+
end
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
class AdminEntryFactory
|
|
378
|
+
def self.create(param)
|
|
379
|
+
Composition::Content::Entry::AdminEntry.new(param)
|
|
380
|
+
end
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
class InstructionDetailsFactory
|
|
384
|
+
def self.create(param)
|
|
385
|
+
Composition::Content::Entry::InstructionDetails.new(param)
|
|
386
|
+
end
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
class IsmTransitionFactory
|
|
390
|
+
def self.create(param)
|
|
391
|
+
Composition::Content::Entry::IsmTransition.new(param)
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
class GenericEntryFactory
|
|
396
|
+
def self.create(param)
|
|
397
|
+
Integration::GenericEntry.new(param)
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
class PartySelfFactory
|
|
402
|
+
def self.create(param)
|
|
403
|
+
Common::Generic::PartySelf.new(param)
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
class PartyRelatedFactory
|
|
408
|
+
def self.create(param)
|
|
409
|
+
Common::Generic::PartyRelated.new(param)
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
class ParticipationFactory
|
|
414
|
+
def self.create(param)
|
|
415
|
+
Common::Generic::Participation.new(param)
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
class LinkFactory
|
|
420
|
+
def self.create(param)
|
|
421
|
+
Common::Archetyped::Link.new(param)
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
class FeederAuditFactory
|
|
426
|
+
def self.create(param)
|
|
427
|
+
Common::Archetyped::FeederAudit.new(param)
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
class AuditDetailsFactory
|
|
432
|
+
def self.create(param)
|
|
433
|
+
Common::Generic::AuditDetails.new(param)
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
class AttestationFactory
|
|
438
|
+
def self.create(param)
|
|
439
|
+
Common::Generic::Attestation.new(param)
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
class ObjectRefFactory
|
|
444
|
+
def self.create(param)
|
|
445
|
+
Support::Identification::ObjectRef.new(param)
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
class LocatableRefFactory
|
|
450
|
+
def self.create(param)
|
|
451
|
+
Support::Identification::LocatableRef.new(param)
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
class ObjectVersionIdFactory
|
|
456
|
+
def self.create(param)
|
|
457
|
+
Support::Identification::ObjectVersionID.new(param)
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
class HierObjectIdFactory
|
|
462
|
+
def self.create(param)
|
|
463
|
+
Support::Identification::HierObjectID.new(param)
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
class UidBasedIdFactory
|
|
468
|
+
def self.create(param)
|
|
469
|
+
Support::Identification::UIDBasedID.new(param)
|
|
470
|
+
end
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
class AccessGroupRefFactory
|
|
474
|
+
def self.create(param)
|
|
475
|
+
Support::Identification::AccessGroupRef.new(param)
|
|
476
|
+
end
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
class PersonFactory
|
|
480
|
+
def self.create(param)
|
|
481
|
+
Demographic::Person.new(param)
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
class OrganisationFactory
|
|
486
|
+
def self.create(param)
|
|
487
|
+
Demographic::Organisation.new(param)
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
class RoleFactory
|
|
492
|
+
def self.create(param)
|
|
493
|
+
Demographic::Role.new(param)
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
class PartyIdentityFactory
|
|
498
|
+
def self.create(param)
|
|
499
|
+
Demographic::PartyIdentity.new(param)
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
class ContactFactory
|
|
504
|
+
def self.create(param)
|
|
505
|
+
Demographic::Contact.new(param)
|
|
506
|
+
end
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
class AddressFactory
|
|
510
|
+
def self.create(param)
|
|
511
|
+
Demographic::Address.new(param)
|
|
512
|
+
end
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
class CapabilityFactory
|
|
516
|
+
def self.create(param)
|
|
517
|
+
Demographic::Capability.new(param)
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
class PartyRelationshipFactory
|
|
522
|
+
def self.create(param)
|
|
523
|
+
Demographic::PartyRelationship.new(param)
|
|
524
|
+
end
|
|
525
|
+
end
|
|
526
|
+
|
|
299
527
|
class CompositionFactory < Factory
|
|
300
528
|
class << self
|
|
301
529
|
def create_from_json(json)
|
|
@@ -68,7 +68,7 @@ module OpenEHR
|
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def value=(value)
|
|
71
|
-
if
|
|
71
|
+
if /\A([a-zA-Z]\w+)-([a-zA-Z]\w+)-([a-zA-Z]\w+)\.([a-zA-Z]\w+)(-([a-zA-Z]\w+))?\.(v\d+)\z/ =~ value
|
|
72
72
|
self.rm_originator = $1
|
|
73
73
|
self.rm_name = $2
|
|
74
74
|
self.rm_entity = $3
|
|
@@ -108,7 +108,7 @@ module OpenEHR
|
|
|
108
108
|
if domain_concept.nil? or domain_concept.empty?
|
|
109
109
|
raise ArgumentError, "domain concept not valid"
|
|
110
110
|
end
|
|
111
|
-
if
|
|
111
|
+
if /\A([a-zA-Z]\w+)(-([a-zA-Z]\w+))?\z/ =~ domain_concept
|
|
112
112
|
self.concept_name = $1
|
|
113
113
|
self.specialisation = $3
|
|
114
114
|
else
|
|
@@ -249,6 +249,8 @@ module OpenEHR
|
|
|
249
249
|
self.objectid = UID.new(:value => $1)
|
|
250
250
|
self.creating_system_id = UID.new(:value => $2)
|
|
251
251
|
self.version_tree_id = VersionTreeID.new(:value => $3)
|
|
252
|
+
@root = @oid
|
|
253
|
+
@extension = @creating_system_id.value + '::' + @version_tree_id.value
|
|
252
254
|
else
|
|
253
255
|
raise ArgumentError, 'invalid format'
|
|
254
256
|
end
|
|
@@ -297,12 +299,14 @@ module OpenEHR
|
|
|
297
299
|
end
|
|
298
300
|
|
|
299
301
|
def path=(path)
|
|
300
|
-
raise ArgumentError if path.nil?
|
|
302
|
+
raise ArgumentError if !path.nil? and path.empty?
|
|
301
303
|
@path = path
|
|
302
304
|
end
|
|
303
305
|
|
|
304
306
|
def as_uri
|
|
305
|
-
'ehr://' + @id.value
|
|
307
|
+
uri = 'ehr://' + @id.value
|
|
308
|
+
uri += '/' + @path unless @path.nil?
|
|
309
|
+
uri
|
|
306
310
|
end
|
|
307
311
|
end
|
|
308
312
|
|
|
@@ -395,16 +399,41 @@ module OpenEHR
|
|
|
395
399
|
end
|
|
396
400
|
|
|
397
401
|
class UUID < UID
|
|
402
|
+
FORMAT = /\A[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\z/
|
|
398
403
|
|
|
404
|
+
def value=(value)
|
|
405
|
+
unless value.is_a?(String) && value =~ FORMAT
|
|
406
|
+
raise ArgumentError, 'invalid UUID form'
|
|
407
|
+
end
|
|
408
|
+
super
|
|
409
|
+
end
|
|
399
410
|
end
|
|
400
411
|
|
|
401
|
-
class InternetID <UID
|
|
402
|
-
|
|
412
|
+
class InternetID < UID
|
|
413
|
+
# RFC 1034 domain-name form: dot-separated labels, each
|
|
414
|
+
# alphanumeric (with internal hyphens allowed).
|
|
415
|
+
FORMAT = /\A[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+\z/
|
|
416
|
+
|
|
417
|
+
def value=(value)
|
|
418
|
+
unless value.is_a?(String) && value =~ FORMAT
|
|
419
|
+
raise ArgumentError, 'invalid internet id form'
|
|
420
|
+
end
|
|
421
|
+
super
|
|
422
|
+
end
|
|
403
423
|
end
|
|
404
424
|
|
|
405
|
-
class IsoOID <UID
|
|
425
|
+
class IsoOID < UID
|
|
426
|
+
# ISO/IEC 8824 OID form: a dot-separated sequence of
|
|
427
|
+
# non-negative integers, e.g. "1.2.840.113619.2.1".
|
|
428
|
+
FORMAT = /\A\d+(\.\d+)+\z/
|
|
406
429
|
|
|
407
|
-
|
|
430
|
+
def value=(value)
|
|
431
|
+
unless value.is_a?(String) && value =~ FORMAT
|
|
432
|
+
raise ArgumentError, 'invalid ISO OID form'
|
|
433
|
+
end
|
|
434
|
+
super
|
|
435
|
+
end
|
|
436
|
+
end
|
|
408
437
|
end # of Identification
|
|
409
438
|
end # of Support
|
|
410
439
|
end # of RM
|
|
@@ -2,7 +2,39 @@ module OpenEHR
|
|
|
2
2
|
module RM
|
|
3
3
|
module Support
|
|
4
4
|
module Measurement
|
|
5
|
+
# A minimal UCUM-lite syntactic checker, not a full UCUM
|
|
6
|
+
# parser/conversion table: it validates that a units string is
|
|
7
|
+
# *shaped* like a UCUM unit (allowed characters, balanced
|
|
8
|
+
# brackets) and treats "equivalent" as exact string equality of
|
|
9
|
+
# two syntactically-valid units strings. It does not perform
|
|
10
|
+
# unit conversion (e.g. "kg" and "1000g" are not recognized as
|
|
11
|
+
# equivalent).
|
|
5
12
|
class MeasurementService
|
|
13
|
+
UCUM_LITE_PATTERN = /\A[A-Za-z0-9%\/.*\[\]{}'_-]+\z/
|
|
14
|
+
|
|
15
|
+
def self.is_valid_units_string?(units)
|
|
16
|
+
return false unless units.is_a?(String) && !units.empty?
|
|
17
|
+
return false unless units =~ UCUM_LITE_PATTERN
|
|
18
|
+
|
|
19
|
+
balanced_brackets?(units, '[', ']') && balanced_brackets?(units, '{', '}')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.units_equivalent?(units1, units2)
|
|
23
|
+
return false unless is_valid_units_string?(units1) && is_valid_units_string?(units2)
|
|
24
|
+
|
|
25
|
+
units1 == units2
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.balanced_brackets?(str, open, close)
|
|
29
|
+
depth = 0
|
|
30
|
+
str.each_char do |c|
|
|
31
|
+
depth += 1 if c == open
|
|
32
|
+
depth -= 1 if c == close
|
|
33
|
+
return false if depth.negative?
|
|
34
|
+
end
|
|
35
|
+
depth.zero?
|
|
36
|
+
end
|
|
37
|
+
private_class_method :balanced_brackets?
|
|
6
38
|
end
|
|
7
39
|
module ExternalEnvironmentAccess
|
|
8
40
|
def eea_terminology_svc
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
require 'active_support/core_ext/string/inflections'
|
|
3
|
+
|
|
4
|
+
module OpenEHR
|
|
5
|
+
module RM
|
|
6
|
+
module TypeName
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def type_name_of(class_or_instance)
|
|
10
|
+
class_of(class_or_instance).name.split('::').last.underscore.upcase
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def class_for(type_name)
|
|
14
|
+
registry[normalize(type_name)]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def subtype_of?(class_or_instance, type_name)
|
|
18
|
+
expected = normalize(type_name)
|
|
19
|
+
ancestor = class_of(class_or_instance)
|
|
20
|
+
while ancestor
|
|
21
|
+
return true if ancestor.name && type_name_of(ancestor) == expected
|
|
22
|
+
|
|
23
|
+
ancestor = ancestor.superclass
|
|
24
|
+
end
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Accepts a spec type name in any of its forms seen across this
|
|
29
|
+
# codebase - UPPER_SNAKE ('DV_QUANTITY', from the ADL/OPT
|
|
30
|
+
# parsers), CamelCase ('DvQuantity', hardcoded by some
|
|
31
|
+
# CDomainType constructors) or lower_snake - and normalises to
|
|
32
|
+
# the UPPER_SNAKE form used as the registry key.
|
|
33
|
+
def normalize(type_name)
|
|
34
|
+
type_name.to_s.underscore.upcase
|
|
35
|
+
end
|
|
36
|
+
private_class_method :normalize
|
|
37
|
+
|
|
38
|
+
def class_of(class_or_instance)
|
|
39
|
+
class_or_instance.is_a?(Module) ? class_or_instance : class_or_instance.class
|
|
40
|
+
end
|
|
41
|
+
private_class_method :class_of
|
|
42
|
+
|
|
43
|
+
def registry
|
|
44
|
+
@registry ||= build_registry
|
|
45
|
+
end
|
|
46
|
+
private_class_method :registry
|
|
47
|
+
|
|
48
|
+
# Skips Factory (OpenEHR::RM::Factory and the *Factory helper
|
|
49
|
+
# classes in factory.rb) - those are builders, not RM types, and
|
|
50
|
+
# would otherwise shadow nothing but add registry noise.
|
|
51
|
+
def build_registry
|
|
52
|
+
classes = {}
|
|
53
|
+
visit(OpenEHR::RM, Set.new.compare_by_identity) do |klass|
|
|
54
|
+
next if klass.name.end_with?('Factory')
|
|
55
|
+
|
|
56
|
+
classes[type_name_of(klass)] ||= klass
|
|
57
|
+
end
|
|
58
|
+
classes
|
|
59
|
+
end
|
|
60
|
+
private_class_method :build_registry
|
|
61
|
+
|
|
62
|
+
def visit(mod, seen, &block)
|
|
63
|
+
mod.constants(false).each do |const_name|
|
|
64
|
+
const = mod.const_get(const_name)
|
|
65
|
+
next unless const.is_a?(Module)
|
|
66
|
+
next if seen.include?(const)
|
|
67
|
+
|
|
68
|
+
seen << const
|
|
69
|
+
yield const if const.is_a?(Class)
|
|
70
|
+
visit(const, seen, &block)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
private_class_method :visit
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
class << self
|
|
77
|
+
def type_name_of(class_or_instance)
|
|
78
|
+
TypeName.type_name_of(class_or_instance)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def class_for(type_name)
|
|
82
|
+
TypeName.class_for(type_name)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def subtype_of?(class_or_instance, type_name)
|
|
86
|
+
TypeName.subtype_of?(class_or_instance, type_name)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|