[open-ils-commits] r812 - in acq_edi/trunk: lib/edi test (mbklein)

svn at svn.open-ils.org svn at svn.open-ils.org
Wed Mar 3 16:22:58 EST 2010


Author: mbklein
Date: 2010-03-03 16:22:53 -0500 (Wed, 03 Mar 2010)
New Revision: 812

Modified:
   acq_edi/trunk/lib/edi/edi2json.rb
   acq_edi/trunk/lib/edi/mapper.rb
   acq_edi/trunk/test/map_spec.rb
   acq_edi/trunk/test/openils_map_spec.rb
Log:
Fixed round-tripping of JSON<->EDI; slightly changed JSON format again

Modified: acq_edi/trunk/lib/edi/edi2json.rb
===================================================================
--- acq_edi/trunk/lib/edi/edi2json.rb	2010-03-02 21:42:25 UTC (rev 811)
+++ acq_edi/trunk/lib/edi/edi2json.rb	2010-03-03 21:22:53 UTC (rev 812)
@@ -9,22 +9,39 @@
     result = {}
     
     self.each { |child|
+      if self[child.name].length > 1 and result[child.name].nil?
+        result[child.name] = []
+      end
       if child.is_a?(Collection)
+        # Data elements first
         hash = child.to_hash
-        result[child.name] = hash unless hash.empty?
-        unless self.children.empty?
-          segments = []
-          self.children.each { |segment|
-            segments << [segment.name, segment.to_hash]
-          }
-          result[self.sg_name] = segments
+        unless hash.empty?
+          if result[child.name].is_a?(Array)
+            result[child.name] << hash
+          else
+            result[child.name] = hash
+          end
         end
       else
         unless child.value.nil?
-          result[child.name] = child.value
+          if result[child.name].is_a?(Array)
+            result[child.name] << child.value
+          else
+            result[child.name] = child.value
+          end
         end
       end
     }
+    
+    # Segment groups last
+    if self.respond_to?(:children) and (self.children.empty? == false)
+      segments = []
+      self.children.each { |segment|
+        segments << [segment.name, segment.to_hash]
+      }
+      result[self.sg_name] = segments
+    end
+    
     result
   end
   
@@ -40,14 +57,18 @@
     
     messages = []
     self.each { |message|
-      messages << [message.name, message.to_hash]
+      messages << {message.name => message.to_hash}
     }
     
     {
-      'UNA' => self.una.to_s,
-      'header' => [self.header.name, self.header.to_hash],
-      'body' => messages,
-      'trailer' => [self.trailer.name, self.trailer.to_hash]
+      'UNA'            => self.una.to_hash,
+      'sender'         => self.header.cS002.d0004,
+      'sender_qual'    => self.header.cS002.d0007,
+      'recipient'      => self.header.cS003.d0010,
+      'recipient_qual' => self.header.cS003.d0007,
+      'header'         => [self.header.name, self.header.to_hash],
+      'body'           => messages,
+      'trailer'        => [self.trailer.name, self.trailer.to_hash]
     }
   end
   
@@ -57,20 +78,26 @@
   
   def to_hash
     segments = []
-    
+    segments << [self.header.name, self.header.to_hash]
     self.find_all { |segment|
       segment.level < 2
     }.each { |segment| 
       segments << [segment.name, segment.to_hash] 
     }
     segments << [self.trailer.name, self.trailer.to_hash]
-    {
-      'header' => [self.header.name, self.header.to_hash],
-      'body' => segments,
-      'trailer' => [self.trailer.name, self.trailer.to_hash]
-    }
+    segments
   end
   
 end
 
+class E::UNA
+  def to_hash
+    result = {}
+    [:ce_sep,:de_sep,:decimal_sign,:esc_char,:rep_sep,:seg_term].each { |field|
+      result[field.to_s] = self.send(field).chr
+    }
+    result
+  end
+end
+
 end
\ No newline at end of file

Modified: acq_edi/trunk/lib/edi/mapper.rb
===================================================================
--- acq_edi/trunk/lib/edi/mapper.rb	2010-03-02 21:42:25 UTC (rev 811)
+++ acq_edi/trunk/lib/edi/mapper.rb	2010-03-03 21:22:53 UTC (rev 812)
@@ -22,14 +22,14 @@
   class Mapper
     extend Forwardable
     
