fhir_models 1.8.2 → 1.8.3
Sign up to get free protection for your applications and to get access to all the features.
- 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__))
|