All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.joda.beans.ser.bin.JodaBeanBinWriter Maven / Gradle / Ivy

The newest version!
/*
 *  Copyright 2001-present Stephen Colebourne
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  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.joda.beans.ser.bin;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.joda.beans.Bean;
import org.joda.beans.ImmutableBean;
import org.joda.beans.ser.JodaBeanSer;

/**
 * Provides the ability for a Joda-Bean to be written to a binary format.
 * 

* This class is immutable and may be used from multiple threads. * *

Standard format

* The binary format is based on MessagePack v2.0. * Each bean is output as a map using the property name. *

* Most simple types, defined by Joda-Convert, are output as MessagePack strings. * However, MessagePack nil, boolean, float, integral and bin types are also used * for null, byte[] and the Java numeric primitive types (excluding char). *

* Beans are output using MessagePack maps where the key is the property name. * Collections are output using MessagePack maps or arrays. * Multisets are output as a map of value to count. *

* If a collection contains a collection then addition meta-type information is * written to aid with deserialization. * At this level, the data read back may not be identical to that written. *

* Where necessary, the Java type is sent using an 'ext' entity. * Three 'ext' types are used, one each for beans, meta-type and simple. * The class name is passed as the 'ext' data. * The 'ext' value is sent as an additional key-value pair for beans, with the * 'ext' as the key and 'nil' as the value. Where the additional type information * is not about a bean, a tuple is written using a size 1 map where the key is the * 'ext' data and the value is the data being annotated. *

* Type names are shortened by the package of the root type if possible. * Certain basic types are also handled, such as String, Integer, File and URI. * *

Referencing format

* The referencing format is based on the standard format. * As a more complex format, it is intended to be consumed only by Joda-Beans * (whereas the standard format could be consumed by any consumer using MsgPack). * Thus this format is not fully documented and may change over time. *

* The referencing format only supports serialization of instances of {@code ImmutableBean} * and other basic types. If any mutable beans are encountered during traversal an exception will be thrown. *

* An initial pass of the bean is used to build up a map of unique immutable beans * and unique immutable instances of other classes (based on an equality check). * Then the class and property names for each bean class is serialized up front as a map of class name to list of * property names, along with class information for any class where type information would be required when parsing * and is not available on the metabean for the enclosing bean object. *

* Each unique immutable bean is output as a list of each property value using the fixed * property order previously serialized. Subsequent instances of unique objects (defined by an * equality check) are replaced by references to the first serialized instance. *

* The Java type names are sent using an 'ext' entity. * Five 'ext' types are used, one each for beans, meta-type and simple, reference keys and reference lookups. * The class name is passed as the 'ext' data. * The 'ext' value is sent as the first item in an array of property values for beans, an integer referring to the * location in the initial class mapping. * Where the additional type information is not about a bean, a tuple is written using a size 1 map where the key is * the 'ext' data and the value is the data being annotated. *

* For references, when an object will be referred back to it is written as a map of size one with 'ext' as the key * and the object that should be referred to as the value. * When that same object is referred back to it is written as 'ext' with the data from the initial 'ext'. */ public class JodaBeanBinWriter { /** * Settings. */ private final JodaBeanSer settings; /** * Whether to use referencing. */ private final boolean referencing; //----------------------------------------------------------------------- /** * Creates an instance. * * @param settings the settings to use, not null */ public JodaBeanBinWriter(JodaBeanSer settings) { this(settings, false); } /** * Creates an instance. * * @param settings the settings to use, not null * @param referencing whether to use referencing */ public JodaBeanBinWriter(JodaBeanSer settings, boolean referencing) { if (settings == null) { throw new NullPointerException("settings"); } this.settings = settings; this.referencing = referencing; } //----------------------------------------------------------------------- /** * Writes the bean to an array of bytes. *

* The type of the bean will be set in the message. * * @param bean the bean to output, not null * @return the binary data, not null */ public byte[] write(Bean bean) { return write(bean, true); } /** * Writes the bean to an array of bytes. * * @param bean the bean to output, not null * @param rootType true to output the root type * @return the binary data, not null */ public byte[] write(Bean bean, boolean rootType) { ByteArrayOutputStream baos = new ByteArrayOutputStream(1024); try { write(bean, rootType, baos); } catch (IOException ex) { throw new IllegalStateException(ex); } return baos.toByteArray(); } /** * Writes the bean to the {@code OutputStream}. *

* The type of the bean will be set in the message. * * @param bean the bean to output, not null * @param output the output stream, not null * @throws IOException if an error occurs */ public void write(Bean bean, OutputStream output) throws IOException { write(bean, true, output); } /** * Writes the bean to the {@code OutputStream}. * * @param bean the bean to output, not null * @param rootType true to output the root type * @param output the output stream, not null * @throws IOException if an error occurs */ public void write(Bean bean, boolean rootType, OutputStream output) throws IOException { if (bean == null) { throw new NullPointerException("bean"); } if (output == null) { throw new NullPointerException("output"); } if (referencing) { if (!(bean instanceof ImmutableBean)) { throw new IllegalArgumentException( "Referencing binary format can only write ImmutableBean instances: " + bean.getClass().getName()); } new JodaBeanReferencingBinWriter(settings, output).write((ImmutableBean) bean); } else { new JodaBeanStandardBinWriter(settings, output).write(bean, rootType); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy