/**
* 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.Key;
import com.persistit.exception.ConversionException;
/**
* <p>
* Interface for specialized encoding and decoding of an <code>Object</code> of
* arbitrary type to or from a {@link Key}. Persistit contains built-in logic to
* encode Objects of certain classes. By registering a <code>KeyCoder</code>
* with the current {@link CoderManager} you can add encoding for classes that
* otherwise are not able to be included in Persistit key values.
* </p>
* <p>
* A <code>KeyCoder</code> implements methods to convert an object of some class
* to an array of bytes and back again. The byte array is used to identify (or
* partially identify) a record in a Persistit <code>Tree</code>. A typical
* <code>KeyCoder</code> simply appends identifying fields of the object.
* </p>
*
*
* @version 1.0
*/
public interface KeyCoder {
/**
* <p>
* Append a key segment derived from an object to a {@link Key}. This method
* will be called only if this <code>KeyCoder</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>Key</code> and its size should be updated to reflect the appended
* key segment. Use the methods {@link Key#getEncodedBytes},
* {@link Key#getEncodedSize} and {@link Key#setEncodedSize} to manipulate
* the byte array directly. More commonly, the implementation of this method
* will simply append appropriate identifying fields within the object to
* the key.
* </p>
* <p>
* This method is not responsible for encoding the class of the object being
* appended. The caller encodes the identity of the class. This method
* merely needs to encode the state of the object.
* </p>
*
* @param key
* The {@link Key} to append to
* @param object
* The object to encode
* @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 appendKeySegment(Key key, Object object, CoderContext context) throws ConversionException;
/**
* <p>
* Decode a key segment as an Object value. This method is invoked when
* {@link Key#decode(Object)} attempts to decode a key segment that was
* previously append by the {@link #appendKeySegment} method. Thus the
* implementation of this method must precisely decode the same bytes that
* were generated by the companion <code>appendKeySegment</code> method of
* this <code>ValueCoder</code>.
* </p>
* <p>
* This method will be called only if this <code>KeyCoder</code> is
* registered with the current {@link CoderManager} to encode and decode
* objects of the class that is actually represented in the <code>Key</code>
* . The class with which the key was encoded is provided as an argument.
* This permits one <code>KeyCoder</code> to handle multiple classes because
* the implementation can dispatch to code appropriate for the particular
* supplied class. The implementation should construct and return an Object
* having the same class as the supplied class.
* </p>
* <p>
* When this method is called the value {@link Key#getIndex()} will be the
* offset within the key of the first encoded byte. The key segment is
* zero-byte terminated.
* </p>
*
* @param key
* The {@link Key} from which data should be decoded
* @param clazz
* The expected <code>Class</code> of the returned object
* @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>.
* @throws ConversionException
*/
public Object decodeKeySegment(Key key, Class<?> clazz, CoderContext context) throws ConversionException;
/**
* <p>
* Since a key segment is terminated by a zero byte value the encoded
* portion of the segment must not contain zeroes. This method should
* indicate whether the encoding implemented by this KeyCoder produces zero
* bytes.
* </p>
* <p>
* If this method returns <code>false</code> then Persistit will insert
* escape sequences into the encoding produced by
* {@link #appendKeySegment(Key, Object, CoderContext)} to a form with no
* zeroes.
* </p>
* <p>
* If this method returns <code>true</code> then Persistit will verify that
* there are no zero bytes and throw an ConversionException otherwise.
*
* @return whether this KeyCoder produces encodings guaranteed not to
* contain zero bytes
* @throws ConversionException
*/
public boolean isZeroByteFree() throws ConversionException;
}