This repository has been archived by the owner on Dec 1, 2023. It is now read-only.
forked from onc-healthit/inferno-community
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FI-930: Support FHIRPath for generating searches (onc-healthit#490)
* support fhirpath for search generation * regenerate us core sequences Co-authored-by: Stephen MacVicar <[email protected]>
- Loading branch information
1 parent
5d103e0
commit 9e2e2f7
Showing
95 changed files
with
1,664 additions
and
942 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# frozen_string_literal: true | ||
|
||
module Inferno | ||
class BasicFHIRPathEvaluator | ||
def evaluate(elements, path, patched = false) | ||
path = patch_path(path) unless patched | ||
elements = Array.wrap(elements) | ||
return elements if path.blank? | ||
|
||
first_path, *rest_paths = path.split('.') | ||
rest_path = rest_paths.join('.') | ||
|
||
elements.flat_map do |element| | ||
evaluate(element&.send(first_path), rest_path, true) | ||
end.compact | ||
end | ||
|
||
private | ||
|
||
def patch_path(path) | ||
path = path.dup | ||
path.sub!(/^[A-Z]\w*\./, '') | ||
path.gsub!(/\bclass\b/, 'local_class') | ||
path.gsub!(/\.where\(.*\)/, '') | ||
as_type = path.scan(/\.as\((.*?)\)/).flatten.first | ||
path.gsub!(/\.as\((.*?)\)/, as_type.upcase_first) if as_type.present? | ||
path | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'rest-client' | ||
require 'json' | ||
require 'fhir_models' | ||
|
||
module Inferno | ||
class FHIRPathEvaluator | ||
# @param fhirpath_url [String] the base url for the FHIRPath /evaluate endpoint | ||
def initialize(fhirpath_url) | ||
raise ArgumentError, 'FHIRPath URL is unset' if fhirpath_url.blank? | ||
|
||
@fhirpath_url = fhirpath_url | ||
end | ||
|
||
# Evaluates the given FHIRPath expression against the given elements by posting each element | ||
# to the FHIRPath wrapper. | ||
# @param elements [Array] | ||
# @param path [String] | ||
def evaluate(elements, path) | ||
elements = Array.wrap(elements) | ||
return elements if path.blank? | ||
|
||
types = elements.map { |e| e.class.name.demodulize } | ||
Inferno.logger.info("Evaluating path '#{path}' on types: #{types}") | ||
|
||
elements.flat_map do |element| | ||
type = type_path(element) | ||
Inferno.logger.info("POST #{@fhirpath_url}/evaluate?path=#{path}&type=#{type}") | ||
result = RestClient.post "#{@fhirpath_url}/evaluate", element.to_json, params: { path: path, type: type } | ||
collection = JSON.parse(result.body) | ||
|
||
collection.map { |container| deserialize(container['element'], container['type']) } | ||
end.compact | ||
end | ||
|
||
private | ||
|
||
# Examples: | ||
# type_path(FHIR::Patient.new) -> 'Patient' | ||
# type_path(FHIR::Patient::Contact.new) -> 'Patient.contact' | ||
# type_path(FHIR::RiskEvidenceSynthesis::Certainty::CertaintySubcomponent.new) | ||
# -> 'RiskEvidenceSynthesis.certainty.certaintySubcomponent' | ||
def type_path(element) | ||
parts = element.class.name.split('::').drop(1) | ||
# Assumes that BackboneElements are named by capitalizing path components | ||
parts[1..-1].each { |part| part[0] = part[0].downcase } | ||
parts.join('.') | ||
end | ||
|
||
def deserialize(element, type) | ||
if element.is_a?(Hash) | ||
first_component, *rest_components = type.split('.') | ||
klass = FHIR.const_get(first_component) | ||
rest_components.each do |component| | ||
klass = FHIR.const_get(klass::METADATA[component]['type']) | ||
end | ||
klass.new(element) | ||
else | ||
element | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative 'fhirpath_evaluator' | ||
require_relative 'basic_fhirpath_evaluator' | ||
|
||
module Inferno | ||
class App | ||
module FHIRPathEvaluatorFactory | ||
def self.new_evaluator(selected_evaluator, external_evaluator_url) | ||
return Inferno::BasicFHIRPathEvaluator.new if ENV['RACK_ENV'] == 'test' | ||
|
||
case selected_evaluator | ||
when 'internal' | ||
Inferno::BasicFHIRPathEvaluator.new | ||
when 'external' | ||
Inferno::FHIRPathEvaluator.new(external_evaluator_url) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.