fhir_dstu2_models 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +1 -1
  3. data/.github/workflows/ruby.yml +2 -1
  4. data/.rubocop.yml +7 -1
  5. data/.rubocop_todo.yml +56 -161
  6. data/.ruby-version +1 -0
  7. data/.simplecov +1 -5
  8. data/.tool-versions +1 -0
  9. data/Gemfile.lock +37 -35
  10. data/Guardfile +1 -1
  11. data/fhir_dstu2_models.gemspec +2 -1
  12. data/lib/fhir_dstu2_models/bootstrap/definitions.rb +18 -4
  13. data/lib/fhir_dstu2_models/bootstrap/field.rb +2 -2
  14. data/lib/fhir_dstu2_models/bootstrap/generator.rb +6 -4
  15. data/lib/fhir_dstu2_models/bootstrap/hashable.rb +6 -5
  16. data/lib/fhir_dstu2_models/bootstrap/json.rb +2 -2
  17. data/lib/fhir_dstu2_models/bootstrap/model.rb +45 -32
  18. data/lib/fhir_dstu2_models/bootstrap/preprocess.rb +19 -11
  19. data/lib/fhir_dstu2_models/bootstrap/xml.rb +9 -7
  20. data/lib/fhir_dstu2_models/deprecate.rb +1 -0
  21. data/lib/fhir_dstu2_models/fhir/metadata.rb +19 -21
  22. data/lib/fhir_dstu2_models/fhir/resources/Account.rb +20 -20
  23. data/lib/fhir_dstu2_models/fhir/resources/AllergyIntolerance.rb +34 -34
  24. data/lib/fhir_dstu2_models/fhir/resources/Appointment.rb +28 -28
  25. data/lib/fhir_dstu2_models/fhir/resources/AppointmentResponse.rb +17 -17
  26. data/lib/fhir_dstu2_models/fhir/resources/AuditEvent.rb +66 -66
  27. data/lib/fhir_dstu2_models/fhir/resources/Basic.rb +14 -14
  28. data/lib/fhir_dstu2_models/fhir/resources/Binary.rb +7 -7
  29. data/lib/fhir_dstu2_models/fhir/resources/BodySite.rb +15 -15
  30. data/lib/fhir_dstu2_models/fhir/resources/Bundle.rb +45 -45
  31. data/lib/fhir_dstu2_models/fhir/resources/CarePlan.rb +63 -63
  32. data/lib/fhir_dstu2_models/fhir/resources/Claim.rb +118 -118
  33. data/lib/fhir_dstu2_models/fhir/resources/ClaimResponse.rb +122 -124
  34. data/lib/fhir_dstu2_models/fhir/resources/ClinicalImpression.rb +42 -42
  35. data/lib/fhir_dstu2_models/fhir/resources/Communication.rb +28 -28
  36. data/lib/fhir_dstu2_models/fhir/resources/CommunicationRequest.rb +30 -30
  37. data/lib/fhir_dstu2_models/fhir/resources/Composition.rb +46 -46
  38. data/lib/fhir_dstu2_models/fhir/resources/ConceptMap.rb +53 -53
  39. data/lib/fhir_dstu2_models/fhir/resources/Condition.rb +44 -44
  40. data/lib/fhir_dstu2_models/fhir/resources/Conformance.rb +138 -138
  41. data/lib/fhir_dstu2_models/fhir/resources/Contract.rb +98 -98
  42. data/lib/fhir_dstu2_models/fhir/resources/Coverage.rb +23 -23
  43. data/lib/fhir_dstu2_models/fhir/resources/DataElement.rb +35 -35
  44. data/lib/fhir_dstu2_models/fhir/resources/DetectedIssue.rb +25 -25
  45. data/lib/fhir_dstu2_models/fhir/resources/Device.rb +25 -25
  46. data/lib/fhir_dstu2_models/fhir/resources/DeviceComponent.rb +25 -25
  47. data/lib/fhir_dstu2_models/fhir/resources/DeviceMetric.rb +25 -25
  48. data/lib/fhir_dstu2_models/fhir/resources/DeviceUseRequest.rb +25 -25
  49. data/lib/fhir_dstu2_models/fhir/resources/DeviceUseStatement.rb +21 -21
  50. data/lib/fhir_dstu2_models/fhir/resources/DiagnosticOrder.rb +36 -36
  51. data/lib/fhir_dstu2_models/fhir/resources/DiagnosticReport.rb +32 -32
  52. data/lib/fhir_dstu2_models/fhir/resources/DocumentManifest.rb +31 -31
  53. data/lib/fhir_dstu2_models/fhir/resources/DocumentReference.rb +51 -51
  54. data/lib/fhir_dstu2_models/fhir/resources/DomainResource.rb +12 -12
  55. data/lib/fhir_dstu2_models/fhir/resources/EligibilityRequest.rb +16 -16
  56. data/lib/fhir_dstu2_models/fhir/resources/EligibilityResponse.rb +19 -19
  57. data/lib/fhir_dstu2_models/fhir/resources/Encounter.rb +59 -59
  58. data/lib/fhir_dstu2_models/fhir/resources/EnrollmentRequest.rb +19 -19
  59. data/lib/fhir_dstu2_models/fhir/resources/EnrollmentResponse.rb +19 -19
  60. data/lib/fhir_dstu2_models/fhir/resources/EpisodeOfCare.rb +31 -31
  61. data/lib/fhir_dstu2_models/fhir/resources/ExplanationOfBenefit.rb +19 -19
  62. data/lib/fhir_dstu2_models/fhir/resources/FamilyMemberHistory.rb +39 -39
  63. data/lib/fhir_dstu2_models/fhir/resources/Flag.rb +17 -17
  64. data/lib/fhir_dstu2_models/fhir/resources/Goal.rb +30 -30
  65. data/lib/fhir_dstu2_models/fhir/resources/Group.rb +33 -33
  66. data/lib/fhir_dstu2_models/fhir/resources/HealthcareService.rb +48 -48
  67. data/lib/fhir_dstu2_models/fhir/resources/ImagingObjectSelection.rb +41 -41
  68. data/lib/fhir_dstu2_models/fhir/resources/ImagingStudy.rb +48 -48
  69. data/lib/fhir_dstu2_models/fhir/resources/Immunization.rb +52 -52
  70. data/lib/fhir_dstu2_models/fhir/resources/ImmunizationRecommendation.rb +35 -35
  71. data/lib/fhir_dstu2_models/fhir/resources/ImplementationGuide.rb +67 -67
  72. data/lib/fhir_dstu2_models/fhir/resources/List.rb +29 -29
  73. data/lib/fhir_dstu2_models/fhir/resources/Location.rb +27 -27
  74. data/lib/fhir_dstu2_models/fhir/resources/Media.rb +21 -21
  75. data/lib/fhir_dstu2_models/fhir/resources/Medication.rb +40 -40
  76. data/lib/fhir_dstu2_models/fhir/resources/MedicationAdministration.rb +36 -36
  77. data/lib/fhir_dstu2_models/fhir/resources/MedicationDispense.rb +49 -49
  78. data/lib/fhir_dstu2_models/fhir/resources/MedicationOrder.rb +57 -57
  79. data/lib/fhir_dstu2_models/fhir/resources/MedicationStatement.rb +41 -41
  80. data/lib/fhir_dstu2_models/fhir/resources/MessageHeader.rb +40 -40
  81. data/lib/fhir_dstu2_models/fhir/resources/NamingSystem.rb +34 -34
  82. data/lib/fhir_dstu2_models/fhir/resources/NutritionOrder.rb +67 -67
  83. data/lib/fhir_dstu2_models/fhir/resources/Observation.rb +68 -68
  84. data/lib/fhir_dstu2_models/fhir/resources/OperationDefinition.rb +51 -51
  85. data/lib/fhir_dstu2_models/fhir/resources/OperationOutcome.rb +21 -21
  86. data/lib/fhir_dstu2_models/fhir/resources/Order.rb +23 -23
  87. data/lib/fhir_dstu2_models/fhir/resources/OrderResponse.rb +16 -16
  88. data/lib/fhir_dstu2_models/fhir/resources/Organization.rb +24 -24
  89. data/lib/fhir_dstu2_models/fhir/resources/Parameters.rb +48 -48
  90. data/lib/fhir_dstu2_models/fhir/resources/Patient.rb +54 -54
  91. data/lib/fhir_dstu2_models/fhir/resources/PaymentNotice.rb +19 -19
  92. data/lib/fhir_dstu2_models/fhir/resources/PaymentReconciliation.rb +39 -39
  93. data/lib/fhir_dstu2_models/fhir/resources/Person.rb +24 -24
  94. data/lib/fhir_dstu2_models/fhir/resources/Practitioner.rb +36 -36
  95. data/lib/fhir_dstu2_models/fhir/resources/Procedure.rb +42 -42
  96. data/lib/fhir_dstu2_models/fhir/resources/ProcedureRequest.rb +27 -27
  97. data/lib/fhir_dstu2_models/fhir/resources/ProcessRequest.rb +29 -29
  98. data/lib/fhir_dstu2_models/fhir/resources/ProcessResponse.rb +27 -27
  99. data/lib/fhir_dstu2_models/fhir/resources/Provenance.rb +39 -39
  100. data/lib/fhir_dstu2_models/fhir/resources/Questionnaire.rb +40 -40
  101. data/lib/fhir_dstu2_models/fhir/resources/QuestionnaireResponse.rb +50 -50
  102. data/lib/fhir_dstu2_models/fhir/resources/ReferralRequest.rb +25 -25
  103. data/lib/fhir_dstu2_models/fhir/resources/RelatedPerson.rb +19 -19
  104. data/lib/fhir_dstu2_models/fhir/resources/Resource.rb +5 -5
  105. data/lib/fhir_dstu2_models/fhir/resources/RiskAssessment.rb +30 -30
  106. data/lib/fhir_dstu2_models/fhir/resources/Schedule.rb +14 -14
  107. data/lib/fhir_dstu2_models/fhir/resources/SearchParameter.rb +29 -29
  108. data/lib/fhir_dstu2_models/fhir/resources/Slot.rb +17 -17
  109. data/lib/fhir_dstu2_models/fhir/resources/Specimen.rb +45 -45
  110. data/lib/fhir_dstu2_models/fhir/resources/StructureDefinition.rb +54 -54
  111. data/lib/fhir_dstu2_models/fhir/resources/Subscription.rb +24 -24
  112. data/lib/fhir_dstu2_models/fhir/resources/Substance.rb +26 -26
  113. data/lib/fhir_dstu2_models/fhir/resources/SupplyDelivery.rb +20 -20
  114. data/lib/fhir_dstu2_models/fhir/resources/SupplyRequest.rb +25 -25
  115. data/lib/fhir_dstu2_models/fhir/resources/TestScript.rb +140 -140
  116. data/lib/fhir_dstu2_models/fhir/resources/ValueSet.rb +108 -108
  117. data/lib/fhir_dstu2_models/fhir/resources/VisionPrescription.rb +35 -35
  118. data/lib/fhir_dstu2_models/fhir/types/Address.rb +16 -16
  119. data/lib/fhir_dstu2_models/fhir/types/Annotation.rb +10 -10
  120. data/lib/fhir_dstu2_models/fhir/types/Attachment.rb +14 -14
  121. data/lib/fhir_dstu2_models/fhir/types/BackboneElement.rb +7 -7
  122. data/lib/fhir_dstu2_models/fhir/types/CodeableConcept.rb +8 -8
  123. data/lib/fhir_dstu2_models/fhir/types/Coding.rb +11 -11
  124. data/lib/fhir_dstu2_models/fhir/types/ContactPoint.rb +11 -11
  125. data/lib/fhir_dstu2_models/fhir/types/Element.rb +3 -3
  126. data/lib/fhir_dstu2_models/fhir/types/ElementDefinition.rb +263 -263
  127. data/lib/fhir_dstu2_models/fhir/types/Extension.rb +40 -40
  128. data/lib/fhir_dstu2_models/fhir/types/HumanName.rb +13 -13
  129. data/lib/fhir_dstu2_models/fhir/types/Identifier.rb +12 -12
  130. data/lib/fhir_dstu2_models/fhir/types/Meta.rb +11 -11
  131. data/lib/fhir_dstu2_models/fhir/types/Narrative.rb +8 -8
  132. data/lib/fhir_dstu2_models/fhir/types/Period.rb +8 -8
  133. data/lib/fhir_dstu2_models/fhir/types/Quantity.rb +11 -11
  134. data/lib/fhir_dstu2_models/fhir/types/Range.rb +8 -8
  135. data/lib/fhir_dstu2_models/fhir/types/Ratio.rb +8 -8
  136. data/lib/fhir_dstu2_models/fhir/types/Reference.rb +5 -5
  137. data/lib/fhir_dstu2_models/fhir/types/SampledData.rb +13 -13
  138. data/lib/fhir_dstu2_models/fhir/types/Signature.rb +12 -12
  139. data/lib/fhir_dstu2_models/fhir/types/Timing.rb +24 -24
  140. data/lib/fhir_dstu2_models/fhir.rb +7 -6
  141. data/lib/fhir_dstu2_models/fhir_ext/element_definition.rb +3 -0
  142. data/lib/fhir_dstu2_models/fhir_ext/structure_definition.rb +19 -14
  143. data/lib/fhir_dstu2_models/fhir_ext/structure_definition_compare.rb +10 -0
  144. data/lib/fhir_dstu2_models/fhir_ext/structure_definition_finding.rb +2 -2
  145. data/lib/fhir_dstu2_models/fluentpath/evaluate.rb +18 -11
  146. data/lib/fhir_dstu2_models/fluentpath/expression.rb +3 -5
  147. data/lib/fhir_dstu2_models/fluentpath/parse.rb +7 -4
  148. data/lib/fhir_dstu2_models/version.rb +1 -1
  149. metadata +11 -9
