/* Stax2 API extension for Streaming Api for Xml processing (StAX).
*
* Copyright (c) 2006- 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 org.codehaus.stax2.ri;
import java.io.
IOException;
import java.io.
Writer;
import java.math.
BigDecimal;
import java.math.
BigInteger;
import javax.xml.namespace.
NamespaceContext;
import javax.xml.namespace.
QName;
import javax.xml.stream.*;
import org.codehaus.stax2.*;
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.validation.*;
import org.codehaus.stax2.ri.typed.
ValueDecoderFactory;
/**
* This is a partial base implementation of {@link XMLStreamReader2},
* the extended stream reader that is part of Stax2.
*/
public abstract class
Stax2ReaderImpl
implements
XMLStreamReader2 /* From Stax2 */
,
AttributeInfo
,
DTDInfo
,
LocationInfo
{
/**
* Factory used for constructing decoders we need for typed access
*/
protected
ValueDecoderFactory _decoderFactory;
/*
////////////////////////////////////////////////////
// Life-cycle methods
////////////////////////////////////////////////////
*/
protected
Stax2ReaderImpl()
{
}
/*
////////////////////////////////////////////////////
// XMLStreamReader2 (StAX2) implementation
////////////////////////////////////////////////////
*/
// // // StAX2, per-reader configuration
@
Deprecated
public
Object getFeature(
String name)
{
// No features defined
return null;
}
@
Deprecated
public void
setFeature(
String name,
Object value)
{
// No features defined
}
// NOTE: getProperty() defined in Stax 1.0 interface
public boolean
isPropertySupported(
String name) {
/* No way to cleanly implement this using just Stax 1.0
* interface, so let's be conservative and decline any knowledge
* of properties...
*/
return false;
}
public boolean
setProperty(
String name,
Object value)
{
return false; // could throw an exception too
}
// // // StAX2, additional traversal methods
public void
skipElement() throws
XMLStreamException
{
if (
getEventType() !=
START_ELEMENT) {
throwNotStartElem();
}
int
nesting = 1; // need one more end elements than start elements
while (true) {
int
type =
next();
if (
type ==
START_ELEMENT) {
++
nesting;
} else if (
type ==
END_ELEMENT) {
if (--
nesting == 0) {
break;
}
}
}
}
// // // StAX2, additional attribute access
public
AttributeInfo getAttributeInfo() throws
XMLStreamException
{
if (
getEventType() !=
START_ELEMENT) {
throwNotStartElem();
}
return this;
}
// // // StAX2, Additional DTD access
public
DTDInfo getDTDInfo() throws
XMLStreamException
{
if (
getEventType() !=
DTD) {
return null;
}
return this;
}
// // // StAX2, Additional location information
/**
* Location information is always accessible, for this reader.
*/
public final
LocationInfo getLocationInfo() {
return this;
}
// // // StAX2, Pass-through text accessors
public int
getText(
Writer w, boolean
preserveContents)
throws
IOException,
XMLStreamException
{
char[]
cbuf =
getTextCharacters();
int
start =
getTextStart();
int
len =
getTextLength();
if (
len > 0) {
w.
write(
cbuf,
start,
len);
}
return
len;
}
// // // StAX 2, Other accessors
/**
* @return Number of open elements in the stack; 0 when parser is in
* prolog/epilog, 1 inside root element and so on.
*/
public abstract int
getDepth();
public abstract boolean
isEmptyElement() throws
XMLStreamException;
public abstract
NamespaceContext getNonTransientNamespaceContext();
public
String getPrefixedName()
{
switch (
getEventType()) {
case
START_ELEMENT:
case
END_ELEMENT:
{
String prefix =
getPrefix();
String ln =
getLocalName();
if (
prefix == null) {
return
ln;
}
StringBuffer sb = new
StringBuffer(
ln.
length() + 1 +
prefix.
length());
sb.
append(
prefix);
sb.
append(':');
sb.
append(
ln);
return
sb.
toString();
}
case
ENTITY_REFERENCE:
return
getLocalName();
case
PROCESSING_INSTRUCTION:
return
getPITarget();
case
DTD:
return
getDTDRootName();
}
throw new
IllegalStateException("Current state not START_ELEMENT, END_ELEMENT, ENTITY_REFERENCE, PROCESSING_INSTRUCTION or DTD");
}
public void
closeCompletely() throws
XMLStreamException
{
/* As usual, Stax 1.0 offers no generic way of doing just this.
* But let's at least call the lame basic close()
*/
close();
}
/*
////////////////////////////////////////////////////
// AttributeInfo implementation (StAX 2)
////////////////////////////////////////////////////
*/
// Already part of XMLStreamReader
//public int getAttributeCount();
public int
findAttributeIndex(
String nsURI,
String localName)
{
// !!! TBI
return -1;
}
public int
getIdAttributeIndex()
{
// !!! TBI
return -1;
}
public int
getNotationAttributeIndex()
{
// !!! TBI
return -1;
}
/*
////////////////////////////////////////////////////
// DTDInfo implementation (StAX 2)
////////////////////////////////////////////////////
*/
public
Object getProcessedDTD() {
return null;
}
public
String getDTDRootName() {
return null;
}
public
String getDTDPublicId() {
return null;
}
public
String getDTDSystemId() {
return null;
}
/**
* @return Internal subset portion of the DOCTYPE declaration, if any;
* empty String if none
*/
public
String getDTDInternalSubset() {
return null;
}
// // StAX2, v2.0
public
DTDValidationSchema getProcessedDTDSchema() {
return null;
}
/*
////////////////////////////////////////////////////
// LocationInfo implementation (StAX 2)
////////////////////////////////////////////////////
*/
// // // First, the "raw" offset accessors:
public long
getStartingByteOffset() {
return -1L;
}
public long
getStartingCharOffset() {
return 0;
}
public long
getEndingByteOffset() throws
XMLStreamException
{
return -1;
}
public long
getEndingCharOffset() throws
XMLStreamException
{
return -1;
}
// // // and then the object-based access methods:
public abstract
XMLStreamLocation2 getStartLocation();
public abstract
XMLStreamLocation2 getCurrentLocation();
public abstract
XMLStreamLocation2 getEndLocation()
throws
XMLStreamException;
/*
////////////////////////////////////////////////////
// Stax2 validation
////////////////////////////////////////////////////
*/
public
XMLValidator validateAgainst(
XMLValidationSchema schema)
throws
XMLStreamException
{
throwUnsupported();
return null;
}
public
XMLValidator stopValidatingAgainst(
XMLValidationSchema schema)
throws
XMLStreamException
{
throwUnsupported();
return null;
}
public
XMLValidator stopValidatingAgainst(
XMLValidator validator)
throws
XMLStreamException
{
throwUnsupported();
return null;
}
public abstract
ValidationProblemHandler setValidationProblemHandler(
ValidationProblemHandler h);
/*
////////////////////////////////////////////////////////
// TypedXMLStreamReader, scalar elements
////////////////////////////////////////////////////////
*/
public boolean
getElementAsBoolean() throws
XMLStreamException
{
ValueDecoderFactory.
BooleanDecoder dec =
_decoderFactory().
getBooleanDecoder();
getElementAs(
dec);
return
dec.
getValue();
}
public int
getElementAsInt() throws
XMLStreamException
{
ValueDecoderFactory.
IntDecoder dec =
_decoderFactory().
getIntDecoder();
getElementAs(
dec);
return
dec.
getValue();
}
public long
getElementAsLong() throws
XMLStreamException
{
ValueDecoderFactory.
LongDecoder dec =
_decoderFactory().
getLongDecoder();
getElementAs(
dec);
return
dec.
getValue();
}
public float
getElementAsFloat() throws
XMLStreamException
{
ValueDecoderFactory.
FloatDecoder dec =
_decoderFactory().
getFloatDecoder();
getElementAs(
dec);
return
dec.
getValue();
}
public double
getElementAsDouble() throws
XMLStreamException
{
ValueDecoderFactory.
DoubleDecoder dec =
_decoderFactory().
getDoubleDecoder();
getElementAs(
dec);
return
dec.
getValue();
}
public
BigInteger getElementAsInteger() throws
XMLStreamException
{
ValueDecoderFactory.
IntegerDecoder dec =
_decoderFactory().
getIntegerDecoder();
getElementAs(
dec);
return
dec.
getValue();
}
public
BigDecimal getElementAsDecimal() throws
XMLStreamException
{
ValueDecoderFactory.
DecimalDecoder dec =
_decoderFactory().
getDecimalDecoder();
getElementAs(
dec);
return
dec.
getValue();
}
public
QName getElementAsQName() throws
XMLStreamException
{
ValueDecoderFactory.
QNameDecoder dec =
_decoderFactory().
getQNameDecoder(
getNamespaceContext());
getElementAs(
dec);
// !!! Should we try to verify validity of name chars?
return
dec.
getValue();
}
public byte[]
getElementAsBinary() throws
XMLStreamException
{
return
getElementAsBinary(
Base64Variants.
getDefaultVariant());
}
// !!! TODO: copy code from Stax2ReaderAdapter?
public abstract byte[]
getElementAsBinary(
Base64Variant v) throws
XMLStreamException;
public void
getElementAs(
TypedValueDecoder tvd) throws
XMLStreamException
{
String value =
getElementText();
try {
tvd.
decode(
value);
} catch (
IllegalArgumentException iae) {
throw
_constructTypeException(
iae,
value);
}
}
/*
////////////////////////////////////////////////////////
// TypedXMLStreamReader2 implementation, array elements
////////////////////////////////////////////////////////
*/
public int
readElementAsIntArray(int[]
value, int
from, int
length) throws
XMLStreamException
{
return
readElementAsArray(
_decoderFactory().
getIntArrayDecoder(
value,
from,
length));
}
public int
readElementAsLongArray(long[]
value, int
from, int
length) throws
XMLStreamException
{
return
readElementAsArray(
_decoderFactory().
getLongArrayDecoder(
value,
from,
length));
}
public int
readElementAsFloatArray(float[]
value, int
from, int
length) throws
XMLStreamException
{
return
readElementAsArray(
_decoderFactory().
getFloatArrayDecoder(
value,
from,
length));
}
public int
readElementAsDoubleArray(double[]
value, int
from, int
length) throws
XMLStreamException
{
return
readElementAsArray(
_decoderFactory().
getDoubleArrayDecoder(
value,
from,
length));
}
/**
* Actual implementation needs to implement tokenization and state
* keeping.
*<p>
* !!! TODO: should be possible to implement completely
*/
public abstract int
readElementAsArray(
TypedArrayDecoder dec)
throws
XMLStreamException;
/*
////////////////////////////////////////////////////////
// TypedXMLStreamReader2 implementation, binary data
////////////////////////////////////////////////////////
*/
public int
readElementAsBinary(byte[]
resultBuffer, int
offset, int
maxLength)
throws
XMLStreamException
{
return
readElementAsBinary(
Base64Variants.
getDefaultVariant(),
resultBuffer,
offset,
maxLength);
}
public abstract int
readElementAsBinary(
Base64Variant b64variant, byte[]
resultBuffer, int
offset, int
maxLength)
throws
XMLStreamException;
/*
///////////////////////////////////////////////////////////
// TypedXMLStreamReader2 implementation, scalar attributes
///////////////////////////////////////////////////////////
*/
public abstract int
getAttributeIndex(
String namespaceURI,
String localName);
public boolean
getAttributeAsBoolean(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
BooleanDecoder dec =
_decoderFactory().
getBooleanDecoder();
getAttributeAs(
index,
dec);
return
dec.
getValue();
}
public int
getAttributeAsInt(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
IntDecoder dec =
_decoderFactory().
getIntDecoder();
getAttributeAs(
index,
dec);
return
dec.
getValue();
}
public long
getAttributeAsLong(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
LongDecoder dec =
_decoderFactory().
getLongDecoder();
getAttributeAs(
index,
dec);
return
dec.
getValue();
}
public float
getAttributeAsFloat(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
FloatDecoder dec =
_decoderFactory().
getFloatDecoder();
getAttributeAs(
index,
dec);
return
dec.
getValue();
}
public double
getAttributeAsDouble(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
DoubleDecoder dec =
_decoderFactory().
getDoubleDecoder();
getAttributeAs(
index,
dec);
return
dec.
getValue();
}
public
BigInteger getAttributeAsInteger(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
IntegerDecoder dec =
_decoderFactory().
getIntegerDecoder();
getAttributeAs(
index,
dec);
return
dec.
getValue();
}
public
BigDecimal getAttributeAsDecimal(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
DecimalDecoder dec =
_decoderFactory().
getDecimalDecoder();
getAttributeAs(
index,
dec);
return
dec.
getValue();
}
public
QName getAttributeAsQName(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
QNameDecoder dec =
_decoderFactory().
getQNameDecoder(
getNamespaceContext());
getAttributeAs(
index,
dec);
// !!! Should we try to verify validity of name chars?
return
dec.
getValue();
}
public void
getAttributeAs(int
index,
TypedValueDecoder tvd) throws
XMLStreamException
{
String value =
getAttributeValue(
index);
try {
tvd.
decode(
value);
} catch (
IllegalArgumentException iae) {
throw
_constructTypeException(
iae,
value);
}
}
public int[]
getAttributeAsIntArray(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
IntArrayDecoder dec =
_decoderFactory().
getIntArrayDecoder();
getAttributeAsArray(
index,
dec);
return
dec.
getValues();
}
public long[]
getAttributeAsLongArray(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
LongArrayDecoder dec =
_decoderFactory().
getLongArrayDecoder();
getAttributeAsArray(
index,
dec);
return
dec.
getValues();
}
public float[]
getAttributeAsFloatArray(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
FloatArrayDecoder dec =
_decoderFactory().
getFloatArrayDecoder();
getAttributeAsArray(
index,
dec);
return
dec.
getValues();
}
public double[]
getAttributeAsDoubleArray(int
index) throws
XMLStreamException
{
ValueDecoderFactory.
DoubleArrayDecoder dec =
_decoderFactory().
getDoubleArrayDecoder();
getAttributeAsArray(
index,
dec);
return
dec.
getValues();
}
/**
* Actual implementation needs to implement tokenization.
*<p>
* !!! TODO: should be possible to implement completely
*/
public abstract int
getAttributeAsArray(int
index,
TypedArrayDecoder tad) throws
XMLStreamException;
public byte[]
getAttributeAsBinary(int
index) throws
XMLStreamException
{
return
getAttributeAsBinary(
Base64Variants.
getDefaultVariant(),
index);
}
public abstract byte[]
getAttributeAsBinary(
Base64Variant v, int
index) throws
XMLStreamException;
/*
////////////////////////////////////////////////////
// Package methods
////////////////////////////////////////////////////
*/
protected
ValueDecoderFactory _decoderFactory()
{
if (
_decoderFactory == null) {
_decoderFactory = new
ValueDecoderFactory();
}
return
_decoderFactory;
}
protected
TypedXMLStreamException _constructTypeException(
IllegalArgumentException iae,
String lexicalValue)
{
return new
TypedXMLStreamException(
lexicalValue,
iae.
getMessage(),
getStartLocation(),
iae);
}
/*
////////////////////////////////////////////////////
// Internal methods
////////////////////////////////////////////////////
*/
protected void
throwUnsupported()
throws
XMLStreamException
{
throw new
XMLStreamException("Unsupported method");
}
protected void
throwNotStartElem()
{
throw new
IllegalStateException("Current state not START_ELEMENT");
}
}