Class: Inferno::DSL::FHIRResourceValidation::Validator

Inherits:
Object
  • Object
show all
Defined in:
lib/inferno/dsl/fhir_resource_validation.rb

Constant Summary collapse

EXPANSION_PARAMETERS_ENV_VAR =

Environment variable containing the default expansion parameters. Used by #expansion_parameters when no value has been set explicitly. May contain either the raw JSON content of a FHIR Parameters resource (if it starts with {) or a path to a file containing one.

'FHIR_RESOURCE_VALIDATOR_EXPANSION_PARAMETERS'.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = nil, test_suite_id = nil, requirements = nil) ⇒ Validator

Returns a new instance of Validator.



47
48
49
50
51
52
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 47

def initialize(name = nil, test_suite_id = nil, requirements = nil, &)
  @name = name
  @test_suite_id = test_suite_id
  instance_eval(&)
  @requirements = requirements
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



45
46
47
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 45

def name
  @name
end

#requirementsObject (readonly)

Returns the value of attribute requirements.



44
45
46
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 44

def requirements
  @requirements
end

#session_idObject

Returns the value of attribute session_id.



45
46
47
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 45

def session_id
  @session_id
end

#test_suite_idObject

Returns the value of attribute test_suite_id.



45
46
47
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 45

def test_suite_id
  @test_suite_id
end

Instance Method Details

#conforms_to_logical_model?(object, model_url, runnable, add_messages_to_runnable: true, message_prefix: '', validator_response_details: nil) ⇒ Boolean

Validate a FHIR resource and determine if it's valid. Adds validation messages to the runnable if add_messages_to_runnable is true.

Returns:

  • (Boolean)


259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 259

def conforms_to_logical_model?(object, model_url, runnable, add_messages_to_runnable: true,
                               message_prefix: '', validator_response_details: nil)

  unless model_url.present?
    raise Inferno::Exceptions::TestSuiteImplementationException.new(
      'Logical Model Validation',
      'The profile of the logical model must be provided.'
    )
  end

  unless object.present?
    if add_messages_to_runnable
      runnable.add_message(:error,
                           "#{message_prefix}No object to check for conformance.")
    end
    return false
  end

  unless object.is_a?(Hash)
    raise Inferno::Exceptions::TestSuiteImplementationException.new(
      'Logical Model Validation',
      "Expected a Hash, got a #{object.class}."
    )
  end

  conformant?(object, model_url, runnable, add_messages_to_runnable:, message_prefix:,
                                           validator_response_details:)
end

#exclude_message {|message| ... } ⇒ Object

Filter out unwanted validation messages. Any messages for which the block evalutates to a truthy value will be excluded.

Examples:

validator do
  exclude_message { |message| message.type == 'info' }
end

Yield Parameters:



252
253
254
255
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 252

def exclude_message(&block)
  @exclude_message = block if block_given?
  @exclude_message
end

#expansion_parameters(value = nil) ⇒ Object

Set the expansion parameters to be sent with each validation request. This configures how the validator's terminology engine expands value sets during validation (e.g. designation preferences, forcing the use of the latest terminology versions, etc.). The content is sent inline with every validation request made by this validator, since the validator does not have access to Inferno's filesystem.

Accepts either a Hash containing the contents of a FHIR Parameters resource, or a String path to a file (JSON or XML) containing one. The file is read once, the first time it's needed.

If never set explicitly, this falls back to the FHIR_RESOURCE_VALIDATOR_EXPANSION_PARAMETERS environment variable, if present. This allows a shared set of expansion parameters to be configured once for every test kit that uses a given validator instance, while still letting individual test kits opt out or override it by calling this method themselves. The environment variable's content is treated as raw JSON if it starts with {, and otherwise as a file path.

Examples:

# Passing a Hash
fhir_resource_validator do
  url 'http://example.com/validator'
  expansion_parameters({
    resourceType: 'Parameters',
    parameter: [{ name: 'excludeNested', valueBoolean: true }]
  })
end
# Passing a file path
fhir_resource_validator do
  url 'http://example.com/validator'
  expansion_parameters 'path/to/expansion_parameters.json'
end

Parameters:

  • value (Hash, String, nil) (defaults to: nil)

    contents of a Parameters resource as a Hash, or a path to a file (JSON or XML) containing one



169
170
171
172
173
174
175
176
177
178
179
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 169

def expansion_parameters(value = nil)
  if value
    @expansion_parameters = build_expansion_parameters(value)
  elsif !@expansion_parameters_resolved
    env_value = ENV.fetch(EXPANSION_PARAMETERS_ENV_VAR, nil)
    @expansion_parameters = build_expansion_parameters_from_env(env_value) if env_value
  end
  @expansion_parameters_resolved = true

  @expansion_parameters
end

#igs(*validator_igs) ⇒ Object

Set the IGs that the validator will need to load

Examples:

igs "hl7.fhir.us.core#4.0.0"
igs("hl7.fhir.us.core#3.1.1", "hl7.fhir.us.core#6.0.0")

Parameters:

  • validator_igs (Array<String>)


73
74
75
76
77
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 73

