Skip to content

Commit

Permalink
Merge multiversion support into r5
Browse files Browse the repository at this point in the history
  • Loading branch information
360dgries committed Sep 24, 2024
2 parents 6ff5f9e + 0f72c12 commit 43790ce
Show file tree
Hide file tree
Showing 38 changed files with 265 additions and 241 deletions.
2 changes: 2 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ Style/HashTransformKeys:
Enabled: true
Style/HashTransformValues:
Enabled: true
Style/ModuleFunction:
Enabled: false
Style/SymbolArray:
Enabled: false
Style/WordArray:
Expand Down
18 changes: 6 additions & 12 deletions lib/fhir_models/bootstrap/json.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
require 'json'

module FHIR
module Json
module ClassJson
#
# This module includes methods to serialize or deserialize FHIR resources to and from JSON.
#

def to_json(opts = nil)
JSON.pretty_generate(to_hash, opts)
end

def self.from_json(json)
def from_json(json)
hash = JSON.parse(json)
resource = nil
begin
Expand All @@ -24,13 +20,11 @@ def self.from_json(json)
end
resource
end
end

def self.fhir_version_string
FHIR.fhir_version_string
end

def self.versioned_fhir_module
FHIR.versioned_fhir_module
module InstanceJson
def to_json(opts = nil)
JSON.pretty_generate(to_hash, opts)
end
end
end
151 changes: 70 additions & 81 deletions lib/fhir_models/bootstrap/xml.rb
Original file line number Diff line number Diff line change
@@ -1,75 +1,7 @@
require 'nokogiri'
module FHIR
module Xml
extend FHIR::Deprecate
#
# This module includes methods to serialize or deserialize FHIR resources to and from XML.
#

def to_xml
hash = to_hash
hash.delete('resourceType')
doc = Nokogiri::XML::Document.new
doc.encoding = 'utf-8'
doc.root = hash_to_xml_node(resourceType, hash, doc)
doc.root.default_namespace = 'http://hl7.org/fhir'
doc.to_xml
end

# Hash keys are ordered in Ruby 1.9 and later, so we can rely on their order
# to be the correct order for the XML serialization.
def hash_to_xml_node(name, hash, doc)
node = Nokogiri::XML::Node.new(name, doc)

# if hash contains resourceType
# create a child node with the name==resourceType
# fill that, and place the child under the above `node`
if hash['resourceType'].is_a?(String) && name != 'instance'
child_name = hash['resourceType']
hash.delete('resourceType')
child = hash_to_xml_node(child_name, hash, doc)
node.add_child(child)
return node
end

hash.each do |key, value|
next if ['extension', 'modifierExtension'].include?(name) && key == 'url'
next if key == 'id' && !versioned_fhir_module::RESOURCES.include?(name)

case value
when Hash
node.add_child(hash_to_xml_node(key, value, doc))
when Array
value.each do |v|
if v.is_a?(Hash)
node.add_child(hash_to_xml_node(key, v, doc))
else
child = Nokogiri::XML::Node.new(key, doc)
child.set_attribute('value', v)
node.add_child(child)
end
end
else
child = Nokogiri::XML::Node.new(key, doc)
if name == 'text' && key == 'div'
child.set_attribute('xmlns', 'http://www.w3.org/1999/xhtml')
html = value.strip
if html.start_with?('<div') && html.end_with?('</div>')
html = html[html.index('>') + 1..-7]
end
child.inner_html = html
else
child.set_attribute('value', value)
end
node.add_child(child)
end
end
node.set_attribute('url', hash['url']) if ['extension', 'modifierExtension'].include?(name)
node.set_attribute('id', hash['id']) if hash['id'] && !versioned_fhir_module::RESOURCES.include?(name)
node
end

def self.from_xml(xml)
module ClassXml
def from_xml(xml)
doc = Nokogiri::XML(xml)
doc.root.add_namespace_definition('f', 'http://hl7.org/fhir')
doc.root.add_namespace_definition('x', 'http://www.w3.org/1999/xhtml')
Expand All @@ -88,7 +20,7 @@ def self.from_xml(xml)
resource
end

