class Measures::ValueSetLoader

Utility class for loading value sets

Public Class Methods

get_value_set_models(value_set_oids, user=nil) click to toggle source
# File lib/measures/loading/value_set_loader.rb, line 18
def self.get_value_set_models(value_set_oids, user=nil)
  HealthDataStandards::SVS::ValueSet.by_user(user).in(oid: value_set_oids)
end
load_value_sets_from_vsac(value_sets, vsac_options, vsac_ticket_granting_ticket, user=nil, measure_id=nil) click to toggle source
# File lib/measures/loading/value_set_loader.rb, line 22
def self.load_value_sets_from_vsac(value_sets, vsac_options, vsac_ticket_granting_ticket, user=nil, measure_id=nil)
  value_set_models = []
  from_vsac = 0
  existing_value_set_map = {}

  errors = {}
  api = Util::VSAC::VSACAPI.new(config: APP_CONFIG['vsac'], ticket_granting_ticket: vsac_ticket_granting_ticket)

  RestClient.proxy = ENV["http_proxy"]
  value_sets.each do |value_set|
    # The vsac_options that will be used for this specific value set. Default to using passed in options from measures controller
    vs_vsac_options = vsac_options

    # If we are allowing measure_defined value sets, determine vsac_options for this value set based on elm info.
    if vsac_options[:measure_defined] == true
      if !value_set[:profile].nil?
        vs_vsac_options = { profile: value_set[:profile] }
      elsif !value_set[:version].nil?
        vs_vsac_options = { version: value_set[:version] }
      end
      # if no parseable options in the ELM were found, we stick with the passed in options from measures controller
    end

    # Determine version to store value sets as after parsing and to use to looking for existing set.
    query_version = ""
    if vs_vsac_options[:include_draft] == true
      query_version = "Draft-#{measure_id}" # Unique draft version based on measure id
    elsif vs_vsac_options[:profile]
      query_version = "Profile:#{vs_vsac_options[:profile]}" # Profile calls return 'N/A' so note profile use.
    elsif vs_vsac_options[:version]
      query_version = vs_vsac_options[:version]
    elsif vs_vsac_options[:release]
      query_version = "Release:#{vs_vsac_options[:release]}"
    end

    # TODO: remove the usage of existing value sets. future work will be always fetching value sets from VSAC and
    # associating them with the new measure.

    # check if we already have this valuset loaded for this user
    set = HealthDataStandards::SVS::ValueSet.where({user_id: user.id, oid: value_set[:oid], version: query_version}).first()

    # delete existing if we are doing include_draft option sinc the existing may be stale. note that this may delete
    # and effectively replace value sets for a measure load that may fail. Unintentionally updating the value sets.
    if (vs_vsac_options[:include_draft] && set)
      set.delete
      set = nil
    end

    # use the existing value set if it exists
    if (set)
      existing_value_set_map[set.oid] = set

    # load this value set from VSAC
    else
      vs_data = api.get_valueset(value_set[:oid], vs_vsac_options)

      # there are some funky unicodes coming out of the vs response that are not in ASCII as the string reports to be
      vs_data.force_encoding("utf-8")
      from_vsac += 1

      doc = Nokogiri::XML(vs_data)

      doc.root.add_namespace_definition("vs","urn:ihe:iti:svs:2008")

      vs_element = doc.at_xpath("/vs:RetrieveValueSetResponse/vs:ValueSet|/vs:RetrieveMultipleValueSetsResponse/vs:DescribedValueSet")

      if vs_element && vs_element['ID'] == value_set[:oid]
        vs_element['id'] = value_set[:oid]
        set = HealthDataStandards::SVS::ValueSet.load_from_xml(doc)
        # make sure this value set has concepts, delete it and raise error if it is empty
        if set.concepts.empty?
          set.delete
          raise Util::VSAC::VSEmptyError.new(value_set[:oid])
        end
        set.user = user

        # bundle id for user should always be the same 1 user to 1 bundle
        # using this to allow cat I generation without extensive modification to HDS
        set.bundle = user.bundle if (user && user.respond_to?(:bundle))

        # As of 9/7/2017, when valuesets are retrieved from VSAC via profile, their version defaults to N/A
        # As such, we set the version to the profile with an indicator.
        set.version = query_version
        set.save!
        existing_value_set_map[set.oid] = set
      else
        raise Util::VSAC::VSNotFoundError.new(value_set[:oid])
      end
    end
  end

  puts "\tloaded #{from_vsac} value sets from vsac" if from_vsac > 0
  existing_value_set_map.values
end
save_value_sets(value_set_models, user = nil) click to toggle source
# File lib/measures/loading/value_set_loader.rb, line 6
def self.save_value_sets(value_set_models, user = nil)
  #loaded_value_sets = HealthDataStandards::SVS::ValueSet.all.map(&:oid)
  value_set_models.each do |vsm|
    HealthDataStandards::SVS::ValueSet.by_user(user).where(oid: vsm.oid).delete_all()
    vsm.user = user
    #bundle id for user should always be the same 1 user to 1 bundle
    #using this to allow cat I generation without extensive modification to HDS
    vsm.bundle = user.bundle if (user && user.respond_to?(:bundle))
    vsm.save!
  end
end