@@ -44,6 +44,7 @@ module FHIR
44
44
  def self.type_definition(type_name)
45
45
  return nil if type_name.nil?
46
46
  return @@cache[type_name] if @@cache[type_name]
47
+
47
48
  definition = types.find { |x| x['xmlId'] == type_name || x['name'] == type_name || x['url'] == type_name }
48
49
  @@cache[type_name] = FHIR::DSTU2::StructureDefinition.new(definition) if definition
49
50
  @@cache[type_name]
@@ -73,6 +74,7 @@ module FHIR
73
74
  def self.resource_definition(resource_name)
74
75
  return nil if resource_name.nil?
75
76
  return @@cache[resource_name] if @@cache[resource_name]
77
+
76
78
  definition = resources.find { |x| x['xmlId'] == resource_name || x['name'] == resource_name || x['url'] == resource_name }
77
79
  @@cache[resource_name] = FHIR::DSTU2::StructureDefinition.new(definition) if definition
78
80
  @@cache[resource_name]
@@ -103,8 +105,10 @@ module FHIR
103
105
 
104
106
  def self.extension_definition(extension_name)
105
107
  return nil if extension_name.nil?
108
+
106
109
  extension = extensions.find { |x| x['xmlId'] == extension_name || x['name'] == extension_name || x['url'] == extension_name }
