class EDI::Dir::Directory
A
Directory
object is currently a set of hashes representing all the entries for data elements, composites, segments, and messages.
Public Class Methods
Tells if caching is currently activated (returns a boolean)
# File lib/edi4r/standards.rb, line 125 def Directory.caching? @@caching end
As long as we employ plain CSV files to store directories, a Directory
can become quite memory-consuming. Therefore Directorys are cached after creation, so that they need to be created and maintained only once when there are several messages of the same type in an interchange.
Turns off this caching mechanism, saving memory but costing time.
# File lib/edi4r/standards.rb, line 113 def Directory.caching_off @@caching = false end
Turns on caching (default setting), saving time but costing memory.
# File lib/edi4r/standards.rb, line 119 def Directory.caching_on @@caching = true end
Creates (and caches) a new directory. Returns reference to existing directory when already in cache.
- std
-
The syntax standard key. Currently supported:
-
‘A’ (ANSI X12),
-
‘E’ (EDIFACT),
-
‘I’ (SAP IDOC)
-
‘S’ (SEDAS)
-
- params
-
A
hash of parameters that uniquely identify the selected dir. Hash parameters use following alternative key sets: - ISO9735
-
:d0002, :d0076 (default: “”, nil)
- UN/TDID
-
:d0065, :d0052, :d0054, :d0051, :d0057; :is_iedi
- SAP IDOC
-
:IDOCTYPE, :SAPTYPE, :EXTENSION (see EDI_DC fields)
- SEDAS
-
(none so far)
UN/TDID: Elements of S009 or S320 are used:
- d0065
-
Message
type like “INVOIC” - d0052
-
Message
version number, like “90” or “D” - d0054
-
Message
release number, like “1” or “03A” - d0051
-
Controlling agency, like “UN” or “EN”
- d0057
-
Association assigned code (optional), like “EAN008”
Interactive EDI
(only limited supported so far):
- is_iedi
-
Flag,
true
orfalse
. Assumedfalse
if missing.
# File lib/edi4r/standards.rb, line 163 def Directory.create( std, params={} ) case std when 'A' # ANSI X12 # par = { :ISA12 => '00401', :is_iedi => false }.update( params ) par = { }.update( params ) when 'E' # UN/EDIFACT par = {:d0051 => '', :d0057 => '', :is_iedi => false }.update( params ) when 'I' # SAP IDocs par = { }.update( params ) when 'S' # SEDAS par = { }.update( params ) else raise "Unsupported syntax standard: #{std}" end if Directory.caching? # Use param set as key for caching # key = par.sort {|a,b| a.to_s <=> b.to_s}.hash obj = @@cache[key] # warn "Looking up #{par.inspect} with key=#{key}" return obj unless obj.nil? obj = new( std, par ) # warn "Caching for #{par.inspect} with key=#{key}" @@cache[key] = obj # cache & return it else new( std, par ) end end
Releases memory by flushing the cache. Needed primarily for unit tests, where many if not all available diagrams are created.
# File lib/edi4r/standards.rb, line 132 def Directory.flush_cache @@cache = {} end
Helper method: Determine path of requested csv file
Will be generalized to a lookup scheme!
# File lib/edi4r/standards.rb, line 320 def Directory.path_finder( prefix, ext, selector ) # # Subset requested: # Try subset first, warn & fall back on standard before giving up # if prefix.is_a? Array raise "Only subset and regular prefix expected" if prefix.size != 2 begin Directory.path_finder( prefix[0], ext, selector ) rescue EDILookupError # warn "Subset data not found - falling back on standard" # $stderr.puts prefix.inspect, ext.inspect, selector.inspect Directory.path_finder( prefix[1], ext, selector ) end else filename = prefix + selector + '.' + ext searchpath = ENV['EDI_NDB_PATH'] searchpath.split(/#{File::PATH_SEPARATOR}/).each do |datadir| path = datadir + filename # warn "Looking for #{path}" return path if File.readable? path end raise EDILookupError, "No readable file '." + filename + "' found below any dir on '" + searchpath + "'" end end
Helper method: Derive path fragments of CSV files from parameters
# File lib/edi4r/standards.rb, line 202 def Directory.prefix_ext_finder( std, par ) ext = '' case std when 'I' # SAP IDocs prefix = '/sap' if par[:IDOCTYPE] prefix += '/idocs'+par[:SAPTYPE]+'/'+par[:IDOCTYPE]+'/' if par[:EXTENSION].is_a? String and not par[:EXTENSION].empty? if par[:EXTENSION] =~ /\/(.*\/)([^\/]+)/ prefix += $1 + 'ED' ext = $2 + '.csv' else prefix += 'ED' ext = par[:EXTENSION] + '.csv' end else prefix += 'ED' ext = '.csv' end else case par[:SAPTYPE] when '40'; ext = '04000' else ; raise "Unsupported SAP Type: #{par[:SAPTYPE]}" end prefix += '/controls/SD' ext += '.csv' end when 'E' # UN/EDIFACT prefix, subset_prefix = '/edifact', nil if par[:d0002] # ISO9735 requested? case par[:d0002] when 1 ext = '10000' when 2 ext = '20000' when 3 ext = '30000' when 4 # Assume that any setting of d0076 implies SV 4-1 # Revise when SV 4-2 arrives! ext = (par[:d0076] == nil) ? '40000' : '40100' else raise "Invalid syntax version: #{par[:d0002]}" end prefix += '/iso9735/SD' ext += '.csv' # Service messages? (AUTACK, CONTRL, KEYMAN): 2/2, D/3, 4/1 ok elsif %w/2 D 4/.include?(par[:d0052]) && %w/2 3 1/.include?(par[:d0054]) if par[:d0052] == '2' && par[:d0054] == '2' ext = '20000' elsif par[:d0052] == 'D' && par[:d0054] == '3' ext = '30000' elsif par[:d0052] == '4' && par[:d0054] == '1' ext = (par[:d0076] == nil) ? '40000' : '40100' else raise "Invalid syntax version: #{par[:d0002]}" end prefix += '/iso9735/SD' ext += '.csv' else # UN/TDID requested? prefix += par[:is_iedi] ? '/untdid/ID' : '/untdid/ED' ext = (par[:d0052].to_s+par[:d0054].to_s).downcase + '.csv' case par[:d0057] when /EAN\d\d\d/, /EDIT\d\d/ subset_prefix = '/edifact/eancom/ED' when '', nil else # raise "Subset not supported: #{par[:d0057]}" EDI::logger.warn "Subset not supported: #{par[:d0057]}" end end when 'S' # SEDAS prefix, subset_prefix, ext = '/sedas/ED', nil, '.csv' when 'A' # ANSI X12 prefix, subset_prefix = '/ansi', nil if par[:ISA12] # control segments requested? msg = "Syntax version not supported: #{par[:ISA12]}" case par[:ISA12] when /00[1-5]0\d/ # , '00401', '00501' etc. EDI::logger.warn msg if par[:ISA12] !~ /^00[45]01$/ ext = par[:ISA12] else raise msg end prefix += '/x12/SD' ext += '.csv' else # Standards directory requested? prefix += '/dir/ED' ext = par[:GS08][0,6] + '.csv' # Subset not supported case par[:GS08][6..-1] when 'X098', 'X098A1', 'X096A1', 'X093', 'X092', 'X091A1', 'X222A1', 'X223A2', /^X2\d\d(A[12])?/ # Conceivable support of a major subset (like HIPAA) # subset_prefix = '/ansi/hipaa/ED' when '', nil else raise "Subset not supported: <<#{par[:GS08][6..-1]}>>" end end else raise "Unsupported syntax standard: #{std}" end return prefix, subset_prefix, ext end
Public Instance Methods
Returns CSV line for CDE
called name
.
# File lib/edi4r/standards.rb, line 446 def cde( name ) @cde_dir[name] end
Returns a sorted list of names of available CDE
# File lib/edi4r/standards.rb, line 452 def cde_names @cde_dir.keys.sort end
Returns CSV line for DE
called name
. If name
is a Regexp, returns the first match or nil
.
# File lib/edi4r/standards.rb, line 429 def de( name ) if name.is_a? Regexp @de_dir[ @de_dir.keys.find {|key| key =~ name} ] else @de_dir[name] end end
Returns a sorted list of names of available DE
# File lib/edi4r/standards.rb, line 439 def de_names @de_dir.keys.sort end
Iterates over each branch (message), composite, data element, or segment found (hence: BCDS) that is matched by id
.
id
is a string. The object type requested by this string is not obvious. This method determines it through a naming convention. See source for details.
Fails with EDI::EDILookupError
when nothing found.
# File lib/edi4r/standards.rb, line 506 def each_BCDS( id, &b ) list = nil case id when /^[CES]\d{3}$/ # C)omposite list = cde(id) when /^\d{4}$/ # Simple D)E list = de(id) when /^[A-Z]{3}$/ # S)egment list = segment(id) when /^[A-Z]{6}:$/ # Message B)ranch list = message(id) # Workaround for the IDoc case: # We identify entry type by a (intermediate) prefix # when /^d(.*)$/ # Simple D)E list = de($1) when /^s(.*)$/ # S)egment, SAP IDOC list = segment($1) when /^m(.*)$/ # Message B)ranch list = message($1) else # Should never occur raise IndexError, "Not a legal BCDS entry id: '#{id}'" end raise EDILookupError, "#{id} not in directory!" if list.nil? list.each( &b ) end
Returns CSV line of top branch for message called name
.
# File lib/edi4r/standards.rb, line 477 def message( name ) # Actually, only one branch! # p name # p @msg_dir# [name] rc = @msg_dir[name] return rc unless rc.nil? # Try without subset if nil: # ex.: CONTRL:D:3:UN:1.3c:SG1, CONTRL:D:3:UN:: return nil unless name =~ /(.*:)([^:]{1,6})(:[^:]*)/ EDI::logger.warn "Subset not supported: #$2 - falling back on standard}" if $3==':' # warn only at top branch # $stderr.puts "Using fallback name: #{$1+$3}" @msg_dir[$1+$3] end
Returns a sorted list of names of available messages
# File lib/edi4r/standards.rb, line 492 def message_names @msg_dir.keys.sort end
Returns CSV line for segment called name
. If name
is a Regexp, returns the first match or nil
.
# File lib/edi4r/standards.rb, line 460 def segment( name ) if name.is_a? Regexp @seg_dir[ @seg_dir.keys.find {|key| key =~ name} ] else @seg_dir[name] end end
Returns a sorted list of names of available segments
# File lib/edi4r/standards.rb, line 470 def segment_names @seg_dir.keys.sort end