/* 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.sw;
import java.io.IOException;
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.ri.typed.AsciiValueEncoder;
import org.codehaus.stax2.ri.typed.ValueEncoderFactory;
import org.codehaus.stax2.validation.XMLValidator;
import com.ctc.wstx.api.WriterConfig;
import com.ctc.wstx.cfg.ErrorConsts;
import com.ctc.wstx.exc.WstxIOException;
/**
* Intermediate base class that implements Typed Access API (Stax2 v3)
* for all (repairing, non-repairing, non-namespace) native stream
* writer implementations.
*/
public abstract class TypedStreamWriter
extends BaseStreamWriter
{
/**
* When outputting using Typed Access API, we will need
* encoders. If so, they will created by lazily-constructed
* factory
*/
protected ValueEncoderFactory mValueEncoderFactory;
/*
////////////////////////////////////////////////////
// Life-cycle
////////////////////////////////////////////////////
*/
protected TypedStreamWriter(XmlWriter xw, String enc, WriterConfig cfg)
{
super(xw, enc, cfg);
}
protected final ValueEncoderFactory valueEncoderFactory()
{
if (mValueEncoderFactory == null) {
mValueEncoderFactory = new ValueEncoderFactory();
}
return mValueEncoderFactory;
}
/*
/////////////////////////////////////////////////
// TypedXMLStreamWriter2 implementation
// (Typed Access API, Stax v3.0)
/////////////////////////////////////////////////
*/
// // // Typed element content write methods
public void writeBoolean(boolean value)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(value));
}
public void writeInt(int value)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(value));
}
public void writeLong(long value)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(value));
}
public void writeFloat(float value)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(value));
}
public void writeDouble(double value)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(value));
}
public void writeInteger(BigInteger value)
throws XMLStreamException
{
/* No really efficient method exposed by JDK, keep it simple
* (esp. considering that length is actually not bound)
*/
writeTypedElement(valueEncoderFactory().getScalarEncoder(value.toString()));
}
public void writeDecimal(BigDecimal value)
throws XMLStreamException
{
/* No really efficient method exposed by JDK, keep it simple
* (esp. considering that length is actually not bound)
*/
writeTypedElement(valueEncoderFactory().getScalarEncoder(value.toString()));
}
public void writeQName(QName name)
throws XMLStreamException
{
/* Can't use AsciiValueEncoder, since QNames can contain
* non-ascii characters
*/
writeCharacters(serializeQName(name));
}
public final void writeIntArray(int[] value, int from, int length)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(value, from, length));
}
public void writeLongArray(long[] value, int from, int length)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(value, from, length));
}
public void writeFloatArray(float[] value, int from, int length)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(value, from, length));
}
public void writeDoubleArray(double[] value, int from, int length)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(value, from, length));
}
public void writeBinary(byte[] value, int from, int length)
throws XMLStreamException
{
Base64Variant v = Base64Variants.getDefaultVariant();
writeTypedElement(valueEncoderFactory().getEncoder(v, value, from, length));
}
public void writeBinary(Base64Variant v, byte[] value, int from, int length)
throws XMLStreamException
{
writeTypedElement(valueEncoderFactory().getEncoder(v, value, from, length));
}
protected final void writeTypedElement(AsciiValueEncoder enc)
throws XMLStreamException
{
if (mStartElementOpen) {
closeStartElement(mEmptyElement);
}
// How about well-formedness?
if (mCheckStructure) {
if (inPrologOrEpilog()) {
reportNwfStructure(ErrorConsts.WERR_PROLOG_NONWS_TEXT);
}
}
// Or validity?
if (mVldContent <= XMLValidator.CONTENT_ALLOW_WS) {
reportInvalidContent(CHARACTERS);
}
// So far so good: let's serialize
try {
XMLValidator vld = (mVldContent == XMLValidator.CONTENT_ALLOW_VALIDATABLE_TEXT) ?
mValidator : null;
if (vld == null) {
mWriter.writeTypedElement(enc);
} else {
mWriter.writeTypedElement(enc, vld, getCopyBuffer());
}
} catch (IOException ioe) {
throw new WstxIOException(ioe);
}
}
// // // Typed attribute value write methods
public void writeBooleanAttribute(String prefix, String nsURI, String localName, boolean value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(value));
}
public void writeIntAttribute(String prefix, String nsURI, String localName, int value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(value));
}
public void writeLongAttribute(String prefix, String nsURI, String localName, long value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(value));
}
public void writeFloatAttribute(String prefix, String nsURI, String localName, float value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(value));
}
public void writeDoubleAttribute(String prefix, String nsURI, String localName, double value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(value));
}
public void writeIntegerAttribute(String prefix, String nsURI, String localName, BigInteger value)
throws XMLStreamException
{
// not optimal, but has to do:
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getScalarEncoder(value.toString()));
}
public void writeDecimalAttribute(String prefix, String nsURI, String localName, BigDecimal value)
throws XMLStreamException
{
// not optimal, but has to do:
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getScalarEncoder(value.toString()));
}
public void writeQNameAttribute(String prefix, String nsURI, String localName, QName name)
throws XMLStreamException
{
/* Can't use AsciiValueEncoder, since QNames can contain
* non-ascii characters
*/
writeAttribute(prefix, nsURI, localName, serializeQName(name));
}
public void writeIntArrayAttribute(String prefix, String nsURI, String localName, int[] value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(value, 0, value.length));
}
public void writeLongArrayAttribute(String prefix, String nsURI, String localName, long[] value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(value, 0, value.length));
}
public void writeFloatArrayAttribute(String prefix, String nsURI, String localName, float[] value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(value, 0, value.length));
}
public void writeDoubleArrayAttribute(String prefix, String nsURI, String localName, double[] value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(value, 0, value.length));
}
public void writeBinaryAttribute(String prefix, String nsURI, String localName, byte[] value)
throws XMLStreamException
{
Base64Variant v = Base64Variants.getDefaultVariant();
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(v, value, 0, value.length));
}
public void writeBinaryAttribute(Base64Variant v, String prefix, String nsURI, String localName, byte[] value)
throws XMLStreamException
{
writeTypedAttribute(prefix, nsURI, localName,
valueEncoderFactory().getEncoder(v, value, 0, value.length));
}
/**
* Method that will write attribute with value that is known not to
* require additional escaping.
*/
protected abstract void writeTypedAttribute(String prefix, String nsURI,
String localName,
AsciiValueEncoder enc)
throws XMLStreamException;
private String serializeQName(QName name)
throws XMLStreamException
{
String vp = validateQNamePrefix(name);
String local = name.getLocalPart();
if (vp == null || vp.length() == 0) {
return local;
}
// Not efficient... but should be ok
return vp + ":" + local;
}
}