diff --git a/src/main/java/io/xlate/edi/internal/schema/ElementType.java b/src/main/java/io/xlate/edi/internal/schema/ElementType.java index 0e1a4159..ddd10b1c 100644 --- a/src/main/java/io/xlate/edi/internal/schema/ElementType.java +++ b/src/main/java/io/xlate/edi/internal/schema/ElementType.java @@ -20,6 +20,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Supplier; @@ -42,27 +43,27 @@ class ElementType extends BasicType implements EDISimpleType { final List versions; static class Version extends VersionedProperty { - final Long minLength; - final Long maxLength; - final Map values; + final Optional minLength; + final Optional maxLength; + final Optional> values; Version(String minVersion, String maxVersion, Long minLength, Long maxLength, Map values) { super(minVersion, maxVersion); - this.minLength = minLength; - this.maxLength = maxLength; - this.values = values; + this.minLength = Optional.ofNullable(minLength); + this.maxLength = Optional.ofNullable(maxLength); + this.values = Optional.ofNullable(values); } public long getMinLength(ElementType defaultElement) { - return minLength != null ? minLength.longValue() : defaultElement.getMinLength(); + return minLength.orElseGet(defaultElement::getMinLength); } public long getMaxLength(ElementType defaultElement) { - return maxLength != null ? maxLength.longValue() : defaultElement.getMaxLength(); + return maxLength.orElseGet(defaultElement::getMaxLength); } public Map getValues(ElementType defaultElement) { - return values != null ? values : defaultElement.getValues(); + return values.orElseGet(defaultElement::getValues); } } diff --git a/src/main/java/io/xlate/edi/internal/schema/Reference.java b/src/main/java/io/xlate/edi/internal/schema/Reference.java index 78ceec99..e26cc959 100644 --- a/src/main/java/io/xlate/edi/internal/schema/Reference.java +++ b/src/main/java/io/xlate/edi/internal/schema/Reference.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.function.BiFunction; import java.util.function.Supplier; @@ -40,21 +41,21 @@ class Reference implements EDIReference { private final String description; static class Version extends VersionedProperty { - final Integer minOccurs; - final Integer maxOccurs; + final Optional minOccurs; + final Optional maxOccurs; Version(String minVersion, String maxVersion, Integer minOccurs, Integer maxOccurs) { super(minVersion, maxVersion); - this.minOccurs = minOccurs; - this.maxOccurs = maxOccurs; + this.minOccurs = Optional.ofNullable(minOccurs); + this.maxOccurs = Optional.ofNullable(maxOccurs); } public int getMinOccurs(Reference defaultElement) { - return minOccurs != null ? minOccurs.intValue() : defaultElement.getMinOccurs(); + return minOccurs.orElseGet(defaultElement::getMinOccurs); } public int getMaxOccurs(Reference defaultElement) { - return maxOccurs != null ? maxOccurs.intValue() : defaultElement.getMaxOccurs(); + return maxOccurs.orElseGet(defaultElement::getMaxOccurs); } } diff --git a/src/main/java/io/xlate/edi/internal/stream/StaEDIStreamLocation.java b/src/main/java/io/xlate/edi/internal/stream/StaEDIStreamLocation.java index 5aa686b4..198ab75a 100644 --- a/src/main/java/io/xlate/edi/internal/stream/StaEDIStreamLocation.java +++ b/src/main/java/io/xlate/edi/internal/stream/StaEDIStreamLocation.java @@ -19,7 +19,9 @@ public class StaEDIStreamLocation extends LocationView implements Location { - private boolean repeated = false; + private boolean composite = false; + private boolean repeating = false; + private int repeatCount = -1; public StaEDIStreamLocation() { super(); @@ -32,7 +34,9 @@ public StaEDIStreamLocation(Location source) { @Override public StaEDIStreamLocation copy() { StaEDIStreamLocation copy = new StaEDIStreamLocation(this); - copy.repeated = this.repeated; + copy.composite = this.composite; + copy.repeating = this.repeating; + copy.repeatCount = this.repeatCount; return copy; } @@ -68,57 +72,93 @@ public void incrementOffset(int value) { this.columnNumber++; } - public void incrementSegmentPosition(String segmentTag) { - if (this.segmentPosition < 0) { - this.segmentPosition = 1; - } else { - this.segmentPosition++; + static int initOrIncrement(int position) { + if (position < 0) { + return 1; } + return position + 1; + } + public void incrementSegmentPosition(String segmentTag) { + this.segmentPosition = initOrIncrement(segmentPosition); this.segmentTag = segmentTag; - clearSegmentLocations(); } public void clearSegmentLocations() { this.elementPosition = -1; this.elementOccurrence = -1; + this.repeating = false; + this.repeatCount = -1; clearComponentPosition(); } public void incrementElementPosition() { - if (this.elementPosition < 0) { - this.elementPosition = 1; - } else { - this.elementPosition++; - } - + this.elementPosition = initOrIncrement(elementPosition); this.elementOccurrence = 1; clearComponentPosition(); } public void incrementElementOccurrence() { - this.elementOccurrence++; + this.elementPosition = Math.max(elementPosition, 1); + this.elementOccurrence = initOrIncrement(elementOccurrence); clearComponentPosition(); } public void incrementComponentPosition() { - if (this.componentPosition < 0) { - this.componentPosition = 1; - } else { - this.componentPosition++; - } + this.componentPosition = initOrIncrement(componentPosition); } public void clearComponentPosition() { + this.composite = false; this.componentPosition = -1; } - public void setRepeated(boolean repeated) { - this.repeated = repeated; + public void setComposite(boolean composite) { + this.composite = composite; } - public boolean isRepeated() { - return repeated; + public void setRepeating(boolean repeating) { + if (repeating) { + // Encountered a repeat delimiter + if (this.repeating) { + // Previous delimiter was repeat, increment + repeatCount++; + } else { + // First repeat delimiter for this element + repeatCount = 0; + } + } else if (this.repeating) { + // Previous delimiter was repeat, this one is not. The element just completed is a repeat + repeatCount++; + } else { + // Repeat does not apply + repeatCount = -1; + } + + this.repeating = repeating; + } + + public void incrementElement(boolean compositeBegin) { + if (composite) { + incrementComponentPosition(); + } else if (elementPosition < 0 || repeatCount == -1) { + // First element of the segment or not a repeating element + incrementElementPosition(); + } else if (repeating) { + if (compositeBegin) { + // Previous element delimiter was a repeater and the first component was encountered + incrementElementOccurrence(); + } else if (repeatCount == 0) { + // First element of the repeating series is in a new element position + incrementElementPosition(); + } else { + incrementElementOccurrence(); + } + } else if (compositeBegin) { + incrementElementPosition(); + } else { + incrementElementOccurrence(); + } } } diff --git a/src/main/java/io/xlate/edi/internal/stream/StaEDIStreamWriter.java b/src/main/java/io/xlate/edi/internal/stream/StaEDIStreamWriter.java index a43c3a7b..21459a75 100644 --- a/src/main/java/io/xlate/edi/internal/stream/StaEDIStreamWriter.java +++ b/src/main/java/io/xlate/edi/internal/stream/StaEDIStreamWriter.java @@ -394,7 +394,7 @@ void writeOutput(int output) throws EDIStreamException { } @Override - public EDIStreamWriter startInterchange() throws EDIStreamException { + public EDIStreamWriter startInterchange() { ensureLevel(LEVEL_INITIAL); ensureState(State.INITIAL); level = LEVEL_INTERCHANGE; @@ -526,6 +526,7 @@ public EDIStreamWriter writeEndSegment() throws EDIStreamException { if (level > LEVEL_SEGMENT) { validateElement(this.elementBuffer::flip, this.elementBuffer); } + level = LEVEL_SEGMENT; validate(validator -> validator.validateSyntax(dialect, this, this, location, false)); if (state == State.ELEMENT_DATA_BINARY) { @@ -858,8 +859,13 @@ public boolean binaryData(InputStream binary) { } @Override - public boolean elementData(char[] text, int start, int length) { - elementHolder.set(text, start, length); + public boolean elementData(CharSequence text, boolean fromStream) { + if (level > LEVEL_ELEMENT) { + location.incrementComponentPosition(); + } else { + location.incrementElementPosition(); + } + dialect.elementData(elementHolder, location); validator().ifPresent(validator -> { diff --git a/src/main/java/io/xlate/edi/internal/stream/tokenization/ElementDataHandler.java b/src/main/java/io/xlate/edi/internal/stream/tokenization/ElementDataHandler.java index 65ab3216..635e97e0 100644 --- a/src/main/java/io/xlate/edi/internal/stream/tokenization/ElementDataHandler.java +++ b/src/main/java/io/xlate/edi/internal/stream/tokenization/ElementDataHandler.java @@ -4,7 +4,7 @@ public interface ElementDataHandler { - boolean elementData(char[] text, int start, int length); + boolean elementData(CharSequence text, boolean fromStream); boolean binaryData(InputStream binary); diff --git a/src/main/java/io/xlate/edi/internal/stream/tokenization/EventHandler.java b/src/main/java/io/xlate/edi/internal/stream/tokenization/EventHandler.java index 423dc0ae..06e5d297 100644 --- a/src/main/java/io/xlate/edi/internal/stream/tokenization/EventHandler.java +++ b/src/main/java/io/xlate/edi/internal/stream/tokenization/EventHandler.java @@ -25,7 +25,7 @@ public interface EventHandler extends ElementDataHandler, ValidationEventHandler boolean segmentEnd(); - boolean compositeBegin(boolean isNil); + boolean compositeBegin(boolean isNil, boolean derived); boolean compositeEnd(boolean isNil); diff --git a/src/main/java/io/xlate/edi/internal/stream/tokenization/Lexer.java b/src/main/java/io/xlate/edi/internal/stream/tokenization/Lexer.java index c13ef60c..455c1cb4 100644 --- a/src/main/java/io/xlate/edi/internal/stream/tokenization/Lexer.java +++ b/src/main/java/io/xlate/edi/internal/stream/tokenization/Lexer.java @@ -18,6 +18,7 @@ import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.UncheckedIOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; @@ -25,8 +26,10 @@ import java.nio.charset.CoderResult; import java.util.ArrayDeque; import java.util.Deque; +import java.util.function.IntSupplier; import java.util.logging.Logger; +import io.xlate.edi.internal.stream.CharArraySequence; import io.xlate.edi.internal.stream.LocationView; import io.xlate.edi.internal.stream.StaEDIStreamLocation; import io.xlate.edi.stream.Location; @@ -60,6 +63,7 @@ private interface Notifier { private char[] readChar = new char[1]; private CharBuffer readCharBuf = CharBuffer.wrap(readChar); private ByteBuffer readByteBuf = ByteBuffer.allocate(4); + private CharArraySequence elementHolder = new CharArraySequence(); private final StaEDIStreamLocation location; private final CharacterSet characters; @@ -104,41 +108,19 @@ public Lexer(InputStream stream, Charset charset, EventHandler handler, StaEDISt ssn = (notifyState, start, length) -> { String segmentTag = new String(buffer.array(), start, length); - location.incrementSegmentPosition(segmentTag); return handler.segmentBegin(segmentTag); }; - sen = (notifyState, start, length) -> { - boolean eventsReady = handler.segmentEnd(); - location.clearSegmentLocations(); - return eventsReady; - }; - - csn = (notifyState, start, length) -> { - if (location.isRepeated()) { - location.incrementElementOccurrence(); - } else { - location.incrementElementPosition(); - } - - return handler.compositeBegin(false); - }; - - cen = (notifyState, start, length) -> { - boolean eventsReady = handler.compositeEnd(false); - location.clearComponentPosition(); - return eventsReady; - }; + sen = (notifyState, start, length) -> handler.segmentEnd(); + csn = (notifyState, start, length) -> handler.compositeBegin(false, false); + cen = (notifyState, start, length) -> handler.compositeEnd(false); + bn = (notifyState, start, length) -> handler.binaryData(binaryStream); en = (notifyState, start, length) -> { - updateLocation(notifyState, location); - return handler.elementData(buffer.array(), start, length); + elementHolder.set(buffer.array(), start, length); + return handler.elementData(elementHolder, true); }; - bn = (notifyState, start, length) -> { - updateLocation(notifyState, location); - return handler.binaryData(binaryStream); - }; } public Dialect getDialect() { @@ -175,6 +157,14 @@ public int read() throws IOException { } public void parse() throws IOException, EDIException { + try { + parse(this::readCharacterUnchecked); + } catch (UncheckedIOException e) { + throw e.getCause(); + } + } + + void parse(IntSupplier inputSource) throws EDIException { if (nextEvent()) { return; } @@ -186,7 +176,7 @@ public void parse() throws IOException, EDIException { boolean eventsReady = false; - while (!eventsReady && (input = readCharacter()) > -1) { + while (!eventsReady && (input = inputSource.getAsInt()) > -1) { location.incrementOffset(input); CharacterClass clazz = characters.getClass(input); @@ -305,6 +295,14 @@ public void parse() throws IOException, EDIException { } } + int readCharacterUnchecked() { + try { + return readCharacter(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + int readCharacter() throws IOException { int next = stream.read(); @@ -455,49 +453,6 @@ private EDIException error(int code) { return new EDIException(code, where); } - private static void updateLocation(State state, StaEDIStreamLocation location) { - if (state == State.ELEMENT_REPEAT) { - if (location.isRepeated()) { - updateElementOccurrence(location); - } else { - location.setElementOccurrence(1); - } - location.setRepeated(true); - } else if (location.isRepeated()) { - if (state != State.COMPONENT_END) { - updateElementOccurrence(location); - location.setRepeated(false); - } - } else { - location.setElementOccurrence(1); - } - - switch (state) { - case COMPONENT_END: - case HEADER_COMPONENT_END: - location.incrementComponentPosition(); - break; - - default: - if (location.getComponentPosition() > 0) { - location.incrementComponentPosition(); - } else if (location.getElementOccurrence() == 1) { - location.incrementElementPosition(); - } - break; - } - } - - static void updateElementOccurrence(StaEDIStreamLocation location) { - /* - * Only increment the position if we have not yet started - * the composite - i.e, only a single component is present. - */ - if (location.getComponentPosition() < 1) { - location.incrementElementOccurrence(); - } - } - private boolean nextEvent() { Notifier event = events.peek(); boolean eventsReady = false; @@ -571,6 +526,8 @@ private void emptySegment() throws EDIException { } private void handleElement() throws EDIException { + location.setRepeating(State.ELEMENT_REPEAT.equals(state)); + if (previous != State.ELEMENT_END_BINARY) { addElementEvent(); } diff --git a/src/main/java/io/xlate/edi/internal/stream/tokenization/ProxyEventHandler.java b/src/main/java/io/xlate/edi/internal/stream/tokenization/ProxyEventHandler.java index 09f615ac..5ce11cde 100644 --- a/src/main/java/io/xlate/edi/internal/stream/tokenization/ProxyEventHandler.java +++ b/src/main/java/io/xlate/edi/internal/stream/tokenization/ProxyEventHandler.java @@ -25,7 +25,6 @@ import java.util.Queue; import java.util.function.Function; -import io.xlate.edi.internal.stream.CharArraySequence; import io.xlate.edi.internal.stream.StaEDIStreamLocation; import io.xlate.edi.internal.stream.validation.UsageError; import io.xlate.edi.internal.stream.validation.Validator; @@ -57,7 +56,6 @@ public class ProxyEventHandler implements EventHandler { private InputStream binary; private String segmentTag; - private CharArraySequence elementHolder = new CharArraySequence(); private final Queue eventPool = new LinkedList<>(); // Use implementation to access as both Deque & List @@ -248,6 +246,7 @@ public void loopEnd(EDIReference typeReference) { @Override public boolean segmentBegin(String segmentTag) { + location.incrementSegmentPosition(segmentTag); this.segmentTag = segmentTag; /* @@ -318,7 +317,12 @@ public boolean segmentEnd() { } @Override - public boolean compositeBegin(boolean isNil) { + public boolean compositeBegin(boolean isNil, boolean derived) { + if (!derived) { + location.incrementElement(true); + } + location.setComposite(true); + EDIReference typeReference = null; boolean eventsReady = true; Validator validator = validator(); @@ -357,18 +361,19 @@ public boolean compositeEnd(boolean isNil) { } @Override - public boolean elementData(char[] text, int start, int length) { + public boolean elementData(CharSequence text, boolean fromStream) { + location.incrementElement(false); + boolean derivedComposite; EDIReference typeReference; final boolean compositeFromStream = location.getComponentPosition() > -1; - elementHolder.set(text, start, length); - dialect.elementData(elementHolder, location); + dialect.elementData(text, location); Validator validator = validator(); boolean valid; if (levelCheckPending && startedLevel != null) { - setLevelIdentifiers(); + setLevelIdentifiers(text); } /* @@ -380,16 +385,16 @@ public boolean elementData(char[] text, int start, int length) { if (validator != null) { derivedComposite = !compositeFromStream && validator.isComposite(dialect, location); - componentReceivedAsSimple = derivedComposite && text != null; + componentReceivedAsSimple = derivedComposite && fromStream; if (componentReceivedAsSimple) { - this.compositeBegin(elementHolder.length() == 0); + this.compositeBegin(text.length() == 0, true); location.incrementComponentPosition(); } - valid = validator.validateElement(dialect, location, elementHolder, null); + valid = validator.validateElement(dialect, location, text, null); typeReference = validator.getElementReference(); - enqueueElementOccurrenceErrors(validator, valid); + enqueueElementOccurrenceErrors(text, validator, valid); } else { valid = true; derivedComposite = false; @@ -397,14 +402,14 @@ public boolean elementData(char[] text, int start, int length) { typeReference = null; } - enqueueElementErrors(validator, valid); + enqueueElementErrors(text, validator, valid); boolean eventsReady = true; - if (text != null && (!derivedComposite || length > 0) /* Not an inferred element */) { + if (fromStream && (!derivedComposite || text.length() > 0) /* Not an inferred element */) { enqueueEvent(EDIStreamEvent.ELEMENT_DATA, EDIStreamValidationError.NONE, - elementHolder, + text, typeReference, location); @@ -412,7 +417,7 @@ public boolean elementData(char[] text, int start, int length) { } if (componentReceivedAsSimple) { - this.compositeEnd(length == 0); + this.compositeEnd(text.length() == 0); location.clearComponentPosition(); } @@ -446,13 +451,13 @@ boolean isHierarchicalLoop(EDIType type) { loop.getParentIdPosition() != null; } - void setLevelIdentifiers() { + void setLevelIdentifiers(CharSequence text) { if (levelIdPosition.matchesLocation(location)) { - startedLevelId = elementHolder.toString(); + startedLevelId = text.toString(); } if (parentIdPosition.matchesLocation(location)) { - startedLevelParentId = elementHolder.toString(); + startedLevelParentId = text.toString(); } } @@ -490,7 +495,7 @@ void completeLevel(StreamEvent successor, String parentId) { } } - void enqueueElementOccurrenceErrors(Validator validator, boolean valid) { + void enqueueElementOccurrenceErrors(CharSequence text, Validator validator, boolean valid) { if (valid) { return; } @@ -510,7 +515,7 @@ void enqueueElementOccurrenceErrors(Validator validator, boolean valid) { case TOO_MANY_REPETITIONS: enqueueEvent(error.getError().getCategory(), error.getError(), - elementHolder, + text, error.getTypeReference(), location); cursor.remove(); @@ -521,7 +526,7 @@ void enqueueElementOccurrenceErrors(Validator validator, boolean valid) { } } - void enqueueElementErrors(Validator validator, boolean valid) { + void enqueueElementErrors(CharSequence text, Validator validator, boolean valid) { if (valid) { return; } @@ -531,7 +536,7 @@ void enqueueElementErrors(Validator validator, boolean valid) { for (UsageError error : errors) { enqueueEvent(error.getError().getCategory(), error.getError(), - elementHolder, + text, error.getTypeReference(), location); } @@ -543,6 +548,7 @@ public boolean isBinaryElementLength() { @Override public boolean binaryData(InputStream binaryStream) { + location.incrementElement(false); Validator validator = validator(); EDIReference typeReference = validator != null ? validator.getElementReference() : null; enqueueEvent(EDIStreamEvent.ELEMENT_DATA_BINARY, EDIStreamValidationError.NONE, "", typeReference, location); diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/Validator.java b/src/main/java/io/xlate/edi/internal/stream/validation/Validator.java index 44de8e8f..e0ad7f89 100644 --- a/src/main/java/io/xlate/edi/internal/stream/validation/Validator.java +++ b/src/main/java/io/xlate/edi/internal/stream/validation/Validator.java @@ -1285,13 +1285,7 @@ public void validateSyntax(Dialect dialect, ElementDataHandler handler, Validati // Ensure the start index is at least zero. Index may be -1 for empty segments for (int i = Math.max(index, 0), max = children.size(); i < max; i++) { - if (isComposite) { - location.incrementComponentPosition(); - } else { - location.incrementElementPosition(); - } - - handler.elementData(null, 0, 0); + handler.elementData("", false); } if (!isComposite && implSegmentSelected && index == children.size()) { diff --git a/src/main/java/io/xlate/edi/stream/EDIStreamReader.java b/src/main/java/io/xlate/edi/stream/EDIStreamReader.java index 83bccde9..433e00cb 100644 --- a/src/main/java/io/xlate/edi/stream/EDIStreamReader.java +++ b/src/main/java/io/xlate/edi/stream/EDIStreamReader.java @@ -119,6 +119,29 @@ public interface EDIStreamReader extends Closeable, EDIStreamConstants { * Calls to this method are only valid when interchange type has been * determined, after START_INTERCHANGE. * + * The elements of the returned array are specific to the standard: + * + *

+ * For EDIFACT: + *

    + *
  1. Syntax identifier: UNB01-1 + *
  2. Syntax version number: UNB01-2 + *
  3. Service code list directory version number: UNB01-3 (syntax version 4+) + *
  4. Character encoding, coded: UNB01-4 (syntax version 4+) + *
  5. Syntax release number: UNB01-5 (syntax version and release 4.1+) + *
+ *

+ * For X12: + *

    + *
  1. Interchange Control Version Number: ISA12 + *
+ *

+ * For TRADACOMS: + *

    + *
  1. Syntax rules identifier: STX01-1 + *
  2. Syntax rules version: STX01-2 + *
+ * * @return the version * @throws IllegalStateException * when the version has not yet been determined, prior to the diff --git a/src/main/java/io/xlate/edi/stream/EDIStreamWriter.java b/src/main/java/io/xlate/edi/stream/EDIStreamWriter.java index a9953cbd..c92bbe80 100644 --- a/src/main/java/io/xlate/edi/stream/EDIStreamWriter.java +++ b/src/main/java/io/xlate/edi/stream/EDIStreamWriter.java @@ -143,6 +143,18 @@ public interface EDIStreamWriter extends AutoCloseable { */ Map getDelimiters(); + /** + * Initialize this writer to begin writing an interchange. + * + * This method does not write any output to the underlying stream. + * + * @return this EDI stream writer + * @throws EDIStreamException + * is not thrown and will be removed in the next major version + * of StAEDI. + * @throws IllegalStateException + * when the writer is in any state other than the initial state + */ EDIStreamWriter startInterchange() throws EDIStreamException; EDIStreamWriter endInterchange() throws EDIStreamException; diff --git a/src/test/java/io/xlate/edi/internal/stream/tokenization/LexerTest.java b/src/test/java/io/xlate/edi/internal/stream/tokenization/LexerTest.java index 331eb0b3..fa9560b7 100644 --- a/src/test/java/io/xlate/edi/internal/stream/tokenization/LexerTest.java +++ b/src/test/java/io/xlate/edi/internal/stream/tokenization/LexerTest.java @@ -80,7 +80,7 @@ public boolean segmentEnd() { } @Override - public boolean compositeBegin(boolean isNil) { + public boolean compositeBegin(boolean isNil, boolean derived) { content.put("LAST", "compositeBegin"); return true; } @@ -92,9 +92,9 @@ public boolean compositeEnd(boolean isNil) { } @Override - public boolean elementData(char[] text, int start, int length) { + public boolean elementData(CharSequence text, boolean fromStream) { content.put("LAST", "elementData"); - content.put("ELEMENT", new String(text, start, length)); + content.put("ELEMENT", text.toString()); return true; } @@ -149,7 +149,7 @@ public boolean segmentEnd() { } @Override - public boolean compositeBegin(boolean isNil) { + public boolean compositeBegin(boolean isNil, boolean derived) { compositeStarted = true; return true; } @@ -160,9 +160,8 @@ public boolean compositeEnd(boolean isNil) { return true; } - @Override - public boolean elementData(char[] text, int start, int length) { - element = new String(text, start, length); + public boolean elementData(CharSequence text, boolean fromStream) { + element = text.toString(); return true; }