-    attr :message
+    attr :message, :ic
     attr_accessor :defaults
-    def_delegators :@ic, :charset, :empty?, :groups_created, :header, 
-      :illegal_charset_pattern, :inspect, :is_iedi?, :messages_created, 
-      :output_mode, :output_mode=, :show_una, :show_una=, :syntax, :to_s, 
-      :to_xml, :to_xml_header, :to_xml_trailer, :trailer, :una, :validate, 
-      :version
-    
+#    def_delegators :@ic, :charset, :empty?, :groups_created, :header, 
+#      :illegal_charset_pattern, :inspect, :is_iedi?, :messages_created, 
+#      :output_mode, :output_mode=, :show_una, :show_una=, :syntax, :to_s, 
+#      :to_xml, :to_xml_header, :to_xml_trailer, :trailer, :una, :validate, 
+#      :version
+
     class << self
       def defaults
         @defaults || {}
@@ -106,19 +106,46 @@
         struct['msg_opts'].each_pair { |k,v| json_msg_opts[k.to_sym] = v }
       end
       
-      result = self.new(struct['msg_type'], json_msg_opts, ic_opts.merge(json_opts))
-      result.add(struct['msg'])
+      result = self.new(ic_opts.merge(json_opts))
+      
+      ['header','trailer'].each { |envseg|
+        if struct[envseg]
+          target = result.send(envseg.to_sym)
+          struct[envseg].last.each_pair { |de,val|
+            if val.is_a?(Hash)
+              val.each_pair { |cde,sval|
+                target[de][0][cde][0].value = sval
+              }
+            else
+              target[de][0].value = val
+            end
+          }
+        end
+      }
+      
+      struct['body'].each { |msg_def|
+        msg_def.each_pair { |msg_type, msg_body|
+          if unh = msg_body.find { |s| s[0] == 'UNH' }
+            version_info = unh[1]['S009']
+            json_msg_opts[:resp_agency] = version_info['0051']
+            json_msg_opts[:version] = version_info['0052']
+            json_msg_opts[:release] = version_info['0054']
+          end
+          result.add_message(msg_type, json_msg_opts)
+          result.add(msg_body)
+        }
+      }
       result.finalize
     end
 
-    def initialize(msg_type, msg_opts = {}, ic_opts = {})
+    def initialize(ic_opts = {})
       # Bug in edi4r 0.9 -- sometimes :recipient is used; sometimes :recip. It doesn't
       # work. We'll override it.
       local_ic_opts = ic_opts.reject { |k,v| [:sender,:sender_qual,:recipient,:recipient_qual].include?(k) }
       @ic = EDI::E::Interchange.new(local_ic_opts || {})
   
       # Apply any envelope defaults.
