/**
* Copyright 2005-2012 Akiban Technologies, Inc.
*
* 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 com.persistit.encoding;
import com.persistit.Value;
import com.persistit.exception.ConversionException;
/**
* <p>
* Interface for specialized encoding and decoding of <code>Object</code>s of
* arbitrary type in a {@link Value}. Persistit contains built-in logic to
* encode objects of certain classes. For other classes, if there is no
* registered <code>ValueCoder</code>, Persistit uses standard object
* serialization to generate a byte array that represents the state of that
* object in the database.
* </p>
* <p>
* By implementing and registering a <code>ValueCoder</code> with the current
* {@link CoderManager} you can override this default encoding. Typically the
* customized encoding of an object will be much shorter than that produced by
* serialization because the customized encoding classes by their Persistit
* class handles (see {@link com.persistit.ClassIndex}) rather than their names.
* In addition, standard serialization serializes the entire graph of other
* objects that may be directly or indirectly referred to by the object being
* made persistent. This behavior may result in storing much more data than is
* required, and more importantly, may result in incorrect semantics. A
* customized <code>ValueEncoder</code> can handle persistence of fields that
* refer to other objects in a manner that is semantically appropriate for the
* specific object. Note that if a class has a <code>ValueCoder</code>, it can
* be stored in Persistit even if it does not implement
* <code>java.io.Serializable</code>.
* </p>
* <p>
* A <code>ValueCoder</code> implements methods to convert an object of some
* class to an array of bytes and back again. Typically the implementation of a
* <code>ValueCoder</code> will simply invoke the <code>Value</code>'s
* <code>put</code> methods to write the fields into the <code>Value</code>. For
* example, the following code defines a class, and a <code>ValueCoder</code> to
* store and retrieve it.
* </p>
* <blockquote>
*
* <pre>
* class MyClass {
* int id;
* int anotherInt;
* String someString;
* MyClass anotherMyClass;
* }
*
* class MyClassValueCoder implements ValueCoder {
* public void put(Value value, Object object, CoderContext context) {
* MyClass mc = (MyClass) object;
* value.put(mc.id);
* value.put(mc.anotherInt);
* value.put(mc.someString);
* value.put(mc.anotherMyClass == null ? -1 : mc.anotherMyClass.id);
* }
*
* public Object get(Value value, Class clazz, CoderContext context) {
* MyClass mc = new MyClass();
* mc.id = value.getInt();
* mc.anotherInt = value.getInt();
* mc.someString = value.getString();
* mc.anotherMyClass = lookupMyClass(value.getInt());
* return mc;
* }
* }
* </pre>
*
* </blockquote>
* <p>
* The application should register this <code>ValueCoder</code> before
* attempting to invoke {@link Value#put(Object)} on an object of class
* <code>MyClass</code> or to retrieve an object value using {@link Value#get()}
* that will resolve to a <code>MyClass</code>. Generally this means that
* applications should register all <code>ValueCoder</code>s and
* <code>KeyCoder</code>s during application startup, immediately after invoking
* {@link com.persistit.Persistit#initialize}. For example: <blockquote>
*
* <pre>
* ...
* try
* {
* Persistit.initialize();
* CoderManager cm = Persistit.getInstance().getCoderManager();
* cm.registerValueCoder(new MyClassValueCoder());
* cm.registerValueCoder(new MyClassValueCoder2());
* ...
* cm.registerKeyCoder(new MyClassKeyCoder());
* ...
* }
* catch (PersistitException e)
* {
* ...
* }
* </pre>
*
* </blockquote>
* </p>
*
* @version 1.0
*/
public interface ValueCoder {
/**
* <p>
* Encodes the supplied <code>Object</code> into the supplied
* <code>Value</code>. This method will be called only if this
* <code>ValueCoder</code> has been registered with the current
* {@link CoderManager} to encode objects having the class of the supplied
* object.
* </p>
* <p>
* Upon completion of this method, the backing byte array of the
* <code>Value</code> and its size should be updated to reflect the
* serialized object. Use the methods {@link Value#getEncodedBytes},
* {@link Value#getEncodedSize} and {@link Value#setEncodedSize} to
* manipulate the byte array directly. More commonly, the implementation of
* this method will simply call the appropriate <code>put</code> methods to
* write the interior field values into the <code>Value</code> object.
* </p>
*
* @param value
* The <code>Value</code> to which the interior data of the
* supplied <code>Object</code> should be encoded
* @param object
* The object value to encode. This parameter will never be
* <code>null</code> because Persistit encodes nulls with a
* built-in encoding.
* @param context
* An arbitrary object that can optionally be supplied by the
* application to convey an application-specific context for the
* operation. (See {@link CoderContext}.) The default value is
* <code>null</code>.
*/
public void put(Value value, Object object, CoderContext context) throws ConversionException;
/**
* <p>
* Creates an instance of the supplied class, populates its state by
* decoding the supplied <code>Value</code>, and returns it. This method
* will be called only if this <code>ValueCoder</code> has been registered
* with the current {@link CoderManager} to encode objects having supplied
* <code>Class</code> value. Persistit will never call this method to decode
* a value that was <code>null</code> when written because null values are
* handled by built-in encoding logic.
* </p>
*
* @param value
* The <code>Value</code> from which interior fields of the
* object are to be retrieved
* @param clazz
* The class of the object to be returned.
* @param context
* An arbitrary object that can optionally be supplied by the
* application to convey an application-specific context for the
* operation. (See {@link CoderContext}.) The default value is
* <code>null</code>.
* @return An <code>Object</code> having the same class as the suppled
* <code>clazz</code> parameter.
* @throws ConversionException
*/
public Object get(Value value, Class<?> clazz, CoderContext context) throws ConversionException;
}