Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: reached end of input before finding ISA segment identifier #12

Closed
Shpigford opened this issue Jun 14, 2013 · 6 comments
Closed

Comments

@Shpigford
Copy link

When trying to read some data, I'm getting this error:

reached end of input before finding ISA segment identifier

Here's the sample data: https://gist.github.com/Shpigford/daedb0a0e2eeb52cd384

This is data directly from the provider (in this case, UPS). And seems pretty standard across all the files I'm receiving from them.

@kputnam
Copy link
Owner

kputnam commented Jun 14, 2013

Hi Josh,

I'm assuming you have something like parser, result = parser.read(...), where parser is a StateMachine instance.

The second return value from this call will always be Result.failure(...) because reaching the end of the file is an error to the tokenizer -- it's unknown to the tokenizer if the caller expected this or not. However, it's labeled a non-fatal error: you can test for more serious errors with result.fatal?, which might happen if the file has invalid delimiters, etc.

The first return value, parser is the new StateMachine which points at the last segment of the parse tree constructed by reading the input. You might check parser.empty? to make sure that the contents of the file were read into the parse tree -- the tokenizer skips past everything until it finds a valid ISA segment.

@Shpigford
Copy link
Author

Here's what I've got...

input = File.open("public/ups/UPSS_06_13_2013_1020110058.DAT", encoding: "ISO-8859-1")
=> #<File:public/ups/UPSS_06_13_2013_1020110058.DAT>

parser, result = parser.read(Stupidedi::Reader.build(input))
=> [#<Stupidedi::Builder::StateMachine:0x3fdf82ffb0a8 ...>, Either.failure("reached end of input before finding ISA segment identifier")]

parser.empty?
=> false

parser.segment
=> Either.success(#<Stupidedi::Zipper::EditedCursor:0x007fbf05ff6358 @node=IEA, @path=root/4/1054, @parent=#<Stupidedi::Zipper::EditedCursor:0x007fbf28739b98 @node=InvalidEnvelopeVal(), @path=root/4, @parent=#<Stupidedi::Zipper::RootCursor:0x007fbf3714b5b0 @node=TransmissionVal(), @path=root>>>)

parser.segment.map(&:node)
=> Either.success(IEA)

parser.segment.map(&:parent).map(&:node)
=> Either.success(InvalidEnvelopeVal())

parser.element(1)
=> Either.failure("invalid segment")

parser.first.map(&:first?)
=> Either.success(true)

parser.next
=> Either.failure("cannot move to next after last segment")

Something just feels...off. I've run through the documentation and tried various methods to access the data and just can't seem to get it.

Maybe I'm doing something wrong?

@kputnam
Copy link
Owner

kputnam commented Jun 17, 2013

Looks like you just need to rewind the parser to the start of the parse tree -- the #read method leaves it positioned on the last segment that was parsed (IEA).

Take a look at bin/edi-pp for an example, but parser = parser.first will give you Either.success(#<Stupidedi::Builder::StateMachine:...>), where the parser is positioned at the start. You'll need to use #map, #tap, and #flatmap to manipulate the StateMachine inside the Either wrapper.

Secondly, your document is QM214, which I recently merged into the contrib namespace. You'll need to use config = Stupidedi::Config.contrib to parse this file -- otherwise you'll see mostly InvalidSegmentVal values in the parse tree. Be sure to pull the latest commits, I fixed a few issues just now.

Since these were contributed by other authors and I don't have the official grammar for this transaction, you probably need to make changes to the grammar. For instance, the grammar in Stupidedi for QM214 doesn't allow MAN, N1, or CD3 segments but your document has these. If you need the information contained in these segments, you'll need to find some documentation like this or this from your EDI trading partner. If you don't need those segments, you can probably leave things as-is -- the parser will add InvalidSegmentVal nodes in their place, which generally are ignored when moving around the parse tree.

-- Kyle

@Shpigford
Copy link
Author

Gotcha! Okay, getting there. One more question...how do I select the second of a duplicate element?

For example, there's this segment:

ST|214|000056390~
B10|0|0|UPSN~
L11|QVD|TN|O4~
L11|1Z6VX489YN03534815|2I~
N1|SH|NA|25|6VX489~
N1|BT||25|6VX489|01~
LX|1~
AT7|X8|AJ|||20130613|003551|LT~
AT7|||AB|BG|20130613~
L11|2U-UPS WILL ATTEMPT DELIVERY|REC|KAGE WILL NOT BE TRANSFERRED T~
MAN|CP|E1|PITTSBURGH DOWNTOWN|CP|PA|US~
CD3|||R4~
N1|UP|NA~
SE|14|000056390~

Then I do this:

a.flatmap{|m| m.find(:GS) }.flatmap{|m| m.find(:ST) }.tap do |m|
   el(m.find(:L11), 3){|e| puts "Transaction Reference Number: #{e}" }
   el(m.find(:L11)){|e| puts "Tracking Number: #{e}" }
end

That first L11 works correctly (and pulls O4). But I want to get the next L11 to retrieve 1Z6VX489YN03534815

(Really appreciate your help so far!)

@kputnam
Copy link
Owner

kputnam commented Jun 17, 2013

It seems like the second element of L11 specifies which "type" of L11 it is, so I would probably do something like this, since TN or 2I probably mean something specific and you'll want to act on them differently:

el(m.find(:L11, nil, "TN"), 3){|e| ... }
el(m.find(:L11, nil, "2I"), 3){|e| ... }

You'll need to check specs for QM 214 to be certain, but usually that's how these documents work. If you can have many L11*...*TN segments or many L11*..*2I segments in a row, or if the second element is not a qualifier, you should do something like this:

# Loop through each L11 sequentially
m.iterate(:L11) do |l11|
  el(l11, 3){|el| ... }
end

@kputnam
Copy link
Owner

kputnam commented Jun 17, 2013

I've also added a method #sequence which isn't documented yet. It's just shorthand for chaining multiple #find calls. Here's an example:

a.flatmap{|m| m.sequence(:GS, :ST) }.tap do |m|
   ...
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants