Class: EDI::Diagram::NodeInstance

Inherits:
Object
  • Object
show all
Defined in:
lib/edi4r/diagrams.rb

Overview

NodeInstance

A given segment of a real message instance needs an instance counter in addition to its location in the diagram. This applies recursively to all segment groups in which it is embedded. This class is equipped with the additional attributes (“co-ordinates”) of node instances.

We also use this class to determine the node instance of a segment when parsing a message. This is done in a sequential manner, starting from the current instance, by following the diagram branches up to the next matching segment tag/name.

Instance Method Summary collapse

Constructor Details

#initialize(diag) ⇒ NodeInstance

A new NodeInstance is inititialized to a “virtual” 0th node before the first real node of the diagramm referenced by diag .



461
462
463
464
465
466
467
468
# File 'lib/edi4r/diagrams.rb', line 461

def initialize( diag )
  @diag = diag # Really needed later?
  
  # Init. to first segment of top branch, e.g. "UNH" or "EDI_DC40"
  @coord = NodeCoords.new(diag.branch, 0, 0)
  @coord_stack = []
  @down_flag = false
end

Instance Method Details

#indexObject



491
# File 'lib/edi4r/diagrams.rb', line 491

def index;  node.index;  end

#inst_cntObject Also known as: rep

Returns the node’s instance counter



472
473
474
# File 'lib/edi4r/diagrams.rb', line 472

def inst_cnt
  @coord.inst_cnt
end

#is_tnode?Boolean

true if this is a TNode (trigger node/segment)

Returns:

  • (Boolean)


513
514
515
# File 'lib/edi4r/diagrams.rb', line 513

def is_tnode?
  node.is_a? TNode
end

#levelObject

Returns this node instance’s level in the diagram. Note that special UN/EDIFACT rules about level 0 are acknowledged: level == 0 for mandatory SNode instances of the main branch with maxrep==1.



496
497
498
499
500
# File 'lib/edi4r/diagrams.rb', line 496

def level
  depth = @coord_stack.length+1
  return 0 if depth == 1 and node.maxrep == 1 and node.required? and not is_tnode? # Special Level 0 case
  depth # Else: Level is depth of segment group stack + 1 (1 if no SG)
end

#maxrepObject



490
# File 'lib/edi4r/diagrams.rb', line 490

def maxrep; node.maxrep; end

#nameObject

Delegate some getters to the underlying diagram node:

index, maxrep, name, status


488
# File 'lib/edi4r/diagrams.rb', line 488

def name;   node.name;   end

#nodeObject

Returns diagram node corresponding to this instance’s co-ordinates



481
482
483
# File 'lib/edi4r/diagrams.rb', line 481

def node
  @coord.branch[@coord.offset]
end

#seek!(seg) ⇒ Object

Main “workhorse”: Seek for next matching segment tag/name

Starts at current location, follows the diagram downstream while searching for next matching segment.

Returns updated location (self) when found, nil otherwise.

Notes:

  1. Search fails when trying to skip a required node

  2. Search fails if we hit the end of the diagram before a match

  3. We might need to loop through segment groups repeatedly!



530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
# File 'lib/edi4r/diagrams.rb', line 530

def seek!(seg) # Segment, Regexp or String expected
  name = (seg.is_a? EDI::Segment) ? seg.name : seg
  #    name = (seg.is_a? String) ? seg : seg.name
  begin
    node = self.node
    # warn "Looking for #{name} in #{self.name} @ level #{self.level} while node.maxrep=#{node.maxrep}..."
    #
    # Case "match"
    #
    if node.nil?
      warn "#{name}: #{@coord.offset} #{@coord.branch.sg_name} #{@coord.branch.desc} #{@coord.branch.size}"
      raise "#{self}: no node!"
    end
    if name === node.name # == name
      #        puts "match!"
      @coord.inst_cnt += 1
      msg = "Segment #{name} at #{@coord.to_s}: More than #{node.maxrep}!"
      if @coord.inst_cnt > node.maxrep
        raise EDI::EDILookupError, msg
      else
        @down_flag = true if node.is_a? TNode
        return self# .node
      end
    end
    #
    # Missed a required node?
    #
    if node.required? and @coord.inst_cnt == 0 # @unmatched
      msg = "Missing required segment #{node.name} at #{@coord.to_s}\n" + \
      " while looking for segment #{name}!"
      raise EDI::EDILookupError, msg
    end
    #      puts
  end while self.next!
  # Already at top level - Error condition!
  raise "End of diagram exceeded!"
end

#sg_nameObject

Returns the branch name (segment group name)



504
505
506
507
508
509
510
# File 'lib/edi4r/diagrams.rb', line 504

def sg_name
  #    (node.is_a? TNode) ? node.sg_name : nil
  if node.is_a? TNode
    return node.sg_name
  end
  @coord.branch.sg_name
end

#statusObject



489
# File 'lib/edi4r/diagrams.rb', line 489

def status; node.status; end