tediparse 2.0.0

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 (176) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +319 -0
  3. data/LICENSE +26 -0
  4. data/README.md +308 -0
  5. data/Rakefile +33 -0
  6. data/bin/tediparse +102 -0
  7. data/doc/Defining.md +97 -0
  8. data/doc/Generating-Grammars.md +241 -0
  9. data/doc/Generating.md +332 -0
  10. data/doc/Navigating.md +670 -0
  11. data/doc/Parsing.md +133 -0
  12. data/doc/README.md +51 -0
  13. data/doc/Serializing.md +100 -0
  14. data/doc/Tokenizing.md +136 -0
  15. data/doc/Validating.md +140 -0
  16. data/lib/ruby/array.rb +226 -0
  17. data/lib/ruby/blank.rb +52 -0
  18. data/lib/ruby/exception.rb +14 -0
  19. data/lib/ruby/hash.rb +14 -0
  20. data/lib/ruby/module.rb +60 -0
  21. data/lib/ruby/object.rb +56 -0
  22. data/lib/ruby/string.rb +89 -0
  23. data/lib/ruby/to_d.rb +82 -0
  24. data/lib/ruby/to_date.rb +26 -0
  25. data/lib/ruby/to_time.rb +21 -0
  26. data/lib/ruby/try.rb +46 -0
  27. data/lib/stupidedi/builder.rb +6 -0
  28. data/lib/stupidedi/color.rb +94 -0
  29. data/lib/stupidedi/config/code_list_config.rb +45 -0
  30. data/lib/stupidedi/config/functional_group_config.rb +72 -0
  31. data/lib/stupidedi/config/interchange_config.rb +86 -0
  32. data/lib/stupidedi/config/transaction_set_config.rb +73 -0
  33. data/lib/stupidedi/config.rb +100 -0
  34. data/lib/stupidedi/either.rb +286 -0
  35. data/lib/stupidedi/exceptions/invalid_element_error.rb +7 -0
  36. data/lib/stupidedi/exceptions/invalid_schema_error.rb +7 -0
  37. data/lib/stupidedi/exceptions/missing_grammar_error.rb +50 -0
  38. data/lib/stupidedi/exceptions/output_error.rb +7 -0
  39. data/lib/stupidedi/exceptions/parse_error.rb +7 -0
  40. data/lib/stupidedi/exceptions/stupidedi_error.rb +7 -0
  41. data/lib/stupidedi/exceptions/tokenize_error.rb +7 -0
  42. data/lib/stupidedi/exceptions/zipper_error.rb +7 -0
  43. data/lib/stupidedi/exceptions.rb +13 -0
  44. data/lib/stupidedi/inspect.rb +26 -0
  45. data/lib/stupidedi/interchanges/element_types/separator_val.rb +79 -0
  46. data/lib/stupidedi/interchanges/element_types/special_val.rb +48 -0
  47. data/lib/stupidedi/interchanges/element_types.rb +11 -0
  48. data/lib/stupidedi/interchanges.rb +21 -0
  49. data/lib/stupidedi/parser/builder_dsl.rb +292 -0
  50. data/lib/stupidedi/parser/constraint_table.rb +566 -0
  51. data/lib/stupidedi/parser/generation.rb +147 -0
  52. data/lib/stupidedi/parser/identifier_stack.rb +248 -0
  53. data/lib/stupidedi/parser/instruction.rb +112 -0
  54. data/lib/stupidedi/parser/instruction_table.rb +222 -0
  55. data/lib/stupidedi/parser/navigation.rb +786 -0
  56. data/lib/stupidedi/parser/state_machine.rb +62 -0
  57. data/lib/stupidedi/parser/states/abstract_state.rb +385 -0
  58. data/lib/stupidedi/parser/states/failure_state.rb +69 -0
  59. data/lib/stupidedi/parser/states/functional_group_state.rb +101 -0
  60. data/lib/stupidedi/parser/states/initial_state.rb +62 -0
  61. data/lib/stupidedi/parser/states/interchange_state.rb +96 -0
  62. data/lib/stupidedi/parser/states/loop_state.rb +74 -0
  63. data/lib/stupidedi/parser/states/table_state.rb +90 -0
  64. data/lib/stupidedi/parser/states/transaction_set_state.rb +120 -0
  65. data/lib/stupidedi/parser/states/transmission_state.rb +59 -0
  66. data/lib/stupidedi/parser/tokenization.rb +195 -0
  67. data/lib/stupidedi/parser.rb +32 -0
  68. data/lib/stupidedi/reader/input/abstract_input.rb +137 -0
  69. data/lib/stupidedi/reader/input/delegated_input.rb +112 -0
  70. data/lib/stupidedi/reader/input/file_input.rb +157 -0
  71. data/lib/stupidedi/reader/input.rb +31 -0
  72. data/lib/stupidedi/reader/position.rb +78 -0
  73. data/lib/stupidedi/reader/result.rb +172 -0
  74. data/lib/stupidedi/reader/segment_dict.rb +176 -0
  75. data/lib/stupidedi/reader/separators.rb +90 -0
  76. data/lib/stupidedi/reader/stream_reader.rb +173 -0
  77. data/lib/stupidedi/reader/token_reader.rb +465 -0
  78. data/lib/stupidedi/reader/tokens/component_element_tok.rb +71 -0
  79. data/lib/stupidedi/reader/tokens/composite_element_tok.rb +85 -0
  80. data/lib/stupidedi/reader/tokens/repeated_element_tok.rb +74 -0
  81. data/lib/stupidedi/reader/tokens/segment_tok.rb +74 -0
  82. data/lib/stupidedi/reader/tokens/simple_element_tok.rb +76 -0
  83. data/lib/stupidedi/reader.rb +121 -0
  84. data/lib/stupidedi/schema/abstract_def.rb +76 -0
  85. data/lib/stupidedi/schema/abstract_element_def.rb +35 -0
  86. data/lib/stupidedi/schema/abstract_element_use.rb +47 -0
  87. data/lib/stupidedi/schema/abstract_use.rb +79 -0
  88. data/lib/stupidedi/schema/code_list.rb +99 -0
  89. data/lib/stupidedi/schema/component_element_use.rb +76 -0
  90. data/lib/stupidedi/schema/composite_element_def.rb +103 -0
  91. data/lib/stupidedi/schema/composite_element_use.rb +78 -0
  92. data/lib/stupidedi/schema/element_req.rb +57 -0
  93. data/lib/stupidedi/schema/functional_group_def.rb +124 -0
  94. data/lib/stupidedi/schema/generation/definition_generator.rb +139 -0
  95. data/lib/stupidedi/schema/generation/element_generator.rb +221 -0
  96. data/lib/stupidedi/schema/generation/flat_file_reader.rb +551 -0
  97. data/lib/stupidedi/schema/generation/functional_group_generator.rb +64 -0
  98. data/lib/stupidedi/schema/generation/interchange_generator.rb +145 -0
  99. data/lib/stupidedi/schema/generation/master_loader_generator.rb +121 -0
  100. data/lib/stupidedi/schema/generation/models.rb +85 -0
  101. data/lib/stupidedi/schema/generation/module_loader_generator.rb +64 -0
  102. data/lib/stupidedi/schema/generation/registration_generator.rb +230 -0
  103. data/lib/stupidedi/schema/generation/runner.rb +161 -0
  104. data/lib/stupidedi/schema/generation/segment_generator.rb +130 -0
  105. data/lib/stupidedi/schema/generation/support.rb +78 -0
  106. data/lib/stupidedi/schema/generation/support_modules_generator.rb +126 -0
  107. data/lib/stupidedi/schema/generation/version_modules.rb +35 -0
  108. data/lib/stupidedi/schema/generation.rb +94 -0
  109. data/lib/stupidedi/schema/interchange_def.rb +103 -0
  110. data/lib/stupidedi/schema/loop_def.rb +156 -0
  111. data/lib/stupidedi/schema/repeat_count.rb +86 -0
  112. data/lib/stupidedi/schema/segment_def.rb +122 -0
  113. data/lib/stupidedi/schema/segment_req.rb +46 -0
  114. data/lib/stupidedi/schema/segment_use.rb +99 -0
  115. data/lib/stupidedi/schema/simple_element_def.rb +51 -0
  116. data/lib/stupidedi/schema/simple_element_use.rb +83 -0
  117. data/lib/stupidedi/schema/syntax_note.rb +52 -0
  118. data/lib/stupidedi/schema/table_def.rb +178 -0
  119. data/lib/stupidedi/schema/transaction_set_def.rb +125 -0
  120. data/lib/stupidedi/schema.rb +30 -0
  121. data/lib/stupidedi/sets.rb +42 -0
  122. data/lib/stupidedi/transaction_sets/builder/dsl.rb +192 -0
  123. data/lib/stupidedi/transaction_sets/builder.rb +188 -0
  124. data/lib/stupidedi/transaction_sets/common/implementations/element_reqs.rb +37 -0
  125. data/lib/stupidedi/transaction_sets/common/implementations/segment_reqs.rb +31 -0
  126. data/lib/stupidedi/transaction_sets/common/implementations.rb +11 -0
  127. data/lib/stupidedi/transaction_sets/common.rb +8 -0
  128. data/lib/stupidedi/transaction_sets/validation/ambiguity.rb +395 -0
  129. data/lib/stupidedi/transaction_sets/validation/implementation.rb +12 -0
  130. data/lib/stupidedi/transaction_sets/validation.rb +9 -0
  131. data/lib/stupidedi/transaction_sets.rb +25 -0
  132. data/lib/stupidedi/values/abstract_element_val.rb +19 -0
  133. data/lib/stupidedi/values/abstract_val.rb +133 -0
  134. data/lib/stupidedi/values/composite_element_val.rb +102 -0
  135. data/lib/stupidedi/values/functional_group_val.rb +105 -0
  136. data/lib/stupidedi/values/interchange_val.rb +102 -0
  137. data/lib/stupidedi/values/invalid_envelope_val.rb +61 -0
  138. data/lib/stupidedi/values/invalid_segment_val.rb +89 -0
  139. data/lib/stupidedi/values/loop_val.rb +73 -0
  140. data/lib/stupidedi/values/repeated_element_val.rb +113 -0
  141. data/lib/stupidedi/values/segment_val.rb +105 -0
  142. data/lib/stupidedi/values/segment_val_group.rb +20 -0
  143. data/lib/stupidedi/values/simple_element_val.rb +80 -0
  144. data/lib/stupidedi/values/table_val.rb +69 -0
  145. data/lib/stupidedi/values/transaction_set_val.rb +69 -0
  146. data/lib/stupidedi/values/transmission_val.rb +56 -0
  147. data/lib/stupidedi/values.rb +22 -0
  148. data/lib/stupidedi/version.rb +4 -0
  149. data/lib/stupidedi/versions/common/element_reqs.rb +13 -0
  150. data/lib/stupidedi/versions/common/element_types/an.rb +386 -0
  151. data/lib/stupidedi/versions/common/element_types/dt.rb +572 -0
  152. data/lib/stupidedi/versions/common/element_types/id.rb +304 -0
  153. data/lib/stupidedi/versions/common/element_types/nn.rb +312 -0
  154. data/lib/stupidedi/versions/common/element_types/operators.rb +128 -0
  155. data/lib/stupidedi/versions/common/element_types/r.rb +342 -0
  156. data/lib/stupidedi/versions/common/element_types/simple_element.rb +73 -0
  157. data/lib/stupidedi/versions/common/element_types/tm.rb +347 -0
  158. data/lib/stupidedi/versions/common/element_types.rb +29 -0
  159. data/lib/stupidedi/versions/common/segment_reqs.rb +15 -0
  160. data/lib/stupidedi/versions/common/syntax_notes.rb +172 -0
  161. data/lib/stupidedi/versions/common.rb +11 -0
  162. data/lib/stupidedi/versions.rb +25 -0
  163. data/lib/stupidedi/writer/claredi.rb +178 -0
  164. data/lib/stupidedi/writer/default.rb +119 -0
  165. data/lib/stupidedi/writer.rb +7 -0
  166. data/lib/stupidedi/zipper/abstract_cursor.rb +351 -0
  167. data/lib/stupidedi/zipper/dangling_cursor.rb +103 -0
  168. data/lib/stupidedi/zipper/edited_cursor.rb +157 -0
  169. data/lib/stupidedi/zipper/memoized_cursor.rb +133 -0
  170. data/lib/stupidedi/zipper/path.rb +132 -0
  171. data/lib/stupidedi/zipper/root_cursor.rb +120 -0
  172. data/lib/stupidedi/zipper/stack_cursor.rb +107 -0
  173. data/lib/stupidedi/zipper.rb +45 -0
  174. data/lib/stupidedi.rb +69 -0
  175. data/lib/tediparse.rb +1 -0
  176. metadata +249 -0
