/**
* 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 java.util.Map;
import com.persistit.DefaultCoderManager;
import com.persistit.Exchange;
import com.persistit.Key;
/**
* <p>
* Manages the collections of {@link KeyCoder}s and {@link ValueCoder}s that
* encode and decode object values in Persistit™. An application should
* register all <code>KeyCoder</code> and <code>ValueCoder</code>
* implementations before storing or accessing objects of the associated classes
* in Persistit.
* </p>
* <p>
* When Persistit is initialized, a instance of {@link DefaultCoderManager} is
* installed as the current <code>CoderManager</code>. Applications can refer to
* it through the method {@link com.persistit.Persistit#getCoderManager}.
* Applications should register <code>KeyCoder</code> and
* <code>ValueCoder</code> instances as follows: <blockquote>
*
* <pre>
* ValueCoder vc1 = new MyClassValueCoder();
* KeyCoder kc1 = new MyClassKeyCoder();
* Persistit.getInstance().getCoderManager().registerValueCoder(MyClass.class, kc1);
* Persistit.getInstance().getCoderManager().registerKeyCoder(MyClass.class, kc1);
* </pre>
*
* </blockquote> Subsequently, any time the application appends an instance of a
* <code>MyClass</code> to a <code>Key</code>, the <code>MyClassKeyCoder</code>
* will be used to convert the interior state of the <code>MyClass</code> into a
* representation within the <code>Key</code>. Likewise, whenever the
* application puts an object of class <code>MyClass</code> into a
* <code>Value</code>, the registered <code>MyClassValueCoder</code> will be
* used to encode it. Persistit uses the {@link #lookupKeyCoder} and
* {@link #lookupValueCoder} methods to acquire the appropriate coder.
* </p>
* <p>
* An application may replace the default implementation provided by
* <code>DefaultCoderManager</code>. Such a custom implementation might, for
* example, handle the relationship between certain classes and their associated
* coders in a special way.
* </p>
* <p>
* An application can create and install a customized <code>CoderManager</code>
* as follows: <blockquote>
*
* <pre>
* CoderManager myCoderManager = new MyCoderManager(Persistit.getInstance().getCoderManager());
* Persistit.getInstance().setCoderManager(myCoderManager);
* </pre>
*
* </blockquote> Note that the <code>MyCoderManager</code> instance receives the
* previously installed <code>CoderManager</code> as an argument of its
* constructor. The new <code>CoderManager</code> should return the previously
* installed one as the value of its {@link #getParent} method, and the
* {@link #lookupKeyCoder} and {@link #lookupValueCoder} should delegate any
* lookups not handled by the customized <code>CoderManager</code> back to the
* parent.
* </p>
* <h3>Key Ordering</h3>
* <p>
* The encoding of key values determines the ordering of traversal for
* {@link Exchange#traverse} and associated methods. See {@link Key} for
* definition of the ordering among the types for which built-in encoding
* exists. The ordering of key values based on objects that are encoded by
* custom <code>KeyCoder</code>s is determined by the implementation of each
* </code>KeyCoder</code>.
* </p>
* This leaves the question of how keys that may contain encoded objects of
* different classes are ordered. For example, consider the code fragment shown
* here: <blockquote>
*
* <pre>
* Exchange exchange = new Exchange(...);
* Object a = new MyClass1(); // where MyClass1 and MyClass2
* Object b = new MyClass2(); // have registered KeyCoders
* exchange.to(a).store(); // store something with a's value as key
* exchange.to(b).store(); // store something with b's value as key
* exchange.to(Key.BEFORE)
* while (exchange.next())
* {
* System.out.println(exchange.indexTo(-1).getTypeName());
* }
* </pre>
*
* </blockquote> This code will insert two records incorporating the values
* <code>a</code> and <code>b</code> into Persistit, and will then traverse the
* resulting tree and print the names of the classes of the key values. The
* question is whether "MyClass2" will be printed before or after "MyClass2".
* </p>
* <p>
* The answer depends on the order in which MyClass1 and MyClass2 were first
* registered within Persistit. At the time a new class is first registered,
* Persistit assigns a permanent <code>int</code>-valued class handle to the
* class. Whenever an instance of that class is encoded within either a
* <code>Key</code> or a <code>Value</code>, that handle value, rather than the
* class name, is used. This reduces disk, memory and CPU consumption whenever
* Persistit stores or retrieves objects. Handles are assigned in increasing
* numeric order as classes are registered. Thus if <code>MyClass1</code> was
* registered <i>before</i> <code>MyClass2</code>, it will precede
* <code>MyClass2</code> in traversal order. Otherwise it will follow
* <code>MyClass2</code>.
* </p>
*
* @version 1.0
*/
public interface CoderManager {
/**
* Create a <code>Map</code> of <code>Class</code>es to registered
* <code>ValueCoder</code>s. The map is an unmodifiable, is sorted by class
* name, and does not change with subsequent registrations or
* unregistrations of <code>ValueCoder</code>s.
*
* @return <code>Map</code> of <code>Class</code>es to
* <code>ValueCoder</code>s.
*/
public Map<Class<?>, ? extends ValueCoder> getRegisteredValueCoders();
/**
* Create a <code>Map</code> of <code>Class</code>es to registered
* <code>KeyCoder</code> s. The map is an unmodifiable, and is sorted by
* class name, and does not change with subsequent registrations or
* unregistrations of <code>KeyCoder</code>s.
*
* @return <code>Map</code> of <code>Class</code>es to <code>KeyCoder</code>
* s.
*/
public Map<Class<?>, ? extends KeyCoder> getRegisteredKeyCoders();
/**
* Register the provided <code>KeyCoder</code> to encode and decode
* instances of supplied class.
*
* @param clazz
* The Class for which this <code>KeyCoder</code> will provide
* encoding and decoding services
* @param coder
* The KeyCoder to register
* @return The <code>KeyCoder</code> formerly registered for this
* <code>Class</code> , or <code>null</code> if there was none.
*/
public KeyCoder registerKeyCoder(Class<?> clazz, KeyCoder coder);
/**
* Remove the registered <code>KeyCoder</code> for the supplied class.
*
* @param clazz
* The <code>Class</code> from which to remove a
* <code>KeyCoder</code>, if present
* @return The <code>KeyCoder</code> that was removed, or <code>null</code>
* if there was none.
*/
public KeyCoder unregisterKeyCoder(Class<?> clazz);
/**
* Remove the supplied <code>KeyCoder</code> from all classes to which it
* was previously registered.
*
* @param coder
* The <code>KeyCoder</code> to remove.
* @return The count of classes this <code>KeyCoder</code> was registered
* for.
*/
public int unregisterKeyCoder(KeyCoder coder);
/**
* Returns the <code>KeyCoder</code> registered for the supplied
* <code>Class</code>, or <code>null</code> if no <code>KeyCoder</code> is
* registered.
*
* @param clazz
* The <code>Class</code>
* @return The <code>KeyCoder</code> or <code>null</code> if there is none.
*/
public KeyCoder lookupKeyCoder(Class<?> clazz);
/**
* Register the provided <code>ValueCoder</code> to encode and decode
* instances of supplied class.
*
* @param clazz
* The Class for which this <code>ValueCoder</code> will provide
* encoding and decoding services
* @param coder
* The ValueCoder to register
* @return The <code>ValueCoder</code> that was removed, or
* <code>null</code> if there was none.
*/
public ValueCoder registerValueCoder(Class<?> clazz, ValueCoder coder);
/**
* Remove the registered <code>ValueCoder</code> for the supplied class.
*
* @param clazz
* The <code>Class</code> from which to remove a
* <code>ValueCoder</code>, if present
* @return The <code>ValueCoder</code> that was removed, or
* <code>null</code> if there was none.
*/
public ValueCoder unregisterValueCoder(Class<?> clazz);
/**
* Remove the supplied <code>ValueCoder</code> from all classes to which it
* was previously registered.
*
* @param coder
* The <code>ValueCoder</code> to remove.
* @return The count of classes this <code>ValueCoder</code> was registered
* for.
*/
public int unregisterValueCoder(ValueCoder coder);
/**
* Returns the <code>ValueCoder</code> registered for the supplied
* <code>Class</code>, or <code>null</code> if no <code>ValueCoder</code> is
* registered.
*
* @param clazz
* The <code>Class</code>
* @return The <code>ValueCoder</code> or <code>null</code> if there is
* none.
*/
public ValueCoder lookupValueCoder(Class<?> clazz);
/**
* Return a <code>ValueCoder</code> for the supplied <code>Class</code>. If
* there is none registered, implicitly create one and register it.
*
* @param clazz
* @return The ValueCoder
*/
public ValueCoder getValueCoder(Class<?> clazz);
/**
* Return the parent <code>CoderManager</code> implementation, or
* <code>null</code> if there is none.
*
* @return The parent <code>CoderManager</code>
*/
public CoderManager getParent();
}