def self.xml_node_to_hash(node)
def xml_node_to_hash(node)
hash = {}
node.children.each do |child|
next if [Nokogiri::XML::Text, Nokogiri::XML::Comment].include?(child.class)
Expand Down Expand Up @@ -126,27 +58,84 @@ def self.xml_node_to_hash(node)
end
end

def self.valid?(xml)
def valid?(xml)
validate(xml).empty?
end
deprecate :is_valid?, :valid?

def self.validate(xml)
def validate(xml)
defns = File.expand_path '../definitions/schema', File.dirname(File.absolute_path(__FILE__))
schema = File.join(defns, 'fhir-all.xsd')
xsd = Nokogiri::XML::Schema(File.new(schema))
xsd.validate(Nokogiri::XML(xml))
end
end

def self.fhir_version_string
FHIR.fhir_version_string
end
module InstanceXml
#
# This module includes methods to serialize or deserialize FHIR resources to and from XML.
#

def self.versioned_fhir_module
FHIR.versioned_fhir_module
def to_xml
hash = to_hash
hash.delete('resourceType')
doc = Nokogiri::XML::Document.new
doc.encoding = 'utf-8'
doc.root = hash_to_xml_node(resourceType, hash, doc)
doc.root.default_namespace = 'http://hl7.org/fhir'
doc.to_xml
end

private :hash_to_xml_node
private_class_method :xml_node_to_hash
# Hash keys are ordered in Ruby 1.9 and later, so we can rely on their order
# to be the correct order for the XML serialization.
def hash_to_xml_node(name, hash, doc)
node = Nokogiri::XML::Node.new(name, doc)

# if hash contains resourceType
# create a child node with the name==resourceType
# fill that, and place the child under the above `node`
if hash['resourceType'].is_a?(String) && name != 'instance'
child_name = hash['resourceType']
hash.delete('resourceType')
child = hash_to_xml_node(child_name, hash, doc)
node.add_child(child)
return node
end

hash.each do |key, value|
next if ['extension', 'modifierExtension'].include?(name) && key == 'url'
next if key == 'id' && !versioned_fhir_module::RESOURCES.include?(name)

case value
when Hash
node.add_child(hash_to_xml_node(key, value, doc))
when Array
value.each do |v|
if v.is_a?(Hash)
node.add_child(hash_to_xml_node(key, v, doc))
else
child = Nokogiri::XML::Node.new(key, doc)
child.set_attribute('value', v)
node.add_child(child)
end
end
else
child = Nokogiri::XML::Node.new(key, doc)
if name == 'text' && key == 'div'
child.set_attribute('xmlns', 'http://www.w3.org/1999/xhtml')
html = value.strip
if html.start_with?('<div') && html.end_with?('</div>')
html = html[html.index('>') + 1..-7]
end
child.inner_html = html
else
child.set_attribute('value', value)
end
node.add_child(child)
end
end
node.set_attribute('url', hash['url']) if ['extension', 'modifierExtension'].include?(name)
node.set_attribute('id', hash['id']) if hash['id'] && !versioned_fhir_module::RESOURCES.include?(name)
node
end
end
end
6 changes: 5 additions & 1 deletion lib/fhir_models/fhir.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def self.primitive?(datatype:, value:)
case datatype.downcase
when 'boolean'
!(value.to_s =~ /\A(true|false)\Z/).nil?
when 'integer'
when 'integer', 'integer64'
!(value.to_s =~ /\A(0|[-+]?[1-9][0-9]*)\Z/).nil?
when 'string', 'markdown'
value.is_a?(String)
Expand Down Expand Up @@ -75,6 +75,10 @@ def self.primitive?(datatype:, value:)
!(value.to_s =~ /\A(0|([1-9][0-9]*))\Z/).nil?
when 'positiveint'
!(value.to_s =~ /\A+?[1-9][0-9]*\Z/).nil?
when 'canonical', 'url'
!(value.to_s =~ /\S*/).nil?
when 'uuid'
!(value.to_s =~ /urn:uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/).nil?
else
FHIR.logger.warn "Unable to check #{value} for datatype #{datatype}"
false
Expand Down
2 changes: 1 addition & 1 deletion lib/fhir_models/generator/metadata_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def generate
# resources
template.constants['RESOURCES'] = ig_resources.resource_definitions.map { |r| r['id'] }

