fhir_models 1.8.2 → 1.8.3
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/.codeclimate.yml +1 -0
- data/.rspec +2 -0
- data/.rubocop.yml +5 -1156
- data/.rubocop_todo.yml +76 -0
- data/.travis.yml +9 -3
- data/Gemfile +1 -1
- data/Guardfile +50 -0
- data/Rakefile +4 -5
- data/bin/console +4 -4
- data/fhir_models.gemspec +6 -3
- data/lib/fhir_models.rb +2 -1
- data/lib/fhir_models/bootstrap/definitions.rb +100 -94
- data/lib/fhir_models/bootstrap/field.rb +1 -1
- data/lib/fhir_models/bootstrap/generator.rb +11 -11
- data/lib/fhir_models/bootstrap/hashable.rb +18 -5
- data/lib/fhir_models/bootstrap/json.rb +2 -1
- data/lib/fhir_models/bootstrap/model.rb +21 -39
- data/lib/fhir_models/bootstrap/preprocess.rb +21 -36
- data/lib/fhir_models/bootstrap/template.rb +5 -9
- data/lib/fhir_models/bootstrap/xml.rb +8 -5
- data/lib/fhir_models/deprecate.rb +22 -0
- data/lib/fhir_models/fhir.rb +58 -0
- data/lib/fhir_models/fhir/metadata.rb +1 -1
- data/lib/fhir_models/fhir_ext/element_definition.rb +47 -0
- data/lib/fhir_models/fhir_ext/structure_definition.rb +203 -524
- data/lib/fhir_models/fhir_ext/structure_definition_compare.rb +375 -0
- data/lib/fhir_models/fluentpath/evaluate.rb +9 -2
- data/lib/fhir_models/fluentpath/expression.rb +8 -1
- data/lib/fhir_models/fluentpath/parse.rb +2 -2
- data/lib/fhir_models/version.rb +1 -1
- metadata +62 -15
- data/lib/fhir_models/fhir/resources/MetadataResource.rb +0 -52
@@ -6,7 +6,7 @@ module FHIR
|
|
6
6
|
# templates keeps track of all the templates in context within a given StructureDefinition
|
7
7
|
attr_accessor :templates
|
8
8
|
|
9
|
-
def initialize(auto_setup
|
9
|
+
def initialize(auto_setup: true)
|
10
10
|
# load the valueset expansions
|
11
11
|
@defn = FHIR::Definitions
|
12
12
|
# templates is an array
|
@@ -29,7 +29,7 @@ module FHIR
|
|
29
29
|
def generate_metadata
|
30
30
|
template = FHIR::Boot::Template.new([], true)
|
31
31
|
|
32
|
-
primitives = @defn.
|
32
|
+
primitives = @defn.primitive_types
|
33
33
|
hash = {}
|
34
34
|
primitives.each do |p|
|
35
35
|
field = FHIR::Field.new
|
@@ -52,10 +52,10 @@ module FHIR
|
|
52
52
|
end
|
53
53
|
template.constants['PRIMITIVES'] = hash
|
54
54
|
|
55
|
-
template.constants['TYPES'] = @defn.
|
55
|
+
template.constants['TYPES'] = @defn.complex_types.map { |t| t['id'] }
|
56
56
|
|
57
57
|
# resources
|
58
|
-
template.constants['RESOURCES'] = @defn.
|
58
|
+
template.constants['RESOURCES'] = @defn.resource_definitions.map { |r| r['id'] }
|
59
59
|
|
60
60
|
filename = File.join(@lib, 'fhir', 'metadata.rb')
|
61
61
|
file = File.open(filename, 'w:UTF-8')
|
@@ -67,13 +67,13 @@ module FHIR
|
|
67
67
|
folder = File.join @lib, 'fhir', 'types'
|
68
68
|
# complex data types start with an uppercase letter
|
69
69
|
# and we'll filter out profiles on types (for example, Age is a profile on Quantity)
|
70
|
-
complex_types = @defn.
|
70
|
+
complex_types = @defn.complex_types
|
71
71
|
generate_class_files(folder, complex_types)
|
72
72
|
end
|
73
73
|
|
74
74
|
def generate_resources
|
75
75
|
folder = File.join @lib, 'fhir', 'resources'
|
76
|
-
generate_class_files(folder, @defn.
|
76
|
+
generate_class_files(folder, @defn.resource_definitions)
|
77
77
|
end
|
78
78
|
|
79
79
|
def generate_class_files(folder = @lib, structure_defs = [])
|
@@ -81,7 +81,7 @@ module FHIR
|
|
81
81
|
@templates.clear
|
82
82
|
type_name = structure_def['id']
|
83
83
|
template = generate_class([type_name], structure_def, true)
|
84
|
-
params = @defn.
|
84
|
+
params = @defn.search_parameters(type_name)
|
85
85
|
template.constants['SEARCH_PARAMS'] = params unless params.nil?
|
86
86
|
filename = File.join(folder, "#{type_name}.rb")
|
87
87
|
file = File.open(filename, 'w:UTF-8')
|
@@ -98,7 +98,7 @@ module FHIR
|
|
98
98
|
|
99
99
|
def generate_class(hierarchy, structure_def, top_level = false)
|
100
100
|
type_name = structure_def['id']
|
101
|
-
constrained_type = structure_def['
|
101
|
+
constrained_type = structure_def['type']
|
102
102
|
path_type = type_name
|
103
103
|
path_type = constrained_type if constrained_type
|
104
104
|
|
@@ -162,7 +162,7 @@ module FHIR
|
|
162
162
|
element['type'].select { |t| t['code'] == 'Reference' || t['code'] == 'Extension' }.each do |data_type|
|
163
163
|
profiles << data_type['targetProfile']
|
164
164
|
end
|
165
|
-
profiles.
|
165
|
+
profiles.reject!(&:nil?)
|
166
166
|
profiles.flatten!
|
167
167
|
|
168
168
|
# Calculate fields that have multiple data types
|
@@ -186,7 +186,7 @@ module FHIR
|
|
186
186
|
field.max = field.max.to_i
|
187
187
|
field.max = '*' if element['max'] == '*'
|
188
188
|
|
189
|
-
if %w
|
189
|
+
if %w[code Coding CodeableConcept].include?(data_type) && element['binding']
|
190
190
|
field.binding = element['binding']
|
191
191
|
field.binding['uri'] = field.binding['valueSetUri']
|
192
192
|
field.binding['uri'] = field.binding['valueSetReference'] if field.binding['uri'].nil?
|
@@ -199,7 +199,7 @@ module FHIR
|
|
199
199
|
codes = @defn.get_codes(field.binding['uri'])
|
200
200
|
field.valid_codes = codes unless codes.nil?
|
201
201
|
FHIR.logger.warn " MISSING EXPANSION -- #{field.path} #{field.min}..#{field.max}: #{field.binding['uri']} (#{field.binding['strength']})" if field.valid_codes.empty? && field.binding['uri'] && !field.binding['uri'].end_with?('bcp47') && !field.binding['uri'].end_with?('bcp13.txt')
|
202
|
-
elsif %w
|
202
|
+
elsif %w[Element BackboneElement].include?(data_type)
|
203
203
|
# This is a nested structure or class
|
204
204
|
field.type = "#{hierarchy.join('::')}::#{cap_first(field.name)}"
|
205
205
|
end
|
@@ -40,9 +40,14 @@ module FHIR
|
|
40
40
|
next if meta.nil?
|
41
41
|
local_name = key
|
42
42
|
local_name = meta['local_name'] if meta['local_name']
|
43
|
-
|
43
|
+
begin
|
44
|
+
instance_variable_set("@#{local_name}", value)
|
45
|
+
rescue
|
46
|
+
# TODO: this appears to be a dead code branch
|
47
|
+
nil
|
48
|
+
end
|
44
49
|
# inflate the value if it isn't a primitive
|
45
|
-
klass =
|
50
|
+
klass = FHIR::PRIMITIVES.key?(meta['type']) ? nil : FHIR.const_get(meta['type'])
|
46
51
|
if !klass.nil? && !value.nil?
|
47
52
|
# handle array of objects
|
48
53
|
if value.is_a?(Array)
|
@@ -78,12 +83,20 @@ module FHIR
|
|
78
83
|
|
79
84
|
def make_child(child, klass)
|
80
85
|
if child['resourceType']
|
81
|
-
klass =
|
86
|
+
klass = begin
|
87
|
+
FHIR.const_get(child['resourceType'])
|
88
|
+
rescue => _exception
|
89
|
+
# TODO: this appears to be a dead code branch
|
90
|
+
# TODO: should this log / re-raise the exception if encountered instead of silently swallowing it?
|
91
|
+
nil
|
92
|
+
end
|
82
93
|
end
|
83
94
|
begin
|
84
95
|
obj = klass.new(child)
|
85
|
-
rescue =>
|
86
|
-
|
96
|
+
rescue => exception
|
97
|
+
# TODO: this appears to be a dead code branch
|
98
|
+
# TODO: should this re-raise the exception if encountered instead of silently swallowing it?
|
99
|
+
FHIR.logger.error("Unable to inflate embedded class #{klass}\n#{exception.backtrace}")
|
87
100
|
end
|
88
101
|
obj
|
89
102
|
end
|
@@ -16,7 +16,8 @@ module FHIR
|
|
16
16
|
klass = Module.const_get("FHIR::#{resource_type}")
|
17
17
|
resource = klass.new(hash)
|
18
18
|
rescue => e
|
19
|
-
FHIR.logger.error("Failed to deserialize JSON:\n#{
|
19
|
+
FHIR.logger.error("Failed to deserialize JSON:\n#{e.backtrace}")
|
20
|
+
FHIR.logger.debug("JSON:\n#{json}")
|
20
21
|
resource = nil
|
21
22
|
end
|
22
23
|
resource
|
@@ -5,6 +5,7 @@ require 'bcp47'
|
|
5
5
|
|
6
6
|
module FHIR
|
7
7
|
class Model
|
8
|
+
extend FHIR::Deprecate
|
8
9
|
def initialize(hash = {})
|
9
10
|
from_hash(hash)
|
10
11
|
self.class::METADATA.each do |key, value|
|
@@ -14,11 +15,11 @@ module FHIR
|
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
17
|
-
def method_missing(method, *
|
18
|
+
def method_missing(method, *_args, &_block)
|
18
19
|
if defined?(self.class::MULTIPLE_TYPES) && self.class::MULTIPLE_TYPES[method.to_s]
|
19
20
|
self.class::MULTIPLE_TYPES[method.to_s].each do |type|
|
20
21
|
type[0] = type[0].upcase
|
21
|
-
value =
|
22
|
+
value = send("#{method}#{type}".to_sym)
|
22
23
|
return value unless value.nil?
|
23
24
|
end
|
24
25
|
return nil
|
@@ -41,7 +42,7 @@ module FHIR
|
|
41
42
|
return ext.first.value.nil? ? ext.first : ext.first.value
|
42
43
|
end
|
43
44
|
end
|
44
|
-
|
45
|
+
raise NoMethodError.new("undefined method `#{method}' for #{inspect}", method)
|
45
46
|
end
|
46
47
|
|
47
48
|
def to_reference
|
@@ -87,9 +88,10 @@ module FHIR
|
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
90
|
-
def
|
91
|
+
def valid?
|
91
92
|
validate.empty?
|
92
93
|
end
|
94
|
+
deprecate :is_valid?, :valid?
|
93
95
|
|
94
96
|
def validate(contained = nil)
|
95
97
|
validate_profile(self.class::METADATA, contained)
|
@@ -125,7 +127,11 @@ module FHIR
|
|
125
127
|
end
|
126
128
|
end # metadata.each
|
127
129
|
# check multiple types
|
128
|
-
multiple_types =
|
130
|
+
multiple_types = begin
|
131
|
+
self.class::MULTIPLE_TYPES
|
132
|
+
rescue
|
133
|
+
{}
|
134
|
+
end
|
129
135
|
multiple_types.each do |prefix, suffixes|
|
130
136
|
present = []
|
131
137
|
suffixes.each do |suffix|
|
@@ -137,10 +143,11 @@ module FHIR
|
|
137
143
|
end
|
138
144
|
errors[prefix] = ["#{prefix}[x]: more than one type present."] if present.length > 1
|
139
145
|
# remove errors for suffixes that are not present
|
146
|
+
next unless present.length == 1
|
140
147
|
suffixes.each do |suffix|
|
141
148
|
typename = "#{prefix}#{suffix[0].upcase}#{suffix[1..-1]}"
|
142
149
|
errors.delete(typename) unless present.include?(typename)
|
143
|
-
end
|
150
|
+
end
|
144
151
|
end
|
145
152
|
errors.keep_if { |_k, v| (v && !v.empty?) }
|
146
153
|
end
|
@@ -195,7 +202,7 @@ module FHIR
|
|
195
202
|
match = (v =~ Regexp.new(primitive_meta['regex']))
|
196
203
|
errors[field] << "#{meta['path']}: #{v} does not match #{datatype} regex" if match.nil?
|
197
204
|
else
|
198
|
-
errors[field] << "#{meta['path']}: #{v} is not a valid #{datatype}" unless
|
205
|
+
errors[field] << "#{meta['path']}: #{v} is not a valid #{datatype}" unless FHIR.primitive?(datatype: datatype, value: v)
|
199
206
|
end
|
200
207
|
end
|
201
208
|
# check binding
|
@@ -226,12 +233,13 @@ module FHIR
|
|
226
233
|
|
227
234
|
def validate_reference_type(ref, meta, contained_here, errors)
|
228
235
|
return unless ref.reference && meta['type_profiles']
|
236
|
+
return if ref.reference.start_with?('urn:uuid:', 'urn:oid:')
|
229
237
|
matches_one_profile = false
|
230
238
|
meta['type_profiles'].each do |p|
|
231
239
|
basetype = p.split('/').last
|
232
240
|
matches_one_profile = true if ref.reference.include?(basetype)
|
233
241
|
# check profiled resources
|
234
|
-
profile_basetype = FHIR::Definitions.
|
242
|
+
profile_basetype = FHIR::Definitions.basetype(p)
|
235
243
|
matches_one_profile = true if profile_basetype && ref.reference.include?(profile_basetype)
|
236
244
|
end
|
237
245
|
matches_one_profile = true if meta['type_profiles'].include?('http://hl7.org/fhir/StructureDefinition/Resource')
|
@@ -250,37 +258,11 @@ module FHIR
|
|
250
258
|
errors << "#{meta['path']}: incorrect Reference type, expected #{meta['type_profiles'].map { |x| x.split('/').last }.join('|')}" unless matches_one_profile
|
251
259
|
end
|
252
260
|
|
253
|
-
def
|
254
|
-
|
255
|
-
|
256
|
-
when 'boolean'
|
257
|
-
value == true || value == false || value.downcase == 'true' || value.downcase == 'false'
|
258
|
-
when 'code'
|
259
|
-
value.is_a?(String) && value.size >= 1 && value.size == value.rstrip.size
|
260
|
-
when 'string', 'markdown'
|
261
|
-
value.is_a?(String)
|
262
|
-
when 'xhtml'
|
263
|
-
fragment = Nokogiri::HTML::DocumentFragment.parse(value)
|
264
|
-
value.is_a?(String) && fragment.errors.size.zero?
|
265
|
-
when 'base64binary'
|
266
|
-
regex = /[^0-9\+\/\=A-Za-z\r\n ]/
|
267
|
-
value.is_a?(String) && (regex =~ value).nil?
|
268
|
-
when 'uri'
|
269
|
-
!URI.parse(value).nil? rescue false
|
270
|
-
when 'instant'
|
271
|
-
regex = /\A[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)))))\Z/
|
272
|
-
value.is_a?(String) && !(regex =~ value).nil?
|
273
|
-
when 'integer', 'unsignedint'
|
274
|
-
(!Integer(value).nil? rescue false)
|
275
|
-
when 'positiveint'
|
276
|
-
(!Integer(value).nil? rescue false) && (Integer(value) >= 0)
|
277
|
-
when 'decimal'
|
278
|
-
(!Float(value).nil? rescue false)
|
279
|
-
else
|
280
|
-
FHIR.logger.warn "Unable to check #{value} for datatype #{datatype}"
|
281
|
-
false
|
282
|
-
end
|
261
|
+
def primitive?(datatype, value)
|
262
|
+
FHIR.logger.warn("prefer using FHIR.primitive? Called from #{caller.first}")
|
263
|
+
FHIR.primitive?(datatype: datatype, value: value)
|
283
264
|
end
|
265
|
+
deprecate :is_primitive?, :primitive?
|
284
266
|
|
285
267
|
def check_binding(uri, value)
|
286
268
|
valid = false
|
@@ -298,6 +280,6 @@ module FHIR
|
|
298
280
|
valid
|
299
281
|
end
|
300
282
|
|
301
|
-
private :validate_reference_type, :
|
283
|
+
private :validate_reference_type, :check_binding, :validate_field
|
302
284
|
end
|
303
285
|
end
|
@@ -11,7 +11,7 @@ module FHIR
|
|
11
11
|
|
12
12
|
# Remove entries that do not interest us: CompartmentDefinitions, OperationDefinitions, Conformance statements
|
13
13
|
hash['entry'].select! do |entry|
|
14
|
-
%w
|
14
|
+
%w[StructureDefinition ValueSet CodeSystem SearchParameter].include? entry['resource']['resourceType']
|
15
15
|
end
|
16
16
|
|
17
17
|
# Remove unnecessary elements from the hash
|
@@ -34,37 +34,25 @@ module FHIR
|
|
34
34
|
|
35
35
|
def self.pre_process_structuredefinition(hash)
|
36
36
|
# Remove large HTML narratives and unused content
|
37
|
-
%w
|
37
|
+
%w[text publisher contact description requirements mapping].each { |key| hash.delete(key) }
|
38
38
|
|
39
|
-
# Remove unused descriptions within the snapshot elements
|
40
|
-
|
41
|
-
hash[
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
-
# Remove unused descriptions within the differential elements
|
46
|
-
if hash['differential']
|
47
|
-
hash['differential']['element'].each do |element|
|
48
|
-
%w(short definition comments requirements alias mapping).each { |key| element.delete(key) }
|
39
|
+
# Remove unused descriptions within the snapshot and differential elements
|
40
|
+
%w[snapshot differential].each do |key|
|
41
|
+
next unless hash[key]
|
42
|
+
hash[key]['element'].each do |element|
|
43
|
+
%w[short definition comments requirements alias mapping].each { |subkey| element.delete(subkey) }
|
49
44
|
end
|
50
45
|
end
|
51
46
|
end
|
52
47
|
|
53
48
|
def self.pre_process_valueset(hash)
|
54
49
|
# Remove large HTML narratives and unused content
|
55
|
-
%w
|
56
|
-
|
57
|
-
if hash['compose'] && hash['compose']['include']
|
58
|
-
hash['compose']['include'].each do |element|
|
59
|
-
next unless element['concept']
|
60
|
-
element['concept'].each do |concept|
|
61
|
-
concept.delete('designation')
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
50
|
+
%w[meta text publisher contact description requirements].each { |key| hash.delete(key) }
|
65
51
|
|
66
|
-
|
67
|
-
|
52
|
+
return unless hash['compose']
|
53
|
+
%w[include exclude].each do |key|
|
54
|
+
next unless hash['compose'][key]
|
55
|
+
hash['compose'][key].each do |element|
|
68
56
|
next unless element['concept']
|
69
57
|
element['concept'].each do |concept|
|
70
58
|
concept.delete('designation')
|
@@ -75,27 +63,24 @@ module FHIR
|
|
75
63
|
|
76
64
|
def self.pre_process_codesystem(hash)
|
77
65
|
# Remove large HTML narratives and unused content
|
78
|
-
%w
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
pre_process_codesystem_concept(concept)
|
83
|
-
end
|
66
|
+
%w[meta text publisher contact description requirements].each { |key| hash.delete(key) }
|
67
|
+
return unless hash['concept']
|
68
|
+
hash['concept'].each do |concept|
|
69
|
+
pre_process_codesystem_concept(concept)
|
84
70
|
end
|
85
71
|
end
|
86
72
|
|
87
73
|
def self.pre_process_codesystem_concept(hash)
|
88
|
-
%w
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
74
|
+
%w[extension definition designation].each { |key| hash.delete(key) }
|
75
|
+
return unless hash['concept']
|
76
|
+
hash['concept'].each do |concept|
|
77
|
+
pre_process_codesystem_concept(concept)
|
93
78
|
end
|
94
79
|
end
|
95
80
|
|
96
81
|
def self.pre_process_searchparam(hash)
|
97
82
|
# Remove large HTML narratives and unused content
|
98
|
-
%w
|
83
|
+
%w[id url name date publisher contact description xpathUsage].each { |key| hash.delete(key) }
|
99
84
|
end
|
100
85
|
|
101
86
|
def self.remove_fhir_comments(hash)
|
@@ -2,6 +2,7 @@ module FHIR
|
|
2
2
|
module Boot
|
3
3
|
class Template
|
4
4
|
include FHIR::Hashable
|
5
|
+
extend FHIR::Deprecate
|
5
6
|
|
6
7
|
attr_accessor :name
|
7
8
|
attr_accessor :hierarchy
|
@@ -21,7 +22,7 @@ module FHIR
|
|
21
22
|
@top_level = top_level
|
22
23
|
end
|
23
24
|
|
24
|
-
def
|
25
|
+
def metadata
|
25
26
|
metadata = {}
|
26
27
|
@fields.each do |field|
|
27
28
|
if metadata.keys.include?(field.name)
|
@@ -41,6 +42,7 @@ module FHIR
|
|
41
42
|
end
|
42
43
|
metadata
|
43
44
|
end
|
45
|
+
deprecate :get_metadata, :metadata
|
44
46
|
|
45
47
|
def to_s(offset = 0)
|
46
48
|
# create an array of Strings, one per line
|
@@ -66,7 +68,6 @@ module FHIR
|
|
66
68
|
s << ''
|
67
69
|
|
68
70
|
# add mandatory METADATA constant
|
69
|
-
metadata = get_metadata
|
70
71
|
@constants['METADATA'] = metadata unless metadata.empty?
|
71
72
|
|
72
73
|
# add constants
|
@@ -94,18 +95,13 @@ module FHIR
|
|
94
95
|
end
|
95
96
|
|
96
97
|
# calculate the longest field name for whitespace layout
|
97
|
-
max_name_size = 0
|
98
|
-
@fields.each do |f|
|
99
|
-
name = f.local_name || f.name
|
100
|
-
max_name_size = name.length if name.length > max_name_size
|
101
|
-
end
|
102
|
-
max_name_size += 1
|
98
|
+
max_name_size = (@fields.map { |field| field.local_name || field.name }.map(&:length).max || 0) + 1
|
103
99
|
|
104
100
|
# declare attributes
|
105
101
|
@fields.each do |field|
|
106
102
|
s << "#{space}attr_accessor :"
|
107
103
|
local_name = field.local_name || field.name
|
108
|
-
s[-1] << ("%-#{max_name_size}s"
|
104
|
+
s[-1] << format("%-#{max_name_size}s", local_name)
|
109
105
|
# add comment after field declaration
|
110
106
|
s[-1] << "# #{field.min}-#{field.max} "
|
111
107
|
s[-1] << '[ ' if field.max.to_i > 1 || field.max == '*'
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'nokogiri'
|
2
2
|
module FHIR
|
3
3
|
module Xml
|
4
|
+
extend FHIR::Deprecate
|
4
5
|
#
|
5
6
|
# This module includes methods to serialize or deserialize FHIR resources to and from XML.
|
6
7
|
#
|
@@ -32,7 +33,7 @@ module FHIR
|
|
32
33
|
end
|
33
34
|
|
34
35
|
hash.each do |key, value|
|
35
|
-
next if %w
|
36
|
+
next if %w[extension modifierExtension].include?(name) && key == 'url'
|
36
37
|
next if key == 'id' && !FHIR::RESOURCES.include?(name)
|
37
38
|
if value.is_a?(Hash)
|
38
39
|
node.add_child(hash_to_xml_node(key, value, doc))
|
@@ -61,7 +62,7 @@ module FHIR
|
|
61
62
|
node.add_child(child)
|
62
63
|
end
|
63
64
|
end
|
64
|
-
node.set_attribute('url', hash['url']) if %w
|
65
|
+
node.set_attribute('url', hash['url']) if %w[extension modifierExtension].include?(name)
|
65
66
|
node.set_attribute('id', hash['id']) if hash['id'] && !FHIR::RESOURCES.include?(name)
|
66
67
|
node
|
67
68
|
end
|
@@ -78,7 +79,8 @@ module FHIR
|
|
78
79
|
klass = Module.const_get("FHIR::#{resource_type}")
|
79
80
|
resource = klass.new(hash)
|
80
81
|
rescue => e
|
81
|
-
FHIR.logger.error("Failed to deserialize XML:\n#{
|
82
|
+
FHIR.logger.error("Failed to deserialize XML:\n#{e.backtrace}")
|
83
|
+
FHIR.logger.debug("XML:\n#{xml}")
|
82
84
|
resource = nil
|
83
85
|
end
|
84
86
|
resource
|
@@ -106,7 +108,7 @@ module FHIR
|
|
106
108
|
end
|
107
109
|
end
|
108
110
|
end
|
109
|
-
hash['url'] = node.get_attribute('url') if %w
|
111
|
+
hash['url'] = node.get_attribute('url') if %w[extension modifierExtension].include?(node.name)
|
110
112
|
hash['id'] = node.get_attribute('id') if node.get_attribute('id') # Testscript fixture ids (applies to any BackboneElement)
|
111
113
|
hash['resourceType'] = node.name if FHIR::RESOURCES.include?(node.name)
|
112
114
|
|
@@ -122,9 +124,10 @@ module FHIR
|
|
122
124
|
end
|
123
125
|
end
|
124
126
|
|
125
|
-
def self.
|
127
|
+
def self.valid?(xml)
|
126
128
|
validate(xml).empty?
|
127
129
|
end
|
130
|
+
deprecate :is_valid?, :valid?
|
128
131
|
|
129
132
|
def self.validate(xml)
|
130
133
|
defns = File.expand_path '../definitions/schema', File.dirname(File.absolute_path(__FILE__))
|