/** * 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; }