107
110
  return nil if extension.nil?
111
+
108
112
  FHIR::DSTU2::StructureDefinition.new(extension)
109
113
  end
110
114
  deprecate :get_extension_definition, :extension_definition
@@ -112,8 +116,10 @@ module FHIR
112
116
  # Get the basetype (String) for a given profile or extension.
113
117
  def self.basetype(uri)
114
118
  return nil if uri.nil?
119
+
115
120
  defn = profiles.detect { |x| x['url'] == uri } || extensions.detect { |x| x['url'] == uri }
116
121
  return nil if defn.nil?
122
+
117
123
  defn['baseType']
118
124
  end
119
125
  deprecate :get_basetype, :basetype
@@ -121,14 +127,17 @@ module FHIR
121
127
  # Get the StructureDefinition for a given profile.
122
128
  def self.profile(uri)
123
129
  return nil if uri.nil?
130
+
124
131
  defn = profiles.detect { |x| x['url'] == uri } || extensions.detect { |x| x['url'] == uri }
125
132
  return nil if defn.nil?
133
+
126
134
  FHIR::DSTU2::StructureDefinition.new(defn)
127
135
  end
128
136
  deprecate :get_profile, :profile
129
137
 
130
138
  def self.profiles_for_resource(resource_name)
131
139
  return nil if resource_name.nil?
140
+
132
141
  profiles.select { |x| x['baseType'] == resource_name }.map { |x| FHIR::DSTU2::StructureDefinition.new(x) }
133
142
  end
134
143
  deprecate :get_profiles_for_resource, :profile_for_resource
@@ -136,6 +145,7 @@ module FHIR
136
145
  # Get a dynamically generated class for a given profile.
137
146
  def self.get_profile_class(uri)
138
147
  return nil if uri.nil?
148
+
139
149
  load_profiles
140
150
  load_extensions
141
151
 
@@ -161,7 +171,7 @@ module FHIR
161
171
  load f
162
172
  # set the return class type
163
173
  klass = Object.const_get("FHIR::DSTU2::Profile::#{id}::#{type}")
164
- rescue
174
+ rescue StandardError
165
175
  FHIR::DSTU2.logger.error "Failed to generate class for profile #{uri}"
166
176
  end
167
177
  # unlink the file so it can be garbage collected
@@ -197,6 +207,7 @@ module FHIR
197
207
  def self.get_codes(uri, parent_code = nil)
198
208
  return nil if uri.nil?
199
209
  return @@cache[uri] if @@cache[uri]
210
+
200
211
  FHIR::DSTU2.logger.debug "Looking up codes for #{uri}"
201
212
  valueset = valuesets.select { |x| x['url'] == uri }.first
202
213
  if valueset.nil?
@@ -234,8 +245,9 @@ module FHIR
234
245
  []
235
246
  end
236
247
  end
237
- x['concept'].each { |y| @@cache[uri][system] += get_codes_from_concept(y, parent_code) } if x['concept']
248
+ x['concept']&.each { |y| @@cache[uri][system] += get_codes_from_concept(y, parent_code) }
238
249
  next unless x['filter']
