openehr 1.2.999999 → 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 +95 -14
- 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 +77 -24
- 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 +306 -27
- data/lib/openehr/parser.rb +2 -0
- data/lib/openehr/path.rb +195 -0
- data/lib/openehr/rm/common/archetyped.rb +117 -7
- 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/data_types/uri.rb +0 -1
- data/lib/openehr/rm/demographic.rb +4 -3
- data/lib/openehr/rm/ehr.rb +20 -1
- data/lib/openehr/rm/factory.rb +345 -36
- 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 +36 -11
- 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
|
@@ -8,10 +8,26 @@ module OpenEHR
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
class << self
|
|
11
|
-
def create(type,
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
def create(type, **param)
|
|
12
|
+
if type.include? '_'
|
|
13
|
+
type = type.downcase.camelize
|
|
14
|
+
else
|
|
15
|
+
type = type.capitalize
|
|
16
|
+
end
|
|
17
|
+
class_eval("#{type}Factory").create(params(param))
|
|
14
18
|
end
|
|
19
|
+
|
|
20
|
+
def params(param)
|
|
21
|
+
param.each_with_object({}) do |item, parameters|
|
|
22
|
+
key = item.shift
|
|
23
|
+
value = item.shift
|
|
24
|
+
if value.instance_of? Hash
|
|
25
|
+
parameters[key] = Factory.create(value[:_type], **value)
|
|
26
|
+
else
|
|
27
|
+
parameters[key] = value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
15
31
|
end
|
|
16
32
|
|
|
17
33
|
def build
|
|
@@ -64,12 +80,6 @@ module OpenEHR
|
|
|
64
80
|
end
|
|
65
81
|
end
|
|
66
82
|
|
|
67
|
-
class TermMappingFactory
|
|
68
|
-
def self.create(*param)
|
|
69
|
-
OpenEHR::RM::DataTypes::Text::TermMapping.new(*param)
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
83
|
class CodePhraseFactory
|
|
74
84
|
def self.create(*param)
|
|
75
85
|
OpenEHR::RM::DataTypes::Text::CodePhrase.new(*param)
|
|
@@ -112,6 +122,12 @@ module OpenEHR
|
|
|
112
122
|
end
|
|
113
123
|
end
|
|
114
124
|
|
|
125
|
+
class DvScaleFactory
|
|
126
|
+
def self.create(*param)
|
|
127
|
+
OpenEHR::RM::DataTypes::Quantity::DvScale.new(*param)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
115
131
|
class DvQuantifiedFactory
|
|
116
132
|
def self.create(*param)
|
|
117
133
|
DataTypes::Quantity::DvQuantified.new(*param)
|
|
@@ -155,75 +171,368 @@ module OpenEHR
|
|
|
155
171
|
end
|
|
156
172
|
|
|
157
173
|
class DvDateFactory
|
|
158
|
-
def self.create(
|
|
159
|
-
OpenEHR::RM::DataTypes::Quantity::DateTime::DvDate.new(
|
|
174
|
+
def self.create(param)
|
|
175
|
+
OpenEHR::RM::DataTypes::Quantity::DateTime::DvDate.new(param)
|
|
160
176
|
end
|
|
161
177
|
end
|
|
162
178
|
|
|
163
179
|
class DvTimeFactory
|
|
164
|
-
def self.create(
|
|
165
|
-
DataTypes::Quantity::DateTime::DvTime.new(
|
|
180
|
+
def self.create(param)
|
|
181
|
+
DataTypes::Quantity::DateTime::DvTime.new(param)
|
|
166
182
|
end
|
|
167
183
|
end
|
|
168
184
|
|
|
169
185
|
class DvDateTimeFactory
|
|
170
|
-
def self.create(
|
|
171
|
-
DataTypes::Quantity::DateTime::DvDateTime.new(
|
|
186
|
+
def self.create(param)
|
|
187
|
+
DataTypes::Quantity::DateTime::DvDateTime.new(param)
|
|
172
188
|
end
|
|
173
189
|
end
|
|
174
190
|
|
|
175
191
|
class DvDurationFactory
|
|
176
|
-
def self.create(
|
|
177
|
-
DataTypes::Quantity::DateTime::DvDuration.new(
|
|
192
|
+
def self.create(param)
|
|
193
|
+
DataTypes::Quantity::DateTime::DvDuration.new(param)
|
|
178
194
|
end
|
|
179
195
|
end
|
|
180
196
|
|
|
181
197
|
class DvEncapsulatedFactory
|
|
182
|
-
def self.create(
|
|
183
|
-
DataTypes::Encapsulated::DvEncapsulated.new(
|
|
198
|
+
def self.create(param)
|
|
199
|
+
DataTypes::Encapsulated::DvEncapsulated.new(param)
|
|
184
200
|
end
|
|
185
201
|
end
|
|
186
202
|
|
|
187
203
|
class DvMultimediaFactory
|
|
188
|
-
def self.create(
|
|
189
|
-
DataTypes::Encapsulated::DvMultimedia.new(
|
|
204
|
+
def self.create(param)
|
|
205
|
+
DataTypes::Encapsulated::DvMultimedia.new(param)
|
|
190
206
|
end
|
|
191
207
|
end
|
|
192
208
|
|
|
193
209
|
class DvParsableFactory
|
|
194
|
-
def self.create(
|
|
195
|
-
DataTypes::Encapsulated::DvParsable.new(
|
|
210
|
+
def self.create(param)
|
|
211
|
+
DataTypes::Encapsulated::DvParsable.new(param)
|
|
196
212
|
end
|
|
197
213
|
end
|
|
198
214
|
|
|
199
215
|
class DvUriFactory
|
|
200
|
-
def self.create(
|
|
201
|
-
DataTypes::URI::DvUri.new(
|
|
216
|
+
def self.create(param)
|
|
217
|
+
DataTypes::URI::DvUri.new(param)
|
|
202
218
|
end
|
|
203
219
|
end
|
|
204
220
|
|
|
205
221
|
class DvEhrUriFactory
|
|
206
|
-
def self.create(
|
|
207
|
-
DataTypes::URI::DvEhrUri.new(
|
|
222
|
+
def self.create(param)
|
|
223
|
+
DataTypes::URI::DvEhrUri.new(param)
|
|
208
224
|
end
|
|
209
225
|
end
|
|
210
226
|
|
|
211
|
-
class
|
|
212
|
-
def self.create(
|
|
213
|
-
Composition::Content::Entry::Observation.new(
|
|
227
|
+
class ObservationFactory
|
|
228
|
+
def self.create(param)
|
|
229
|
+
Composition::Content::Entry::Observation.new(param)
|
|
214
230
|
end
|
|
215
231
|
end
|
|
216
232
|
|
|
217
|
-
class
|
|
218
|
-
def self.create(
|
|
219
|
-
Composition::Content::Navigation::Section.new(
|
|
233
|
+
class SectionFactory
|
|
234
|
+
def self.create(param)
|
|
235
|
+
Composition::Content::Navigation::Section.new(param)
|
|
220
236
|
end
|
|
221
237
|
end
|
|
222
238
|
|
|
223
|
-
class
|
|
224
|
-
def self.create(
|
|
225
|
-
DataStructures::ItemStructure::Representation::Cluster.new(
|
|
239
|
+
class ClusterFactory
|
|
240
|
+
def self.create(param)
|
|
241
|
+
DataStructures::ItemStructure::Representation::Cluster.new(param)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
class ArchetypedFactory
|
|
246
|
+
def self.create(param)
|
|
247
|
+
OpenEHR::RM::Common::Archetyped::Archetyped.new(**param)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
class ArchetypeIdFactory
|
|
252
|
+
def self.create(param)
|
|
253
|
+
OpenEHR::RM::Support::Identification::ArchetypeID.new(param)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
class TemplateIdFactory
|
|
258
|
+
def self.create(param)
|
|
259
|
+
OpenEHR::RM::Support::Identification::TemplateID.new(param)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
class TerminologyIdFactory
|
|
264
|
+
def self.create(param)
|
|
265
|
+
OpenEHR::RM::Support::Identification::TerminologyID.new(param)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
class GenericIdFactory
|
|
270
|
+
def self.create(param)
|
|
271
|
+
OpenEHR::RM::Support::Identification::GenericID.new(param)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
class PartyRefFactory
|
|
276
|
+
def self.create(param)
|
|
277
|
+
OpenEHR::RM::Support::Identification::PartyRef.new(param)
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
class PartyIdentifiedFactory
|
|
282
|
+
def self.create(param)
|
|
283
|
+
OpenEHR::RM::Common::Generic::PartyIdentified.new(param)
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
class EventContextFactory
|
|
288
|
+
def self.create(param)
|
|
289
|
+
OpenEHR::RM::Composition::EventContext.new(param)
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
class TermMappingFactory
|
|
294
|
+
def self.create(param)
|
|
295
|
+
OpenEHR::RM::DataTypes::Text::TermMapping.new(param)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
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
|
+
|
|
527
|
+
class CompositionFactory < Factory
|
|
528
|
+
class << self
|
|
529
|
+
def create_from_json(json)
|
|
530
|
+
hash = JSON.parse(json, max_nesting: false, symbolize_names: true)
|
|
531
|
+
OpenEHR::RM::Composition::Composition.new(params(hash))
|
|
532
|
+
end
|
|
226
533
|
end
|
|
227
534
|
end
|
|
228
535
|
end
|
|
229
536
|
end
|
|
537
|
+
|
|
538
|
+
|
|
@@ -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
|