X12 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. data/CHANGELOG +13 -0
  2. data/COPYING +502 -0
  3. data/README +309 -0
  4. data/Rakefile +157 -0
  5. data/TODO +6 -0
  6. data/doc/classes/X12.html +174 -0
  7. data/doc/classes/X12/Base.html +677 -0
  8. data/doc/classes/X12/Composite.html +156 -0
  9. data/doc/classes/X12/Empty.html +186 -0
  10. data/doc/classes/X12/Field.html +339 -0
  11. data/doc/classes/X12/Loop.html +202 -0
  12. data/doc/classes/X12/Parser.html +306 -0
  13. data/doc/classes/X12/Segment.html +277 -0
  14. data/doc/classes/X12/Table.html +198 -0
  15. data/doc/created.rid +1 -0
  16. data/doc/files/CHANGELOG.html +108 -0
  17. data/doc/files/README.html +474 -0
  18. data/doc/files/TODO.html +95 -0
  19. data/doc/files/lib/X12/Base_rb.html +83 -0
  20. data/doc/files/lib/X12/Composite_rb.html +83 -0
  21. data/doc/files/lib/X12/Empty_rb.html +83 -0
  22. data/doc/files/lib/X12/Field_rb.html +83 -0
  23. data/doc/files/lib/X12/Loop_rb.html +83 -0
  24. data/doc/files/lib/X12/Parser_rb.html +83 -0
  25. data/doc/files/lib/X12/Segment_rb.html +83 -0
  26. data/doc/files/lib/X12/Table_rb.html +83 -0
  27. data/doc/files/lib/X12_rb.html +100 -0
  28. data/doc/fr_class_index.html +35 -0
  29. data/doc/fr_file_index.html +38 -0
  30. data/doc/fr_method_index.html +62 -0
  31. data/doc/index.html +27 -0
  32. data/doc/rdoc-style.css +208 -0
  33. data/example/factory.rb +92 -0
  34. data/example/parse.rb +56 -0
  35. data/lib/X12.rb +50 -0
  36. data/lib/X12/Base.rb +192 -0
  37. data/lib/X12/Composite.rb +37 -0
  38. data/lib/X12/Empty.rb +43 -0
  39. data/lib/X12/Field.rb +81 -0
  40. data/lib/X12/Loop.rb +74 -0
  41. data/lib/X12/Parser.rb +98 -0
  42. data/lib/X12/Segment.rb +92 -0
  43. data/lib/X12/Table.rb +44 -0
  44. data/lib/X12/x12syntax.treetop +256 -0
  45. data/misc/997.d12 +885 -0
  46. data/misc/rdoc_template.rb +697 -0
  47. data/test/tc_factory_997.rb +130 -0
  48. data/test/tc_parse_997.rb +146 -0
  49. data/test/ts_x12.rb +27 -0
  50. metadata +108 -0
