class ProfileParser
Constants
- FILTER_ADM
- FILTER_FM
- FILTER_GEN
- FILTER_LAB
- FILTER_MSR
- FILTER_OBS
- FILTER_PH
Attributes
base[R]
instance attributes
base?[R]
instance attributes
xml[R]
instance attributes
Public Class Methods
getExclusionFilterRule(std, version)
click to toggle source
# File lib/ez7gen/profile_parser.rb, line 100 def self.getExclusionFilterRule(std, version) path = self.get_schema_location rules_file = "#{path}#{std}/rules/#{version}.yml" if File.exists? (rules_file) yml = YAML.load_file rules_file all = [] all += (yml['exclusion.errors'])?yml['exclusion.errors']:[] all += (yml['exclusion.blacklist'])?yml['exclusion.blacklist']:[] else [] end end
getVersionUrlRule(std, version)
click to toggle source
# File lib/ez7gen/profile_parser.rb, line 114 def self.getVersionUrlRule(std, version) path = self.get_schema_location rules_file = "#{path}#{std}/rules/#{version}.yml" if File.exists? (rules_file) yml = YAML.load_file rules_file (yml['version.url'])?yml['version.url']:nil else nil end end
get_schema_location()
click to toggle source
instance methods
# File lib/ez7gen/profile_parser.rb, line 66 def self.get_schema_location #properties_file = File.expand_path('../resources/properties.yml', __FILE__) #yml = YAML.load_file properties_file #path = yml['web.install.dir'] # set when run intall gem with argument, example: gem install 'c:/ez7Gen/ez7gen-web/config/resources/' path = File.expand_path('../', __FILE__) path = File.join(path, 'config/schema/') #puts path + ' : self.get_schema_location' # path = path<<'config/schema/' # path = path<<'config/resources/' end
lookup_versions()
click to toggle source
# File lib/ez7gen/profile_parser.rb, line 77 def self.lookup_versions path = self.get_schema_location puts path + " self.lookup_versions" names = Dir.glob("#{path}*").select {|f| File.directory? f} versions = names.map{|it| { std: it.sub(path,''), path: it}} # for each version # look get list of .xml files, except added,own directory for added? versions.each{|version| profiles = [] Dir.glob("#{version[:path]}/**").select {|file| !File.directory? file}.each{|path| xml = Ox.parse(IO.read(path)) # for each schema collect metadata profile = xml.Export.Document.attributes profile[:doc] = profile.delete(:name) # resolve collision with same keys profile.merge!(xml.Export.Document.Category.attributes) profile[:path] = path profiles << profile } version[:profiles] = profiles } end
new(args)
click to toggle source
Child class has a wrapper TODO: Refactor def initialize(version=nil, event=nil)
# File lib/ez7gen/profile_parser.rb, line 31 def initialize(args) args.each do |k,v| instance_variable_set("@#{k}", v) unless v.nil? end # set to false if it has not been set already # @base ||= false profile, path = nil # if(@version_store) profile = @version_store.find{|v| v[:std] == @std}[:profiles].find{|p| p[:doc] == @version }[:path] path = @version_store.detect{|v| v[:std] == @std}[:path] # else # # path = self.class.get_schema_location # # profile = File.path(path+ @@HL7_VERSIONS[@version]) # end @xml = Ox.parse(IO.read(profile)) # added = File.path(path+'added.xml') begin added = File.path(path+'/added/coded-tables.xml') @added = Ox.parse(IO.read(added)) rescue => e # puts e.message $log.error ("#{self.class.to_s}:#{__method__.to_s}") { e.message } end # set flag if this is base or custom schema @base = (@xml.Export.Document.Category.attributes[:std] == '1') end
Public Instance Methods
build_event_attributes(event, templates, path)
click to toggle source
build all the details for event type including template information
# File lib/ez7gen/profile_parser.rb, line 247 def build_event_attributes(event, templates, path) attr = {} attr[:name] = event #chek if there is a match otherwise use the segment name attr[:code] = get_message_event_desc(event) # check if this event has matching template files # event_templates = templates.collect { |template| template =~/#{event}/ } unless blank?(templates) # attr[:templates] = templates unless blank?(event_templates) if (!blank?(templates)) # try to match templates to an event by name event_templates = templates.select { |template| template =~/#{event}/i } # if found set event attribute with template names if(!blank?(event_templates)) # attr[:templates] = [] #update event code with template count #code = "<b> +#{event_templates.size}" << (event_templates.size == 1) ? "TEMPLATE" : "TEMPLATES" << "</b>" # attr[:code] += "<div><b><font color=#337ab7>#{event_templates.size} #{(event_templates.size == 1) ? 'TEMPLATE' : 'TEMPLATES'}</font></b></div>" attr[:code] += "<small><b><font color=#337ab7> (#{event_templates.size}#{(event_templates.size == 1) ? 'TEMPLATE' : 'TEMPLATES'})</font></b></small>" # if (event_templates.size == 1) then code.chop! end # attr[:code] += "#{code}" # if (event_templates.size == 1) then attr[:code].chop! end attr[:templates] = event_templates.collect{ |tmpl| desc = Ox.parse(IO.read("#{path}/#{tmpl}")).HL7v2xConformanceProfile.HL7v2xStaticDef.attributes[:EventDesc] # desc = (!blank?(desc)) ? desc : "Custom #{event}" desc = (!blank?(desc)) ? desc : tmpl.gsub('_',' ').sub('.xml','') {:desc => desc.upcase , :file => tmpl} } end end return attr end
get_code_table(tableName)
click to toggle source
get hash of attributes for codeTable values
# File lib/ez7gen/profile_parser.rb, line 165 def get_code_table(tableName) #exclude 361,362 sending/receiving app and facility #if(tableName in ['72','88','132','264','269','471','9999']){ # println tableName #} #empty hash if no table name return [] if blank?(tableName) attributes = lookup_code_table(tableName, @xml) if(blank?(attributes))||(attributes.size == 1 && attributes[0][:value] =='...') attributes = lookup_code_table(tableName, @added) end # Per Galina, code table values with special characters. Ensemble validation fails. # Filter out codes which have html encoded characters - Ensemble has problem handling it. # a bit of awkward logic - if either description or value has html encoded chars, remove the item attributes.select!{|a| (has_html_encoded_ch?(a[:description]) || has_html_encoded_ch?(a[:value]))?false:true } return attributes end
get_message_definition()
click to toggle source
find message structure by event type
# File lib/ez7gen/profile_parser.rb, line 128 def get_message_definition msg_type = get_message_structure(@event) # p msg_type $log.info("#{self.class.to_s}:#{__method__.to_s}") { msg_type } definition = @xml.Export.Document.Category.locate('MessageStructure').select{|it| it.attributes[:name] == msg_type }.first.attributes[:definition] post_process(definition) end
get_message_event_desc(event)
click to toggle source
look up for event description
# File lib/ez7gen/profile_parser.rb, line 298 def get_message_event_desc(event) desc = nil tbl = @xml.Export.Document.Category.locate('CodeTable').select { |it| (it.attributes[:description] == 'Event type') } if(!blank?(tbl)) # get event/message name ex: NO2 for ACK_NO2 event_name = (event.split('_')).last for t in tbl # could be multiple tables, iterate desc = (( e = t.locate('Enumerate').select{ |it| it.attributes[:value] == event_name }); e!=[])? (e.first().attributes[:description]) : nil if(desc)then break end # brake after first match end # for end # if return desc || event end
get_message_structure(event)
click to toggle source
# File lib/ez7gen/profile_parser.rb, line 159 def get_message_structure(event) msg_type = @xml.Export.Document.Category.locate('MessageType').select { |it| it.attributes[:name] == event }.first.attributes[:structure] end
get_segment_structure(segment)
click to toggle source
# File lib/ez7gen/profile_parser.rb, line 193 def get_segment_structure(segment) segmentName = get_segment_name(segment) # $log.info (segment) $log.info("#{self.class.to_s}:#{__method__.to_s}") { segment } # node = export.Document.Category.SegmentStructure.find{ it.@name == segmentName} # values = @xml.elements.collect("Export/Document/Category/SegmentStructure[@name ='#{segmentName}']/SegmentSubStructure"){|x| x.attributes} @xml.Export.Document.Category.locate('SegmentStructure').select{|it| it.attributes[:name] == segmentName }.first.locate('SegmentSubStructure').map{|it| it.attributes} #values.each {|it| puts it} end
get_templates(path)
click to toggle source
look up for message template files in a specified directory
# File lib/ez7gen/profile_parser.rb, line 288 def get_templates(path) begin Dir.entries(path).select {|f| f =~/.xml/i}.sort # rescue => e rescue [] # handle case when dir is missing end end
lookup_code_table(tableName, path)
click to toggle source
# File lib/ez7gen/profile_parser.rb, line 188 def lookup_code_table(tableName, path) tbl = path.Export.Document.Category.locate('CodeTable').select { |it| it.attributes[:name] == tableName } (!blank?(tbl)) ? tbl.first.locate('Enumerate').map { |it| it.attributes } : [Utils::DATA_LOOKUP_MIS] end
lookup_events(params)
click to toggle source
# File lib/ez7gen/profile_parser.rb, line 224 def lookup_events(params) #all events for version events = @xml.Export.Document.Category.locate('MessageType').map!{|it| it.attributes[:name]} #if there are exclusion rule, remove the exclusions if(!blank?(params[:exclusions])) events -= params[:exclusions] end path = params[:templates_path] templates = (!blank?(path))? get_templates(path) : [] # go over the events and build attributes of the array events_with_attr = events.map{ |el| build_event_attributes(el, templates, path) } #events_with_attr end
lookup_message_groups(groups)
click to toggle source
helper method to look up messages for specific groups of messages
# File lib/ez7gen/profile_parser.rb, line 315 def lookup_message_groups (groups) messages = [] groups.each{ |group| messages += lookup_message_types(group) } return messages end
lookup_message_types(map=nil, exclusion=nil)
click to toggle source
# File lib/ez7gen/profile_parser.rb, line 203 def lookup_message_types(map=nil, exclusion=nil) # match everything if no filter defined map ||= @@FILTER_ALL filter = map[:filter] messageTypeColl = @xml.Export.Document.Category.locate('MessageType').select{|it| it.attributes[:name] =~/#{filter}/}.map!{|it| it.attributes[:name]} if(!blank?(exclusion)) messageTypeColl = messageTypeColl - exclusion end messages = messageTypeColl.map{ |el| event = (el.split('_')).last { name: el, #chek if there is a match otherwise use the segment name code: ((e = @xml.Export.Document.Category.locate('MessageEvent').select{|it| it.attributes[:name] == event}); e!=[] )? (e.first().attributes[:description]): el, group: map[:group] } } return messages end
post_process(definition)
click to toggle source
helper method to handle corner cases
# File lib/ez7gen/profile_parser.rb, line 137 def post_process(definition) if(@base && (@event == 'OSR_Q06')) # 1.If the OSQ_O06 query is about the status of the general messages OMG_O19 General Clinical Order and OML_O21 Lab Order, which only have the OBR segment, then the OSR_O06 should only have the OBR segment in its Order Detail Segment < >. # 2.If the OSQ_O06 query is about the status of the Pharmacy order messages (OMP_O09, RDE_O11) that do not have OBR segment, but have RXO segment, then the OSR_O06 Order Detail Segment < > should only contain RXO. # definition.sub!(/<(.*?)>/,['OBR','RXO'].sample()) # puts definition definition = definition.sub!(/<(.*?)>/,['OBR','RXO'].sample()) # puts definition elsif(@base && (@event == 'ORL_O22')) # work around for Ensemble issue where repeating group causes error in validation, remove repeating {} tag # MSH~MSA~[~ERR~]~[~{~NTE~}~]~[~[~PID~{~[~SAC~[~{~OBX~}~]~]~[~{~ORC~[~OBR~[~{~SAC~}~]~]~}~]~}~]~] # 'MSH~MSA~[~ERR~]~[~{~NTE~}~]~[~PID~{~[~SAC~[~{~OBX~}~]~]~[~{~ORC~[~OBR~[~{~SAC~}~]~]~}~]~}~]' #simplified # 'MSH~MSA~[~ERR~]~[~{~NTE~}~]~[~PID~[~[~SAC~[~{~OBX~}~]~]~[~{~ORC~[~OBR~[~{~SAC~}~]~]~}~]~]~]' #changed definition = 'MSH~MSA~[~ERR~]~[~{~NTE~}~]~[~PID~[~[~SAC~[~{~OBX~}~]~]~[~{~ORC~[~OBR~[~{~SAC~}~]~]~}~]~]~]' # definition.sub('[~{~ORC~[~OBR~[~{~SAC~}~]~]~}~]', '[~ORC~[~OBR~[~{~SAC~}~]~]~]') else definition end return definition end