class EDI::A::Interchange
Interchange: Class of the top-level objects of ANSI X12 data
Attributes
Public Class Methods
Create an empty ANSI X.12 interchange
Supported parameters (passed hash-style):¶ ↑
Essentials, should not be changed later¶ ↑
- :charset
-
Not applicable, do not use. Default = ‘UNOB’
- :version
-
Sets I11 (ISA12), default = ‘00401’
Optional parameters affecting to_s
, with corresponding setters¶ ↑
- :output_mode
-
See setter output_mode=(), default = :verbatim
- :ce_sep
-
Component element separator, default = ?\
- :de_sep
-
Data element separator, default = ?*
- :rep_sep
-
Repetition element separator, default = ?^ (version 5)
- :seg_term
-
Segment
terminator, default = ?~
Optional ISA presets for your convenience, may be changed later¶ ↑
- :sender
-
Presets
DE
I07, default = nil - :recipient
-
Presets
DE
I09, default = nil - :interchange_control_reference
-
Presets
DE
I12, default = ‘1’ - :interchange_control_standards_id
-
Presets
DE
I10, default = ‘U’ - :acknowledgment_request
-
Presets
DE
I13, default = 0 - :test_indicator
-
Presets
DE
I14, default = ‘P’
Notes¶ ↑
-
Date (I08) and time (I09) are set to the current values automatically.
-
Add or change any data element later.
Examples:¶ ↑
-
ic =
EDI::A::Interchange.new
# Empty interchange, default settings -
ic =
EDI::A::Interchange.new
(:output_mode=> :linebreak)
EDI::Interchange::new
# File lib/edi4r/ansi_x12.rb, line 95 def initialize( user_par={} ) super( user_par ) # just in case... if (illegal_keys = user_par.keys - @@interchange_default_keys) != [] msg = "Illegal parameter(s) found: #{illegal_keys.join(', ')}\n" msg += "Valid param keys (symbols): #{@@interchange_default_keys.join(', ')}" raise ArgumentError, msg end par = @@interchange_defaults.merge( user_par ) @groups_created = 0 @syntax = 'A' # par[:syntax] # A = ANSI X12 @charset = par[:charset] # FIXME: Outdated? @version = par[:version] @ce_sep = par[:ce_sep] @re_ce_sep = Regexp.new( Regexp.escape( @ce_sep.chr ) ) @de_sep = par[:de_sep] @re_de_sep = Regexp.new( Regexp.escape( @de_sep.chr ) ) @rep_sep = par[:rep_sep] @seg_term = par[:seg_term] self.output_mode = par[:output_mode] check_consistencies init_ndb( @version ) @header = new_segment('ISA') @trailer = new_segment('IEA') #@header.cS001.d0001 = par[:charset] @header.dI06 = par[:sender] unless par[:sender].nil? @header.dI07 = par[:recipient] unless par[:recip].nil? @header.dI10 = par[:interchange_control_standards_id] @header.dI11 = par[:version] @header.dI12 = par[:interchange_control_reference] @header.dI13 = par[:acknowledgment_request] @header.dI14 = par[:test_indicator] @header.dI15 = @ce_sep t = Time.now @header.dI08 = t.strftime('%y%m%d') @header.dI09 = t.strftime('%H%M') @trailer.dI16 = 0 end
Reads EDI
data from given stream (default: $stdin), parses it and returns an Interchange
object
# File lib/edi4r/ansi_x12.rb, line 148 def Interchange.parse( hnd=$stdin, auto_validate=true ) builder = StreamingBuilder.new( auto_validate ) builder.go( hnd ) builder.interchange end
Returns a REXML document that represents the interchange
- xdoc
-
REXML document that contains the XML representation of a ANSI X12 interchange
# File lib/edi4r/ansi_x12-rexml.rb, line 29 def Interchange.parse_xml( xdoc ) _root = xdoc.root _header = _root.elements["Header"] _trailer = _root.elements["Trailer"] _version = _root.attributes["version"] _ce_sep = REXML::XPath.first(xdoc, "/Interchange/Header/Segment/DE[@name='I15']").text.to_i params = { :ce_sep => _ce_sep, :version => _version } ic = Interchange.new( params ) if _root.elements["Message"].nil? # correct ?? _root.elements.each('MsgGroup') do |xel| ic.add( MsgGroup.parse_xml( ic, xel ), false ) end else _root.elements.each('Message') do |xel| ic.add( Message.parse_xml( ic, xel ), false ) end end ic.header = Segment.parse_xml( ic, _header.elements["Segment"] ) ic.header.dI15 = _ce_sep ic.trailer = Segment.parse_xml( ic, _trailer.elements["Segment"] ) ic.validate ic end
Read maxlen
bytes from $stdin (default) or from given stream (ANSI data expected), and peek into first segment (ISA).
Returns an empty Interchange
object with a properly header filled.
Intended use:
Efficient routing by reading just ISA data: sender/recipient/ref/test
# File lib/edi4r/ansi_x12.rb, line 163 def Interchange.peek(hnd=$stdin, params={}) # Handle to input stream builder = StreamingBuilder.new( false ) if params[:deep_peek] def builder.on_segment( s, tag ) end else def builder.on_gs( s ) throw :done end def builder.on_st( s, tag ) throw :done # FIXME: Redundant, since GS must occur? end end builder.go( hnd ) builder.interchange end
Read maxlen
bytes from $stdin (default) or from given stream (ANSI X12 data expected), and peek into first segment (ISA).
Returns an empty Interchange
object with a properly header filled.
Intended use:
Efficient routing by reading just ISA data: sender/recipient/ref/test
# File lib/edi4r/ansi_x12-rexml.rb, line 63 def Interchange.peek_xml(xdoc) # Handle to REXML document _root = xdoc.root _header = _root.elements["Header"] _trailer = _root.elements["Trailer"] _version = _root.attributes["version"] _ce_sep = REXML::XPath.first(xdoc, "/Interchange/Header/Segment/DE[@name='I15']").text.to_i params = { :ce_sep => _ce_sep, :version => _version } ic = Interchange.new( params ) ic.header = Segment.parse_xml( ic, _header.elements["Segment"] ) ic.header.dI15 = _ce_sep ic.trailer = Segment.parse_xml( ic, _trailer.elements["Segment"] ) ic end
Public Instance Methods
Add a MsgGroup
(Functional Group) object to the interchange.
GE counter is automatically incremented.
EDI::Interchange#add
# File lib/edi4r/ansi_x12.rb, line 215 def add( obj, auto_validate=true ) super @trailer.dI16 += 1 #if @trailer # FIXME: Warn/fail if ST id is not unique (at validation?) end
Yields a readable, properly indented list of all contained objects, including the empty ones. This may be a very long string!
EDI::Collection#inspect
# File lib/edi4r/ansi_x12.rb, line 270 def inspect( indent='', symlist=[] ) # symlist << :una super end
Derive an empty message group from this interchange context. Parameters may be passed hash-like. See MsgGroup.new
for details
# File lib/edi4r/ansi_x12.rb, line 225 def new_msggroup(params={}) # to be completed ... @groups_created += 1 MsgGroup.new(self, params) end
This method modifies the behaviour of method to_s
(): ANSI X12 interchanges and their components are turned into strings either “verbatim” (default) or in some more readable way. This method corresponds to a parameter with the same name that may be set at creation time.
Valid values:
- :linebreak
-
One-segment-per-line representation
- :indented
-
Like :linebreak but with additional indentation (2 blanks per hierarchy level).
- :verbatim
-
No linebreak (default), ISO compliant
# File lib/edi4r/ansi_x12.rb, line 194 def output_mode=( value ) super( value ) @e_linebreak = @e_indent = '' case value when :verbatim # NOP (default) when :linebreak @e_linebreak = "\n" when :indented @e_linebreak = "\n" @e_indent = ' ' else raise "Unknown output mode '#{value}'. Supported modes: :linebreak, :indented, :verbatim (default)" end end
Returns the string representation of the interchange.
Type conversion and escaping are provided. See output_mode
for modifiers.
EDI::Collection_HT#to_s
# File lib/edi4r/ansi_x12.rb, line 260 def to_s s = '' postfix = '' << seg_term << @e_linebreak s << super( postfix ) end
Returns a REXML document that represents the interchange
EDI::Interchange#to_xml
# File lib/edi4r/ansi_x12-rexml.rb, line 82 def to_xml( xdoc = REXML::Document.new ) rc = super # Add parameter(s) to header in rc[1] # rc xdoc end
Returns the number of warnings found and logs them
EDI::Collection_HT#validate
# File lib/edi4r/ansi_x12.rb, line 278 def validate( err_count=0 ) if (h=self.size) != (t=@trailer.dI16) EDI::logger.warn "Counter IEA, DE I16 does not match content: #{t} vs. #{h}" EDI::logger.warn "classes: #{t.class} vs. #{h.class}" err_count += 1 end #if (h=@header.cS001.d0001) != @charset # warn "Charset UNZ/UIZ, S001/0001 mismatch: #{h} vs. #@charset" # err_count += 1 #end if (h=@header.dI11) != @version EDI::logger.warn "Syntax version number ISA, ISA12 mismatch: #{h} vs. #@version" err_count += 1 end check_consistencies if (t=@trailer.dI12) != (h=@header.dI12) EDI::logger.warn "ISA/IEA mismatch in refno (I12): #{h} vs. #{t}" err_count += 1 end # FIXME: Check if messages/groups are uniquely numbered super end
Private Instance Methods
Private method: Check if basic UNB elements are set properly
# File lib/edi4r/ansi_x12.rb, line 317 def check_consistencies # FIXME - @syntax should be completely avoided, use sub-module name if not ['A'].include?(@syntax) # More anticipated here raise "#{@syntax} - syntax not supported!" end =begin case @version when 1 if @charset != 'UNOA' raise "Syntax version 1 permits only charset UNOA!" end when 2 if not @charset =~ /UNO[AB]/ raise "Syntax version 2 permits only charsets UNOA, UNOB!" end when 3 if not @charset =~ /UNO[A-F]/ raise "Syntax version 3 permits only charsets UNOA...UNOF!" end when 4 # A,B: ISO 646 subsets, C-K: ISO-8859-x, X: ISO 2022, Y: ISO 10646-1 if not @charset =~ /UNO[A-KXY]/ raise "Syntax version 4 permits only charsets UNOA...UNOZ!" end else raise "#{@version} - no such syntax version!" end =end @illegal_charset_pattern = Illegal_Charset_Patterns['@version'] # Add more rules ... end
Private method: Loads EDI
norm database
# File lib/edi4r/ansi_x12.rb, line 309 def init_ndb(d0002, d0076 = nil) @basedata = EDI::Dir::Directory.create(root.syntax, :ISA12 => @version ) end