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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +319 -0
- data/LICENSE +26 -0
- data/README.md +308 -0
- data/Rakefile +33 -0
- data/bin/tediparse +102 -0
- data/doc/Defining.md +97 -0
- data/doc/Generating-Grammars.md +241 -0
- data/doc/Generating.md +332 -0
- data/doc/Navigating.md +670 -0
- data/doc/Parsing.md +133 -0
- data/doc/README.md +51 -0
- data/doc/Serializing.md +100 -0
- data/doc/Tokenizing.md +136 -0
- data/doc/Validating.md +140 -0
- data/lib/ruby/array.rb +226 -0
- data/lib/ruby/blank.rb +52 -0
- data/lib/ruby/exception.rb +14 -0
- data/lib/ruby/hash.rb +14 -0
- data/lib/ruby/module.rb +60 -0
- data/lib/ruby/object.rb +56 -0
- data/lib/ruby/string.rb +89 -0
- data/lib/ruby/to_d.rb +82 -0
- data/lib/ruby/to_date.rb +26 -0
- data/lib/ruby/to_time.rb +21 -0
- data/lib/ruby/try.rb +46 -0
- data/lib/stupidedi/builder.rb +6 -0
- data/lib/stupidedi/color.rb +94 -0
- data/lib/stupidedi/config/code_list_config.rb +45 -0
- data/lib/stupidedi/config/functional_group_config.rb +72 -0
- data/lib/stupidedi/config/interchange_config.rb +86 -0
- data/lib/stupidedi/config/transaction_set_config.rb +73 -0
- data/lib/stupidedi/config.rb +100 -0
- data/lib/stupidedi/either.rb +286 -0
- data/lib/stupidedi/exceptions/invalid_element_error.rb +7 -0
- data/lib/stupidedi/exceptions/invalid_schema_error.rb +7 -0
- data/lib/stupidedi/exceptions/missing_grammar_error.rb +50 -0
- data/lib/stupidedi/exceptions/output_error.rb +7 -0
- data/lib/stupidedi/exceptions/parse_error.rb +7 -0
- data/lib/stupidedi/exceptions/stupidedi_error.rb +7 -0
- data/lib/stupidedi/exceptions/tokenize_error.rb +7 -0
- data/lib/stupidedi/exceptions/zipper_error.rb +7 -0
- data/lib/stupidedi/exceptions.rb +13 -0
- data/lib/stupidedi/inspect.rb +26 -0
- data/lib/stupidedi/interchanges/element_types/separator_val.rb +79 -0
- data/lib/stupidedi/interchanges/element_types/special_val.rb +48 -0
- data/lib/stupidedi/interchanges/element_types.rb +11 -0
- data/lib/stupidedi/interchanges.rb +21 -0
- data/lib/stupidedi/parser/builder_dsl.rb +292 -0
- data/lib/stupidedi/parser/constraint_table.rb +566 -0
- data/lib/stupidedi/parser/generation.rb +147 -0
- data/lib/stupidedi/parser/identifier_stack.rb +248 -0
- data/lib/stupidedi/parser/instruction.rb +112 -0
- data/lib/stupidedi/parser/instruction_table.rb +222 -0
- data/lib/stupidedi/parser/navigation.rb +786 -0
- data/lib/stupidedi/parser/state_machine.rb +62 -0
- data/lib/stupidedi/parser/states/abstract_state.rb +385 -0
- data/lib/stupidedi/parser/states/failure_state.rb +69 -0
- data/lib/stupidedi/parser/states/functional_group_state.rb +101 -0
- data/lib/stupidedi/parser/states/initial_state.rb +62 -0
- data/lib/stupidedi/parser/states/interchange_state.rb +96 -0
- data/lib/stupidedi/parser/states/loop_state.rb +74 -0
- data/lib/stupidedi/parser/states/table_state.rb +90 -0
- data/lib/stupidedi/parser/states/transaction_set_state.rb +120 -0
- data/lib/stupidedi/parser/states/transmission_state.rb +59 -0
- data/lib/stupidedi/parser/tokenization.rb +195 -0
- data/lib/stupidedi/parser.rb +32 -0
- data/lib/stupidedi/reader/input/abstract_input.rb +137 -0
- data/lib/stupidedi/reader/input/delegated_input.rb +112 -0
- data/lib/stupidedi/reader/input/file_input.rb +157 -0
- data/lib/stupidedi/reader/input.rb +31 -0
- data/lib/stupidedi/reader/position.rb +78 -0
- data/lib/stupidedi/reader/result.rb +172 -0
- data/lib/stupidedi/reader/segment_dict.rb +176 -0
- data/lib/stupidedi/reader/separators.rb +90 -0
- data/lib/stupidedi/reader/stream_reader.rb +173 -0
- data/lib/stupidedi/reader/token_reader.rb +465 -0
- data/lib/stupidedi/reader/tokens/component_element_tok.rb +71 -0
- data/lib/stupidedi/reader/tokens/composite_element_tok.rb +85 -0
- data/lib/stupidedi/reader/tokens/repeated_element_tok.rb +74 -0
- data/lib/stupidedi/reader/tokens/segment_tok.rb +74 -0
- data/lib/stupidedi/reader/tokens/simple_element_tok.rb +76 -0
- data/lib/stupidedi/reader.rb +121 -0
- data/lib/stupidedi/schema/abstract_def.rb +76 -0
- data/lib/stupidedi/schema/abstract_element_def.rb +35 -0
- data/lib/stupidedi/schema/abstract_element_use.rb +47 -0
- data/lib/stupidedi/schema/abstract_use.rb +79 -0
- data/lib/stupidedi/schema/code_list.rb +99 -0
- data/lib/stupidedi/schema/component_element_use.rb +76 -0
- data/lib/stupidedi/schema/composite_element_def.rb +103 -0
- data/lib/stupidedi/schema/composite_element_use.rb +78 -0
- data/lib/stupidedi/schema/element_req.rb +57 -0
- data/lib/stupidedi/schema/functional_group_def.rb +124 -0
- data/lib/stupidedi/schema/generation/definition_generator.rb +139 -0
- data/lib/stupidedi/schema/generation/element_generator.rb +221 -0
- data/lib/stupidedi/schema/generation/flat_file_reader.rb +551 -0
- data/lib/stupidedi/schema/generation/functional_group_generator.rb +64 -0
- data/lib/stupidedi/schema/generation/interchange_generator.rb +145 -0
- data/lib/stupidedi/schema/generation/master_loader_generator.rb +121 -0
- data/lib/stupidedi/schema/generation/models.rb +85 -0
- data/lib/stupidedi/schema/generation/module_loader_generator.rb +64 -0
- data/lib/stupidedi/schema/generation/registration_generator.rb +230 -0
- data/lib/stupidedi/schema/generation/runner.rb +161 -0
- data/lib/stupidedi/schema/generation/segment_generator.rb +130 -0
- data/lib/stupidedi/schema/generation/support.rb +78 -0
- data/lib/stupidedi/schema/generation/support_modules_generator.rb +126 -0
- data/lib/stupidedi/schema/generation/version_modules.rb +35 -0
- data/lib/stupidedi/schema/generation.rb +94 -0
- data/lib/stupidedi/schema/interchange_def.rb +103 -0
- data/lib/stupidedi/schema/loop_def.rb +156 -0
- data/lib/stupidedi/schema/repeat_count.rb +86 -0
- data/lib/stupidedi/schema/segment_def.rb +122 -0
- data/lib/stupidedi/schema/segment_req.rb +46 -0
- data/lib/stupidedi/schema/segment_use.rb +99 -0
- data/lib/stupidedi/schema/simple_element_def.rb +51 -0
- data/lib/stupidedi/schema/simple_element_use.rb +83 -0
- data/lib/stupidedi/schema/syntax_note.rb +52 -0
- data/lib/stupidedi/schema/table_def.rb +178 -0
- data/lib/stupidedi/schema/transaction_set_def.rb +125 -0
- data/lib/stupidedi/schema.rb +30 -0
- data/lib/stupidedi/sets.rb +42 -0
- data/lib/stupidedi/transaction_sets/builder/dsl.rb +192 -0
- data/lib/stupidedi/transaction_sets/builder.rb +188 -0
- data/lib/stupidedi/transaction_sets/common/implementations/element_reqs.rb +37 -0
- data/lib/stupidedi/transaction_sets/common/implementations/segment_reqs.rb +31 -0
- data/lib/stupidedi/transaction_sets/common/implementations.rb +11 -0
- data/lib/stupidedi/transaction_sets/common.rb +8 -0
- data/lib/stupidedi/transaction_sets/validation/ambiguity.rb +395 -0
- data/lib/stupidedi/transaction_sets/validation/implementation.rb +12 -0
- data/lib/stupidedi/transaction_sets/validation.rb +9 -0
- data/lib/stupidedi/transaction_sets.rb +25 -0
- data/lib/stupidedi/values/abstract_element_val.rb +19 -0
- data/lib/stupidedi/values/abstract_val.rb +133 -0
- data/lib/stupidedi/values/composite_element_val.rb +102 -0
- data/lib/stupidedi/values/functional_group_val.rb +105 -0
- data/lib/stupidedi/values/interchange_val.rb +102 -0
- data/lib/stupidedi/values/invalid_envelope_val.rb +61 -0
- data/lib/stupidedi/values/invalid_segment_val.rb +89 -0
- data/lib/stupidedi/values/loop_val.rb +73 -0
- data/lib/stupidedi/values/repeated_element_val.rb +113 -0
- data/lib/stupidedi/values/segment_val.rb +105 -0
- data/lib/stupidedi/values/segment_val_group.rb +20 -0
- data/lib/stupidedi/values/simple_element_val.rb +80 -0
- data/lib/stupidedi/values/table_val.rb +69 -0
- data/lib/stupidedi/values/transaction_set_val.rb +69 -0
- data/lib/stupidedi/values/transmission_val.rb +56 -0
- data/lib/stupidedi/values.rb +22 -0
- data/lib/stupidedi/version.rb +4 -0
- data/lib/stupidedi/versions/common/element_reqs.rb +13 -0
- data/lib/stupidedi/versions/common/element_types/an.rb +386 -0
- data/lib/stupidedi/versions/common/element_types/dt.rb +572 -0
- data/lib/stupidedi/versions/common/element_types/id.rb +304 -0
- data/lib/stupidedi/versions/common/element_types/nn.rb +312 -0
- data/lib/stupidedi/versions/common/element_types/operators.rb +128 -0
- data/lib/stupidedi/versions/common/element_types/r.rb +342 -0
- data/lib/stupidedi/versions/common/element_types/simple_element.rb +73 -0
- data/lib/stupidedi/versions/common/element_types/tm.rb +347 -0
- data/lib/stupidedi/versions/common/element_types.rb +29 -0
- data/lib/stupidedi/versions/common/segment_reqs.rb +15 -0
- data/lib/stupidedi/versions/common/syntax_notes.rb +172 -0
- data/lib/stupidedi/versions/common.rb +11 -0
- data/lib/stupidedi/versions.rb +25 -0
- data/lib/stupidedi/writer/claredi.rb +178 -0
- data/lib/stupidedi/writer/default.rb +119 -0
- data/lib/stupidedi/writer.rb +7 -0
- data/lib/stupidedi/zipper/abstract_cursor.rb +351 -0
- data/lib/stupidedi/zipper/dangling_cursor.rb +103 -0
- data/lib/stupidedi/zipper/edited_cursor.rb +157 -0
- data/lib/stupidedi/zipper/memoized_cursor.rb +133 -0
- data/lib/stupidedi/zipper/path.rb +132 -0
- data/lib/stupidedi/zipper/root_cursor.rb +120 -0
- data/lib/stupidedi/zipper/stack_cursor.rb +107 -0
- data/lib/stupidedi/zipper.rb +45 -0
- data/lib/stupidedi.rb +69 -0
- data/lib/tediparse.rb +1 -0
- metadata +249 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
using Refinements
|
|
4
|
+
|
|
5
|
+
module Versions
|
|
6
|
+
module Common
|
|
7
|
+
module ElementTypes
|
|
8
|
+
class TM < SimpleElementDef
|
|
9
|
+
def initialize(id, name, min_length, max_length, description = nil, parent = nil)
|
|
10
|
+
super(id, name, min_length, max_length, description)
|
|
11
|
+
|
|
12
|
+
unless min_length == 2 or min_length == 4 or min_length >= 6
|
|
13
|
+
raise Exceptions::InvalidSchemaError,
|
|
14
|
+
"min_length must be either 2, 4, 6, or greater"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
unless max_length == 2 or max_length == 4 or max_length >= 6
|
|
18
|
+
raise Exceptions::InvalidSchemaError,
|
|
19
|
+
"max_length must be either 2, 4, 6, or greater"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def companion
|
|
24
|
+
TimeVal
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
#
|
|
29
|
+
# @see X222.pdf B.1.1.3.1.6 Time
|
|
30
|
+
#
|
|
31
|
+
class TimeVal < Values::SimpleElementVal
|
|
32
|
+
def time?
|
|
33
|
+
true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def too_short?
|
|
37
|
+
false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def too_long?
|
|
41
|
+
false
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Invalid < TimeVal
|
|
45
|
+
# @return [Object]
|
|
46
|
+
attr_reader :value
|
|
47
|
+
|
|
48
|
+
def initialize(value, usage, position)
|
|
49
|
+
@value = value
|
|
50
|
+
super(usage, position)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def valid?
|
|
54
|
+
false
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def empty?
|
|
58
|
+
false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @return [TimeVal]
|
|
62
|
+
def map
|
|
63
|
+
self
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @return [String]
|
|
67
|
+
# :nocov:
|
|
68
|
+
def inspect
|
|
69
|
+
id = definition.bind do |d|
|
|
70
|
+
"[#{"% 5s" % d.id}: #{d.name}]".bind do |s|
|
|
71
|
+
if usage.forbidden?
|
|
72
|
+
ansi.forbidden(s)
|
|
73
|
+
elsif usage.required?
|
|
74
|
+
ansi.required(s)
|
|
75
|
+
else
|
|
76
|
+
ansi.optional(s)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
ansi.element("TM.invalid#{id}") + "(#{ansi.invalid(@value.inspect)})"
|
|
82
|
+
end
|
|
83
|
+
# :nocov:
|
|
84
|
+
|
|
85
|
+
# @return [String]
|
|
86
|
+
def to_s
|
|
87
|
+
""
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @return [String]
|
|
91
|
+
def to_x12(truncate = true)
|
|
92
|
+
""
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# @return [Boolean]
|
|
96
|
+
def ==(other)
|
|
97
|
+
eql?(other)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def copy(changes = {})
|
|
101
|
+
self
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
class Valid < TimeVal
|
|
106
|
+
def valid?
|
|
107
|
+
true
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# @return [TimeVal]
|
|
111
|
+
def map
|
|
112
|
+
TimeVal.value(yield(value), usage, position)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def copy(changes = {})
|
|
116
|
+
TimeVal.value \
|
|
117
|
+
changes.fetch(:value, value),
|
|
118
|
+
changes.fetch(:usage, usage),
|
|
119
|
+
changes.fetch(:position, position)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def coerce(other)
|
|
123
|
+
return TimeVal.value(other, usage, position), self
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# @return [Boolean]
|
|
127
|
+
def ==(other)
|
|
128
|
+
other = TimeVal.value(other, usage, position)
|
|
129
|
+
other.valid? and other.value == value
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
class Empty < Valid
|
|
134
|
+
def value
|
|
135
|
+
nil
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def empty?
|
|
139
|
+
true
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# @return [String]
|
|
143
|
+
# :nocov:
|
|
144
|
+
def inspect
|
|
145
|
+
id = definition.bind do |d|
|
|
146
|
+
"[#{"% 5s" % d.id}: #{d.name}]".bind do |s|
|
|
147
|
+
if usage.forbidden?
|
|
148
|
+
ansi.forbidden(s)
|
|
149
|
+
elsif usage.required?
|
|
150
|
+
ansi.required(s)
|
|
151
|
+
else
|
|
152
|
+
ansi.optional(s)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
ansi.element("TM.empty#{id}")
|
|
158
|
+
end
|
|
159
|
+
# :nocov:
|
|
160
|
+
|
|
161
|
+
# @return [String]
|
|
162
|
+
def to_s
|
|
163
|
+
""
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# @return [String]
|
|
167
|
+
def to_x12(truncate = true)
|
|
168
|
+
""
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
class NonEmpty < Valid
|
|
173
|
+
# @return [Integer]
|
|
174
|
+
attr_reader :hour
|
|
175
|
+
|
|
176
|
+
# @return [Integer]
|
|
177
|
+
attr_reader :minute
|
|
178
|
+
|
|
179
|
+
# @return [Integer, BigDecimal]
|
|
180
|
+
attr_reader :second
|
|
181
|
+
|
|
182
|
+
def initialize(hour, minute, second, usage, position)
|
|
183
|
+
@hour, @minute, @second = hour, minute, second
|
|
184
|
+
|
|
185
|
+
valid = ( hour.nil? or hour.between?(0, 24))
|
|
186
|
+
valid &&= (minute.nil? or not hour.nil?)
|
|
187
|
+
valid &&= (minute.nil? or minute.between?(0, 60))
|
|
188
|
+
valid &&= (second.nil? or not minute.nil?)
|
|
189
|
+
valid &&= (second.nil? or second.between?(0, 60))
|
|
190
|
+
|
|
191
|
+
super(usage, position)
|
|
192
|
+
|
|
193
|
+
unless valid
|
|
194
|
+
raise Exceptions::InvalidElementError,
|
|
195
|
+
"invalid time #{inspect}"
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def copy(changes = {})
|
|
200
|
+
if [:hour, :minute, :second].any?{|x| changes.include?(x) }
|
|
201
|
+
changes[:value] = [changes.fetch(:hour, @hour),
|
|
202
|
+
changes.fetch(:minute, @minute),
|
|
203
|
+
changes.fetch(:second, @second)]
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
super(changes)
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def value
|
|
210
|
+
[@hour, @minute, @second]
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def empty?
|
|
214
|
+
false
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def too_short?
|
|
218
|
+
to_x12(false).length < definition.min_length
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# @return [Time]
|
|
222
|
+
def to_time(date, minute = nil, second = nil)
|
|
223
|
+
minute = @minute || minute
|
|
224
|
+
second = @second || second
|
|
225
|
+
|
|
226
|
+
if not second.nil?
|
|
227
|
+
Time.utc(date.year, date.month, date.day, @hour, minute, second.to_f)
|
|
228
|
+
elsif not minute.nil?
|
|
229
|
+
Time.utc(date.year, date.month, date.day, @hour, minute)
|
|
230
|
+
else
|
|
231
|
+
Time.utc(date.year, date.month, date.day, @hour)
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
# @return [String]
|
|
236
|
+
# :nocov:
|
|
237
|
+
def inspect
|
|
238
|
+
id = definition.bind do |d|
|
|
239
|
+
"[#{"% 5s" % d.id}: #{d.name}]".bind do |s|
|
|
240
|
+
if usage.forbidden?
|
|
241
|
+
ansi.forbidden(s)
|
|
242
|
+
elsif usage.required?
|
|
243
|
+
ansi.required(s)
|
|
244
|
+
else
|
|
245
|
+
ansi.optional(s)
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
hh = @hour.try{|h| "%02d" % h } || "hh"
|
|
251
|
+
mm = @minute.try{|m| "%02d" % m } || "mm"
|
|
252
|
+
ss = @second.try{|s| s.to_s("F") } || "ss"
|
|
253
|
+
ss = ss.gsub(/^0*\.|\.0*$/, "")
|
|
254
|
+
|
|
255
|
+
ansi.element("TM.value#{id}") + "(#{hh}:#{mm}:#{ss})"
|
|
256
|
+
end
|
|
257
|
+
# :nocov:
|
|
258
|
+
|
|
259
|
+
# @return [String]
|
|
260
|
+
def to_s(hh = "hh", mm = "mm", ss = "ss")
|
|
261
|
+
hh = @hour.try{|h| "%02d" % h } || hh
|
|
262
|
+
mm = @minute.try{|m| "%02d" % m } || mm
|
|
263
|
+
ss = @second.try{|s| "%02f" % s } || ss
|
|
264
|
+
"#{hh}:#{mm}:#{ss}".gsub(/\.?0*$|:$/, "")
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# @return [String]
|
|
268
|
+
def to_x12(truncate = true)
|
|
269
|
+
hh = @hour.try{|h| "%02d" % h }
|
|
270
|
+
mm = @minute.try{|m| "%02d" % m }
|
|
271
|
+
ss = @second.try{|s| "%02d" % s }
|
|
272
|
+
ff = @second.try{|s| s.frac.to_s("F").gsub(/^0*\.|0+$/, "") }
|
|
273
|
+
|
|
274
|
+
x12 = "#{hh}#{mm}#{ss}#{ff}"
|
|
275
|
+
|
|
276
|
+
truncate ? x12.take(definition.max_length) : x12
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
class << TimeVal
|
|
282
|
+
# @group Constructors
|
|
283
|
+
###################################################################
|
|
284
|
+
|
|
285
|
+
# @return [TimeVal]
|
|
286
|
+
def empty(usage, position)
|
|
287
|
+
self::Empty.new(usage, position)
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
# @return [TimeVal]
|
|
291
|
+
def value(object, usage, position)
|
|
292
|
+
if object.is_a?(TimeVal)
|
|
293
|
+
object#.copy(:usage => usage, :position => position)
|
|
294
|
+
elsif object.blank?
|
|
295
|
+
self::Empty.new(usage, position)
|
|
296
|
+
elsif object.is_a?(String) or object.is_a?(StringVal)
|
|
297
|
+
return self::Invalid.new(object, usage, position) \
|
|
298
|
+
unless object =~ /^\d{4,}$/
|
|
299
|
+
|
|
300
|
+
hour = object.to_s.slice(0, 2).to_i
|
|
301
|
+
minute = object.to_s.slice(2, 2).try{|mm| mm.to_i unless mm.blank? }
|
|
302
|
+
second = object.to_s.slice(4, 2).try{|ss| ss.to_d unless ss.blank? }
|
|
303
|
+
|
|
304
|
+
if decimal = object.to_s.slice(6..-1)
|
|
305
|
+
decimal = 0 if decimal.empty?
|
|
306
|
+
second += "0.#{decimal}".to_d
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
self::NonEmpty.new(hour, minute, second, usage, position)
|
|
310
|
+
elsif object.respond_to?(:hour) and
|
|
311
|
+
object.respond_to?(:min) and
|
|
312
|
+
object.respond_to?(:sec)
|
|
313
|
+
sec = object.sec.to_d
|
|
314
|
+
|
|
315
|
+
if object.respond_to?(:usec)
|
|
316
|
+
sec += object.usec.to_d / 1000000
|
|
317
|
+
elsif object.respond_to?(:sec_fraction)
|
|
318
|
+
sec += object.sec_fraction.to_d
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
self::NonEmpty.new(object.hour, object.min, sec, usage, position)
|
|
322
|
+
elsif object.respond_to?(:hour) and
|
|
323
|
+
object.respond_to?(:minute) and
|
|
324
|
+
object.respond_to?(:second)
|
|
325
|
+
self::NonEmpty.new(object.hour, object.minute, object.second.to_d, usage, position)
|
|
326
|
+
elsif object.is_a?(Array) and object.length == 3
|
|
327
|
+
self::NonEmpty.new(*object, usage, position)
|
|
328
|
+
else
|
|
329
|
+
self::Invalid.new(object, usage, position)
|
|
330
|
+
end
|
|
331
|
+
rescue Exceptions::InvalidElementError
|
|
332
|
+
self::Invalid.new(object, usage, position)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# @endgroup
|
|
336
|
+
###################################################################
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
# Prevent direct instantiation of abstract class TimeVal
|
|
340
|
+
TimeVal.eigenclass.send(:protected, :new)
|
|
341
|
+
TimeVal::Empty.eigenclass.send(:public, :new)
|
|
342
|
+
TimeVal::Invalid.eigenclass.send(:public, :new)
|
|
343
|
+
TimeVal::NonEmpty.eigenclass.send(:public, :new)
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Versions
|
|
4
|
+
module Common
|
|
5
|
+
module ElementTypes
|
|
6
|
+
autoload :DT, "stupidedi/versions/common/element_types/dt"
|
|
7
|
+
autoload :DateVal, "stupidedi/versions/common/element_types/dt"
|
|
8
|
+
|
|
9
|
+
autoload :R, "stupidedi/versions/common/element_types/r"
|
|
10
|
+
autoload :FloatVal, "stupidedi/versions/common/element_types/r"
|
|
11
|
+
|
|
12
|
+
autoload :ID, "stupidedi/versions/common/element_types/id"
|
|
13
|
+
autoload :IdentifierVal, "stupidedi/versions/common/element_types/id"
|
|
14
|
+
|
|
15
|
+
autoload :Nn, "stupidedi/versions/common/element_types/nn"
|
|
16
|
+
autoload :FixnumVal, "stupidedi/versions/common/element_types/nn"
|
|
17
|
+
|
|
18
|
+
autoload :AN, "stupidedi/versions/common/element_types/an"
|
|
19
|
+
autoload :StringVal, "stupidedi/versions/common/element_types/an"
|
|
20
|
+
|
|
21
|
+
autoload :TM, "stupidedi/versions/common/element_types/tm"
|
|
22
|
+
autoload :TimeVal, "stupidedi/versions/common/element_types/tm"
|
|
23
|
+
|
|
24
|
+
autoload :Operators, "stupidedi/versions/common/element_types/operators"
|
|
25
|
+
autoload :SimpleElementDef, "stupidedi/versions/common/element_types/simple_element"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Versions
|
|
4
|
+
module Common
|
|
5
|
+
#
|
|
6
|
+
# @see X222.pdf A.1.3.9 Condition Designator
|
|
7
|
+
# @see X222.pdf A.1.3.12.6 Data Segment Requirement Designator
|
|
8
|
+
#
|
|
9
|
+
module SegmentReqs
|
|
10
|
+
Mandatory = Schema::SegmentReq.new(true, false, "M")
|
|
11
|
+
Optional = Schema::SegmentReq.new(false, false, "O")
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
using Refinements
|
|
4
|
+
|
|
5
|
+
module Versions
|
|
6
|
+
module Common
|
|
7
|
+
#
|
|
8
|
+
# @see X222.pdf A.1.3.4 Syntax Notes
|
|
9
|
+
# @see X222.pdf A.1.3.8 Condition Designator
|
|
10
|
+
#
|
|
11
|
+
module SyntaxNotes
|
|
12
|
+
#
|
|
13
|
+
# Paired or Multiple: if any element specified in the relational
|
|
14
|
+
# condition is present, then all of the elements specified must
|
|
15
|
+
# be present.
|
|
16
|
+
#
|
|
17
|
+
class P < Schema::SyntaxNote
|
|
18
|
+
def required(zipper)
|
|
19
|
+
# if zipper.node.present?
|
|
20
|
+
xs = children(zipper)
|
|
21
|
+
xs.any?{|x| x.node.present? } ? xs : []
|
|
22
|
+
# else
|
|
23
|
+
# []
|
|
24
|
+
# end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def forbidden(zipper)
|
|
28
|
+
[]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def reason(zipper)
|
|
32
|
+
present = indexes.select{|n| zipper.child(n - 1).node.present? }
|
|
33
|
+
missing = indexes - present
|
|
34
|
+
"elements #{missing.join(", ")} must be present when elements #{present.join(", ")} are present"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# Required: at least one of the elements specified in the condition
|
|
40
|
+
# must be present
|
|
41
|
+
#
|
|
42
|
+
class R < Schema::SyntaxNote
|
|
43
|
+
def required(zipper)
|
|
44
|
+
# if zipper.node.present?
|
|
45
|
+
xs = children(zipper)
|
|
46
|
+
xs.any?{|x| x.node.present? } ? [] : xs
|
|
47
|
+
# else
|
|
48
|
+
# []
|
|
49
|
+
# end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def forbidden(zipper)
|
|
53
|
+
[]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def reason(zipper)
|
|
57
|
+
present = indexes.select{|n| zipper.child(n - 1).node.present? }
|
|
58
|
+
missing = indexes - present
|
|
59
|
+
"at least one of elements #{missing.join(", ")} must be present"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
#
|
|
64
|
+
# Exclusion: not more than one of the elements in the condition may
|
|
65
|
+
# be present
|
|
66
|
+
#
|
|
67
|
+
class E < Schema::SyntaxNote
|
|
68
|
+
def required(zipper)
|
|
69
|
+
[]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def forbidden(zipper)
|
|
73
|
+
# if zipper.node.present?
|
|
74
|
+
xs = children(zipper)
|
|
75
|
+
xs.count{|x| x.node.present? } <= 1 ? [] : xs
|
|
76
|
+
# else
|
|
77
|
+
# []
|
|
78
|
+
# end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def reason(zipper)
|
|
82
|
+
present = indexes.select{|n| zipper.child(n - 1).node.present? }
|
|
83
|
+
"only one of elements #{present.join(", ")} may be present"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
#
|
|
88
|
+
# Conditional: if the first element specified in the condition is
|
|
89
|
+
# present, then all other elements must be specified.
|
|
90
|
+
#
|
|
91
|
+
class C < Schema::SyntaxNote
|
|
92
|
+
def required(zipper)
|
|
93
|
+
# if zipper.node.present?
|
|
94
|
+
if zipper.child(indexes.head - 1).node.present?
|
|
95
|
+
children(zipper).tail
|
|
96
|
+
else
|
|
97
|
+
[]
|
|
98
|
+
end
|
|
99
|
+
# else
|
|
100
|
+
# []
|
|
101
|
+
# end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def forbidden(zipper)
|
|
105
|
+
[]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def reason(zipper)
|
|
109
|
+
"elements #{indexes.tail.join(", ")} must be present when element #{indexes.head} is present"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
#
|
|
114
|
+
# List Conditional: if the first element specified in the condition is
|
|
115
|
+
# present, then at least one of the remaining elements must be present
|
|
116
|
+
#
|
|
117
|
+
class L < Schema::SyntaxNote
|
|
118
|
+
def required(zipper)
|
|
119
|
+
# if zipper.node.present?
|
|
120
|
+
if zipper.child(indexes.head - 1).node.present?
|
|
121
|
+
xs = children(zipper).tail
|
|
122
|
+
xs.any?{|x| x.node.present? } ? [] : xs
|
|
123
|
+
else
|
|
124
|
+
[]
|
|
125
|
+
end
|
|
126
|
+
# else
|
|
127
|
+
# []
|
|
128
|
+
# end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def forbidden(zipper)
|
|
132
|
+
[]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def reason(zipper)
|
|
136
|
+
"at least one of elements #{indexes.tail.join(", ")} must be present when element #{indexes.head} is present"
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
class << P
|
|
141
|
+
def build(*args)
|
|
142
|
+
new(args)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
class << R
|
|
147
|
+
def build(*args)
|
|
148
|
+
new(args)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
class << E
|
|
153
|
+
def build(*args)
|
|
154
|
+
new(args)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
class << C
|
|
159
|
+
def build(*args)
|
|
160
|
+
new(args)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
class << L
|
|
165
|
+
def build(*args)
|
|
166
|
+
new(args)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Versions
|
|
4
|
+
module Common
|
|
5
|
+
autoload :ElementReqs, "stupidedi/versions/common/element_reqs"
|
|
6
|
+
autoload :ElementTypes, "stupidedi/versions/common/element_types"
|
|
7
|
+
autoload :SegmentReqs, "stupidedi/versions/common/segment_reqs"
|
|
8
|
+
autoload :SyntaxNotes, "stupidedi/versions/common/syntax_notes"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Stupidedi
|
|
3
|
+
module Versions
|
|
4
|
+
autoload :Common, "stupidedi/versions/common"
|
|
5
|
+
|
|
6
|
+
# Per-era namespaces that lived under +Stupidedi::Versions+ in the
|
|
7
|
+
# upstream stupidedi gem (plus the two long-deprecated
|
|
8
|
+
# +FunctionalGroups+ / +Interchanges+ aliases). tediparse does not ship
|
|
9
|
+
# them; reach for one by name and we surface a helpful error rather
|
|
10
|
+
# than +NameError+.
|
|
11
|
+
REMOVED_ERAS = %i[
|
|
12
|
+
TwoThousandOne ThirtyTen ThirtyForty ThirtyFifty FortyTen FiftyTen
|
|
13
|
+
FunctionalGroups Interchanges
|
|
14
|
+
].freeze
|
|
15
|
+
private_constant :REMOVED_ERAS
|
|
16
|
+
|
|
17
|
+
def self.const_missing(name)
|
|
18
|
+
if REMOVED_ERAS.include?(name.to_sym)
|
|
19
|
+
raise Stupidedi::Exceptions::MissingGrammarError.new("#{self}::#{name}")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
super
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|