-      ['UNA','UNB','UNZ'].each { |seg|
+      ['UNB','UNZ'].each { |seg|
         seg_defs = self.class.defaults[seg]
         if seg_defs
           seg_defs.each_pair { |cde,defs|
@@ -136,7 +163,9 @@
       @ic.header.cS002.d0007 = ic_opts[:sender_qual] unless ic_opts[:sender_qual].nil?
       @ic.header.cS003.d0010 = ic_opts[:recipient] unless ic_opts[:recipient].nil?
       @ic.header.cS003.d0007 = ic_opts[:recipient_qual] unless ic_opts[:recipient_qual].nil?
-      
+    end
+    
+    def add_message(msg_type, msg_opts = {})
       @message = @ic.new_message( { :msg_type => msg_type, :version => 'D', :release => '96A', :resp_agency => 'UN' }.merge(msg_opts || {}) )
       @ic.add(@message,false)
     end
@@ -166,16 +195,26 @@
       @ic.to_s
     end
     
+    def method_missing(sym, *args)
+      if @ic.respond_to?(sym)
+        @ic.send(sym, *args)
+      else
+        super(sym, *args)
+      end
+    end
+    
     private
     def add_segment(seg_name, value)
       if seg_name =~ /^[A-Z]{3}$/
-        seg = @message.new_segment(seg_name)
-        @message.add(seg)
-        default = self.class.defaults[seg_name]
-        data = default.nil? ? value : default.merge(value)
-        data.each_pair { |de,val|
-          add_element(seg,de,val,default)
-        }
+        if seg_name !~ /^UN[HT]$/
+          seg = @message.new_segment(seg_name)
+          @message.add(seg)
+          default = self.class.defaults[seg_name]
+          data = default.nil? ? value : default.merge(value)
+          data.each_pair { |de,val|
+            add_element(seg,de,val,default)
+          }
+        end
       else
         apply_mapping(seg_name, value)
       end
@@ -184,7 +223,9 @@
     def add_element(parent, de, value, default)
       default = default[de] unless default.nil?
       
-      if value.is_a?(Hash)
+      if de =~ /^SG[0-9]+$/
+        value.each { |v| self.add(*v) }
+      elsif value.is_a?(Hash)
         new_parent = parent.send("c#{de}")
         data = default.nil? ? value : default.merge(value)
         data.each_pair { |k,v| add_element(new_parent,k,v,default) }

Modified: acq_edi/trunk/test/map_spec.rb
===================================================================
--- acq_edi/trunk/test/map_spec.rb	2010-03-02 21:42:25 UTC (rev 811)
+++ acq_edi/trunk/test/map_spec.rb	2010-03-03 21:22:53 UTC (rev 812)
@@ -5,7 +5,8 @@
 describe EDI::E::Mapper do
   
   before(:each) do
-    @map = EDI::E::Mapper.new('ORDERS')
+    @map = EDI::E::Mapper.new
+    @map.add_message('ORDERS')
   end
   
   it "should chunk text" do
@@ -42,7 +43,8 @@
   end
   
   it "should properly fill in interchange envelope defaults" do
-    map = EDI::E::Mapper.new('ORDERS', nil, {:sender => '123456', :recipient => '654321'})
+    map = EDI::E::Mapper.new({:sender => '123456', :recipient => '654321'})
+    map.add_message('ORDERS')
     map.to_s.should =~ /UNA:\+\.\? 'UNB\+UNOB:3\+123456\+654321\+[0-9]{6}:[0-9]{4}\+1'UNH\+1\+ORDERS:D:96A:UN'UNT\+2\+1'UNZ\+1\+1'/
   end
   
@@ -112,7 +114,7 @@
     }
     # Can't compare everything because of timestamping, so we'll just compare
     # the bodies for a high degree of confidence
-    interchange.to_hash['body'].should == [["ORDERS", {"trailer"=>["UNT", {"0074"=>33, "0062"=>"1"}], "body"=>[["BGM", {"C002"=>{"1001"=>"220"}, "1225"=>"9", "1004"=>"2"}], ["DTM", {"C507"=>{"2005"=>"137", "2380"=>"20090331", "2379"=>"102"}}], ["NAD", {"C082"=>{"3039"=>"3472205", "3055"=>"91"}, "SG2"=>[["RFF", {"C506"=>{"1153"=>"API", "1154"=>"3472205 0001"}}]], "3035"=>"BY"}], ["NAD", {"C082"=>{"3039"=>"3472205", "3055"=>"31B"}, "SG2"=>[["RFF", {"C506"=>{"1153"=>"API", "1154"=>"3472205 0001"}}]], "3035"=>"BY"}], ["NAD", {"C082"=>{"3039"=>"1556150", "3055"=>"31B"}, "3035"=>"SU"}], ["NAD", {"C082"=>{"3039"=>"1556150", "3055"=>"91"}, "SG2"=>[["RFF", {"C506"=>{"1153"=>"IA", "1154"=>"1865"}}]], "3035"=>"SU"}], ["CUX", {"C504"=>{"6345"=>"USD", "6347"=>"2", "6343"=>"9"}}], ["LIN", {"SG25"=>[["PIA", {"C212"=>{"7140"=>"03-0010837", "7143"=>"SA"}, "4347"=>"5"}], ["IMD", {"C273"=>{"7008"=>"Discernment"}, "7077"=>"F", "7081"=>"BTI"}], ["IMD", {"C273"=>{"7008"=>"Concord Records,"}, "7077"=>"F", "7081"=>"BPU"}], ["IMD", {"C273"=>{"7008"=>"1986."}, "7077"=>"F", "7081"=>"BPD"}], ["IMD", {"C273"=>{"7008"=>"1 sound disc :"}, "7077"=>"F", "7081"=>"BPH"}], ["QTY", {"C186"=>{"6060"=>2, "6063"=>"21"}}], ["PRI", {"C509"=>{"5125"=>"AAB", "5118"=>35.95}}], ["RFF", {"C506"=>{"1153"=>"LI", "1154"=>"2/1"}}]], "1082"=>1}], ["LIN", {"SG25"=>[["PIA", {"C212"=>{"7140"=>"03-0010840", "7143"=>"SA"}, "4347"=>"5"}], ["IMD", {"C273"=>{"7008"=>"The inner source"}, "7077"=>"F", "7081"=>"BTI"}], ["IMD", {"C273"=>{"7008"=>"Duke, George, 1946-"}, "7077"=>"F", "7081"=>"BAU"}], ["IMD", {"C273"=>{"7008"=>"MPS Records,"}, "7077"=>"F", "7081"=>"BPU"}], ["IMD", {"C273"=>{"7008"=>"1973."}, "7077"=>"F", "7081"=>"BPD"}], ["IMD", {"C273"=>{"7008"=>"2 sound discs :"}, "7077"=>"F", "7081"=>"BPH"}], ["QTY", {"C186"=>{"6060"=>1, "6063"=>"21"}}], ["PRI", {"C509"=>{"5125"=>"AAB", "5118"=>28.95}}], ["RFF", {"C506"=>{"1153"=>"LI", "1154"=>"2/2"}}]], "1082"=>2}], ["UNS", {"0081"=>"S"}], ["CNT", {"C270"=>{"6069"=>"2", "6066"=>2}}], ["UNT", {"0074"=>33, "0062"=>"1"}]], "header"=>["UNH", {"S009"=>{"0052"=>"D", "0065"=>"ORDERS", "0054"=>"96A", "0051"=>"UN"}, "0062"=>"1"}]}]]
+    interchange.to_hash['body'].should == [{"ORDERS"=>[["UNH", {"S009"=>{"0052"=>"D", "0054"=>"96A", "0065"=>"ORDERS", "0051"=>"UN"}, "0062"=>"1"}], ["BGM", {"1225"=>"9", "C002"=>{"1001"=>"220"}, "1004"=>"2"}], ["DTM", {"C507"=>{"2379"=>"102", "2380"=>"20090331", "2005"=>"137"}}], ["NAD", {"C080"=>{"3036"=>[]}, "C058"=>{"3124"=>[]}, "C059"=>{"3042"=>[]}, "C082"=>{"3039"=>"3472205", "3055"=>"91"}, "SG2"=>[["RFF", {"C506"=>{"1153"=>"API", "1154"=>"3472205 0001"}}]], "3035"=>"BY"}], ["NAD", {"C080"=>{"3036"=>[]}, "C058"=>{"3124"=>[]}, "C059"=>{"3042"=>[]}, "C082"=>{"3039"=>"3472205", "3055"=>"31B"}, "SG2"=>[["RFF", {"C506"=>{"1153"=>"API", "1154"=>"3472205 0001"}}]], "3035"=>"BY"}], ["NAD", {"C080"=>{"3036"=>[]}, "C058"=>{"3124"=>[]}, "C059"=>{"3042"=>[]}, "C082"=>{"3039"=>"1556150", "3055"=>"31B"}, "3035"=>"SU"}], ["NAD", {"C080"=>{"3036"=>[]}, "C058"=>{"3124"=>[]}, "C059"=>{"3042"=>[]}, "C082"=>{"3039"=>"1556150", "3055"=>"91"}, "SG2"=>[["RFF", {"C506"=>{"1153"=>"IA", "1154"=>"1865"}}]], "3035"=>"SU"}], ["CUX", {"C504"=>[{"6345"=>"USD", "6347"=>"2", "6343"=>"9"}]}], ["LIN", {"SG25"=>[["PIA", {"C212"=>[{"7140"=>"03-0010837", "7143"=>"SA"}], "4347"=>"5"}], ["IMD", {"C273"=>{"7008"=>["Discernment"]}, "7077"=>"F", "7081"=>"BTI"}], ["IMD", {"C273"=>{"7008"=>["Concord Records,"]}, "7077"=>"F", "7081"=>"BPU"}], ["IMD", {"C273"=>{"7008"=>["1986."]}, "7077"=>"F", "7081"=>"BPD"}], ["IMD", {"C273"=>{"7008"=>["1 sound disc :"]}, "7077"=>"F", "7081"=>"BPH"}], ["QTY", {"C186"=>{"6060"=>2, "6063"=>"21"}}], ["PRI", {"C509"=>{"5125"=>"AAB", "5118"=>35.95}}], ["RFF", {"C506"=>{"1153"=>"LI", "1154"=>"2/1"}}]], "1082"=>1}], ["LIN", {"SG25"=>[["PIA", {"C212"=>[{"7140"=>"03-0010840", "7143"=>"SA"}], "4347"=>"5"}], ["IMD", {"C273"=>{"7008"=>["The inner source"]}, "7077"=>"F", "7081"=>"BTI"}], ["IMD", {"C273"=>{"7008"=>["Duke, George, 1946-"]}, "7077"=>"F", "7081"=>"BAU"}], ["IMD", {"C273"=>{"7008"=>["MPS Records,"]}, "7077"=>"F", "7081"=>"BPU"}], ["IMD", {"C273"=>{"7008"=>["1973."]}, "7077"=>"F", "7081"=>"BPD"}], ["IMD", {"C273"=>{"7008"=>["2 sound discs :"]}, "7077"=>"F", "7081"=>"BPH"}], ["QTY", {"C186"=>{"6060"=>1, "6063"=>"21"}}], ["PRI", {"C509"=>{"5125"=>"AAB", "5118"=>28.95}}], ["RFF", {"C506"=>{"1153"=>"LI", "1154"=>"2/2"}}]], "1082"=>2}], ["UNS", {"0081"=>"S"}], ["CNT", {"C270"=>{"6069"=>"2", "6066"=>2}}], ["UNT", {"0074"=>33, "0062"=>"1"}]]}]
   end
 
 end
\ No newline at end of file

Modified: acq_edi/trunk/test/openils_map_spec.rb
===================================================================
--- acq_edi/trunk/test/openils_map_spec.rb	2010-03-02 21:42:25 UTC (rev 811)
+++ acq_edi/trunk/test/openils_map_spec.rb	2010-03-03 21:22:53 UTC (rev 812)
@@ -3,7 +3,8 @@
 describe OpenILS::Mapper do
   
   before(:each) do
-    @map = OpenILS::Mapper.new('ORDERS')
+    @map = OpenILS::Mapper.new
+    @map.add_message('ORDERS')
   end
   
   it "should add both qualified and unqualified buyer/vendor fields" do
@@ -32,7 +33,7 @@
 
   it "should create a message from high-level JEDI input" do
     json = File.read(File.join(File.dirname(__FILE__), 'test_po.json'))
-    @map = OpenILS::Mapper.from_json(%{{ "msg_type": "ORDERS", "msg": #{json}, "sender": "123456", "recipient": {"id": "999999999", "id-qualifier": "1"}}})
+    @map = OpenILS::Mapper.from_json(%{{ "body": [{ "ORDERS": #{json}}], "sender": "123456", "recipient": {"id": "999999999", "id-qualifier": "1"}}})
     @map.message.to_s.should == "UNH+1+ORDERS:D:96A:UN'BGM+220+2+9'DTM+137:20090331:102'NAD+BY+3472205::91'RFF+API:3472205 0001'NAD+BY+3472205::31B'RFF+API:3472205 0001'NAD+SU+1556150::31B'NAD+SU+1556150::91'RFF+IA:1865'CUX+2:USD:9'LIN+1'PIA+5+03-0010837:SA'IMD+F+BTI+:::Discernment'IMD+F+BPU+:::Concord Records,'IMD+F+BPD+:::1986.'IMD+F+BPH+:::1 sound disc ?:'QTY+21:2'PRI+AAB:35.95'RFF+LI:2/1'LIN+2'PIA+5+03-0010840:SA'IMD+F+BTI+:::The inner source'IMD+F+BAU+:::Duke, George, 1946-'IMD+F+BPU+:::MPS Records,'IMD+F+BPD+:::1973.'IMD+F+BPH+:::2 sound discs ?:'QTY+21:1'PRI+AAB:28.95'RFF+LI:2/2'UNS+S'CNT+2:2'UNT+33+1'"
     @map.header.cS002.to_s.should == "123456:31B"
     @map.header.cS003.to_s.should == "999999999:1"



More information about the open-ils-commits mailing list