Skip to content

Commit

Permalink
Merge branch 'master' into migrate-to-hl7-validator
Browse files Browse the repository at this point in the history
  • Loading branch information
projkov committed Jun 23, 2024
2 parents 9957b90 + d126a23 commit c74196d
Show file tree
Hide file tree
Showing 51 changed files with 357 additions and 295 deletions.
2 changes: 1 addition & 1 deletion infra/modules/au_fhir_inferno/input.tf
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ variable "terminology_server" {

variable "inferno_image" {
description = "Docker image for inferno"
default = "ghcr.io/hl7au/au-fhir-core-inferno:b51589c96511f38a24fc3cc6dc6774904318e096"
default = "ghcr.io/hl7au/au-fhir-core-inferno:d9dfcc93e634a8fbfb2ca5acbe5b98408d60f56d"
}

variable "validator_base_path" {
Expand Down
90 changes: 62 additions & 28 deletions lib/au_core_test_kit/fhir_resource_navigation.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# frozen_string_literal: true

require_relative './primitive_type'

module AUCoreTestKit
module FHIRResourceNavigation
DAR_EXTENSION_URL = 'http://hl7.org/fhir/StructureDefinition/data-absent-reason'
DAR_EXTENSION_URL = 'http://hl7.org/fhir/StructureDefinition/data-absent-reason'.freeze
PRIMITIVE_DATA_TYPES = FHIR::PRIMITIVES.keys

def resolve_path(elements, path)
elements = Array.wrap(elements)
Expand All @@ -18,19 +21,41 @@ def resolve_path(elements, path)
end.compact
end

def find_a_value_at(element, path, include_dar: false, &block)
def get_extension_url(str)
match = str.match(/extension\('([^']+)'\)\.value/)
match ? match[1] : nil
end

def is_extension?(str)
!!str.match(/extension\('https?:\/\/[^\s]+?\)\.value/)
end

def get_value_from_extension(element, extension_url)
extension_elements = element.extension.filter { |ext| ext.url == extension_url}
if extension_elements.length > 0
extension_element = extension_elements.first
extension_element.valueCoding
else
return nil
end
end

def find_a_value_at(element, path, include_dar: false)
return nil if element.nil?

if is_extension?(path)
return get_value_from_extension(element, get_extension_url(path))
end

elements = Array.wrap(element)
if path.empty?
unless include_dar
elements = elements.reject do |el|
el.respond_to?(:extension) && el.extension.any? { |ext| ext.url == DAR_EXTENSION_URL }
el.respond_to?(:extension) && el.extension.any? { |ext| ext.url == DAR_EXTENSION_URL}
end
end

return elements.find(&block) if block_given?

return elements.find { |el| yield(el) } if block_given?
return elements.first
end

Expand All @@ -39,19 +64,19 @@ def find_a_value_at(element, path, include_dar: false, &block)
segment = path_segments.shift.delete_suffix('[x]').gsub(/^class$/, 'local_class').gsub(/\[x\]:/, ':').to_sym
no_elements_present =
elements.none? do |element|
child = get_next_value(element, segment)
child.present? || child == false
end
child = get_next_value(element, segment)
child.present? || child == false
end
return nil if no_elements_present

remaining_path = path_segments.join('.')
elements.each do |element|
child = get_next_value(element, segment)
element_found =
if block_given?
find_a_value_at(child, remaining_path, include_dar:, &block)
find_a_value_at(child, remaining_path, include_dar: include_dar) { |value_found| yield(value_found) }
else
find_a_value_at(child, remaining_path, include_dar:)
find_a_value_at(child, remaining_path, include_dar: include_dar)
end
return element_found if element_found.present? || element_found == false
end
Expand All @@ -64,30 +89,42 @@ def get_next_value(element, property)
if extension_url.present?
element.url == extension_url ? element : nil
elsif property.to_s.include?(':') && !property.to_s.include?('url')
find_slice_via_discriminator(element, property)

slice = find_slice_via_discriminator(element, property)
slice
else
element.send(property)
value = element.send(property)
primitive_value = get_primitive_type_value(element, property, value)
primitive_value.present? ? primitive_value : value
end
rescue NoMethodError
nil
end

def get_primitive_type_value(element, property, value)
source_value = element.source_hash["_#{property}"]

return nil unless source_value.present?

primitive_value = USCoreTestKit::PrimitiveType.new(source_value)
primitive_value.value = value
primitive_value
end

def find_slice_via_discriminator(element, property)
element_name = property.to_s.split(':')[0].gsub(/^class$/, 'local_class')
slice_name = property.to_s.split(':')[1].gsub(/^class$/, 'local_class')
if metadata.present?
slice_by_name = metadata.must_supports[:slices].find { |slice| slice[:slice_name] == slice_name }
slice_by_name = metadata.must_supports[:slices].find{ |slice| slice[:slice_name] == slice_name }
discriminator = slice_by_name[:discriminator]
slices = Array.wrap(element.send(element_name))
slices.find do |slice|
case discriminator[:type]
when 'patternCodeableConcept'
slice_value = discriminator[:path].present? ? slice.send((discriminator[:path]).to_s).coding : slice.coding
slice_value.any? { |coding| coding.code == discriminator[:code] && coding.system == discriminator[:system] }
slice_value = discriminator[:path].present? ? slice.send("#{discriminator[:path]}")&.coding : slice.coding
slice_value&.any? { |coding| coding.code == discriminator[:code] && coding.system == discriminator[:system] }
when 'patternCoding'
slice_value = discriminator[:path].present? ? slice.send(discriminator[:path]) : slice
slice_value.code == discriminator[:code] && slice_value.system == discriminator[:system]
slice_value&.code == discriminator[:code] && slice_value&.system == discriminator[:system]
when 'patternIdentifier'
slice.identifier.system == discriminator[:system]
when 'value'
Expand All @@ -113,12 +150,12 @@ def find_slice_via_discriminator(element, property)
slice.is_a? FHIR.const_get(discriminator[:code])
end
when 'requiredBinding'
discriminator[:path].present? ? slice.send((discriminator[:path]).to_s).coding : slice.coding
slice_value { |coding| discriminator[:values].include?(coding.code) }
slice_value = discriminator[:path].present? ? slice.send("#{discriminator[:path]}").coding : slice.coding
slice_value {|coding| discriminator[:values].include?(coding.code) }
end
end
else
# TODO: Error handling for if this file doesn't have access to metadata for some reason (begin/rescue with StandardError?)
#TODO: Error handling for if this file doesn't have access to metadata for some reason (begin/rescue with StandardError?)
end
end

Expand All @@ -127,22 +164,19 @@ def verify_slice_by_values(element, value_definitions)
path_prefixes.all? do |path_prefix|
value_definitions_for_path =
value_definitions
.select { |value_definition| value_definition[:path].first == path_prefix }
.each { |value_definition| value_definition[:path].shift }
.select { |value_definition| value_definition[:path].first == path_prefix }
.each { |value_definition| value_definition[:path].shift }
find_a_value_at(element, path_prefix) do |el_found|
child_element_value_definitions, current_element_value_definitions =
value_definitions_for_path.partition { |value_definition| value_definition[:path].present? }

current_element_values_match =
current_element_value_definitions
.all? { |value_definition| value_definition[:value] == el_found }
.all? { |value_definition| value_definition[:value] == el_found }

child_element_values_match =
if child_element_value_definitions.present?
verify_slice_by_values(el_found, child_element_value_definitions)
else
true
end
child_element_value_definitions.present? ?
verify_slice_by_values(el_found, child_element_value_definitions) : true
current_element_values_match && child_element_values_match
end
end
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit c74196d

Please sign in to comment.