output_file_name = File.join(output_folder, 'metadata.rb')
output_file_name = File.join(output_folder, "#{output_folder.split('/')[-2]}.rb")
file = File.open(output_file_name, 'w:UTF-8')
file.write(template.to_s)
file.close
Expand Down
1 change: 1 addition & 0 deletions lib/fhir_models/generator/template.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ def to_s(offset = 0)
s << "#{space}include FHIR::Hashable" unless @name.empty?
s << "#{space}include FHIR::Json" unless @name.empty?
s << "#{space}include FHIR::Xml" unless @name.empty?
s << "#{space}include FHIR::Common#{@name.first}" if ['StructureDefinition', 'ElementDefinition'].include?(@name.first)
s << ''

# add mandatory METADATA constant
Expand Down
22 changes: 18 additions & 4 deletions lib/fhir_models/r4.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@

require File.join(root, 'fhir_models', 'fhir.rb')

# Require the fhir_ext code
Dir.glob(File.join(root, 'fhir_models', 'fhir_ext', '*.rb')).sort.each do |file|
require file
end

# Require the FHIRPath code
Dir.glob(File.join(root, 'fhir_models', 'fhirpath', '*.rb')).sort.each do |file|
require file
Expand All @@ -34,11 +39,20 @@
require file
end

# Require the fhir_ext code
Dir.glob(File.join(root, 'fhir_models', 'fhir_ext', '*.rb')).sort.each do |file|
Dir.glob(File.join(root, 'fhir_models', 'r4', 'fhir_ext', '*.rb')).sort.each do |file|
require file
end

Dir.glob(File.join(root, 'fhir_models', 'r4', 'fhir_ext', '*.rb')).sort.each do |file|
require file
module FHIR
module R4
extend self

def fhir_version_string
'R4'
end

def versioned_fhir_module
FHIR::R4
end
end
end
9 changes: 1 addition & 8 deletions lib/fhir_models/r4/bootstrap/definitions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,10 @@ module FHIR
module R4
class Definitions
include CommonDefinitions
extend FHIR::R4
@ig_file_name = File.join(Dir.pwd, 'lib', 'fhir_models', 'igs', 'hl7.fhir.r4.core.tgz')

load_igs(@ig_file_name)

def self.fhir_version_string
'R4'
end

def self.versioned_fhir_module
FHIR::R4
end
end
end

Expand Down
15 changes: 15 additions & 0 deletions lib/fhir_models/r4/bootstrap/json.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module FHIR
module R4
module Json
extend FHIR::R4
extend FHIR::ClassJson
include FHIR::InstanceJson
end
end

module Json
extend FHIR::R4
extend FHIR::ClassJson
include FHIR::InstanceJson
end
end
8 changes: 1 addition & 7 deletions lib/fhir_models/r4/bootstrap/model.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
module FHIR
module R4
class Model < FHIR::Model
def fhir_version_string
'R4'
end

def versioned_fhir_module
FHIR::R4
end
include FHIR::R4
end
end
end
15 changes: 15 additions & 0 deletions lib/fhir_models/r4/bootstrap/xml.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module FHIR
module R4
module Xml
extend FHIR::R4
extend FHIR::ClassXml
include FHIR::InstanceXml
end
end

module Xml
extend FHIR::R4
extend FHIR::ClassXml
include FHIR::InstanceXml
end
end
17 changes: 0 additions & 17 deletions lib/fhir_models/r4/fhir_ext/element_definition.rb

This file was deleted.

Loading

0 comments on commit 43790ce

Please sign in to comment.