250
+
239
251
  x['filter'].each do |filter|
240
252
  if filter['property'] == 'concept' && filter['op'] == 'is-a'
241
253
  codes = get_codes(system, filter['value'])
@@ -255,7 +267,7 @@ module FHIR
255
267
  []
256
268
  end
257
269
  end
258
- x['concept'].each { |y| @@cache[uri][system].delete(y['code']) } if x['concept']
270
+ x['concept']&.each { |y| @@cache[uri][system].delete(y['code']) }
259
271
  end
260
272
  end
261
273
  end
@@ -273,6 +285,7 @@ module FHIR
273
285
  codes = lookup[sys] if lookup
274
286
  end
275
287
  next unless codes
288
+
276
289
  codes.each do |code|
277
290
  @@cache[uri][sys] = [] unless @@cache[uri].keys.include?(sys)
278
291
  @@cache[uri][sys] << code
@@ -296,7 +309,7 @@ module FHIR
296
309
  end
297
310
  end
298
311
  codes
299
- rescue => e
312
+ rescue StandardError => e
300
313
  FHIR::DSTU2.logger.debug "Unable to extract codes from concept #{concept}: #{e.message}"
301
314
  end
302
315
 
@@ -342,6 +355,7 @@ module FHIR
342
355
 
343
356
  def self.search_parameters(type_name)
344
357
  return nil if type_name.nil?
358
+
345
359
  search_params.select { |p| p['base'].include?(type_name) && p['xpath'] && !p['xpath'].include?('extension') }.map { |p| p['code'] }
346
360
  end
347
361
  deprecate :get_search_parameters, :search_parameters
@@ -23,7 +23,7 @@ module FHIR
23
23
  def serialize
24
24
  hash = {}
25
25
  instance_variables.each do |v|
26
- hash[v.to_s[1..-1]] = instance_variable_get(v)
26
+ hash[v.to_s[1..]] = instance_variable_get(v)
27
27
  end
28
28
  hash.delete('name')
29
29
  hash.keep_if do |_key, value|
@@ -37,7 +37,7 @@ module FHIR
37
37
 
38
38
  def fix_name(name)
39
39
  fix = nil
40
- fix = "local_#{name}" if %w[class method resourceType].include?(name)
40
+ fix = "local_#{name}" if ['class', 'method', 'resourceType'].include?(name)
41
41
  fix
42
42
  end
43
43
  end
@@ -120,6 +120,7 @@ module FHIR
120
120
  # skip the first element
121
121
  next if element['path'] == path_type
122
122
  next unless element['type']
123
+
123
124
  unique_types = element['type'].map { |t| t['code'] }.uniq
124
125
  if unique_types.include?('Element') || unique_types.include?('BackboneElement')
125
126
  child_templates << element['path']
@@ -129,6 +130,7 @@ module FHIR
129
130
  child_templates.each do |child_name|
130
131
  child_fixed_name = cap_first(child_name.gsub("#{type_name}.", ''))
131
132
  next if child_fixed_name.include?('.')
133
+
132
134
  child_def = { 'id' => child_fixed_name, 'snapshot' => { 'element' => [] } }
133
135
  # Copy the element definitions for the child structure
134
136
  structure_def['snapshot']['element'].each do |element|
@@ -183,13 +185,13 @@ module FHIR
183
185
  field.path = element['path'].gsub(path_type, type_name)
184
186
  field.type = data_type
185
187
  field.type = 'Extension' if field.path.end_with?('extension')
186
- field.type_profiles = profiles if %w[Reference Extension].include?(data_type)
188
+ field.type_profiles = profiles if ['Reference', 'Extension'].include?(data_type)
187
189
  field.min = element['min']
188
190
  field.max = element['max']
189
191
  field.max = field.max.to_i
190
192
  field.max = '*' if element['max'] == '*'
191
193
 
192
- if %w[code Coding CodeableConcept].include?(data_type) && element['binding']
194
+ if ['code', 'Coding', 'CodeableConcept'].include?(data_type) && element['binding']
193
195
  field.binding = element['binding']
194
196
  field.binding['uri'] = field.binding['valueSetUri']
195
197
  field.binding['uri'] = field.binding['valueSetReference'] if field.binding['uri'].nil?
@@ -206,7 +208,7 @@ module FHIR
206
208
  @missing_expansions = true
207
209
  @missing_required_expansion = (field.binding['strength'] == 'required') unless @missing_required_expansion
208
210
  end
209
- elsif %w[Element BackboneElement].include?(data_type)
211
+ elsif ['Element', 'BackboneElement'].include?(data_type)
210
212
  # This is a nested structure or class
211
213
  field.type = "#{hierarchy.join('::')}::#{cap_first(field.name)}"
212
214
  end
@@ -217,7 +219,7 @@ module FHIR
217
219
  field = FHIR::DSTU2::Field.new(field_base_name)
218
220
  field.path = element['path'].gsub(path_type, type_name)
219
221
  field.type = element['nameReference']
220
- field.type = field.type[1..-1] if field.type[0] == '#'
222
+ field.type = field.type[1..] if field.type[0] == '#'
221
223
  hindex = hierarchy.index { |x| x.casecmp(field.type).zero? }
222
224
  if hindex
223
225
  # reference to self
@@ -39,11 +39,12 @@ module FHIR
39
39
  key = key.to_s
40
40
  meta = self.class::METADATA[key]
41
41
  next if meta.nil?
42
+
42
43
  local_name = key
43
44
  local_name = meta['local_name'] if meta['local_name']
44
45
  begin
45
46
  instance_variable_set("@#{local_name}", value)
46
- rescue
47
+ rescue StandardError
47
48
  # TODO: this appears to be a dead code branch
48
49
  nil
49
50
  end
@@ -86,17 +87,17 @@ module FHIR
86
87
  if child['resourceType'] && !klass::METADATA['resourceType']
87
88
  klass = begin
88
89
  FHIR::DSTU2.const_get(child['resourceType'])
