stupidedi 1.2.20 → 1.3.21
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -1
- data/bin/edi-obfuscate +112 -0
- data/lib/stupidedi/builder/generation.rb +39 -11
- data/lib/stupidedi/builder/navigation.rb +15 -2
- data/lib/stupidedi/either.rb +1 -1
- data/lib/stupidedi/reader/tokens/component_element_tok.rb +12 -0
- data/lib/stupidedi/reader/tokens/composite_element_tok.rb +17 -0
- data/lib/stupidedi/reader/tokens/segment_tok.rb +19 -1
- data/lib/stupidedi/reader/tokens/simple_element_tok.rb +12 -0
- data/lib/stupidedi/values/functional_group_val.rb +1 -1
- data/lib/stupidedi/values/interchange_val.rb +1 -1
- data/lib/stupidedi/values/loop_val.rb +1 -1
- data/lib/stupidedi/values/table_val.rb +1 -1
- data/lib/stupidedi/values/transaction_set_val.rb +1 -1
- data/lib/stupidedi/values/transmission_val.rb +1 -1
- data/lib/stupidedi/version.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/002001/element_defs.rb +1 -14
- data/lib/stupidedi/versions/functional_groups/002001/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/002001/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/002001/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/002001/element_types/identifier_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/002001/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/002001/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_defs.rb +1 -14
- data/lib/stupidedi/versions/functional_groups/003010/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/003010/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_types/identifier_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_defs.rb +1 -14
- data/lib/stupidedi/versions/functional_groups/003040/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/003040/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_types/identifier_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_defs.rb +1 -14
- data/lib/stupidedi/versions/functional_groups/003050/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/003050/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_types/identifier_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/004010/element_defs.rb +2 -3
- data/lib/stupidedi/versions/functional_groups/004010/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/004010/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/004010/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/004010/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/004010/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/005010/element_types/date_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/005010/element_types/fixnum_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/005010/element_types/float_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/005010/element_types/string_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/005010/element_types/time_val.rb +1 -1
- data/lib/stupidedi/versions/interchanges/00200/element_defs.rb +1 -1
- data/lib/stupidedi/versions/interchanges/00300/element_defs.rb +1 -1
- data/lib/stupidedi/versions/interchanges/00400/element_defs.rb +1 -1
- data/lib/stupidedi/versions/interchanges/00401/element_defs.rb +1 -1
- data/spec/examples/integration/navigating_spec.rb +44 -0
- data/spec/examples/integration/nondeterminism_spec.rb +165 -0
- metadata +4 -2
@@ -98,7 +98,7 @@ module Stupidedi
|
|
98
98
|
|
99
99
|
def inspect
|
100
100
|
id = definition.try{|d| ansi.bold("[#{d.id}]") }
|
101
|
-
ansi.element("SeparatorElementVal.value#{id}")
|
101
|
+
ansi.element("SeparatorElementVal.value#{id}") + "(#{@value || "nil"})"
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -98,7 +98,7 @@ module Stupidedi
|
|
98
98
|
|
99
99
|
def inspect
|
100
100
|
id = definition.try{|d| ansi.bold("[#{d.id}]") }
|
101
|
-
ansi.element("SeparatorElementVal.value#{id}")
|
101
|
+
ansi.element("SeparatorElementVal.value#{id}") + "(#{@value || "nil"})"
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -98,7 +98,7 @@ module Stupidedi
|
|
98
98
|
|
99
99
|
def inspect
|
100
100
|
id = definition.try{|d| ansi.bold("[#{d.id}]") }
|
101
|
-
ansi.element("SeparatorElementVal.value#{id}")
|
101
|
+
ansi.element("SeparatorElementVal.value#{id}") + "(#{@value || "nil"})"
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -99,7 +99,7 @@ module Stupidedi
|
|
99
99
|
|
100
100
|
def inspect
|
101
101
|
id = definition.try{|d| ansi.bold("[#{d.id}]") }
|
102
|
-
ansi.element("SeparatorElementVal.value#{id}")
|
102
|
+
ansi.element("SeparatorElementVal.value#{id}") + "(#{@value || "nil"})"
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
@@ -49,6 +49,50 @@ describe "Navigating" do
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
context "repeatable segments" do
|
53
|
+
specify "can be iterated" do
|
54
|
+
expect(lambda do
|
55
|
+
payment.flatmap do |m|
|
56
|
+
m.iterate(:ISA) do |isa|
|
57
|
+
raise "didn't expect a second ISA segment"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end).not_to raise_error
|
61
|
+
end
|
62
|
+
|
63
|
+
specify "can be iterated" do
|
64
|
+
expect(lambda do
|
65
|
+
payment.flatmap do |m|
|
66
|
+
m.iterate(:GS) do |gs|
|
67
|
+
expect(gs.segment.tap do |segment|
|
68
|
+
expect(segment.node.id).to eq(:GS)
|
69
|
+
end).to be_defined
|
70
|
+
|
71
|
+
gs.iterate(:ST) do |st|
|
72
|
+
expect(st.segment.tap do |segment|
|
73
|
+
expect(segment.node.id).to eq(:ST)
|
74
|
+
end).to be_defined
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end).not_to raise_error
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "non-repeatable segments" do
|
83
|
+
specify "cannot be iterated" do
|
84
|
+
expect(lambda do
|
85
|
+
payment.flatmap do |m|
|
86
|
+
m.iterate(:GS) do |gs|
|
87
|
+
gs.iterate(:ST) do |st|
|
88
|
+
st.iterate(:BHT)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end).to raise_error("BHT segment is not repeatable")
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
52
96
|
describe "error handling" do
|
53
97
|
context "accessing an undefined element" do
|
54
98
|
it "raises an exception" do
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "pp"
|
3
|
+
|
4
|
+
describe "Non-determinism" do
|
5
|
+
include NavigationMatchers
|
6
|
+
|
7
|
+
let(:strict) { Stupidedi::Builder::BuilderDsl.build(config, true) }
|
8
|
+
let(:relaxed) { Stupidedi::Builder::BuilderDsl.build(config, false) }
|
9
|
+
|
10
|
+
let(:config) do
|
11
|
+
Stupidedi::Config.default.customize do |c|
|
12
|
+
c.transaction_set.customize do |x|
|
13
|
+
x.register("005010", "BE", "999") { schema }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:schema) do
|
19
|
+
d = Stupidedi::Schema
|
20
|
+
r = Stupidedi::Versions::FunctionalGroups::FiftyTen::SegmentReqs
|
21
|
+
s = Stupidedi::Versions::FunctionalGroups::FiftyTen::SegmentDefs
|
22
|
+
|
23
|
+
d::TransactionSetDef.build("BE", "000", "Example of Ambiguous Grammar",
|
24
|
+
d::TableDef.header("Table 1",
|
25
|
+
s::ST.use(10, r::Mandatory, d::RepeatCount.bounded(1))),
|
26
|
+
d::TableDef.detail("Table 2",
|
27
|
+
d::LoopDef.build("Loop 1", d::RepeatCount.bounded(1),
|
28
|
+
s::N1.use(20, r::Mandatory, d::RepeatCount.bounded(1)),
|
29
|
+
s::N3.use(30, r::Optional, d::RepeatCount.bounded(1))),
|
30
|
+
d::LoopDef.build("Loop 2", d::RepeatCount.bounded(1),
|
31
|
+
s::N1.use(40, r::Mandatory, d::RepeatCount.bounded(1)),
|
32
|
+
s::N4.use(50, r::Optional, d::RepeatCount.bounded(1)))),
|
33
|
+
d::TableDef.summary("Table 3",
|
34
|
+
s::SE.use(60, r::Mandatory, d::RepeatCount.bounded(1))))
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:nondet_zero) { Fixtures.parse_("GH-129/1.txt") }
|
38
|
+
let(:nondet_five) { Fixtures.parse_("GH-129/1.txt") }
|
39
|
+
let(:nondet_nine) { Fixtures.parse_("GH-129/1.txt") }
|
40
|
+
|
41
|
+
def prelude(dsl)
|
42
|
+
dsl.ISA("00", "", "00", "", "ZZ", "_", "ZZ", "_",
|
43
|
+
Time.now.utc, Time.now.utc, "", "00501",
|
44
|
+
123456789, "1", "T", "")
|
45
|
+
|
46
|
+
dsl.GS("BE", "SENDER ID", "RECEIVER ID",
|
47
|
+
Time.now.utc, Time.now.utc, "1", "X", "005010")
|
48
|
+
|
49
|
+
dsl.ST("999", "0000", "005010")
|
50
|
+
end
|
51
|
+
|
52
|
+
context "generating an ambiguous segment" do
|
53
|
+
context "when strict" do
|
54
|
+
it "throws an exception" do
|
55
|
+
expect(lambda do
|
56
|
+
prelude(strict)
|
57
|
+
.N1("6Y", "BOB BELCHER")
|
58
|
+
.N1("6Y", "NON DETERMINISM") # could be Loop 1 or Loop 2
|
59
|
+
end).to raise_error \
|
60
|
+
"non-deterministic machine state: N1 Party Identification, N1 Party Identification"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when non-strict" do
|
65
|
+
it "does not throw an exception" do
|
66
|
+
expect(lambda do
|
67
|
+
prelude(relaxed)
|
68
|
+
.N1("6Y", "BOB BELCHER")
|
69
|
+
.N1("6Y", "NON DETERMINISM") # could be Loop 1 or Loop 2
|
70
|
+
end).not_to raise_error
|
71
|
+
end
|
72
|
+
|
73
|
+
context "with later unambiguous input" do
|
74
|
+
it "does not discard invalid trees" do
|
75
|
+
expect(prelude(relaxed)
|
76
|
+
.N1("6Y", "BOB BELCHER")
|
77
|
+
.N1("6Y", "NON DETERMINISM") # could be Loop 1 or Loop 2
|
78
|
+
.N3("OCEAN AVENUE") # could only be Loop 1
|
79
|
+
.machine.active.length
|
80
|
+
).to eq(2)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "does not discard invalid trees" do
|
84
|
+
expect(prelude(relaxed)
|
85
|
+
.N1("6Y", "BOB BELCHER")
|
86
|
+
.N1("6Y", "NON DETERMINISM") # could be Loop 1 or Loop 2
|
87
|
+
.N4("UNKNOWN CITY") # could only be Loop 2
|
88
|
+
.machine.active.length
|
89
|
+
).to eq(2)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "reading" do
|
96
|
+
def read(suffix, nondeterminism: 1)
|
97
|
+
input =
|
98
|
+
["ISA*00*..........*01*SECRET....*ZZ*SUBMITTERS.ID..*ZZ*RECEIVERS.ID...*030101*1253*^*00501*000000905*1*T*:~",
|
99
|
+
"GS*BE*SENDER ID*RECEIVER ID*19991231*0802*1*x*005010~",
|
100
|
+
"ST*999*0000*005010~",
|
101
|
+
"N1*6Y*LINDA BELCHER~",
|
102
|
+
suffix].join("\n")
|
103
|
+
|
104
|
+
machine = Stupidedi::Builder::StateMachine.build(config)
|
105
|
+
machine.read(Stupidedi::Reader.build(input), nondeterminism: nondeterminism)
|
106
|
+
end
|
107
|
+
|
108
|
+
context "when nondenterminism = 1" do
|
109
|
+
it "ordinary input suceeds" do
|
110
|
+
machine, result = read("N3*OCEAN AVENUE~", nondeterminism: 1)
|
111
|
+
|
112
|
+
result.should_not be_fatal
|
113
|
+
result.reason.should eq("reached end of input without finding a segment identifier")
|
114
|
+
machine.should be_deterministic
|
115
|
+
end
|
116
|
+
|
117
|
+
it "ambiguous input causes a failure result" do
|
118
|
+
machine, result = read("N1*6Y*NON DETERMINISM~...", nondeterminism: 1)
|
119
|
+
|
120
|
+
result.should be_fatal # no usable parse tree
|
121
|
+
result.reason.should eq("too much non-determinism: N1 Party Identification, N1 Party Identification")
|
122
|
+
result.remainder.should eq("...")
|
123
|
+
machine.should_not be_deterministic
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "when nondenterminism = 2" do
|
128
|
+
it "acceptably ambiguous input succeeds" do
|
129
|
+
machine, result = read("N1*6Y*NON DETERMINISM~...", nondeterminism: 2)
|
130
|
+
|
131
|
+
result.should_not be_fatal # we have a usable parse tree, despite trailing garbage
|
132
|
+
result.remainder.should eq("...")
|
133
|
+
machine.should_not be_deterministic
|
134
|
+
machine.active.length.should eq(2)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "too much ambiguity causes a failure" do
|
138
|
+
machine, result = read(
|
139
|
+
"N1*6Y*NON DETERMINISM~" \
|
140
|
+
"N1*6Y*THIS IS TOO MUCH~...", nondeterminism: 2)
|
141
|
+
|
142
|
+
result.should be_fatal # no useable parse tree
|
143
|
+
result.remainder.should eq("...")
|
144
|
+
machine.should_not be_deterministic
|
145
|
+
machine.active.length.should eq(1 + 2)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context "when nondenterminism = 3" do
|
150
|
+
it "too much ambiguity causes a failure" do
|
151
|
+
machine, result = read(
|
152
|
+
"N1*6Y*NON DETERMINISM~" \
|
153
|
+
"N1*6Y*BLAH BLAH BLAH~" \
|
154
|
+
"N1*6Y*THIS IS TOO MUCH~" \
|
155
|
+
"N1*6Y*NOT GONNA SEE THIS~...", nondeterminism: 3)
|
156
|
+
|
157
|
+
result.should be_fatal # no useable parse tree
|
158
|
+
result.remainder.should eq("N1*6Y*NOT GONNA SEE THIS~...")
|
159
|
+
machine.should_not be_deterministic
|
160
|
+
machine.active.length.should eq(1 + 2*2)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stupidedi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.21
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyle Putnam/Isi Robayna
|
@@ -49,6 +49,7 @@ files:
|
|
49
49
|
- README.md
|
50
50
|
- Rakefile
|
51
51
|
- bin/edi-ed
|
52
|
+
- bin/edi-obfuscate
|
52
53
|
- bin/edi-pp
|
53
54
|
- doc/Generating.md
|
54
55
|
- doc/Navigating.md
|
@@ -973,6 +974,7 @@ files:
|
|
973
974
|
- lib/stupidedi/zipper/root_cursor.rb
|
974
975
|
- spec/examples/integration/generating_spec.rb
|
975
976
|
- spec/examples/integration/navigating_spec.rb
|
977
|
+
- spec/examples/integration/nondeterminism_spec.rb
|
976
978
|
- spec/examples/integration/parsing/005010/X091A1-HP835_spec.rb
|
977
979
|
- spec/examples/integration/parsing/005010/X212-HR276_spec.rb
|
978
980
|
- spec/examples/integration/parsing/005010/X221-HP835_spec.rb
|
@@ -1211,7 +1213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1211
1213
|
version: '0'
|
1212
1214
|
requirements: []
|
1213
1215
|
rubyforge_project:
|
1214
|
-
rubygems_version: 2.7.
|
1216
|
+
rubygems_version: 2.7.8
|
1215
1217
|
signing_key:
|
1216
1218
|
specification_version: 4
|
1217
1219
|
summary: Parse, generate, validate ASC X12 EDI
|