irobayna/stupidedi

View on GitHub
notes/builder

Summary

Maintainability
Test Coverage

  Appending to Syntax Tree
    b = Stupidedi::Builder::BuilderDsl.new

    b.ISA("00", b.blank,
          "01", "SECRET",
          "ZZ", "SUBMITTERS ID",
          "ZZ", "RECEIVERS ID",
          Date.current, Time.current,
          "U", "00401",
          "000000905", "1", "T", b.default)

    b.GS("HC",
         "SENDER CODE",
         "RECEIVER CODE",
         Date.current, Time.current,
         b.default,
         "X", "004010X098")

    b.ST("837", b.default).
      BHT("0019", "00", "0123", Date.current, Time.current, "CH").
      NM1("41", "2", "CRAMMER, DOLE, PALMER, AND JOHANSON",
          b.blank, b.blank, b.blank, b.blank, "46", "W7933THU").
       N2("N ASSOCIATES, INC").
      PER("IC", "JANE DOE", "TE", "9005555555")

    ...

    b.CLM("A37YH556", 500, b.blank, b.blank,
          b.composite(11, b.blank, 1),
          "Y", "A", "Y", "Y", "C")

    # Unlike the TokenReader, Ruby evaluates the elements before evaluating
    # the segment. That means we can't really validate the correctness of
    # each element as the value is constructed -- we have to do it in the
    # method that builds segments.

    ...

    b.IEA(b.default, b.default)

  Shorthand
    # These methods could be implemented to capture the caller's stack trace,
    # but we probably don't need very fine granularity. Knowing the location
    # that generated the segment would suffice, and any element-level errors
    # can be noted with the element descriptor: CLM05-02

    b.composite
    b.repeated
    b.blank
    b.default
      # Proxy/Thunk
      #   x = b.default
      #   x.class   #=> DefaultVal
      #   ...
      #   x.force!
      #   x.to_s    #=> "ABCDEF"
      #   x.class   #=> StringVal

  Current State
    b.current.interchange       #=> InterchangeVal
    b.current.functional_group  #=> FunctionalGroupVal
    b.current.transaction_set   #=> TransactionSetVal
    b.current.table             #=> TableVal
    b.current.loop              #=> LoopVal
    b.current.segment           #=> SegmentVal

    b.current.position #=> interchange no
                       #   functional group no
                       #   transaction set no
                       #   segment no

  Syntax Tree Iteration
    o.interchanges
    o.functional_groups
    o.transaction_sets
    o.tables
    o.loops
    o.segments

  Reader Interface
    # This operation might only make sense as a way to create a new interchange,
    # not so much as a way to concatenate a blob of X12 into the middle of some
    # half-generated document. The main concern is if {input} doesn't start with
    # an ISA segment, we need to tell the tokenizer about separators.
    b.read(input)

# Right now, StreamReader can read ISA and construct a TokenReader, but it
# does/should not need to know about InterchangeConfig etc to create the
# dictionary that TokenReader needs. The dictionary would include all of the
# ISA, ISB, ISE, IEA, TA1 etc SegmentDefs, plus the GS segment's definition.
#
# When Builder gets an ISA SegmentTok, it should construct the correct version
# of the InterchangeVal and ask it for the segment dictionary. Then it should
# copy/update the TokenReader with the interchange version-specific dictionary
#
# When Builder gets a GS SegmentTok, it should construct the correct version of
# FunctionalGroupVal and ask it for the segment dictionary, which it will merge
# with the InterchangeVal's dictionary. The current TokenReader will be updated
# with the merged dictionary.
#
# When Builder closes a FunctionalGroupVal, eg after reading an interchange
# segment, it should once again update TokenReader with the *unmerged* segment
# dictionary, in preperation for the next functional group.

  Writer Interface
    o.used_chars #=> "ABC...abc...123"
    o.write(delimiters, settings)

  Writers
    X12
    XML
    Annotated HTML
    Annotated Text

  Error Handling
    b.xxx
    o.errors    #=> [Error("Invalid segment 'XXX'",
                            severity,
                            SegmentVal[XXX](..),
                            ["test.rb:30", ...]),

                     Error("Invalid segment 'XXX'",
                            severity,
                            Failure)]
      interchange.errors
      functional_group.errors
      transaction_set.errors
      table.errors
      loop.errors
      segment.errors
      element.errors

    interchange.generate_interchange_acknowledgment
    functional_group.generate_functional_acknowledgment
    functional_group.generate_implementation_acknowledgment