diff --git a/lib/message.rb b/lib/message.rb index 170759d..5b448a8 100644 --- a/lib/message.rb +++ b/lib/message.rb @@ -48,9 +48,12 @@ def initialize( raw_msg=nil, &blk ) @item_delim = "^" @element_delim = '|' @segment_delim = "\r" + @repetition_delim = '~' @delimiter = HL7::Message::Delimiter.new( @element_delim, @item_delim, - @segment_delim) + @segment_delim, + @repetition_delim + ) @message_parser = HL7::MessageParser.new(@delimiter) diff --git a/lib/message_parser.rb b/lib/message_parser.rb index 67e84db..5a83de7 100644 --- a/lib/message_parser.rb +++ b/lib/message_parser.rb @@ -72,4 +72,9 @@ def parse_element_delim(str) def parse_item_delim(str) (str && str.kind_of?(String)) ? str.slice(4,1) : "^" end -end \ No newline at end of file + + # Get the repetition delimiter from an MSH segment + def parse_repetition_delim(str) + (str && str.kind_of?(String)) ? str.slice(5,1) : "~" + end +end diff --git a/lib/segment.rb b/lib/segment.rb index 51752b1..946e0a4 100644 --- a/lib/segment.rb +++ b/lib/segment.rb @@ -24,6 +24,7 @@ class HL7::Message::Segment attr_accessor :segment_parent attr_reader :element_delim attr_reader :item_delim + attr_reader :repetition_delim attr_reader :segment_weight METHOD_MISSING_FOR_INITIALIZER = <<-END @@ -38,6 +39,7 @@ def method_missing( sym, *args, &blk ) # delims:: an optional array of delimiters, where # delims[0] = element delimiter # delims[1] = item delimiter + # delims[2] = repetition delimiter def initialize(raw_segment="", delims=[], &blk) @segments_by_name = {} @field_total = 0 @@ -75,6 +77,12 @@ def elements_from_segment(raw_segment) elements << "" end end + elements[1..]&.each_with_index do |element, index| + is_msh_encoding_characters_field = elements[0] == 'MSH' && index == 0 + if element.include?(repetition_delim) && !is_msh_encoding_characters_field + elements[index + 1] = HL7::MessageParser.split_by_delimiter(element, repetition_delim) + end + end elements end @@ -84,7 +92,16 @@ def to_info # output the HL7 spec version of the segment def to_s - @elements.join( @element_delim ) + @elements + .collect do |element| + case element + when Array + element.join(repetition_delim) + else + element + end + end + .join(element_delim) end # at the segment level there is no difference between to_s and to_hl7 @@ -107,10 +124,10 @@ def method_missing( sym, *args, &blk ) end if sym.to_s.include?( "=" ) - write_field( base_sym, args ) + write_field( base_sym, *args ) else if args.length > 0 - write_field( base_sym, args.flatten.select { |arg| arg } ) + write_field( base_sym, *args.flatten.select { |arg| arg } ) else read_field( base_sym ) end @@ -168,8 +185,9 @@ class << self; self end def setup_delimiters(delims) delims = [ delims ].flatten - @element_delim = ( delims.length>0 ) ? delims[0] : "|" - @item_delim = ( delims.length>1 ) ? delims[1] : "^" + @element_delim = ( delims.length > 0 ) ? delims[0] : "|" + @item_delim = ( delims.length > 1 ) ? delims[1] : "^" + @repetition_delim = ( delims.length > 2 ) ? delims[2] : "~" end # DSL element to define a segment's sort weight diff --git a/lib/segment_fields.rb b/lib/segment_fields.rb index f68dc56..68c0404 100644 --- a/lib/segment_fields.rb +++ b/lib/segment_fields.rb @@ -93,7 +93,7 @@ def []( index ) end def []=( index, value ) - @elements[index] = value.to_s + @elements[index] = value end def read_field( name ) #:nodoc: @@ -102,7 +102,6 @@ def read_field( name ) #:nodoc: return nil if (idx >= @elements.length) ret = @elements[ idx ] - ret = ret.first if (ret.kind_of?(Array) && ret.length == 1) ret = field_blk.call( ret ) if field_blk ret end @@ -118,8 +117,7 @@ def write_field( name, value ) #:nodoc: @elements += missing end - value = value.first if (value && value.kind_of?(Array) && value.length == 1) value = field_blk.call( value ) if field_blk - @elements[ idx ] = value.to_s + @elements[ idx ] = value end end diff --git a/lib/segment_generator.rb b/lib/segment_generator.rb index 75a579d..e17a144 100644 --- a/lib/segment_generator.rb +++ b/lib/segment_generator.rb @@ -1,11 +1,12 @@ # Class for grouping the messages delimiter class HL7::Message::Delimiter - attr_accessor :item, :element, :segment + attr_accessor :item, :element, :segment, :repetition - def initialize(element_delim, item_delim, segment_delim) + def initialize(element_delim, item_delim, segment_delim, repetition_delim) @element = element_delim @item = item_delim @segment = segment_delim + @repetition = repetition_delim end end @@ -38,7 +39,7 @@ def valid_segments_parts? def build klass = get_segment_class - new_seg = klass.new( @element, [@delimiter.element, @delimiter.item] ) + new_seg = klass.new( @element, [@delimiter.element, @delimiter.item, @delimiter.repetition] ) new_seg end @@ -52,4 +53,4 @@ def get_segment_class HL7::Message::Segment::Default end end -end \ No newline at end of file +end diff --git a/spec/basic_parsing_spec.rb b/spec/basic_parsing_spec.rb index a6300b3..e355bf1 100644 --- a/spec/basic_parsing_spec.rb +++ b/spec/basic_parsing_spec.rb @@ -75,6 +75,12 @@ expect(msg[:MSH].to_s).to eq @base_msh end + it 'returns an Array for segments with repetitions' do + test_file = open( './test_data/test.hl7' ) + msg = HL7::Message.new( test_file ) + expect(msg[:PID].patient_id_list).to eq(['3131313', '4141414']) + end + it 'inserts segments by index' do msg = HL7::Message.new msg.parse @simple_msh_txt @@ -199,9 +205,9 @@ ntec = HL7::Message::Segment::NTE.new ntec.comment = "third" msg << ntec - expect(ntea.set_id).to eq "1" - expect(nteb.set_id).to eq "2" - expect(ntec.set_id).to eq "3" + expect(ntea.set_id).to eq 1 + expect(nteb.set_id).to eq 2 + expect(ntec.set_id).to eq 3 end it 'parses Enumerable data' do @@ -288,8 +294,8 @@ expect(msg[:OBR].length).to eq 11 expect(msg[:OBX]).not_to be_nil expect(msg[:OBX].length).to eq 102 - expect(msg[:OBR][4].children[1].set_id).to eq "2" - expect(msg[:OBR][5].children[1].set_id).to eq "2" + expect(msg[:OBR][4].children[1].set_id).to eq 2 + expect(msg[:OBR][5].children[1].set_id).to eq 2 final_output = msg.to_hl7 expect(orig_output).not_to eq(final_output) diff --git a/spec/ft1_segment_spec.rb b/spec/ft1_segment_spec.rb index a2b2d81..9477d83 100644 --- a/spec/ft1_segment_spec.rb +++ b/spec/ft1_segment_spec.rb @@ -24,7 +24,7 @@ expect(ft1.transaction_description).to eq 'Description' expect(ft1.transaction_quantity).to eq '1' expect(ft1.assigned_patient_location).to eq '123456^The Location' - expect(ft1.diagnosis_code).to eq 'R45.82^Worries~H18.892^Other specified disorders of cornea' + expect(ft1.diagnosis_code).to eq(['R45.82^Worries', 'H18.892^Other specified disorders of cornea']) expect(ft1.performed_by_provider).to eq '1043312457^Provider^Testing^^^^' expect(ft1.ordering_provider).to eq '1043312457^Provider^Testing^^^^' expect(ft1.procedure_code).to eq '99392^HEART FAILURE COMPOSITE' diff --git a/spec/obr_segment_spec.rb b/spec/obr_segment_spec.rb index 59875de..0a99038 100644 --- a/spec/obr_segment_spec.rb +++ b/spec/obr_segment_spec.rb @@ -19,7 +19,7 @@ it 'allows modification of an OBR segment' do @obr.set_id = 1 - expect(@obr.set_id).to eq "1" + expect(@obr.set_id).to eq 1 @obr.placer_order_number = "^DMCRES" expect(@obr.placer_order_number).to eq "^DMCRES" end diff --git a/spec/segment_field_spec.rb b/spec/segment_field_spec.rb index c793120..71a59c9 100644 --- a/spec/segment_field_spec.rb +++ b/spec/segment_field_spec.rb @@ -33,7 +33,7 @@ class MockSegment < HL7::Message::Segment msg.validating = "good" expect(msg.validating).to eq "good" msg.validating = "bad" - expect(msg.validating).to eq "" + expect(msg.validating).to be_nil msg.converting = "empty" expect(msg.converting).to eq "XXempty" diff --git a/spec/segment_generator_spec.rb b/spec/segment_generator_spec.rb index d5675ed..59c2cb9 100644 --- a/spec/segment_generator_spec.rb +++ b/spec/segment_generator_spec.rb @@ -4,7 +4,7 @@ describe 'valid_segments_parts?' do let(:element){ "MSH|1|2|3" } - let(:delimiter){ HL7::Message::Delimiter.new('|', '^', '\r') } + let(:delimiter){ HL7::Message::Delimiter.new('|', '^', '\r', '~') } let(:segment_generator) do HL7::Message::SegmentGenerator.new(element, nil, delimiter) end diff --git a/spec/segment_spec.rb b/spec/segment_spec.rb index 22dd518..5b18c6b 100644 --- a/spec/segment_spec.rb +++ b/spec/segment_spec.rb @@ -31,8 +31,27 @@ let(:time_now){ DateTime.now } let(:formated_time){ time_now.strftime('%Y%m%d%H%M%S') } - it "should conver to the hl7 time format" do + it "should convert to the hl7 time format" do expect(HL7::Message::Segment.convert_to_ts(time_now)).to eq formated_time end end + + describe 'to_s' do + let(:segment){ HL7::Message::Segment.new "MSA|AR|ZZ9380 ERR" } + + it 'concatenates the elements' do + expect(segment.to_s).to eq("MSA|AR|ZZ9380 ERR") + end + + context 'when an element is an array' do + before do + segment[2] = ['value_1', 'value_2'] + segment[2] << 'value_3' + end + + it 'concatenates the repetition' do + expect(segment.to_s).to eq("MSA|AR|value_1~value_2~value_3") + end + end + end end diff --git a/test_data/test.hl7 b/test_data/test.hl7 index 3bfee7e..c2901d6 100644 --- a/test_data/test.hl7 +++ b/test_data/test.hl7 @@ -1 +1 @@ -MSH|^~\&|LAB1||DESTINATION||19910127105114||ORU^R03|LAB1003929 PID|||3131313||SANDIEGO^CARMEN||| PV1||I| ORC|RE OBR||A485388^OE|H29847^LAB1|BLOOD CULTURE||| OBX||FT|SDES^SOURCE||BLOOD-RAPID|| OBX||FT|EXAM^MICROSCOPIC||GRAM POSITIVE COCCI IN GROUPS|| +MSH|^~\&|LAB1||DESTINATION||19910127105114||ORU^R03|LAB1003929 PID|||3131313~4141414||SANDIEGO^CARMEN||| PV1||I| ORC|RE OBR||A485388^OE|H29847^LAB1|BLOOD CULTURE||| OBX||FT|SDES^SOURCE||BLOOD-RAPID|| OBX||FT|EXAM^MICROSCOPIC||GRAM POSITIVE COCCI IN GROUPS||