89
- rescue => exception
90
+ rescue StandardError => e
90
91
  # TODO: this appears to be a dead code branch
91
- FHIR::DSTU2.logger.error("Unable to identify embedded class #{child['resourceType']}\n#{exception.message}\n#{exception.backtrace}")
92
+ FHIR::DSTU2.logger.error("Unable to identify embedded class #{child['resourceType']}\n#{e.message}\n#{e.backtrace}")
92
93
  nil
93
94
  end
94
95
  end
95
96
  begin
96
97
  obj = klass.new(child)
97
- rescue => exception
98
+ rescue StandardError => e
98
99
  # TODO: this appears to be a dead code branch
99
- FHIR::DSTU2.logger.error("Unable to inflate embedded class #{klass}\n#{exception.message}\n#{exception.backtrace}")
100
+ FHIR::DSTU2.logger.error("Unable to inflate embedded class #{klass}\n#{e.message}\n#{e.backtrace}")
100
101
  end
101
102
  obj
102
103
  end
@@ -7,7 +7,7 @@ module FHIR
7
7
  # This module includes methods to serialize or deserialize FHIR::DSTU2 resources to and from JSON.
8
8
  #
9
9
 
10
- def to_json
10
+ def to_json(*_args)
11
11
  JSON.pretty_unparse(to_hash)
12
12
  end
13
13
 
@@ -18,7 +18,7 @@ module FHIR
18
18
  resource_type = hash['resourceType']
19
19
  klass = Module.const_get("FHIR::DSTU2::#{resource_type}")
20
20
  resource = klass.new(hash)
21
- rescue => e
21
+ rescue StandardError => e
22
22
  FHIR::DSTU2.logger.error("Failed to deserialize JSON:\n#{e.message}\n#{e.backtrace}")
23
23
  FHIR::DSTU2.logger.debug("JSON:\n#{json}")
24
24
  resource = nil
@@ -23,40 +23,39 @@ module FHIR
23
23
  to_hash.hash
24
24
  end
25
25
 
26
+ def respond_to_missing?(method_name, *)
27
+ (defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method_name.to_s]) ||
28
+ (!@extension.nil? && !@extension.empty? && !find_extension(@extension, method_name).first.nil?) ||
29
+ (!@modifierExtension.nil? && !@modifierExtension.empty? && !find_extension(@modifierExtension, method_name).first.nil?) ||
30
+ super
31
+ end
32
+
26
33
  # allow two FHIR::DSTU2 models to be compared for equality
27
34
  def ==(other)
28
35
  self.class == other.class && to_hash == other.to_hash
29
36
  end
30
37
  alias eql? ==
31
38
 
32
- def method_missing(method, *_args, &_block)
33
- if defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method.to_s]
34
- self.class::MULTIPLE_TYPES[method.to_s].each do |type|
39
+ def method_missing(method_name, *_args, &_block)
40
+ if defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method_name.to_s]
41
+ self.class::MULTIPLE_TYPES[method_name.to_s].each do |type|
35
42
  type[0] = type[0].upcase
36
- value = send("#{method}#{type}".to_sym)
43
+ value = send("#{method_name}#{type}".to_sym)
37
44
  return value unless value.nil?
38
45
  end
39
46
  return nil
40
47
  elsif !@extension.nil? && !@extension.empty?
41
- ext = @extension.select do |x|
42
- name = x.url.tr('-', '_').split('/').last
43
- anchor = name.split('#').last
44
- (method.to_s == name || method.to_s == anchor)
45
- end
46
- unless ext.first.nil?
47
- return ext.first.value.nil? ? ext.first : ext.first.value
48
+ desired_extension = find_extension(@extension, method_name)
49
+ unless desired_extension.first.nil?
50
+ return desired_extension.first.value.nil? ? desired_extension.first : desired_extension.first.value
48
51
  end
49
52
  elsif !@modifierExtension.nil? && !@modifierExtension.empty?
50
- ext = @modifierExtension.select do |x|
51
- name = x.url.tr('-', '_').split('/').last
52
- anchor = name.split('#').last
53
- (method.to_s == name || method.to_s == anchor)
54
- end
55
- unless ext.first.nil?
56
- return ext.first.value.nil? ? ext.first : ext.first.value
53
+ desired_extension = find_extension(@modifierExtension, method_name)
54
+ unless desired_extension.first.nil?
55
+ return desired_extension.first.value.nil? ? desired_extension.first : desired_extension.first.value
57
56
  end
58
57
  end
59
- raise NoMethodError.new("undefined method `#{method}' for #{self.class.name}", method)
58
+ raise NoMethodError.new("undefined method `#{method_name}' for #{self.class.name}", method_name)
60
59
  end
61
60
 
62
61
  def to_reference
@@ -66,6 +65,7 @@ module FHIR
66
65
  def equals?(other, exclude = [])
67
66
  self.class::METADATA.each do |key, value|
68
67
  next if exclude.include?(key)
68
+
69
69
  local_name = key
70
70
  local_name = value['local_name'] if value['local_name']
71
71
  return false unless compare_attribute(instance_variable_get("@#{local_name}".to_sym), other.instance_variable_get("@#{local_name}".to_sym), exclude)
@@ -77,6 +77,7 @@ module FHIR
77
77
  misses = []
78
78
  self.class::METADATA.each do |key, value|
79
79
  next if exclude.include?(key)
80
+
80
81
  local_name = key
81
82
  local_name = value['local_name'] if value['local_name']
82
83
  these = attribute_mismatch(instance_variable_get("@#{local_name}".to_sym), other.instance_variable_get("@#{local_name}".to_sym), exclude)
@@ -150,14 +151,14 @@ module FHIR
150
151
  end # metadata.each
151
152
  # check multiple types
152
153
  multiple_types = begin
153
- self.class::MULTIPLE_TYPES
154
- rescue
155
- {}
156
- end
154
+ self.class::MULTIPLE_TYPES
155
+ rescue StandardError
156
+ {}
157
+ end
157
158
  multiple_types.each do |prefix, suffixes|
158
159
  present = []
159
160
  suffixes.each do |suffix|
160
- typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..-1]}"
161
+ typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..]}"
161
162
  # check which multiple data types are actually present, not just errors