@@ -0,0 +1,27 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
5
+
6
+ <!--
7
+
8
+ X12 -- an X12 parsing library
9
+
10
+ -->
11
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
12
+ <head>
13
+ <title>X12 -- an X12 parsing library</title>
14
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
15
+ </head>
16
+
17
+ <frameset cols="20%,*">
18
+ <frameset rows="15%,35%,50%">
19
+ <frame src="fr_file_index.html" title="Files" name="Files">
20
+ <frame src="fr_class_index.html" name="Classes">
21
+ <frame src="fr_method_index.html" name="Methods">
22
+ </frameset>
23
+ <frameset>
24
+ <frame src="files/README.html" name="docwin">
25
+ </frameset>
26
+ </frameset>
27
+ </html>
@@ -0,0 +1,208 @@
1
+
2
+ body {
3
+ font-family: Verdana,Arial,Helvetica,sans-serif;
4
+ font-size: 90%;
5
+ margin: 0;
6
+ margin-left: 40px;
7
+ padding: 0;
8
+ background: #efefef;
9
+ }
10
+
11
+ h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
12
+ h1 { font-size: 150%; }
13
+ h2,h3,h4 { margin-top: 1em; }
14
+
15
+ a { background: #eef; color: #039; text-decoration: none; }
16
+ a:hover { background: #039; color: #eef; }
17
+
18
+ /* Override the base stylesheet's Anchor inside a table cell */
19
+ td > a {
20
+ background: transparent;
21
+ color: #039;
22
+ text-decoration: none;
23
+ }
24
+
25
+ /* and inside a section title */
26
+ .section-title > a {
27
+ background: transparent;
28
+ color: #eee;
29
+ text-decoration: none;
30
+ }
31
+
32
+ /* === Structural elements =================================== */
33
+
34
+ div#index {
35
+ margin: 0;
36
+ margin-left: -40px;
37
+ padding: 0;
38
+ font-size: 90%;
39
+ }
40
+
41
+
42
+ div#index a {
43
+ margin-left: 0.7em;
44
+ }
45
+
46
+ div#index .section-bar {
47
+ margin-left: 0px;
48
+ padding-left: 0.7em;
49
+ background: #ccc;
50
+ font-size: small;
51
+ }
52
+
53
+
54
+ div#classHeader, div#fileHeader {
55
+ width: auto;
56
+ color: white;
57
+ padding: 0.5em 1.5em 0.5em 1.5em;
58
+ margin: 0;
59
+ margin-left: -40px;
60
+ border-bottom: 3px solid #006;
61
+ }
62
+
63
+ div#classHeader a, div#fileHeader a {
64
+ background: inherit;
65
+ color: white;
66
+ }
67
+
68
+ div#classHeader td, div#fileHeader td {
69
+ background: inherit;
70
+ color: white;
71
+ }
72
+
73
+
74
+ div#fileHeader {
75
+ background: #057;
76
+ }
77
+
78
+ div#classHeader {
79
+ background: #048;
80
+ }
81
+
82
+
83
+ .class-name-in-header {
84
+ font-size: 180%;
85
+ font-weight: bold;
86
+ }
87
+
88
+
89
+ div#bodyContent {
90
+ padding: 0 0 0 0;
91
+ }
92
+
93
+ div#description {
94
+ padding: 0.5em 0.5em;
95
+ border: 1px dotted #999;
96
+ margin-left: -40px;
97
+ }
98
+
99
+ div#description h1,h2,h3,h4,h5,h6 {
100
+ color: #125;;
101
+ background: transparent;
102
+ }
103
+
104
+ div#validator-badges {
105
+ text-align: center;
106
+ }
107
+ div#validator-badges img { border: 0; }
108
+
109
+ div#copyright {
110
+ color: #333;
111
+ background: #efefef;
112
+ font: 0.75em sans-serif;
113
+ margin-top: 5em;
114
+ margin-bottom: 0;
115
+ padding: 0.5em 2em;
116
+ }
117
+
118
+
119
+ /* === Classes =================================== */
120
+
121
+ table.header-table {
122
+ color: white;
123
+ font-size: small;
124
+ }
125
+
126
+ .type-note {
127
+ font-size: small;
128
+ color: #DEDEDE;
129
+ }
130
+
131
+ .xxsection-bar {
132
+ background: #eee;
133
+ color: #333;
134
+ padding: 3px;
135
+ }
136
+
137
+ .section-bar {
138
+ color: #333;
139
+ border-bottom: 1px solid #999;
140
+ margin-left: -20px;
141
+ }
142
+
143
+
144
+ .section-title {
145
+ background: #79a;
146
+ color: #eee;
147
+ padding: 3px;
148
+ margin-top: 2em;
149
+ margin-left: -30px;
150
+ border: 1px solid #999;
151
+ }
152
+
153
+ .top-aligned-row { vertical-align: top }
154
+ .bottom-aligned-row { vertical-align: bottom }
155
+
156
+ /* --- Context section classes ----------------------- */
157
+
158
+ .context-row { }
159
+ .context-item-name { font-family: monospace; font-weight: bold; color: black; }
160
+ .context-item-value { font-size: small; color: #448; }
161
+ .context-item-desc { color: #333; padding-left: 2em; }
162
+
163
+ /* --- Method classes -------------------------- */
164
+ .method-detail {
165
+ background: #efefef;
166
+ padding: 0;
167
+ margin-top: 0.5em;
168
+ margin-bottom: 1em;
169
+ border: 1px dotted #ccc;
170
+ }
171
+ .method-heading {
172
+ color: black;
173
+ background: #ccc;
174
+ border-bottom: 1px solid #666;
175
+ padding: 0.2em 0.5em 0 0.5em;
176
+ }
177
+ .method-signature { color: black; background: inherit; }
178
+ .method-name { font-weight: bold; }
179
+ .method-args { font-style: italic; }
180
+ .method-description { padding: 0 0.5em 0 0.5em; }
181
+
182
+ /* --- Source code sections -------------------- */
183
+
184
+ a.source-toggle { font-size: 90%; }
185
+ div.method-source-code {
186
+ background: #888888;
187
+ color: #ffdead;
188
+ margin: 1em;
189
+ padding: 0.5em;
190
+ border: 1px dashed #999;
191
+ overflow: hidden;
192
+ }
193
+
194
+ div.method-source-code pre { color: #ffdead; overflow: hidden; }
195
+
196
+ /* --- Ruby keyword styles --------------------- */
197
+
198
+ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
199
+
200
+ .ruby-constant { color: #7fffd4; background: transparent; }
201
+ .ruby-keyword { color: #00ffff; background: transparent; }
202
+ .ruby-ivar { color: #eedd82; background: transparent; }
203
+ .ruby-operator { color: #00ffee; background: transparent; }
204
+ .ruby-identifier { color: #ffdead; background: transparent; }
205
+ .ruby-node { color: #ffa07a; background: transparent; }
206
+ .ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
207
+ .ruby-regexp { color: #ffa07a; background: transparent; }
208
+ .ruby-value { color: #7fffd4; background: transparent; }
@@ -0,0 +1,92 @@
1
+ #--
2
+ # This file is part of the X12Parser library that provides tools to
3
+ # manipulate X12 messages using Ruby native syntax.
4
+ #
5
+ # http://x12parser.rubyforge.org
6
+ #
7
+ # Copyright (C) 2008 APP Design, Inc.
8
+ #
9
+ # This library is free software; you can redistribute it and/or
10
+ # modify it under the terms of the GNU Lesser General Public
11
+ # License as published by the Free Software Foundation; either
12
+ # version 2.1 of the License, or (at your option) any later version.
13
+ #
14
+ # This library is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ # Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public
20
+ # License along with this library; if not, write to the Free Software
21
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
+ #++
23
+ #
24
+ require 'x12'
25
+
26
+ # Read message definition and create an actual parser
27
+ # by compiling .d12 file
28
+ parser = X12::Parser.new('misc/997.d12')
29
+
30
+ # Make a new 997 message
31
+ r = parser.factory('997')
32
+
33
+ #
34
+ # Set various fields as desired
35
+ #
36
+
37
+ # Set fields directly
38
+ r.ST.TransactionSetIdentifierCode = 997
39
+ r.ST.TransactionSetControlNumber = '2878'
40
+
41
+ # Set fields inside a segment (AK1 in this case)
42
+ r.AK1 { |ak1|
43
+ ak1.FunctionalIdentifierCode = 'HS'
44
+ ak1.GroupControlNumber = 293328532
45
+ }
46
+
47
+ # Set fields deeply inside a segment inside
48
+ # nested loops (L1000/L1010/AK4 in this case)
49
+ r.L1000.L1010.AK4.DataElementSyntaxErrorCode = 55
50
+ r.L1000.AK2.TransactionSetIdentifierCode = 270
51
+
52
+ # Set nested loops
53
+ r.L1000.L1010 {|l|
54
+ l.AK3 {|s|
55
+ s.SegmentIdCode = 'NM1'
56
+ s.LoopIdentifierCode = 'L1000D'
57
+ }
58
+ l.AK4 {|s|
59
+ s.CopyOfBadDataElement = 'Bad element'
60
+ }
61
+ }
62
+
63
+ # Add loop repeats
64
+ r.L1000.repeat {|l1000|
65
+ (0..1).each {|loop_repeat| # Two repeats of the loop L1010
66
+ l1000.L1010.repeat {|l1010|
67
+ l1010.AK3 {|s|
68
+ s.SegmentIdCode = 'DMG'
69
+ s.SegmentPositionInTransactionSet = 0
70
+ s.LoopIdentifierCode = 'L1010'
71
+ s.SegmentSyntaxErrorCode = 22
72
+ } if loop_repeat == 0 # AK3 only in the first repeat of L1010
73
+ (0..1).each {|ak4_repeat| # Two repeats of the segment AK4
74
+ l1010.AK4.repeat {|s|
75
+ s.PositionInSegment = loop_repeat
76
+ s.DataElementSyntaxErrorCode = ak4_repeat
77
+ } # s
78
+ } # ak4_repeat
79
+ } # l1010
80
+ } # loop_repeat
81
+
82
+ l1000.AK5{|a|
83
+ a.TransactionSetAcknowledgmentCode = 666
84
+ a.TransactionSetSyntaxErrorCode4 = 999
85
+ } # a
86
+ } # l1000
87
+
88
+ # Print the message as a string -> ST*997*2878~AK1*HS*293328532~
89
+ # AK2*270*~AK3*NM1**L1000D~AK4***55*Bad element~AK5*~AK3*DMG*0*
90
+ # L1010*22~AK4*0**0~AK4*0**1~AK4*1**0~AK4*1**1~AK5*666****999~
91
+ # AK9****~SE**~
92
+ puts r.render
@@ -0,0 +1,56 @@
1
+ #--
2
+ # This file is part of the X12Parser library that provides tools to
3
+ # manipulate X12 messages using Ruby native syntax.
4
+ #
5
+ # http://x12parser.rubyforge.org
6
+ #
7
+ # Copyright (C) 2008 APP Design, Inc.
8
+ #
9
+ # This library is free software; you can redistribute it and/or
10
+ # modify it under the terms of the GNU Lesser General Public
11
+ # License as published by the Free Software Foundation; either
12
+ # version 2.1 of the License, or (at your option) any later version.
13
+ #
14
+ # This library is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ # Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public
20
+ # License along with this library; if not, write to the Free Software
21
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
+ #++
23
+ #
24
+ require 'x12'
25
+
26
+ # Read message definition and create an actual parser
27
+ # by compiling .d12 file
28
+ parser = X12::Parser.new('misc/997.d12')
29
+
30
+ # Define a test message to parse
31
+ m997='ST*997*2878~AK1*HS*293328532~AK2*270*307272179~'\
32
+ 'AK3*NM1*8*L1010_0*8~AK4*0:0*66*1~AK4*0:1*66*1~AK4*0:2*'\
33
+ '66*1~AK3*NM1*8*L1010_1*8~AK4*1:0*66*1~AK4*1:1*66*1~AK3*'\
34
+ 'NM1*8*L1010_2*8~AK4*2:0*66*1~AK5*R*5~AK9*R*1*1*0~SE*8*2878~'
35
+
36
+ # Parse the message
37
+ r = parser.parse('997', m997)
38
+
39
+ # Access components of the message as desired
40
+
41
+ # Whole ST segment: -> ST*997*2878~
42
+ puts r.ST
43
+
44
+ # One filed, Group Control Number of AK1 -> 293328532
45
+ puts r.AK1.GroupControlNumber
46
+
47
+ # Individual loop, namely, third L1010 subloop of
48
+ # L1000 loop: -> AK3*NM1*8*L1010_2*8~AK4*2:0*66*1~
49
+ puts r.L1000.L1010[2]
50
+
51
+ # First encounter of Data Element Reference Number of the
52
+ # first L1010 sub-loop of L1000 loop -> 66
53
+ puts r.L1000.L1010.AK4.DataElementReferenceNumber
54
+
55
+ # Number of L1010 sub-loops in L1000 loop -> 3
56
+ puts r.L1000.L1010.size
@@ -0,0 +1,50 @@
1
+ #--
2
+ # This file is part of the X12Parser library that provides tools to
3
+ # manipulate X12 messages using Ruby native syntax.
4
+ #
5
+ # http://x12parser.rubyforge.org
6
+ #
7
+ # Copyright (C) 2008 APP Design, Inc.
8
+ #
9
+ # This library is free software; you can redistribute it and/or
10
+ # modify it under the terms of the GNU Lesser General Public
11
+ # License as published by the Free Software Foundation; either
12
+ # version 2.1 of the License, or (at your option) any later version.
13
+ #
14
+ # This library is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ # Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public
20
+ # License along with this library; if not, write to the Free Software
21
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
+ #++
23
+ #
24
+ $:.unshift(File.dirname(__FILE__))
25
+
26
+ require 'rubygems'
27
+ require 'treetop'
28
+
29
+ require 'X12/base'
30
+ require 'X12/empty'
31
+ require 'X12/field'
32
+ require 'X12/composite'
33
+ require 'X12/segment'
34
+ require 'X12/table'
35
+ require 'X12/loop'
36
+ require 'X12/parser'
37
+
38
+ # This relies on the polyglot package to compile and load x12syntax.treetop
39
+ require 'x12/x12syntax'
40
+
41
+ # $Id: X12.rb 35 2008-11-13 18:33:44Z ikk $
42
+ #
43
+ # Package implementing direct manipulation of X12 structures using Ruby syntax.
44
+
45
+ module X12
46
+
47
+ VERSION = '0.0.5'
48
+ EMPTY = Empty.new()
49
+
50
+ end
@@ -0,0 +1,192 @@
1
+ #--
2
+ # This file is part of the X12Parser library that provides tools to
3
+ # manipulate X12 messages using Ruby native syntax.
4
+ #
5
+ # http://x12parser.rubyforge.org
6
+ #
7
+ # Copyright (C) 2008 APP Design, Inc.
8
+ #
9
+ # This library is free software; you can redistribute it and/or
10
+ # modify it under the terms of the GNU Lesser General Public
11
+ # License as published by the Free Software Foundation; either
12
+ # version 2.1 of the License, or (at your option) any later version.
13
+ #
14
+ # This library is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
+ # Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public
20
+ # License along with this library; if not, write to the Free Software
21
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
+ #++
23
+ #
24
+ module X12
25
+
26
+ # $Id: Base.rb 35 2008-11-13 18:33:44Z ikk $
27
+ #
28
+ # Base class for Segment, Composite, and Loop. Contains setable
29
+ # segment_separator, field_separator, and composite_separator fields.
30
+
31
+ class Base
32
+
33
+ attr_reader :name, :repeats
34
+ attr_reader :segment_separator, :field_separator, :composite_separator, :next_repeat, :parsed_str, :nodes
35
+ attr_writer :segment_separator, :field_separator, :composite_separator, :next_repeat, :parsed_str, :nodes
36
+
37
+ # Creates a new base element with a given name, array of sub-elements, and array of repeats if any.
38
+ def initialize(name, arr, repeats = nil)
39
+ @nodes = arr
40
+ @name = name
41
+ @repeats = repeats
42
+ @next_repeat = nil # Next repeat of the same element, if any
43
+ @parsed_str = nil
44
+
45
+ @segment_separator = '~'
46
+ @field_separator = '*'
47
+ @composite_separator = ':'
48
+
49
+ #puts "Created #{name} #{object_id} #{self.class} "
50
+ end
51
+
52
+ # Formats a printable string containing the base element's content
53
+ def inspect
54
+ "#{self.class.to_s.sub(/^.*::/, '')} (#{name}) #{repeats} #{super.inspect[1..-2]} =<#{parsed_str}, #{next_repeat.inspect}> ".gsub(/\\*\"/, '"')
55
+ end
56
+
57
+ # Prints a tree-like representation of the element
58
+ def show(ind = '')
59
+ count = 0
60
+ self.to_a.each{|i|
61
+ #puts "#{ind}#{i.name} #{i.object_id} #{i.super.object_id} [#{count}]: #{i.parsed_str} #{i.super.class}"
62
+ puts "#{ind}#{i.name} [#{count}]: #{i.to_s.sub(/^(.{30})(.*?)(.{30})$/, '\1...\3')}"
63
+ i.nodes.each{|j|
64
+ case
65
+ when j.kind_of?(X12::Base) : j.show(ind+' ')
66
+ when j.kind_of?(X12::Field) : puts "#{ind+' '}#{j.name} -> '#{j.to_s}'"
67
+ end
68
+ }
69
+ count += 1
70
+ }
71
+ end
72
+
73
+ # Try to parse the current element one more time if required. Returns the rest of the string
74
+ # or the same string if no more repeats are found or required.
75
+ def do_repeats(s)
76
+ if self.repeats.end > 1
77
+ possible_repeat = self.dup
78
+ p_s = possible_repeat.parse(s)
79
+ if p_s
80
+ s = p_s
81
+ self.next_repeat = possible_repeat
82
+ end # if parsed
83
+ end # more repeats
84
+ s
85
+ end # do_repeats
86
+
87
+ # Empty out the current element
88
+ def set_empty!
89
+ @next_repeat = nil
90
+ @parsed_str = nil
91
+ self
92
+ end
93
+
94
+ # Make a deep copy of the element
95
+ def dup
96
+ n = clone
97
+ n.set_empty!
98
+ n.nodes = n.nodes.dup
99
+ n.nodes.each_index{|i|
100
+ n.nodes[i] = n.nodes[i].dup
101
+ n.nodes[i].set_empty!
102
+ }
103
+ #puts "Duped #{self.class} #{self.name} #{self.object_id} #{super.object_id} -> #{n.name} #{n.super.object_id} #{n.object_id} "
104
+ n
105
+ end # dup
106
+
107
+ # Recursively find a sub-element, which also has to be of type Base.
108
+ def find(e)
109
+ #puts "Finding [#{e}] in #{self.class} #{name}"
110
+ case self
111
+ when X12::Loop
112
+ nodes.each{|i|
113
+ return i if e==i.name
114
+ res = i.find(e) if i.kind_of?(X12::Loop)
115
+ return res unless res.nil? or EMPTY==res # otherwise keep looping
116
+ }
117
+ when X12::Segment
118
+ return find_field(e).to_s
119
+ end # case
120
+ return EMPTY
121
+ end
122
+
123
+ # Present self and all repeats as an array with self being #0
124
+ def to_a
125
+ res = [self]
126
+ nr = self.next_repeat
127
+ while nr do
128
+ res << nr
129
+ nr = nr.next_repeat
130
+ end
131
+ res
132
+ end
133
+
134
+ # Returns a parsed string representation of the element
135
+ def to_s
136
+ @parsed_str || ''
137
+ end
138
+
139
+ # The main method implementing Ruby-like access methods for nested elements
140
+ def method_missing(meth, *args, &block)
141
+ str = meth.id2name
142
+ if str =~ /=$/
143
+ # Assignment
144
+ str.chop!
145
+ #puts str
146
+ case self
147
+ when X12::Segment
148
+ res = find_field(str)
149
+ throw Exception.new("No field '#{str}' in segment '#{self.name}'") if EMPTY == res
150
+ res.content = args[0].to_s
151
+ #puts res.inspect
152
+ else
153
+ throw Exception.new("Illegal assignment to #{meth} of #{self.class}")
154
+ end # case
155
+ else
156
+ # Retrieval
157
+ res = find(str)
158
+ yield res if block_given?
159
+ res
160
+ end # if assignment
161
+ end
162
+
163
+ # The main method implementing Ruby-like access methods for repeating elements
164
+ def [](*args)
165
+ #puts "squares #{args.inspect}"
166
+ return self.to_a[args[0]] || EMPTY
167
+ end
168
+
169
+ # Returns number of repeats
170
+ def size
171
+ return self.to_a.size
172
+ end
173
+
174
+ # Check if any of the fields has been set yet
175
+ def has_content?
176
+ self.nodes.find{|i| i.has_content?}
177
+ end
178
+
179
+ # Adds a repeat to a segment or loop. Returns a new segment/loop or self if empty.
180
+ def repeat
181
+ res = if self.has_content? # Do not repeat an empty segment
182
+ last_repeat = self.to_a[-1]
183
+ last_repeat.next_repeat = last_repeat.dup
184
+ else
185
+ self
186
+ end
187
+ yield res if block_given?
188
+ res
189
+ end
190
+
191
+ end # Base
192
+ end