def igs(*validator_igs)
  validation_context(igs: validator_igs) if validator_igs.any?

  validation_context.igs
end

#perform_additional_validation {|resource, profile_url| ... } ⇒ Object

Perform validation steps in addition to FHIR validation.

Examples:

perform_additional_validation do |resource, profile_url|
  if something_is_wrong
    { type: 'error', message: 'something is wrong' }
  else
    { type: 'info', message: 'everything is ok' }
  end
end

Yield Parameters:

  • resource (FHIR::Model)

    the resource being validated

  • profile_url (String)

    the profile the resource is being validated against

Yield Returns:

  • (Array<Hash<Symbol, String>>, Hash<Symbol, String>)

    The block should return a Hash or an Array of Hashes if any validation messages should be added. The Hash must contain two keys: :type and :message. :type can have a value of 'info', 'warning', or 'error'. A type of 'error' means the resource is invalid. :message contains the message string itself.



240
241
242
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 240

def perform_additional_validation(&block)
  additional_validations << block
end

#resource_is_valid?(resource, profile_url, runnable, add_messages_to_runnable: true, message_prefix: '', validator_response_details: nil) ⇒ Boolean

Validate a FHIR resource and determine if it's valid. Adds validation messages to the runnable if add_messages_to_runnable is true.

Parameters:

  • resource (FHIR::Model)

    the resource to validate

  • profile_url (String)

    the profile URL to validate against

  • runnable (Object)

    the runnable context (test/group/suite)

  • add_messages_to_runnable (Boolean) (defaults to: true)

    whether to add messages to the runnable

  • message_prefix (String) (defaults to: '')

    Prefix to add to the start of logged messages

  • validator_response_details (Array, nil) (defaults to: nil)

    if not nil, the service will populate this array with the detailed response message from the validator service. Can be used by test kits to perform custom handling of error messages.

Returns:

  • (Boolean)

    true if the resource is valid

See Also:

  • Inferno::DSL::FHIRResourceValidation#resource_is_valid?


301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 301

def resource_is_valid?(resource, profile_url, runnable, add_messages_to_runnable: true,
                       message_prefix: '', validator_response_details: nil)

  unless resource.present?
    runnable.add_message(:error, "#{message_prefix}No resource to validate.") if add_messages_to_runnable
    return false
  end

  unless resource.is_a?(FHIR::Model)
    raise Inferno::Exceptions::TestSuiteImplementationException.new(
      'FHIR Resource Validation',
      "Expected a FHIR::Model, got a #{resource.class}."
    )

  end
  profile_url ||= FHIR::Definitions.resource_definition(resource.resourceType).url

  conformant?(resource, profile_url, runnable, add_messages_to_runnable:, message_prefix:,
                                               validator_response_details:)
end

#url(validator_url = nil) ⇒ Object

Set the url of the validator service

Parameters:

  • validator_url (String) (defaults to: nil)


61
62
63
64
65
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 61

def url(validator_url = nil)
  @url = validator_url if validator_url
  @url ||= ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')
  @url
end

#validation_context(definition = nil) ⇒ Object Also known as: cli_context

Set the validationContext used as part of each validation request. Fields may be passed as either a Hash or block. Note that all fields included here will be sent directly in requests, there is no check that the fields are correct.

Examples:

# Passing fields in a block
fhir_resource_validator do
  url 'http://example.com/validator'
  validation_context do
    noExtensibleBindingMessages true
    allowExampleUrls true
    txServer nil
  end
end
# Passing fields in a Hash
fhir_resource_validator do
  url 'http://example.org/validator'
  validation_context({
    noExtensibleBindingMessages: true,
    allowExampleUrls: true,
    txServer: nil
  })
end

Parameters:

  • definition (Hash) (defaults to: nil)

    raw fields to set, optional



107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 107

def validation_context(definition = nil, &)
  if @validation_context
    if definition
      @validation_context.definition.merge!(definition.deep_symbolize_keys)
    elsif block_given?
      @validation_context.instance_eval(&)
    end
  else
    @validation_context = ValidationContext.new(definition || {}, &)
  end
  @validation_context
end

#validator_session_repoObject



54
55
56
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 54

def validator_session_repo
  @validator_session_repo ||= Inferno::Repositories::ValidatorSessions.new
end

#warm_up(target, profile_url) ⇒ Object

Warm up the validator session by sending a test validation request. This initializes the validator session and persists it for future use.

Parameters:

  • target (FHIR::Model, Hash)

    the object to validate

  • profile_url (String)

    the profile URL to validate against



387
388
389
390
391
392
393
394
395
396
397
# File 'lib/inferno/dsl/fhir_resource_validation.rb', line 387

def warm_up(target, profile_url)
  response_body = validate(target, profile_url)
  res = JSON.parse(response_body)
  session_id = res['sessionId']
  validator_session_repo.save(test_suite_id:, validator_session_id: session_id,
                              validator_name: name.to_s, suite_options: requirements)
  self.session_id = session_id
rescue JSON::ParserError
  Application[:logger]
    .error("Validator warm_up - error unexpected response format from validator: #{response_body}")
end