162
163
  # actually, this might be allowed depending on cardinality
163
164
  value = instance_variable_get("@#{typename}")
@@ -166,8 +167,9 @@ module FHIR
166
167
  errors[prefix] = ["#{prefix}[x]: more than one type present."] if present.length > 1
167
168
  # remove errors for suffixes that are not present
168
169
  next unless present.length == 1
170
+
169
171
  suffixes.each do |suffix|
170
- typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..-1]}"
172
+ typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..]}"
171
173
  errors.delete(typename) unless present.include?(typename)
172
174
  end
173
175
  end
@@ -230,10 +232,12 @@ module FHIR
230
232
  # check binding
231
233
  next unless meta['binding']
232
234
  next unless meta['binding']['strength'] == 'required'
235
+
233
236
  the_codes = [v]
234
- if meta['type'] == 'Coding'
237
+ case meta['type']
238
+ when 'Coding'
235
239
  the_codes = [v.code]
236
- elsif meta['type'] == 'CodeableConcept'
240
+ when 'CodeableConcept'
237
241
  the_codes = v.coding.map(&:code).compact
238
242
  end
239
243
  has_valid_code = false
@@ -256,6 +260,7 @@ module FHIR
256
260
  def validate_reference_type(ref, meta, contained_here, errors)
257
261
  return unless ref.reference && meta['type_profiles']
258
262
  return if ref.reference.start_with?('urn:uuid:', 'urn:oid:')
263
+
259
264
  matches_one_profile = false
260
265
  meta['type_profiles'].each do |p|
261
266
  basetype = p.split('/').last
@@ -267,7 +272,7 @@ module FHIR
267
272
  matches_one_profile = true if meta['type_profiles'].include?('http://hl7.org/fhir/StructureDefinition/Resource')
268
273
  if !matches_one_profile && ref.reference.start_with?('#')
269
274
  # we need to look at the local contained resources
270
- r = contained_here.find { |x| x.id == ref.reference[1..-1] }
275
+ r = contained_here.find { |x| x.id == ref.reference[1..] }
271
276
  if !r.nil?
272
277
  meta['type_profiles'].each do |p|
273
278
  p = p.split('/').last
@@ -288,12 +293,12 @@ module FHIR
288
293
 
289
294
  def check_binding_uri(uri, value)
290
295
  valid = false
