Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: FI-3556: Migrate MustSupport logic into core #584

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ Lint/EmptyBlock:
Exclude:
- 'dev_suites/ui_onc_program/**/*'

inherit_mode:
merge:
- AllowedNames

Naming/MethodParameterName:
AllowedNames:
- ig

Style/BlockComments:
Exclude:
- 'spec/spec_helper.rb'
Expand Down
23 changes: 11 additions & 12 deletions lib/inferno/apps/cli/evaluate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,20 @@ class Evaluate < Thor::Group

def evaluate(ig_path, data_path, _log_level)
validate_args(ig_path, data_path)
_ig = get_ig(ig_path)
ig = get_ig(ig_path)

# Rule execution, and result output below will be integrated soon.

# if data_path
# DatasetLoader.from_path(File.join(__dir__, data_path))
# else
# ig.examples
# end
data =
if data_path
DatasetLoader.from_path(File.join(__dir__, data_path))
else
ig.examples
end

# config = Config.new
# evaluator = Inferno::DSL::FHIREvaluation::Evaluator.new(data, config)
evaluator = Inferno::DSL::FHIREvaluation::Evaluator.new(ig)

# results = evaluate()
# output_results(results, options[:output])
config = Inferno::DSL::FHIREvaluation::Config.new
results = evaluator.evaluate(data, config)
output_results(results, options[:output])
end

def validate_args(ig_path, data_path)
Expand Down
23 changes: 23 additions & 0 deletions lib/inferno/dsl/fhir_evaluation/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,26 @@ Environment:
Url: 'https://cts.nlm.nih.gov'

Rule:
AllMustSupportsPresent:
Description: 'An instance of all MustSupport elements, extensions, and slices is present in the given resources'
Enabled: true
# RequirementExtensionUrl accepts an extension URL which tags element definitions as required for the purposes of this test, even if not Must Support.
# For instance, US Core elements with the "http://hl7.org/fhir/us/core/StructureDefinition/uscdi-requirement" extension
# may be considered required even if not necessarily tagged Must Support.
# An instance of the extension must have valueBoolean=true to be recognized.
RequirementExtensionUrl: null
ConformanceOptions:
# ConformanceOptions allows selecting from a few approaches to determine which subset of resources
# should be used to search for the MustSupport elements from each profile.
# Resources that are not the same type as the target of the profile are never searched, regardless of option.

# - If considerMetaProfile, the search will include resources that declare the current profile in meta.profile
considerMetaProfile: true

# - If considerValidationResults, resources will be validated against each profile to determine which they should be checked against.
# The search will include resources that validate against the current profile
# (in other words, resources for which a validation request produces no errors).
considerValidationResults: false

# - If considerOnlyResourceType, the search will include resources of the same type as the profile target type (StructureDefintion.type)
considerOnlyResourceType: false
6 changes: 4 additions & 2 deletions lib/inferno/dsl/fhir_evaluation/evaluation_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ module FHIREvaluation
# - The data being evaluated
# - A summary/characterization of the data
# - Evaluation results
# - A Validator instance, configured to point to the given IG
class EvaluationContext
attr_reader :ig, :data, :results, :config
attr_reader :ig, :data, :results, :config, :validator

def initialize(ig, data, config) # rubocop:disable Naming/MethodParameterName
def initialize(ig, data, config, validator)
@ig = ig
@data = data
@results = []
@config = config
@validator = validator
end

def add_result(result)
Expand Down
8 changes: 5 additions & 3 deletions lib/inferno/dsl/fhir_evaluation/evaluator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@
require_relative 'evaluation_context'
require_relative 'evaluation_result'
require_relative 'dataset_loader'
require_relative 'rules/all_must_supports_present'

module Inferno
module DSL
module FHIREvaluation
class Evaluator
attr_accessor :ig
attr_accessor :ig, :validator

def initialize(ig) # rubocop:disable Naming/MethodParameterName
def initialize(ig, validator = nil)
@ig = ig
@validator = validator
end

def evaluate(data, config = Config.new)
context = EvaluationContext.new(@ig, data, config)
context = EvaluationContext.new(@ig, data, config, validator)

active_rules = []
config.data['Rule'].each do |rulename, rule_details|
Expand Down
48 changes: 48 additions & 0 deletions lib/inferno/dsl/fhir_evaluation/profile_conformance_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Inferno
module DSL
module FHIREvaluation
# This module is used to decide whether a resource instantiates a given profile.
# Aligning resources to profiles is necessary when evaluating the comprehensiveness
# of the resources with respect to those profiles, unfortunately it's impossible to
# programmatically determine intent. (i.e, is this resource supposed to instantiate this profile?)
# This module offers some approaches to make that determination.
module ProfileConformanceHelper
DEFAULT_OPTIONS = {
considerMetaProfile: true,
considerValidationResults: false,
considerOnlyResourceType: false
}.freeze

def conforms_to_profile?(resource, profile, options = DEFAULT_OPTIONS, validator = nil)
return false if resource.resourceType != profile.type

options[:considerOnlyResourceType] ||
consider_meta_profile(resource, profile, options) ||
consider_validation_results(resource, profile, options, validator) ||
(block_given? && yield(resource))
end

def consider_meta_profile(resource, profile, options)
options[:considerMetaProfile] && declares_meta_profile?(resource, profile)
end

def declares_meta_profile?(resource, profile)
declared_profiles = resource&.meta&.profile || []
profile_url = profile.url
versioned_url = "#{profile_url}|#{profile.version}"

declared_profiles.include?(profile_url) || declared_profiles.include?(versioned_url)
end

def consider_validation_results(resource, profile, options, validator)
options[:considerValidationResults] && validates_profile?(resource, profile, validator)
end

def validates_profile?(_resource, _profile, _validator)
raise 'Profile validation is not yet implemented. ' \
'Set considerValidationResults=false.'
end
end
end
end
end
Loading
Loading