/* Woodstox XML processor
*
* Copyright (c) 2004- Tatu Saloranta, tatu.saloranta@iki.fi
*
* Licensed under the License specified in file LICENSE, included with
* the source code.
* You may not use this file except in compliance with the License.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ctc.wstx.sr;
import java.math.BigDecimal;
import java.math.BigInteger;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import org.codehaus.stax2.typed.Base64Variant;
import org.codehaus.stax2.typed.Base64Variants;
import org.codehaus.stax2.typed.TypedArrayDecoder;
import org.codehaus.stax2.typed.TypedValueDecoder;
import org.codehaus.stax2.typed.TypedXMLStreamException;
import org.codehaus.stax2.ri.Stax2Util;
import org.codehaus.stax2.ri.typed.ValueDecoderFactory;
import org.codehaus.stax2.ri.typed.CharArrayBase64Decoder;
import com.ctc.wstx.api.ReaderConfig;
import com.ctc.wstx.cfg.ErrorConsts;
import com.ctc.wstx.io.BranchingReaderSource;
import com.ctc.wstx.io.InputBootstrapper;
import com.ctc.wstx.io.WstxInputData;
Complete implementation of XMLStreamReader2
, including Typed Access API (Stax2 v3.0) implementation. Only functionality missing is DTD validation, which is provided by a specialized sub-class. /**
* Complete implementation of {@link org.codehaus.stax2.XMLStreamReader2},
* including Typed Access API (Stax2 v3.0) implementation.
* Only functionality missing is DTD validation, which is provided by a
* specialized sub-class.
*/
public class TypedStreamReader
extends BasicStreamReader
{
Mask of event types that are legal (starting) states
to call Typed Access API from.
/**
* Mask of event types that are legal (starting) states
* to call Typed Access API from.
*
*/
final protected static int MASK_TYPED_ACCESS_ARRAY =
(1 << START_ELEMENT)
| (1 << END_ELEMENT) // for convenience
| (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE)
// Not ok for PI or COMMENT? Let's assume so
;
final protected static int MASK_TYPED_ACCESS_BINARY =
(1 << START_ELEMENT) // note: END_ELEMENT handled separately
| (1 << CHARACTERS) | (1 << CDATA) | (1 << SPACE)
;
Minimum length of text chunks to parse before base64 decoding.
Will try to limit it to fit within regular result buffers.
/**
* Minimum length of text chunks to parse before base64 decoding.
* Will try to limit it to fit within regular result buffers.
*/
final static int MIN_BINARY_CHUNK = 2000;
Factory used for constructing decoders we need for typed access
/**
* Factory used for constructing decoders we need for typed access
*/
protected ValueDecoderFactory _decoderFactory;
Lazily-constructed decoder object for decoding base64 encoded
element binary content.
/**
* Lazily-constructed decoder object for decoding base64 encoded
* element binary content.
*/
protected CharArrayBase64Decoder _base64Decoder = null;
/*
////////////////////////////////////////////////////
// Instance construction
////////////////////////////////////////////////////
*/
protected TypedStreamReader(InputBootstrapper bs,
BranchingReaderSource input, ReaderCreator owner,
ReaderConfig cfg, InputElementStack elemStack,
boolean forER)
throws XMLStreamException
{
super(bs, input, owner, cfg, elemStack, forER);
}
Factory method for constructing readers.
Params: - owner – "Owner" of this reader, factory that created the reader;
needed for returning updated symbol table information after parsing.
- input – Input source used to read the XML document.
- cfg – Object that contains reader configuration info.
/**
* Factory method for constructing readers.
*
* @param owner "Owner" of this reader, factory that created the reader;
* needed for returning updated symbol table information after parsing.
* @param input Input source used to read the XML document.
* @param cfg Object that contains reader configuration info.
*/
public static TypedStreamReader createStreamReader
(BranchingReaderSource input, ReaderCreator owner, ReaderConfig cfg,
InputBootstrapper bs, boolean forER)
throws XMLStreamException
{
TypedStreamReader sr = new TypedStreamReader
(bs, input, owner, cfg, createElementStack(cfg), forER);
return sr;
}
/*
////////////////////////////////////////////////////////
// TypedXMLStreamReader2 implementation, scalar elements
////////////////////////////////////////////////////////
*/
@Override
public boolean getElementAsBoolean() throws XMLStreamException
{
ValueDecoderFactory.BooleanDecoder dec = _decoderFactory().getBooleanDecoder();
getElementAs(dec);
return dec.getValue();
}
@Override
public int getElementAsInt() throws XMLStreamException
{
ValueDecoderFactory.IntDecoder dec = _decoderFactory().getIntDecoder();
getElementAs(dec);
return dec.getValue();
}
@Override
public long getElementAsLong() throws XMLStreamException
{
ValueDecoderFactory.LongDecoder dec = _decoderFactory().getLongDecoder();
getElementAs(dec);
return dec.getValue();
}
@Override
public float getElementAsFloat() throws XMLStreamException
{
ValueDecoderFactory.FloatDecoder dec = _decoderFactory().getFloatDecoder();
getElementAs(dec);
return dec.getValue();
}
@Override
public double getElementAsDouble() throws XMLStreamException
{
ValueDecoderFactory.DoubleDecoder dec = _decoderFactory().getDoubleDecoder();
getElementAs(dec);
return dec.getValue();
}
@Override
public BigInteger getElementAsInteger() throws XMLStreamException
{
ValueDecoderFactory.IntegerDecoder dec = _decoderFactory().getIntegerDecoder();
getElementAs(dec);
return dec.getValue();
}
@Override
public BigDecimal getElementAsDecimal() throws XMLStreamException
{
ValueDecoderFactory.DecimalDecoder dec = _decoderFactory().getDecimalDecoder();
getElementAs(dec);
return dec.getValue();
}
@Override
public QName getElementAsQName() throws XMLStreamException
{
ValueDecoderFactory.QNameDecoder dec = _decoderFactory().getQNameDecoder(getNamespaceContext());
getElementAs(dec);
return _verifyQName(dec.getValue());
}
@Override
public final byte[] getElementAsBinary() throws XMLStreamException
{
return getElementAsBinary(Base64Variants.getDefaultVariant());
}
@Override
public byte[] getElementAsBinary(Base64Variant v) throws XMLStreamException
{
// note: code here is similar to Base64DecoderBase.aggregateAll(), see comments there
Stax2Util.ByteAggregator aggr = _base64Decoder().getByteAggregator();
byte[] buffer = aggr.startAggregation();
while (true) {
int offset = 0;
int len = buffer.length;
do {
int readCount = readElementAsBinary(buffer, offset, len, v);
if (readCount < 1) { // all done!
return aggr.aggregateAll(buffer, offset);
}
offset += readCount;
len -= readCount;
} while (len > 0);
buffer = aggr.addFullBlock(buffer);
}
}
@Override
public void getElementAs(TypedValueDecoder tvd) throws XMLStreamException
{
if (mCurrToken != START_ELEMENT) {
throwParseError(ErrorConsts.ERR_STATE_NOT_STELEM);
}
/* Ok, now: with START_ELEMENT we know that it's not partially
* processed; that we are in-tree (not prolog or epilog).
* The only possible complication would be:
*/
if (mStEmptyElem) {
/* And if so, we'll then get 'virtual' close tag; things
* are simple as location info was set when dealing with
* empty start element; and likewise, validation (if any)
* has been taken care of
*/
mStEmptyElem = false;
mCurrToken = END_ELEMENT;
_handleEmptyValue(tvd);
return;
}
// First need to find a textual event
while (true) {
int type = next();
if (type == END_ELEMENT) {
_handleEmptyValue(tvd);
return;
}
if (type == COMMENT || type == PROCESSING_INSTRUCTION) {
continue;
}
if (((1 << type) & MASK_GET_ELEMENT_TEXT) == 0) {
throwParseError("Expected a text token, got "+tokenTypeDesc(type)+".");
}
break;
}
if (mTokenState < TOKEN_FULL_SINGLE) {
readCoalescedText(mCurrToken, false);
}
/* Ok: then a quick check; if it looks like we are directly
* followed by the end tag, we need not construct String
* quite yet.
*/
if ((mInputPtr + 1) < mInputEnd &&
mInputBuffer[mInputPtr] == '<' && mInputBuffer[mInputPtr+1] == '/') {
// Note: next() has validated text, no need for more validation
mInputPtr += 2;
mCurrToken = END_ELEMENT;
/* Can by-pass next(), nextFromTree(), in this case.
* However, must do decoding first, and only then call
* readEndElem(), since this latter call may invalidate
* underlying input buffer (when end tag is at buffer
* boundary)
*/
try { // buffer now has all the data
mTextBuffer.decode(tvd);
} catch (IllegalArgumentException iae) {
throw _constructTypeException(iae, mTextBuffer.contentsAsString());
}
readEndElem();
return;
}
// Otherwise, we'll need to do slower processing
int extra = 1 + (mTextBuffer.size() >> 1); // let's add 50% space
StringBuilder sb = mTextBuffer.contentsAsStringBuilder(extra);
int type;
while ((type = next()) != END_ELEMENT) {
if (((1 << type) & MASK_GET_ELEMENT_TEXT) != 0) {
if (mTokenState < TOKEN_FULL_SINGLE) {
readCoalescedText(type, false);
}
mTextBuffer.contentsToStringBuilder(sb);
continue;
}
if (type != COMMENT && type != PROCESSING_INSTRUCTION) {
throwParseError("Expected a text token, got "+tokenTypeDesc(type)+".");
}
}
// Note: calls next() have validated text, no need for more validation
String str = sb.toString();
String tstr = Stax2Util.trimSpaces(str);
if (tstr == null) {
_handleEmptyValue(tvd);
} else {
try {
tvd.decode(tstr);
} catch (IllegalArgumentException iae) {
throw _constructTypeException(iae, str);
}
}
}
/*
////////////////////////////////////////////////////////
// TypedXMLStreamReader2 implementation, array elements
////////////////////////////////////////////////////////
*/
@Override
public int readElementAsIntArray(int[] value, int from, int length) throws XMLStreamException
{
return readElementAsArray(_decoderFactory().getIntArrayDecoder(value, from, length));
}
@Override
public int readElementAsLongArray(long[] value, int from, int length) throws XMLStreamException
{
return readElementAsArray(_decoderFactory().getLongArrayDecoder(value, from, length));
}
@Override
public int readElementAsFloatArray(float[] value, int from, int length) throws XMLStreamException
{
return readElementAsArray(_decoderFactory().getFloatArrayDecoder(value, from, length));
}
@Override
public int readElementAsDoubleArray(double[] value, int from, int length) throws XMLStreamException
{
return readElementAsArray(_decoderFactory().getDoubleArrayDecoder(value, from, length));
}
Method called to parse array of primitives.
!!! 05-Sep-2008, tatu: Current implementation is not optimal
either performance-wise, or from getting accurate Location
for decoding problems. But it works otherwise, and we need
to get Woodstox 4.0 out by the end of the year... so it'll
do, for now.
Returns: Number of elements decoded (if any were decoded), or
-1 to indicate that no more values can be decoded.
/**
* Method called to parse array of primitives.
*<p>
* !!! 05-Sep-2008, tatu: Current implementation is not optimal
* either performance-wise, or from getting accurate Location
* for decoding problems. But it works otherwise, and we need
* to get Woodstox 4.0 out by the end of the year... so it'll
* do, for now.
*
* @return Number of elements decoded (if any were decoded), or
* -1 to indicate that no more values can be decoded.
*/
@Override
public final int readElementAsArray(TypedArrayDecoder dec)
throws XMLStreamException
{
int type = mCurrToken;
// First things first: must be acceptable start state:
if (((1 << type) & MASK_TYPED_ACCESS_ARRAY) == 0) {
throwNotTextualOrElem(type);
}
// Are we just starting (START_ELEMENT)?
if (type == START_ELEMENT) {
// Empty? Not common, but can short-cut handling if occurs
if (mStEmptyElem) {
mStEmptyElem = false;
mCurrToken = END_ELEMENT;
return -1;
}
// Otherwise let's just find the first text segment
while (true) {
type = next();
if (type == END_ELEMENT) {
// Simple... no textul content
return -1;
}
if (type == COMMENT || type == PROCESSING_INSTRUCTION) {
continue;
}
if (type == CHARACTERS || type == CDATA) {
break;
}
// otherwise just not legal (how about SPACE, unexpanded entities?)
throw _constructUnexpectedInTyped(type);
}
}
int count = 0;
while (type != END_ELEMENT) {
/* Ok then: we will have a valid textual type. Just need to
* ensure current segment is completed. Plus, for current impl,
* also need to coalesce to prevent artificial CDATA/text
* boundary from splitting tokens
*/
if (type == CHARACTERS || type == CDATA || type == SPACE) {
if (mTokenState < TOKEN_FULL_SINGLE) {
readCoalescedText(type, false);
}
} else if (type == COMMENT || type == PROCESSING_INSTRUCTION) {
type = next();
continue;
} else {
throw _constructUnexpectedInTyped(type);
}
count += mTextBuffer.decodeElements(dec, this);
if (!dec.hasRoom()) {
break;
}
type = next();
}
// If nothing was found, needs to be indicated via -1, not 0
return (count > 0) ? count : -1;
}
/*
////////////////////////////////////////////////////////
// TypedXMLStreamReader2 implementation, binary data
////////////////////////////////////////////////////////
*/
@Override
public final int readElementAsBinary(byte[] resultBuffer, int offset, int maxLength)
throws XMLStreamException
{
return readElementAsBinary(resultBuffer, offset, maxLength, Base64Variants.getDefaultVariant());
}
@Override
public int readElementAsBinary(byte[] resultBuffer, int offset, int maxLength, Base64Variant v)
throws XMLStreamException
{
if (resultBuffer == null) {
throw new IllegalArgumentException("resultBuffer is null");
}
if (offset < 0) {
throw new IllegalArgumentException("Illegal offset ("+offset+"), must be [0, "+resultBuffer.length+"[");
}
if (maxLength < 1 || (offset + maxLength) > resultBuffer.length) {
if (maxLength == 0) { // special case, allowed, but won't do anything
return 0;
}
throw new IllegalArgumentException("Illegal maxLength ("+maxLength+"), has to be positive number, and offset+maxLength can not exceed"+resultBuffer.length);
}
final CharArrayBase64Decoder dec = _base64Decoder();
int type = mCurrToken;
// First things first: must be acceptable start state:
if (((1 << type) & MASK_TYPED_ACCESS_BINARY) == 0) {
if (type == END_ELEMENT) {
// Minor complication: may have unflushed stuff (non-padded versions)
if (!dec.hasData()) {
return -1;
}
} else {
throwNotTextualOrElem(type);
}
} else if (type == START_ELEMENT) { // just starting (START_ELEMENT)?
if (mStEmptyElem) { // empty element? simple...
mStEmptyElem = false;
mCurrToken = END_ELEMENT;
return -1;
}
// Otherwise let's just find the first text segment
while (true) {
type = next();
if (type == END_ELEMENT) {
// Simple... no textual content
return -1;
}
if (type == COMMENT || type == PROCESSING_INSTRUCTION) {
continue;
}
/* 12-Dec-2009, tatu: Important: in coalescing mode we may
* have incomplete segment that needs to be completed
*/
if (mTokenState < mStTextThreshold) {
finishToken(false);
}
_initBinaryChunks(v, dec, type, true);
break;
}
}
int totalCount = 0;
main_loop:
while (true) {
// Ok, decode:
int count;
try {
count = dec.decode(resultBuffer, offset, maxLength);
} catch (IllegalArgumentException iae) {
// !!! 26-Sep-2008, tatus: should try to figure out which char (etc) triggered problem to pass with typed exception
throw _constructTypeException(iae.getMessage(), "");
}
offset += count;
totalCount += count;
maxLength -= count;
/* And if we filled the buffer we are done. Or, an edge
* case: reached END_ELEMENT (for non-padded variant)
*/
if (maxLength < 1 || mCurrToken == END_ELEMENT) {
break;
}
// Otherwise need to advance to the next event
while (true) {
type = next();
if (type == COMMENT || type == PROCESSING_INSTRUCTION
|| type == SPACE) { // space is ignorable too
continue;
}
if (type == END_ELEMENT) {
/* Just need to verify we don't have partial stuff
* (missing one to three characters of a full quartet
* that encodes 1 - 3 bytes). Also: non-padding
* variants can be in incomplete state, from which
* data may need to be flushed...
*/
int left = dec.endOfContent();
if (left < 0) { // incomplete, error
throw _constructTypeException("Incomplete base64 triplet at the end of decoded content", "");
} else if (left > 0) { // 1 or 2 more bytes of data, loop some more
continue main_loop;
}
// Otherwise, no more data, we are done
break main_loop;
}
/* 12-Dec-2009, tatu: Important: in coalescing mode we may
* have incomplete segment that needs to be completed
*/
if (mTokenState < mStTextThreshold) {
finishToken(false);
}
_initBinaryChunks(v, dec, type, false);
break;
}
}
// If nothing was found, needs to be indicated via -1, not 0
return (totalCount > 0) ? totalCount : -1;
}
private final void _initBinaryChunks(Base64Variant v, CharArrayBase64Decoder dec, int type, boolean isFirst)
throws XMLStreamException
{
if (type == CHARACTERS) {
if (mTokenState < mStTextThreshold) {
mTokenState = readTextSecondary(MIN_BINARY_CHUNK, false)
? TOKEN_FULL_SINGLE : TOKEN_PARTIAL_SINGLE;
}
} else if (type == CDATA) {
if (mTokenState < mStTextThreshold) {
mTokenState = readCDataSecondary(MIN_BINARY_CHUNK)
? TOKEN_FULL_SINGLE : TOKEN_PARTIAL_SINGLE;
}
} else {
throw _constructUnexpectedInTyped(type);
}
mTextBuffer.initBinaryChunks(v, dec, isFirst);
}
/*
///////////////////////////////////////////////////////////
// TypedXMLStreamReader2 implementation, scalar attributes
///////////////////////////////////////////////////////////
*/
@Override
public int getAttributeIndex(String namespaceURI, String localName)
{
// Note: cut'n pasted from "getAttributeInfo()"
if (mCurrToken != START_ELEMENT) {
throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM);
}
return mElementStack.findAttributeIndex(namespaceURI, localName);
}
@Override
public boolean getAttributeAsBoolean(int index) throws XMLStreamException
{
ValueDecoderFactory.BooleanDecoder dec = _decoderFactory().getBooleanDecoder();
getAttributeAs(index, dec);
return dec.getValue();
}
@Override
public int getAttributeAsInt(int index) throws XMLStreamException
{
ValueDecoderFactory.IntDecoder dec = _decoderFactory().getIntDecoder();
getAttributeAs(index, dec);
return dec.getValue();
}
@Override
public long getAttributeAsLong(int index) throws XMLStreamException
{
ValueDecoderFactory.LongDecoder dec = _decoderFactory().getLongDecoder();
getAttributeAs(index, dec);
return dec.getValue();
}
@Override
public float getAttributeAsFloat(int index) throws XMLStreamException
{
ValueDecoderFactory.FloatDecoder dec = _decoderFactory().getFloatDecoder();
getAttributeAs(index, dec);
return dec.getValue();
}
@Override
public double getAttributeAsDouble(int index) throws XMLStreamException
{
ValueDecoderFactory.DoubleDecoder dec = _decoderFactory().getDoubleDecoder();
getAttributeAs(index, dec);
return dec.getValue();
}
@Override
public BigInteger getAttributeAsInteger(int index) throws XMLStreamException
{
ValueDecoderFactory.IntegerDecoder dec = _decoderFactory().getIntegerDecoder();
getAttributeAs(index, dec);
return dec.getValue();
}
@Override
public BigDecimal getAttributeAsDecimal(int index) throws XMLStreamException
{
ValueDecoderFactory.DecimalDecoder dec = _decoderFactory().getDecimalDecoder();
getAttributeAs(index, dec);
return dec.getValue();
}
@Override
public QName getAttributeAsQName(int index) throws XMLStreamException
{
ValueDecoderFactory.QNameDecoder dec = _decoderFactory().getQNameDecoder(getNamespaceContext());
getAttributeAs(index, dec);
return _verifyQName(dec.getValue());
}
@Override
public void getAttributeAs(int index, TypedValueDecoder tvd) throws XMLStreamException
{
if (mCurrToken != START_ELEMENT) {
throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM);
}
try {
mAttrCollector.decodeValue(index, tvd);
} catch (IllegalArgumentException iae) {
throw _constructTypeException(iae, mAttrCollector.getValue(index));
}
}
@Override
public int[] getAttributeAsIntArray(int index) throws XMLStreamException
{
ValueDecoderFactory.IntArrayDecoder dec = _decoderFactory().getIntArrayDecoder();
getAttributeAsArray(index, dec);
return dec.getValues();
}
@Override
public long[] getAttributeAsLongArray(int index) throws XMLStreamException
{
ValueDecoderFactory.LongArrayDecoder dec = _decoderFactory().getLongArrayDecoder();
getAttributeAsArray(index, dec);
return dec.getValues();
}
@Override
public float[] getAttributeAsFloatArray(int index) throws XMLStreamException
{
ValueDecoderFactory.FloatArrayDecoder dec = _decoderFactory().getFloatArrayDecoder();
getAttributeAsArray(index, dec);
return dec.getValues();
}
@Override
public double[] getAttributeAsDoubleArray(int index) throws XMLStreamException
{
ValueDecoderFactory.DoubleArrayDecoder dec = _decoderFactory().getDoubleArrayDecoder();
getAttributeAsArray(index, dec);
return dec.getValues();
}
Method that allows reading contents of an attribute as an array
of whitespace-separate tokens, decoded using specified decoder.
Returns: Number of tokens decoded, 0 if none found
/**
* Method that allows reading contents of an attribute as an array
* of whitespace-separate tokens, decoded using specified decoder.
*
* @return Number of tokens decoded, 0 if none found
*/
@Override
public int getAttributeAsArray(int index, TypedArrayDecoder tad) throws XMLStreamException
{
if (mCurrToken != START_ELEMENT) {
throw new IllegalStateException(ErrorConsts.ERR_STATE_NOT_STELEM);
}
return mAttrCollector.decodeValues(index, tad, this);
}
@Override
public byte[] getAttributeAsBinary(int index) throws XMLStreamException
{
return getAttributeAsBinary(index, Base64Variants.getDefaultVariant());
}
@Override
public byte[] getAttributeAsBinary(int index, Base64Variant v) throws XMLStreamException {
return mAttrCollector.decodeBinary(index, v, _base64Decoder(), this);
}
/*
/////////////////////////////////////////////////////
// Internal helper methods
/////////////////////////////////////////////////////
*/
Method called to verify validity of the parsed QName element
or attribute value. At this point binding of a prefixed name
(if qname has a prefix) has been verified, and thereby prefix
also must be valid (since there must have been a preceding
declaration). But local name might still not be a legal
well-formed xml name, so let's verify that.
/**
* Method called to verify validity of the parsed QName element
* or attribute value. At this point binding of a prefixed name
* (if qname has a prefix) has been verified, and thereby prefix
* also must be valid (since there must have been a preceding
* declaration). But local name might still not be a legal
* well-formed xml name, so let's verify that.
*/
protected QName _verifyQName(QName n)
throws TypedXMLStreamException
{
String ln = n.getLocalPart();
int ix = WstxInputData.findIllegalNameChar(ln, mCfgNsEnabled, mXml11);
if (ix >= 0) {
String prefix = n.getPrefix();
String pname = (prefix != null && prefix.length() > 0) ?
(prefix + ":" +ln) : ln;
throw _constructTypeException("Invalid local name \""+ln+"\" (character at #"+ix+" is invalid)", pname);
}
return n;
}
protected ValueDecoderFactory _decoderFactory()
{
if (_decoderFactory == null) {
_decoderFactory = new ValueDecoderFactory();
}
return _decoderFactory;
}
protected CharArrayBase64Decoder _base64Decoder()
{
if (_base64Decoder == null) {
_base64Decoder = new CharArrayBase64Decoder();
}
return _base64Decoder;
}
Method called to handle value that has empty String
as representation. This will usually either lead to an
exception, or parsing to the default value for the
type in question (null for nullable types and so on).
/**
* Method called to handle value that has empty String
* as representation. This will usually either lead to an
* exception, or parsing to the default value for the
* type in question (null for nullable types and so on).
*/
private void _handleEmptyValue(TypedValueDecoder dec)
throws XMLStreamException
{
try { // default action is to throw an exception
dec.handleEmptyValue();
} catch (IllegalArgumentException iae) {
throw _constructTypeException(iae, "");
}
}
Method called to wrap or convert given conversion-fail exception into a full TypedXMLStreamException
, Params: - iae – Problem as reported by converter
- lexicalValue – Lexical value (element content, attribute value)
that could not be converted succesfully.
/**
* Method called to wrap or convert given conversion-fail exception
* into a full {@link TypedXMLStreamException},
*
* @param iae Problem as reported by converter
* @param lexicalValue Lexical value (element content, attribute value)
* that could not be converted succesfully.
*/
protected TypedXMLStreamException _constructTypeException(IllegalArgumentException iae, String lexicalValue)
{
return new TypedXMLStreamException(lexicalValue, iae.getMessage(), getStartLocation(), iae);
}
}