Skip to content

Commit

Permalink
Continue reading input following end of interchange (#359)
Browse files Browse the repository at this point in the history
Fixes #358

Signed-off-by: Michael Edgar <[email protected]>
  • Loading branch information
MikeEdgar authored Apr 30, 2023
1 parent 4b8ddc3 commit a313ef2
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 9 deletions.
25 changes: 17 additions & 8 deletions src/main/java/io/xlate/edi/internal/stream/StaEDIStreamReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

import io.xlate.edi.internal.schema.SchemaUtils;
import io.xlate.edi.internal.stream.tokenization.Dialect;
import io.xlate.edi.internal.stream.tokenization.EDIException;
import io.xlate.edi.internal.stream.tokenization.Lexer;
import io.xlate.edi.internal.stream.tokenization.ProxyEventHandler;
import io.xlate.edi.schema.EDIReference;
Expand Down Expand Up @@ -61,6 +62,11 @@ public class StaEDIStreamReader implements EDIStreamReader, Configurable {
private boolean closed = false;
private boolean deprecationLogged = false;

@FunctionalInterface
interface EDIStreamReaderRunner {
void execute() throws IOException, EDIException;
}

public StaEDIStreamReader(
InputStream stream,
Charset charset,
Expand Down Expand Up @@ -176,6 +182,15 @@ public Map<String, Character> getDelimiters() {
return Collections.unmodifiableMap(delimiters);
}

void executeTask(EDIStreamReaderRunner runner, String errorMessage) throws EDIStreamException {
try {
runner.execute();
} catch (IOException e) {
Location where = getLocation();
throw new EDIStreamException(errorMessage, where, e);
}
}

private EDIStreamEvent nextEvent() throws EDIStreamException {
ensureOpen();
ensureIncomplete();
Expand All @@ -198,21 +213,15 @@ private EDIStreamEvent nextEvent() throws EDIStreamException {

if (!proxy.nextEvent()) {
proxy.resetEvents();

try {
lexer.parse();
} catch (IOException e) {
Location where = getLocation();
throw new EDIStreamException("Error parsing input", where, e);
}
executeTask(lexer::parse, "Error parsing input");
}

final EDIStreamEvent event = proxy.getEvent();

LOGGER.finer(() -> "EDI event: " + event);

if (event == EDIStreamEvent.END_INTERCHANGE) {
complete = true;
executeTask(() -> complete = !proxy.hasNext() && !lexer.hasRemaining(), "Error reading input");
}

if (event == EDIStreamEvent.ELEMENT_DATA && proxy.isBinaryElementLength()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,24 @@ public boolean isDelimiter(int character) {
}
}

public boolean isWhitespace(int character) {
CharacterClass clazz = getClass(character);

switch (clazz) {
case SPACE:
case WHITESPACE:
return true;
default:
return ignore(clazz);
}
}

public boolean isIgnored(int character) {
switch (getClass(character)) {
return ignore(getClass(character));
}

private boolean ignore(CharacterClass clazz) {
switch (clazz) {
case CONTROL:
case INVALID:
case WHITESPACE:
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/io/xlate/edi/internal/stream/tokenization/Lexer.java
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,19 @@ public int read() throws IOException {
state = State.ELEMENT_DATA_BINARY;
}

public boolean hasRemaining() throws IOException {
stream.mark(200);
int peekInput;
boolean spaceOnly = true;

while ((peekInput = stream.read()) > -1 && spaceOnly) {
spaceOnly = characters.isWhitespace(peekInput);
}

stream.reset();
return !spaceOnly;
}

public void parse() throws IOException, EDIException {
try {
parse(this::readCharacterUnchecked);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ public CharBuffer getCharacters() {
return current(StreamEvent::getData, null);
}

public boolean hasNext() {
// Current event is in the first position, second will be used for `nextEvent`
return eventQueue.size() > 1;
}

public boolean nextEvent() {
if (eventQueue.isEmpty()) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2107,4 +2107,32 @@ void testHierarchicalLoopsNested() throws IOException {

assertEquals(expected, actual.toString());
}

@Test
void testMultipleInterchangesInStream() throws EDIStreamException, IOException {
EDIInputFactory factory = EDIInputFactory.newFactory();
EDIStreamReader reader = factory.createEDIStreamReader(getClass().getResourceAsStream("/x12/simple997-multiple-interchanges.edi"));
int interchangeStart = 0;
int interchangeEnd = 0;

try {
while (reader.hasNext()) {
switch (reader.next()) {
case START_INTERCHANGE:
interchangeStart++;
break;
case END_INTERCHANGE:
interchangeEnd++;
break;
default:
break;
}
}
} finally {
reader.close();
}

assertEquals(2, interchangeStart);
assertEquals(2, interchangeEnd);
}
}
24 changes: 24 additions & 0 deletions src/test/resources/x12/simple997-multiple-interchanges.edi
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
ISA*00* *00* *ZZ*ReceiverID *ZZ*Sender *050812*1953*^*00501*508121953*0*P*:~
GS*FA*ReceiverDept*SenderDept*20050812*195335*000005*X*005010X230~
ST*997*0001~
AK1*HC*000001~
AK2*837*0021~
AK3*NM1*8**8~
AK4*8*66*7*MI~
AK5*R*5~
AK9*R*1*1*0~
SE*8*0001~
GE*1*000005~
IEA*1*508121953~
ISA*00* *00* *ZZ*ReceiverID *ZZ*Sender *050812*1953*^*00501*508121953*0*P*:~
GS*FA*ReceiverDept*SenderDept*20050812*195335*000005*X*005010X230~
ST*997*0001~
AK1*HC*000001~
AK2*837*0021~
AK3*NM1*8**8~
AK4*8*66*7*MI~
AK5*R*5~
AK9*R*1*1*0~
SE*8*0001~
GE*1*000005~
IEA*1*508121953~

0 comments on commit a313ef2

Please sign in to comment.