@@ -0,0 +1,286 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ class Either
6
+ # @return [Boolean]
7
+ abstract :defined?
8
+
9
+ ###########################################################################
10
+ # @group Filtering the Value
11
+
12
+ # @return [Either]
13
+ abstract :select, :args => %w(reason='select' &block)
14
+
15
+ # @return [Either]
16
+ abstract :reject, :args => %w(reason='reject' &block)
17
+
18
+ # @endgroup
19
+ ###########################################################################
20
+
21
+ ###########################################################################
22
+ # @group Transforming the Value
23
+
24
+ # @return [Either]
25
+ abstract :map, :args => %w(&block)
26
+
27
+ # @return [Either]
28
+ abstract :flatmap, :args => %w(&block)
29
+
30
+ # @return [Either]
31
+ abstract :or, :args => %w(&block)
32
+
33
+ # @return [Either]
34
+ abstract :explain, :args => %w(&block)
35
+
36
+ # @return [Object]
37
+ abstract :fetch, :args => %w(default)
38
+
39
+ # @endgroup
40
+ ###########################################################################
41
+
42
+ class Success < Either
43
+ def initialize(value)
44
+ @value = value
45
+ end
46
+
47
+ def copy(changes = {})
48
+ Success.new \
49
+ changes.fetch(:value, @value)
50
+ end
51
+
52
+ # @return true
53
+ def defined?
54
+ true
55
+ end
56
+
57
+ def fetch(default = nil)
58
+ @value
59
+ end
60
+
61
+ #########################################################################
62
+ # @group Filtering the Value
63
+
64
+ # @return [Either]
65
+ # @yieldparam value
66
+ # @yieldreturn [Boolean]
67
+ def select(reason = "select", &block)
68
+ if deconstruct(block)
69
+ self
70
+ else
71
+ failure(reason)
72
+ end
73
+ end
74
+
75
+ # @return [Either]
76
+ # @yieldparam value
77
+ # @yieldreturn [Boolean]
78
+ def reject(reason = "reject", &block)
79
+ if deconstruct(block)
80
+ failure(reason)
81
+ else
82
+ self
83
+ end
84
+ end
85
+
86
+ # @endgroup
87
+ #########################################################################
88
+
89
+ #########################################################################
90
+ # @group Transforming the Value
91
+
92
+ # @return [Success]
93
+ # @yieldparam value
94
+ # @yieldreturn value
95
+ def map(&block)
96
+ copy(:value => deconstruct(block))
97
+ end
98
+
99
+ # @return [Either]
100
+ # @yieldparam value
101
+ # @yieldreturn [Either]
102
+ def flatmap(&block)
103
+ result = deconstruct(block)
104
+
105
+ if result.is_a?(Either)
106
+ result
107
+ else
108
+ raise TypeError, "block did not return an instance of Either"
109
+ end
110
+ end
111
+
112
+ # @return [Success]
113
+ def or
114
+ self
115
+ end
116
+
117
+ # @return [Success]
118
+ def explain
119
+ self
120
+ end
121
+
122
+ # @endgroup
123
+ #########################################################################
124
+
125
+ def tap(&block)
126
+ deconstruct(block); self
127
+ end
128
+
129
+ # @return [Boolean]
130
+ def ==(other)
131
+ other.is_a?(self.class) and other.select{|x| x == @value }.defined?
132
+ end
133
+
134
+ # @return [void]
135
+ def pretty_print(q)
136
+ q.text("Either.success")
137
+ q.group(2, "(", ")") do
138
+ q.breakable ""
139
+ q.pp @value
140
+ end
141
+ end
142
+
143
+ # @return [String]
144
+ def inspect
145
+ "Either.success(#{@value.inspect})"
146
+ end
147
+
148
+ private
149
+
150
+ def deconstruct(block)
151
+ block.call(@value)
152
+ end
153
+
154
+ def failure(reason)
155
+ Either::Failure.new(reason)
156
+ end
157
+ end
158
+
159
+ class Failure < Either
160
+ attr_reader :reason
161
+
162
+ def initialize(reason)
163
+ @reason = reason
164
+ end
165
+
166
+ # @return [Failure]
167
+ def copy(changes = {})
168
+ Failure.new \
169
+ changes.fetch(:reason, @reason)
170
+ end
171
+
172
+ # @return false
173
+ def defined?
174
+ false
175
+ end
176
+
177
+ def fetch(default = nil)
178
+ default
179
+ end
180
+
181
+ #########################################################################
182
+ # @group Filtering the Value
183
+
184
+ # @return [Failure]
185
+ def select(reason = nil)
186
+ self
187
+ end
188
+
189
+ # @return [Failure]
190
+ def reject(reason = nil)
191
+ self
192
+ end
193
+
194
+ # @endgroup
195
+ #########################################################################
196
+
197
+ #########################################################################
198
+ # @group Transforming the Value
199
+
200
+ # @return [Failure]
201
+ def map
202
+ self
203
+ end
204
+
205
+ # @return [Failure]
206
+ def flatmap
207
+ self
208
+ end
209
+
210
+ # @return [Either]
211
+ # @yieldparam reason
212
+ # @yieldreturn [Either]
213
+ def or(&block)
214
+ result = deconstruct(block)
215
+
216
+ if result.is_a?(Either)
217
+ result
218
+ else
219
+ raise TypeError, "block did not return an instance of Either"
220
+ end
221
+ end
222
+
223
+ # @return [Failure]
224
+ # @yieldparam reason
225
+ # @yieldreturn reason
226
+ def explain(&block)
227
+ copy(:reason => deconstruct(block))
228
+ end
229
+
230
+ # @endgroup
231
+ #########################################################################
232
+
233
+ def tap
234
+ self
235
+ end
236
+
237
+ # @return [Boolean]
238
+ def ==(other)
239
+ other.is_a?(self.class) and other.reason == @reason
240
+ end
241
+
242
+ # @return [void]
243
+ def pretty_print(q)
244
+ q.text("Either.failure")
245
+ q.group(2, "(", ")") do
246
+ q.breakable ""
247
+ q.pp @reason
248
+ end
249
+ end
250
+
251
+ # @return [String]
252
+ def inspect
253
+ "Either.failure(#{@reason.inspect})"
254
+ end
255
+
256
+ private
257
+
258
+ def deconstruct(block)
259
+ block.call(@reason)
260
+ end
261
+ end
262
+ end
263
+
264
+ class << Either
265
+ ###########################################################################
266
+ # @group Constructors
267
+
268
+ # @return [Success]
269
+ def success(value)
270
+ Either::Success.new(value)
271
+ end
272
+
273
+ # @return [Failure]
274
+ def failure(reason)
275
+ Either::Failure.new(reason)
276
+ end
277
+
278
+ # @endgroup
279
+ ###########################################################################
280
+ end
281
+
282
+ Either.eigenclass.send(:protected, :new)
283
+ Either::Success.eigenclass.send(:public, :new)
284
+ Either::Failure.eigenclass.send(:public, :new)
285
+
286
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Exceptions
4
+ class InvalidElementError < StupidediError
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Exceptions
4
+ class InvalidSchemaError < StupidediError
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Exceptions
4
+ #
5
+ # Raised when application code reaches for a grammar that tediparse does
6
+ # not ship. tediparse is the parser/writer engine only; transaction-set
7
+ # grammars, code lists, and implementation guides are not bundled (they
8
+ # are X12 IP). Users must register their own grammar against
9
+ # +Stupidedi::Config+ before parsing.
10
+ #
11
+ # Three places raise this:
12
+ #
13
+ # 1. +Stupidedi::Interchanges.const_missing+,
14
+ # +Stupidedi::Versions.const_missing+, and
15
+ # +Stupidedi::TransactionSets.const_missing+ raise it when application
16
+ # code references a per-era constant by name
17
+ # (e.g. +Stupidedi::Versions::FiftyTen+).
18
+ #
19
+ # 2. The three envelope parser states (+InterchangeState+,
20
+ # +FunctionalGroupState+, +TransactionSetState+) surface this message
21
+ # as the +reason+ on +InvalidSegmentVal+ when the relevant config
22
+ # sub-registry is empty. The parser itself does not raise — it
23
+ # produces a +FailureState+ — but the message is the same so users
24
+ # see one consistent UX whether they hit a bare +const_missing+ or a
25
+ # parse failure.
26
+ #
27
+ class MissingGrammarError < StupidediError
28
+ DEFAULT_MESSAGE =
29
+ "tediparse does not ship with X12 grammars or transaction-set " \
30
+ "definitions. Register your own grammar against Stupidedi::Config " \
31
+ "before parsing — see the README for an authoring example."
32
+
33
+ # @param context [String, nil]
34
+ # When given, appended to the default message as " (while resolving
35
+ # <context>)". Used by the +const_missing+ hooks to name the
36
+ # per-era constant the caller reached for; left nil at parser-state
37
+ # callsites where no constant name is in play.
38
+ def initialize(context = nil)
39
+ message =
40
+ if context
41
+ "#{DEFAULT_MESSAGE} (while resolving #{context})"
42
+ else
43
+ DEFAULT_MESSAGE
44
+ end
45
+
46
+ super(message)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Exceptions
4
+ class OutputError < StupidediError
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Exceptions
4
+ class ParseError < StupidediError
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Exceptions
4
+ class StupidediError < StandardError
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Exceptions
4
+ class TokenizeError < StupidediError
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Exceptions
4
+ class ZipperError < StupidediError
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Exceptions
4
+ autoload :StupidediError, "stupidedi/exceptions/stupidedi_error"
5
+ autoload :InvalidElementError, "stupidedi/exceptions/invalid_element_error"
6
+ autoload :InvalidSchemaError, "stupidedi/exceptions/invalid_schema_error"
7
+ autoload :MissingGrammarError, "stupidedi/exceptions/missing_grammar_error"
8
+ autoload :OutputError, "stupidedi/exceptions/output_error"
9
+ autoload :ParseError, "stupidedi/exceptions/parse_error"
10
+ autoload :TokenizeError, "stupidedi/exceptions/tokenize_error"
11
+ autoload :ZipperError, "stupidedi/exceptions/zipper_error"
12
+ end
13
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ #
6
+ # When an exception is raised, in some cases `#inspect` is called on a
7
+ # huge object graph to generate the message `"undefined method '...' for
8
+ # <Stupidedi::Schema::TransactionSetDef:0x...>"`. This can take several
9
+ # seconds, since `Object#inspect` descends recursively into each instance
10
+ # variable.
11
+ #
12
+ # This mixin defines an alternative default implementation for `#inspect`,
13
+ # which should be significantly faster than the default Ruby implementation
14
+ # since it does not descend into the object.
15
+ #
16
+ module Inspect
17
+ # @return [String]
18
+ def inspect
19
+ if self.class.name.nil? or self.class.name !~ /\S/
20
+ "#<\#<Class:0x#{self.class.object_id.abs.to_s(16)}>"
21
+ else
22
+ "#<#{self.class.name}"
23
+ end + ":0x#{object_id.abs.to_s(16)} ...>"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Interchanges
6
+ module ElementTypes
7
+ class Separator < Versions::Common::ElementTypes::AN
8
+ def companion
9
+ SeparatorVal
10
+ end
11
+ end
12
+
13
+ class SeparatorVal < Values::SimpleElementVal
14
+ def_delegators :@value, :to_s, :length, :==
15
+
16
+ def initialize(value, usage, position)
17
+ @value = value
18
+ super(usage, position)
19
+ end
20
+
21
+ # @return [SeparatorVal]
22
+ def copy(changes = {})
23
+ SeparatorVal.new \
24
+ changes.fetch(:value, @value),
25
+ changes.fetch(:usage, usage),
26
+ changes.fetch(:position, position)
27
+ end
28
+
29
+ def valid?
30
+ true
31
+ end
32
+
33
+ def empty?
34
+ @value.blank?
35
+ end
36
+
37
+ def too_short?
38
+ @value.length < 1
39
+ end
40
+
41
+ def too_long?
42
+ @value.length > 1
43
+ end
44
+
45
+ def separator?
46
+ true
47
+ end
48
+
49
+ # @return [String]
50
+ def to_x12(truncate = true)
51
+ @value.to_s
52
+ end
53
+
54
+ def inspect
55
+ id = definition.try{|d| ansi.bold("[#{d.id}]") }
56
+ ansi.element("SeparatorVal.value#{id}") + "(#{@value || "nil"})"
57
+ end
58
+ end
59
+
60
+ class << SeparatorVal
61
+ # @group Constructors
62
+ ###################################################################
63
+
64
+ # @raise NoMethodError
65
+ def empty(usage, position)
66
+ SeparatorVal.new(nil, usage, position)
67
+ end
68
+
69
+ # @return [SeparatorVal]
70
+ def value(character, usage, position)
71
+ SeparatorVal.new(character, usage, position)
72
+ end
73
+
74
+ # @endgroup
75
+ ###################################################################
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ using Refinements
4
+
5
+ module Interchanges
6
+ module ElementTypes
7
+ AN = Versions::Common::ElementTypes::AN
8
+ StringVal = Versions::Common::ElementTypes::StringVal
9
+
10
+ #
11
+ # The specifications declare ISA02 and ISA04 are required elements, but
12
+ # they only have "meaningful information" when ISA01 and ISA03 qualifiers
13
+ # aren't "00".
14
+ #
15
+ # Without specifications regarding what should be entered in these
16
+ # required elements, our best option is to defer to convention, which
17
+ # seems to be that these elements should have 10 spaces -- which means
18
+ # they're blank. So we can't really make these elements required! Even
19
+ # stupider, these are the only blank elements that should be written out
20
+ # space-padded to the min_length -- every other element should be
21
+ # collapsed to an empty string.
22
+ #
23
+ # So this "Special" class overrides to_x12 for empty values, but it
24
+ # otherwise looks and acts like a normal AN and StringVal
25
+ #
26
+ class SpecialAN < AN
27
+ def companion
28
+ SpecialVal
29
+ end
30
+ end
31
+
32
+ class SpecialVal < StringVal
33
+ class Empty < StringVal::Empty
34
+ # @return [String]
35
+ def to_x12
36
+ " " * definition.min_length
37
+ end
38
+ end
39
+
40
+ class NonEmpty < StringVal::NonEmpty
41
+ def too_short?
42
+ false
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Interchanges
4
+ module ElementTypes
5
+ autoload :SpecialAN, "stupidedi/interchanges/element_types/special_val"
6
+ autoload :SpecialVal, "stupidedi/interchanges/element_types/special_val"
7
+ autoload :Separator, "stupidedi/interchanges/element_types/separator_val"
8
+ autoload :SeparatorVal, "stupidedi/interchanges/element_types/separator_val"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ module Stupidedi
3
+ module Interchanges
4
+ autoload :ElementTypes, "stupidedi/interchanges/element_types"
5
+
6
+ # Per-era envelope namespaces that lived under +Stupidedi::Interchanges+
7
+ # in the upstream stupidedi gem. tediparse does not ship them; if user
8
+ # code references one by name we surface a helpful error rather than the
9
+ # bare +NameError+ Ruby would raise for an undefined constant.
10
+ REMOVED_ERAS = %i[TwoHundred ThreeHundred FourHundred FourOhOne FiveOhOne].freeze
11
+ private_constant :REMOVED_ERAS
12
+
13
+ def self.const_missing(name)
14
+ if REMOVED_ERAS.include?(name.to_sym)
15
+ raise Stupidedi::Exceptions::MissingGrammarError.new("#{self}::#{name}")
16
+ end
17
+
18
+ super
19
+ end
20
+ end
21
+ end