/*
 * Copyright 2012-2016 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://aws.amazon.com/apache2.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.fasterxml.jackson.dataformat.ion;

import java.io.CharArrayReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;

import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.core.util.TextBuffer;
import com.fasterxml.jackson.dataformat.ion.util.CloseSafeUTF8Writer;

import com.amazon.ion.IonReader;
import com.amazon.ion.IonSystem;
import com.amazon.ion.IonValue;
import com.amazon.ion.IonWriter;
import com.amazon.ion.system.IonSystemBuilder;

Sub-class of JsonFactory that will work on Ion content, instead of JSON content.
/** * Sub-class of {@link JsonFactory} that will work on Ion content, instead of JSON * content. */
@SuppressWarnings("resource") public class IonFactory extends JsonFactory { private static final long serialVersionUID = 1L; public final static String FORMAT_NAME_ION = "AmazonIon"; final IonSystem _system;
Whether we will produce binary or text Ion writers: default is textual.
/** * Whether we will produce binary or text Ion writers: default is textual. */
protected boolean _cfgCreateBinaryWriters = false; public IonFactory() { this((ObjectCodec) null); } public IonFactory(ObjectCodec mapper) { this(mapper, IonSystemBuilder.standard().build()); } public IonFactory(ObjectCodec mapper, IonSystem system) { super(mapper); _system = system; } protected IonFactory(IonFactory src, ObjectCodec oc) { super(src, oc); // 21-Feb-2017, tatu: Not 100% sure if this should be made copy of // too; for now assume it may be shared. _system = src._system; _cfgCreateBinaryWriters = src._cfgCreateBinaryWriters; }
Constructors used by IonFactoryBuilder for instantiation.
Since:3.0
/** * Constructors used by {@link IonFactoryBuilder} for instantiation. * * @since 3.0 */
protected IonFactory(IonFactoryBuilder b) { super(b, false); _cfgCreateBinaryWriters = b.willCreateBinaryWriters(); _system = b.ionSystem(); } @Override public IonFactoryBuilder rebuild() { return new IonFactoryBuilder(this); }
Method for creating IonFactory that will create binary (not textual) writers.
/** * Method for creating {@link IonFactory} that will * create binary (not textual) writers. */
public static IonFactory forBinaryWriters() { return new IonFactoryBuilder(true).build(); }
Method for creating IonFactoryBuilder initialized with settings to create binary (not textual) writers.
/** * Method for creating {@link IonFactoryBuilder} initialized with settings to * create binary (not textual) writers. */
public static IonFactoryBuilder builderForBinaryWriters() { return new IonFactoryBuilder(true); }
Method for creating IonFactory that will create textual (not binary) writers.
/** * Method for creating {@link IonFactory} that will * create textual (not binary) writers. */
public static IonFactory forTextualWriters() { return new IonFactoryBuilder(false).build(); }
Method for creating IonFactoryBuilder initialized with settings to create textual (not binary) writers.
/** * Method for creating {@link IonFactoryBuilder} initialized with settings to * create textual (not binary) writers. */
public static IonFactoryBuilder builderForTextualWriters() { return new IonFactoryBuilder(false); } @Override public IonFactory copy() { _checkInvalidCopy(IonFactory.class); // note: as with base class, must NOT copy mapper reference return new IonFactory(this, null); } @Override public Version version() { return PackageVersion.VERSION; } @Override public String getFormatName() { return FORMAT_NAME_ION; } public void setCreateBinaryWriters(boolean b) { _cfgCreateBinaryWriters = b; } public boolean createBinaryWriters() { return _cfgCreateBinaryWriters; } @Override // since 2.3 public boolean canHandleBinaryNatively() { // 21-Feb-2017, tatu: I think only support with binary backend return _cfgCreateBinaryWriters; } @Override // since 2.4 public boolean canUseCharArrays() { return false; } /* *************************************************************** * Extended API *************************************************************** */
Since:2.7
/** * @since 2.7 */
public IonParser createParser(IonReader in) { return new IonParser(in, _system, _createContext(in, false), getCodec()); }
Since:2.7
/** * @since 2.7 */
public IonParser createParser(IonValue value) { IonReader in = value.getSystem().newReader(value); return new IonParser(in, _system, _createContext(in, true), getCodec()); }
Since:2.7
/** * @since 2.7 */
public JsonGenerator createGenerator(IonWriter out) { return _createGenerator(out, false, _createContext(out, false), out); }
Deprecated:Since 2.7
/** * @deprecated Since 2.7 */
@Deprecated public IonParser createJsonParser(IonReader in) { return new IonParser(in, _system, _createContext(in, false), getCodec()); }
Deprecated:Since 2.7
/** * @deprecated Since 2.7 */
@Deprecated public IonParser createJsonParser(IonValue value) { IonReader in = value.getSystem().newReader(value); return new IonParser(in, _system, _createContext(in, true), getCodec()); }
Deprecated:Since 2.7
/** * @deprecated Since 2.7 */
@Deprecated public JsonGenerator createJsonGenerator(IonWriter out) { return _createGenerator(out, false, _createContext(out, false), out); } /* *************************************************************** * Overridden factory methods *************************************************************** */ @Override protected JsonParser _createParser(InputStream in, IOContext ctxt) throws IOException { IonReader ion = _system.newReader(in); return new IonParser(ion, _system, ctxt, getCodec()); } @Override protected JsonParser _createParser(Reader r, IOContext ctxt) throws IOException { return new IonParser(_system.newReader(r), _system, ctxt, getCodec()); } @Override protected JsonParser _createParser(char[] data, int offset, int len, IOContext ctxt, boolean recyclable) throws IOException { return _createParser(new CharArrayReader(data, offset, len), ctxt); } @Override protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException { return new IonParser(_system.newReader(data, offset, len), _system, ctxt, getCodec()); } @Override public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException { return _createGenerator(out, enc, false); } @Override public JsonGenerator createGenerator(Writer out) throws IOException { // First things first: no binary writer for Writers: if (createBinaryWriters()) { throw new IOException("Can only create binary Ion writers that output to OutputStream, not Writer"); } return _createGenerator(_system.newTextWriter(out), true, _createContext(out, false), out); } @Override public JsonGenerator createGenerator(File f, JsonEncoding enc) throws IOException { return _createGenerator(new FileOutputStream(f), enc, true); } /* *************************************************************** * Helper methods *************************************************************** */ @Deprecated protected String _readAll(Reader r, IOContext ctxt) throws IOException { // Let's use Jackson's efficient aggregators... better than JDK defaults TextBuffer tb = ctxt.constructTextBuffer(); char[] buf = tb.emptyAndGetCurrentSegment(); // this gets bit ugly. Blah. int offset = 0; main_loop: while (true) { while (offset < buf.length) { int count = r.read(buf, offset, buf.length - offset); if (count < 0) { break main_loop; } offset += count; } // got full buffer; get another one buf = tb.finishCurrentSegment(); offset = 0; } // Ok, last one is incomplete... tb.setCurrentLength(offset); String result = tb.contentsAsString(); tb.releaseBuffers(); return result; } protected IonGenerator _createGenerator(OutputStream out, JsonEncoding enc, boolean isManaged) throws IOException { IonWriter ion; IOContext ctxt = _createContext(out, isManaged); Closeable dst; // not necessarily same as 'out'... // Binary writers are simpler: no alternate encodings if (createBinaryWriters()) { ctxt.setEncoding(enc); ion = _system.newBinaryWriter(out); dst = out; } else { if (enc != JsonEncoding.UTF8) { // not sure if non-UTF-8 encodings would be legal... throw new IOException("Ion only supports UTF-8 encoding, can not use "+enc); } /* In theory Ion package could take some advantage of getting OutputStream. * In practice we seem to be better off using Jackson's efficient buffering * encoder */ ctxt.setEncoding(enc); // This is bit unfortunate, since out != dst now... Writer w = new CloseSafeUTF8Writer(ctxt, out); ion = _system.newTextWriter(w); dst = w; } return _createGenerator(ion, true, ctxt, dst); } protected IonGenerator _createGenerator(IonWriter ion, boolean ionWriterIsManaged, IOContext ctxt, Closeable dst) { return new IonGenerator(_generatorFeatures, _objectCodec, ion, ionWriterIsManaged, ctxt, dst); } }