package com.fasterxml.jackson.dataformat.javaprop;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.base.GeneratorBase;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.core.json.JsonWriteContext;
import com.fasterxml.jackson.core.util.JacksonFeatureSet;
import com.fasterxml.jackson.dataformat.javaprop.io.JPropWriteContext;
import com.fasterxml.jackson.dataformat.javaprop.util.Markers;
public abstract class JavaPropsGenerator extends GeneratorBase
{
final protected static int SHORT_WRITE = 100;
protected final static JsonWriteContext BOGUS_WRITE_CONTEXT = JsonWriteContext.createRootContext(null);
private final static JavaPropsSchema EMPTY_SCHEMA;
static {
EMPTY_SCHEMA = JavaPropsSchema.emptySchema();
}
final protected IOContext _ioContext;
protected JavaPropsSchema _schema = EMPTY_SCHEMA;
protected JPropWriteContext _jpropContext;
protected final StringBuilder _basePath = new StringBuilder(50);
protected boolean ;
protected int _indentLength;
public JavaPropsGenerator(IOContext ctxt, int stdFeatures, ObjectCodec codec)
{
super(stdFeatures, codec, BOGUS_WRITE_CONTEXT);
_ioContext = ctxt;
_jpropContext = JPropWriteContext.createRootContext();
}
@Override
public Object getCurrentValue() {
return _jpropContext.getCurrentValue();
}
@Override
public void setCurrentValue(Object v) {
_jpropContext.setCurrentValue(v);
}
@Override
public Version version() {
return PackageVersion.VERSION;
}
@Override
public JsonGenerator useDefaultPrettyPrinter() {
return this;
}
@Override
public JsonGenerator setPrettyPrinter(PrettyPrinter pp) {
return this;
}
@Override
public void setSchema(FormatSchema schema) {
if (schema instanceof JavaPropsSchema) {
_schema = (JavaPropsSchema) schema;
if (_jpropContext.inRoot()) {
String indent = _schema.lineIndentation();
_indentLength = (indent == null) ? 0 : indent.length();
if (_indentLength > 0) {
_basePath.setLength(0);
_basePath.append(indent);
_jpropContext = JPropWriteContext.createRootContext(_indentLength);
}
final String prefix = _schema.prefix();
if (prefix != null) {
_basePath.append(prefix);
}
}
return;
}
super.setSchema(schema);
}
@Override
public FormatSchema getSchema() { return _schema; }
@Override
public boolean canUseSchema(FormatSchema schema) {
return schema instanceof JavaPropsSchema;
}
@Override
public boolean canWriteObjectId() { return false; }
@Override
public boolean canWriteTypeId() { return false; }
@Override
public boolean canWriteBinaryNatively() { return false; }
@Override
public boolean canOmitFields() { return true; }
@Override
public boolean canWriteFormattedNumbers() { return true; }
@Override
public JacksonFeatureSet<StreamWriteCapability> getWriteCapabilities() {
return DEFAULT_TEXTUAL_WRITE_CAPABILITIES;
}
@Override
public JsonStreamContext getOutputContext() {
return _jpropContext;
}
@Override
public void writeFieldName(String name) throws IOException
{
if (!_jpropContext.writeFieldName(name)) {
_reportError("Can not write a field name, expecting a value");
}
if (!_headerChecked) {
_headerChecked = true;
String header = _schema.header();
if (header != null && !header.isEmpty()) {
_writeRaw(header);
}
}
_jpropContext.truncatePath(_basePath);
if (_basePath.length() > _indentLength) {
String sep = _schema.pathSeparator();
if (!sep.isEmpty()) {
_basePath.append(sep);
}
}
_appendFieldName(_basePath, name);
}
protected abstract void _appendFieldName(StringBuilder path, String name);
@Override
public void writeStartArray() throws IOException {
_verifyValueWrite("start an array");
_jpropContext = _jpropContext.createChildArrayContext(_basePath.length());
}
@Override
public void writeEndArray() throws IOException {
if (!_jpropContext.inArray()) {
_reportError("Current context not an Array but "+_jpropContext.typeDesc());
}
_jpropContext = _jpropContext.getParent();
}
@Override
public void writeStartObject() throws IOException {
_verifyValueWrite("start an object");
_jpropContext = _jpropContext.createChildObjectContext(_basePath.length());
}
@Override
public void writeEndObject() throws IOException
{
if (!_jpropContext.inObject()) {
_reportError("Current context not an Ibject but "+_jpropContext.typeDesc());
}
_jpropContext = _jpropContext.getParent();
}
@Override
public void writeString(String text) throws IOException
{
if (text == null) {
writeNull();
return;
}
_verifyValueWrite("write String value");
_writeEscapedEntry(text);
}
@Override
public void writeString(char[] text, int offset, int len)
throws IOException
{
_verifyValueWrite("write String value");
_writeEscapedEntry(text, offset, len);
}
@Override
public void writeRawUTF8String(byte[] text, int offset, int len)throws IOException
{
_reportUnsupportedOperation();
}
@Override
public void writeUTF8String(byte[] text, int offset, int len) throws IOException
{
writeString(new String(text, offset, len, "UTF-8"));
}
@Override
public void writeRaw(String text) throws IOException {
_writeRaw(text);
}
@Override
public void writeRaw(String text, int offset, int len) throws IOException {
_writeRaw(text.substring(offset, offset+len));
}
@Override
public void writeRaw(char[] text, int offset, int len) throws IOException {
_writeRaw(text, offset, len);
}
@Override
public void writeRaw(char c) throws IOException {
_writeRaw(c);
}
@Override
public void writeRaw(SerializableString text) throws IOException, JsonGenerationException {
writeRaw(text.toString());
}
@Override
public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len)
throws IOException
{
if (data == null) {
writeNull();
return;
}
_verifyValueWrite("write Binary value");
if (offset > 0 || (offset+len) != data.length) {
data = Arrays.copyOfRange(data, offset, offset+len);
}
String encoded = b64variant.encode(data);
_writeEscapedEntry(encoded);
}
@Override
public void writeBoolean(boolean state) throws IOException
{
_verifyValueWrite("write boolean value");
_writeUnescapedEntry(state ? "true" : "false");
}
@Override
public void writeNumber(int i) throws IOException
{
_verifyValueWrite("write number");
_writeUnescapedEntry(String.valueOf(i));
}
@Override
public void writeNumber(long l) throws IOException
{
_verifyValueWrite("write number");
_writeUnescapedEntry(String.valueOf(l));
}
@Override
public void writeNumber(BigInteger v) throws IOException
{
if (v == null) {
writeNull();
return;
}
_verifyValueWrite("write number");
_writeUnescapedEntry(String.valueOf(v));
}
@Override
public void writeNumber(double d) throws IOException
{
_verifyValueWrite("write number");
_writeUnescapedEntry(String.valueOf(d));
}
@Override
public void writeNumber(float f) throws IOException
{
_verifyValueWrite("write number");
_writeUnescapedEntry(String.valueOf(f));
}
@Override
public void writeNumber(BigDecimal dec) throws IOException
{
if (dec == null) {
writeNull();
return;
}
_verifyValueWrite("write number");
String str = isEnabled(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN) ? dec.toPlainString() : dec.toString();
_writeUnescapedEntry(str);
}
@Override
public void writeNumber(String encodedValue) throws IOException
{
if (encodedValue == null) {
writeNull();
return;
}
_verifyValueWrite("write number");
_writeUnescapedEntry(encodedValue);
}
@Override
public void writeNull() throws IOException
{
_verifyValueWrite("write null value");
_writeUnescapedEntry("");
}
@Override
protected void _verifyValueWrite(String typeMsg) throws IOException
{
if (!_jpropContext.writeValue()) {
_reportError("Can not "+typeMsg+", expecting field name");
}
if (_jpropContext.inArray()) {
_jpropContext.truncatePath(_basePath);
int ix = _jpropContext.getCurrentIndex() + _schema.firstArrayOffset();
if (_schema.writeIndexUsingMarkers()) {
Markers m = _schema.indexMarker();
_basePath.append(m.getStart());
_basePath.append(ix);
_basePath.append(m.getEnd());
} else {
if (_basePath.length() > 0) {
String sep = _schema.pathSeparator();
if (!sep.isEmpty()) {
_basePath.append(sep);
}
}
_basePath.append(ix);
}
}
}
protected abstract void _writeEscapedEntry(String value) throws IOException;
protected abstract void _writeEscapedEntry(char[] text, int offset, int len) throws IOException;
protected abstract void _writeUnescapedEntry(String value) throws IOException;
protected abstract void _writeRaw(char c) throws IOException;
protected abstract void _writeRaw(String text) throws IOException;
protected abstract void _writeRaw(StringBuilder text) throws IOException;
protected abstract void _writeRaw(char[] text, int offset, int len) throws IOException;
}