com.amazon.ion.impl.IonWriterSystemTree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ion-java Show documentation
Show all versions of ion-java Show documentation
A Java implementation of the Amazon Ion data notation.
The newest version!
/*
* Copyright 2007-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file 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.amazon.ion.impl;
import static com.amazon.ion.impl._Private_Utils.valueIsLocalSymbolTable;
import com.amazon.ion.IonBlob;
import com.amazon.ion.IonCatalog;
import com.amazon.ion.IonClob;
import com.amazon.ion.IonContainer;
import com.amazon.ion.IonDatagram;
import com.amazon.ion.IonDecimal;
import com.amazon.ion.IonException;
import com.amazon.ion.IonFloat;
import com.amazon.ion.IonSequence;
import com.amazon.ion.IonString;
import com.amazon.ion.IonStruct;
import com.amazon.ion.IonSymbol;
import com.amazon.ion.IonTimestamp;
import com.amazon.ion.IonType;
import com.amazon.ion.IonValue;
import com.amazon.ion.SymbolTable;
import com.amazon.ion.SymbolToken;
import com.amazon.ion.Timestamp;
import com.amazon.ion.ValueFactory;
import com.amazon.ion.system.IonWriterBuilder.InitialIvmHandling;
import com.amazon.ion.system.IonWriterBuilder.IvmMinimizing;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* Provides a concrete implementation of the IonWriter where
* the output of the this writer is one or more IonValues,
* typically an IonDatagram with contents.
*/
final class IonWriterSystemTree
extends IonWriterSystem
{
/** Factory for constructing local symbol tables. Not null. */
private final LocalSymbolTableAsStruct.Factory _lst_factory;
private final ValueFactory _factory;
/** Used to construct new local symtabs. May be null */
private final IonCatalog _catalog;
private final int _initialDepth;
private boolean _in_struct;
/**
* The container into which we are currently appending values.
* Never null.
*/
private IonContainer _current_parent;
private int _parent_stack_top = 0;
private IonContainer[] _parent_stack = new IonContainer[10];
/**
* @param defaultSystemSymbolTable must not be null.
* @param catalog may be null.
* @param rootContainer must not be null.
*/
protected IonWriterSystemTree(SymbolTable defaultSystemSymbolTable,
IonCatalog catalog,
IonContainer rootContainer,
InitialIvmHandling initialIvmHandling)
{
super(defaultSystemSymbolTable, initialIvmHandling,
IvmMinimizing.ADJACENT, true);
_factory = rootContainer.getSystem();
_lst_factory = (LocalSymbolTableAsStruct.Factory)((_Private_ValueFactory)_factory).getLstFactory();
_catalog = catalog;
_current_parent = rootContainer;
_in_struct = (_current_parent instanceof IonStruct);
int depth = 0;
if (! (rootContainer instanceof IonDatagram)) {
IonContainer c = rootContainer;
do {
depth++;
c = c.getContainer();
} while (c != null);
}
_initialDepth = depth;
}
//
// informational methods
//
@Override
public int getDepth()
{
return _parent_stack_top + _initialDepth;
}
protected IonType getContainer()
{
IonType containerType;
if (_parent_stack_top > 0) {
containerType = _parent_stack[_parent_stack_top-1].getType();
}
else {
containerType = IonType.DATAGRAM;
}
return containerType;
}
public boolean isInStruct() {
return _in_struct;
}
//
// helpers
//
protected IonValue get_root()
{
IonValue container;
if (_parent_stack_top > 0) {
container = _parent_stack[0];
}
else {
container = _current_parent;
}
return container;
}
/**
* @param newParent must not be null.
*/
private void pushParent(IonContainer newParent)
{
int oldlen = _parent_stack.length;
if (_parent_stack_top >= oldlen) {
int newlen = oldlen * 2;
IonContainer[] temp = new IonContainer[newlen];
System.arraycopy(_parent_stack, 0, temp, 0, oldlen);
_parent_stack = temp;
}
_parent_stack[_parent_stack_top++] = _current_parent;
_current_parent = newParent;
_in_struct = (_current_parent instanceof IonStruct);
}
private void popParent()
{
if (_parent_stack_top < 1) {
throw new IllegalStateException(IonMessages.CANNOT_STEP_OUT);
}
_parent_stack_top--;
_current_parent = _parent_stack[_parent_stack_top];
_in_struct = (_current_parent instanceof IonStruct);
}
private void append(IonValue value)
{
try
{
super.startValue();
}
catch (IOException e)
{
throw new IonException(e); // Shouldn't happen
}
if (hasAnnotations()) {
SymbolToken[] annotations = getTypeAnnotationSymbols();
// TODO this makes an extra copy of the array
((_Private_IonValue)value).setTypeAnnotationSymbols(annotations);
this.clearAnnotations();
}
if (_in_struct) {
SymbolToken sym = assumeFieldNameSymbol();
IonStruct struct = (IonStruct) _current_parent;
struct.add(sym, value);
this.clearFieldName();
}
else {
((IonSequence)_current_parent).add(value);
}
}
public void stepIn(IonType containerType) throws IOException
{
IonContainer v;
switch (containerType)
{
case LIST: v = _factory.newEmptyList(); break;
case SEXP: v = _factory.newEmptySexp(); break;
case STRUCT: v = _factory.newEmptyStruct(); break;
default:
throw new IllegalArgumentException();
}
append(v);
pushParent(v);
}
public void stepOut() throws IOException
{
_Private_IonValue prior = (_Private_IonValue)_current_parent;
popParent();
if (_current_parent instanceof IonDatagram
&& valueIsLocalSymbolTable(prior))
{
// We just finish writing a symbol table!
SymbolTable symbol_table = _lst_factory.newLocalSymtab(_catalog, (IonStruct) prior);
setSymbolTable(symbol_table);
}
}
@Override
void writeIonVersionMarkerAsIs(SymbolTable systemSymtab)
throws IOException
{
startValue();
IonValue root = get_root();
((_Private_IonDatagram)root).appendTrailingSymbolTable(systemSymtab);
endValue();
}
@Override
void writeLocalSymtab(SymbolTable symtab)
throws IOException
{
IonValue root = get_root();
((_Private_IonDatagram)root).appendTrailingSymbolTable(symtab);
super.writeLocalSymtab(symtab);
}
@Override
final SymbolTable inject_local_symbol_table() throws IOException
{
return _lst_factory.newLocalSymtab(getSymbolTable());
}
//========================================================================
public void writeNull(IonType type)
throws IOException
{
IonValue v = _factory.newNull(type);
append(v);
}
public void writeBool(boolean value)
throws IOException
{
IonValue v = _factory.newBool(value);
append(v);
}
public void writeInt(int value)
throws IOException
{
IonValue v = _factory.newInt(value);
append(v);
}
public void writeInt(long value)
throws IOException
{
IonValue v = _factory.newInt(value);
append(v);
}
public void writeInt(BigInteger value)
throws IOException
{
IonValue v = _factory.newInt(value);
append(v);
}
public void writeFloat(double value)
throws IOException
{
IonFloat v = _factory.newNullFloat();
v.setValue(value);
append(v);
}
@Override
public void writeDecimal(BigDecimal value) throws IOException
{
IonDecimal v = _factory.newNullDecimal();
v.setValue(value);
append(v);
}
public void writeTimestamp(Timestamp value) throws IOException
{
IonTimestamp v = _factory.newTimestamp(value);
append(v);
}
public void writeString(String value)
throws IOException
{
IonString v = _factory.newString(value);
append(v);
}
@Override
void writeSymbolAsIs(int symbolId)
{
String name = getSymbolTable().findKnownSymbol(symbolId);
SymbolTokenImpl is = new SymbolTokenImpl(name, symbolId);
IonSymbol v = _factory.newSymbol(is);
append(v);
}
@Override
public void writeSymbolAsIs(String value)
{
IonSymbol v = _factory.newSymbol(value);
append(v);
}
public void writeClob(byte[] value, int start, int len)
throws IOException
{
IonClob v = _factory.newClob(value, start, len);
append(v);
}
public void writeBlob(byte[] value, int start, int len)
throws IOException
{
IonBlob v = _factory.newBlob(value, start, len);
append(v);
}
public void flush()
{
// flush is not meaningful for a tree writer
}
public void close()
{
// close is not meaningful for a tree writer
}
}