291
- if %w[http://hl7.org/fhir/ValueSet/content-type http://www.rfc-editor.org/bcp/bcp13.txt].include?(uri)
296
+ if ['http://hl7.org/fhir/ValueSet/content-type', 'http://www.rfc-editor.org/bcp/bcp13.txt'].include?(uri)
292
297
  matches = MIME::Types[value]
293
298
  json_or_xml = value.downcase.include?('xml') || value.downcase.include?('json')
294
- known_weird = %w[text/cql application/cql+text].include?(value)
299
+ known_weird = ['text/cql', 'application/cql+text'].include?(value)
295
300
  valid = json_or_xml || known_weird || (!matches.nil? && !matches.empty?)
296
- elsif %w[http://hl7.org/fhir/ValueSet/languages http://tools.ietf.org/html/bcp47].include?(uri)
301
+ elsif ['http://hl7.org/fhir/ValueSet/languages', 'http://tools.ietf.org/html/bcp47'].include?(uri)
297
302
  has_region = !(value =~ /-/).nil?
298
303
  valid = !BCP47::Language.identify(value.downcase).nil? && (!has_region || !BCP47::Region.identify(value.upcase).nil?)
299
304
  else
@@ -323,7 +328,15 @@ module FHIR
323
328
  self
324
329
  end
325
330
 
326
- private :validate_reference_type, :check_binding_uri, :validate_field
331
+ def find_extension(extension_source, method_name)
332
+ extension_source.select do |extension|
333
+ name = extension.url.tr('-', '_').split('/').last
334
+ anchor = name.split('#').last
335
+ (method_name.to_s == name || method_name.to_s == anchor)
336
+ end
337
+ end
338
+
339
+ private :validate_reference_type, :check_binding_uri, :validate_field, :find_extension
327
340
  end
328
341
  end
329
342
  end
@@ -12,12 +12,13 @@ module FHIR
12
12
 
13
13
  # Remove entries that do not interest us: CompartmentDefinitions, OperationDefinitions, Conformance statements
14
14
  hash['entry'].select! do |entry|
15
- %w[StructureDefinition ValueSet CodeSystem SearchParameter].include? entry['resource']['resourceType']
15
+ ['StructureDefinition', 'ValueSet', 'CodeSystem', 'SearchParameter'].include? entry['resource']['resourceType']
16
16
  end
17
17
 
18
18
  # Remove unnecessary elements from the hash
19
19
  hash['entry'].each do |entry|
20
20
  next unless entry['resource']
21
+
21
22
  pre_process_structuredefinition(entry['resource']) if entry['resource']['resourceType'] == 'StructureDefinition'
22
23
  pre_process_valueset(entry['resource']) if entry['resource']['resourceType'] == 'ValueSet'
23
24
  pre_process_codesystem(entry['resource']) if entry['resource']['resourceType'] == 'CodeSystem'
@@ -35,26 +36,30 @@ module FHIR
35
36
 
36
37
  def self.pre_process_structuredefinition(hash)
37
38
  # Remove large HTML narratives and unused content
38
- %w[text publisher contact description requirements mapping].each { |key| hash.delete(key) }
39
+ ['text', 'publisher', 'contact', 'description', 'requirements', 'mapping'].each { |key| hash.delete(key) }
39
40
 
40
41
  # Remove unused descriptions within the snapshot and differential elements
41
- %w[snapshot differential].each do |key|
42
+ ['snapshot', 'differential'].each do |key|
42
43
  next unless hash[key]
44
+
43
45
  hash[key]['element'].each do |element|
44
- %w[short definition comments requirements alias mapping].each { |subkey| element.delete(subkey) }
46
+ ['short', 'definition', 'comments', 'requirements', 'alias', 'mapping'].each { |subkey| element.delete(subkey) }
45
47
  end
46
48
  end
47
49
  end
48
50
 
49
51
  def self.pre_process_valueset(hash)
50
52
  # Remove large HTML narratives and unused content
51
- %w[meta text publisher contact description requirements].each { |key| hash.delete(key) }
53
+ ['meta', 'text', 'publisher', 'contact', 'description', 'requirements'].each { |key| hash.delete(key) }
52
54
 
53
55
  return unless hash['compose']
54
- %w[include exclude].each do |key|
56
+
57
+ ['include', 'exclude'].each do |key|
55
58
  next unless hash['compose'][key]
59
+
56
60
  hash['compose'][key].each do |element|
57
61
  next unless element['concept']
62
+
58
63
  element['concept'].each do |concept|
59
64
  concept.delete('designation')
60
65
  end
@@ -64,16 +69,18 @@ module FHIR
64
69
 
65
70
  def self.pre_process_codesystem(hash)
66
71
  # Remove large HTML narratives and unused content
67
- %w[meta text publisher contact description requirements].each { |key| hash.delete(key) }
72
+ ['meta', 'text', 'publisher', 'contact', 'description', 'requirements'].each { |key| hash.delete(key) }
68
73
  return unless hash['concept']
74
+
69
75
  hash['concept'].each do |concept|
70
76
  pre_process_codesystem_concept(concept)
71
77
  end
72
78
  end
73
79
 
74
80
  def self.pre_process_codesystem_concept(hash)
75
- %w[extension definition designation].each { |key| hash.delete(key) }
81
+ ['extension', 'definition', 'designation'].each { |key| hash.delete(key) }
76
82
  return unless hash['concept']
83
+
77
84
  hash['concept'].each do |concept|
78
85
  pre_process_codesystem_concept(concept)
79
86
  end
@@ -81,15 +88,16 @@ module FHIR
81
88
 
82
89
  def self.pre_process_searchparam(hash)
83
90
  # Remove large HTML narratives and unused content
84
- %w[id url name date publisher contact description xpathUsage].each { |key| hash.delete(key) }
91
+ ['id', 'url', 'name', 'date', 'publisher', 'contact', 'description', 'xpathUsage'].each { |key| hash.delete(key) }
85
92
  end
86
93
 
87
94
  def self.remove_fhir_comments(hash)
88
95
  hash.delete('fhir_comments')
89
96
  hash.each do |_key, value|
90
- if value.is_a?(Hash)
97
+ case value
98
+ when Hash
91
99
  remove_fhir_comments(value)
92
- elsif value.is_a?(Array)
100
+ when Array
93
101
  value.each do |v|
94
102
  remove_fhir_comments(v) if v.is_a?(Hash)
95
103
  end
@@ -25,7 +25,7 @@ module FHIR
25
25
  # if hash contains resourceType
26
26
  # create a child node with the name==resourceType
27
27
  # fill that, and place the child under the above `node`
28
- if hash['resourceType'] && hash['resourceType'].is_a?(String)
28
+ if hash['resourceType'].is_a?(String)
29
29
  child_name = hash['resourceType']
30
30
  hash.delete('resourceType')
31
31
  child = hash_to_xml_node(child_name, hash, doc)
@@ -34,11 +34,13 @@ module FHIR
34
34
  end
35
35
 
36
36
  hash.each do |key, value|
37
- next if %w[extension modifierExtension].include?(name) && key == 'url'
37
+ next if ['extension', 'modifierExtension'].include?(name) && key == 'url'
38
38
  next if key == 'id' && !FHIR::DSTU2::RESOURCES.include?(name)
39
- if value.is_a?(Hash)
39
+
40
+ case value
41
+ when Hash
40
42
  node.add_child(hash_to_xml_node(key, value, doc))
41
- elsif value.is_a?(Array)
43
+ when Array
42
44
  value.each do |v|
43
45
  if v.is_a?(Hash)
44
46
  node.add_child(hash_to_xml_node(key, v, doc))
@@ -63,7 +65,7 @@ module FHIR
63
65
  node.add_child(child)
64
66
  end
65
67
  end
66
- node.set_attribute('url', hash['url']) if %w[extension modifierExtension].include?(name)
68
+ node.set_attribute('url', hash['url']) if ['extension', 'modifierExtension'].include?(name)
67
69
  node.set_attribute('id', hash['id']) if hash['id'] && !FHIR::DSTU2::RESOURCES.include?(name)
68
70
  node
69
71
  end
@@ -79,7 +81,7 @@ module FHIR
79
81
  resource_type = doc.root.name
80
82
  klass = Module.const_get("FHIR::DSTU2::#{resource_type}")
81
83
  resource = klass.new(hash)
82
- rescue => e
84
+ rescue StandardError => e
83
85
  FHIR::DSTU2.logger.error("Failed to deserialize XML:\n#{e.message}\n#{e.backtrace}")
84
86
  FHIR::DSTU2.logger.debug("XML:\n#{xml}")
85
87
  resource = nil
@@ -109,7 +111,7 @@ module FHIR
109
111
  end
110
112
  end
111
113
  end
112
- hash['url'] = node.get_attribute('url') if %w[extension modifierExtension].include?(node.name)
114
+ hash['url'] = node.get_attribute('url') if ['extension', 'modifierExtension'].include?(node.name)
113
115
  hash['id'] = node.get_attribute('id') if node.get_attribute('id') # Testscript fixture ids (applies to any BackboneElement)
114
116
  hash['resourceType'] = node.name if FHIR::DSTU2::RESOURCES.include?(node.name)
115
117
 
@@ -11,6 +11,7 @@ module FHIR
11
11
  end
12
12
  end
13
13
  return unless methods.include? new_method
14
+
14
15
  (class << self; self; end).instance_eval do
15
16
  define_method(old_method) do |*args, &block|
16
17
  message = "DEPRECATED: `#{old_method}` has been deprecated. Use `#{new_method}` instead. Called from #{caller.first}"
@@ -1,28 +1,26 @@
1
1
  module FHIR
2
2
  module DSTU2
3
-
4
3
  PRIMITIVES = {
5
- 'markdown' => {'type'=>'string'},
6
- 'integer' => {'type'=>'number', 'regex'=>'-?([0]|([1-9][0-9]*))'},
7
- 'dateTime' => {'type'=>'string', 'regex'=>'-?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\\.[0-9]+)?(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)?'},
8
- 'unsignedInt' => {'type'=>'number', 'regex'=>'[0]|([1-9][0-9]*)'},
9
- 'code' => {'type'=>'string', 'regex'=>'[^\\s]+([\\s][^\\s]+)*'},
10
- 'date' => {'type'=>'string', 'regex'=>'-?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1]))?)?'},
11
- 'decimal' => {'type'=>'number', 'regex'=>'-?([0]|([1-9][0-9]*))(\\.[0-9]+)?'},
12
- 'uri' => {'type'=>'string'},
13
- 'id' => {'type'=>'string', 'regex'=>'[A-Za-z0-9\\-\\.]{1,64}'},
14
- 'base64Binary' => {'type'=>'string'},
15
- 'time' => {'type'=>'string', 'regex'=>'([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\\.[0-9]+)?'},
16
- 'oid' => {'type'=>'string', 'regex'=>'urn:oid:(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))*'},
17
- 'positiveInt' => {'type'=>'number', 'regex'=>'[1-9][0-9]*'},
18
- 'string' => {'type'=>'string'},
19
- 'boolean' => {'type'=>'true | false'},
20
- 'uuid' => {'type'=>'string', 'regex'=>'urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'},
21
- 'instant' => {'type'=>'string'},
22
- 'xhtml' => {'type'=>'string'}
4
+ 'markdown' => { 'type' => 'string' },
5
+ 'integer' => { 'type' => 'number', 'regex' => '-?([0]|([1-9][0-9]*))' },
6
+ 'dateTime' => { 'type' => 'string', 'regex' => '-?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1])(T([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\\.[0-9]+)?(Z|(\\+|-)((0[0-9]|1[0-3]):[0-5][0-9]|14:00)))?)?)?' },
7
+ 'unsignedInt' => { 'type' => 'number', 'regex' => '[0]|([1-9][0-9]*)' },
8
+ 'code' => { 'type' => 'string', 'regex' => '[^\\s]+([\\s][^\\s]+)*' },
9
+ 'date' => { 'type' => 'string', 'regex' => '-?[0-9]{4}(-(0[1-9]|1[0-2])(-(0[0-9]|[1-2][0-9]|3[0-1]))?)?' },
10
+ 'decimal' => { 'type' => 'number', 'regex' => '-?([0]|([1-9][0-9]*))(\\.[0-9]+)?' },
11
+ 'uri' => { 'type' => 'string' },
12
+ 'id' => { 'type' => 'string', 'regex' => '[A-Za-z0-9\\-\\.]{1,64}' },
13
+ 'base64Binary' => { 'type' => 'string' },
14
+ 'time' => { 'type' => 'string', 'regex' => '([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](\\.[0-9]+)?' },
15
+ 'oid' => { 'type' => 'string', 'regex' => 'urn:oid:(0|[1-9][0-9]*)(\\.(0|[1-9][0-9]*))*' },
16
+ 'positiveInt' => { 'type' => 'number', 'regex' => '[1-9][0-9]*' },
17
+ 'string' => { 'type' => 'string' },
18
+ 'boolean' => { 'type' => 'true | false' },
19
+ 'uuid' => { 'type' => 'string', 'regex' => 'urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' },
20
+ 'instant' => { 'type' => 'string' },
21
+ 'xhtml' => { 'type' => 'string' }
23
22
  }
24
23
  TYPES = ['Address', 'Annotation', 'Attachment', 'BackboneElement', 'CodeableConcept', 'Coding', 'ContactPoint', 'Element', 'ElementDefinition', 'Extension', 'HumanName', 'Identifier', 'Meta', 'Narrative', 'Period', 'Quantity', 'Range', 'Ratio', 'Reference', 'SampledData', 'Signature', 'Timing']
25
24
  RESOURCES = ['Account', 'AllergyIntolerance', 'Appointment', 'AppointmentResponse', 'AuditEvent', 'Basic', 'Binary', 'BodySite', 'Bundle', 'CarePlan', 'Claim', 'ClaimResponse', 'ClinicalImpression', 'Communication', 'CommunicationRequest', 'Composition', 'ConceptMap', 'Condition', 'Conformance', 'Contract', 'Coverage', 'DataElement', 'DetectedIssue', 'Device', 'DeviceComponent', 'DeviceMetric', 'DeviceUseRequest', 'DeviceUseStatement', 'DiagnosticOrder', 'DiagnosticReport', 'DocumentManifest', 'DocumentReference', 'DomainResource', 'EligibilityRequest', 'EligibilityResponse', 'Encounter', 'EnrollmentRequest', 'EnrollmentResponse', 'EpisodeOfCare', 'ExplanationOfBenefit', 'FamilyMemberHistory', 'Flag', 'Goal', 'Group', 'HealthcareService', 'ImagingObjectSelection', 'ImagingStudy', 'Immunization', 'ImmunizationRecommendation', 'ImplementationGuide', 'List', 'Location', 'Media', 'Medication', 'MedicationAdministration', 'MedicationDispense', 'MedicationOrder', 'MedicationStatement', 'MessageHeader', 'NamingSystem', 'NutritionOrder', 'Observation', 'OperationDefinition', 'OperationOutcome', 'Order', 'OrderResponse', 'Organization', 'Parameters', 'Patient', 'PaymentNotice', 'PaymentReconciliation', 'Person', 'Practitioner', 'Procedure', 'ProcedureRequest', 'ProcessRequest', 'ProcessResponse', 'Provenance', 'Questionnaire', 'QuestionnaireResponse', 'ReferralRequest', 'RelatedPerson', 'Resource', 'RiskAssessment', 'Schedule', 'SearchParameter', 'Slot', 'Specimen', 'StructureDefinition', 'Subscription', 'Substance', 'SupplyDelivery', 'SupplyRequest', 'TestScript', 'ValueSet', 'VisionPrescription']
26
-
27
25
  end
28
- end
26
+ end