001// Copyright 2004, 2005 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.hivemind.lib.util;
016
017/**
018 * An implementation of the <b>strategy </b> pattern. The strategy pattern allows new functionality
019 * to be assigned to an existing class. As implemented here, this is a smart lookup between a
020 * particular class (called the <em>subject class</em>) and some object instance that can provide
021 * the extra functionality (called the <em>strategy</em>). The implementation of the strategy is
022 * not relevant to the StrategyRegistry class.
023 * <p>
024 * Strategies are registered before they can be used; the registration maps a particular class to a
025 * strategy instance. The strategy instance will be used when the subject class matches the
026 * registered class, or the subject class inherits from the registered class.
027 * <p>
028 * This means that a search must be made that walks the inheritance tree (upwards from the subject
029 * class) to find a registered mapping.
030 * <p>
031 * In addition, strategies can be registered against <em>interfaces</em>. Searching of interfaces
032 * occurs after searching of classes. The exact order is:
033 * <ul>
034 * <li>Search for the subject class, then each super-class of the subject class (excluding
035 * java.lang.Object)
036 * <li>Search interfaces, starting with interfaces implemented by the subject class, continuing
037 * with interfaces implemented by the super-classes, then interfaces extended by earlier interfaces
038 * (the exact order is a bit fuzzy)
039 * <li>Search for a match for java.lang.Object, if any
040 * </ul>
041 * <p>
042 * The first match terminates the search.
043 * <p>
044 * The StrategyRegistry caches the results of search; a subsequent search for the same subject class
045 * will be resolved immediately.
046 * <p>
047 * StrategyRegistry does a minor tweak of the "natural" inheritance. Normally, the parent class of
048 * an object array (i.e., <code>Foo[]</code>) is simply <code>Object</code>, even though you
049 * may assign <code>Foo[]</code> to a variable of type <code>Object[]</code>. StrategyRegistry
050 * "fixes" this by searching for <code>Object[]</code> as if it was the superclass of any object
051 * array. This means that the search path for <code>Foo[]</code> is <code>Foo[]</code>,
052 * <code>Object[]</code>, then a couple of interfaces {@link java.lang.Cloneable},
053 * {@link java.io.Serializable}, etc. that are implicitily implemented by arrays), and then,
054 * finally, <code>Object</code>
055 * <p>
056 * This tweak doesn't apply to arrays of primitives, since such arrays may <em>not</em> be
057 * assigned to <code>Object[]</code>.
058 * 
059 * @author Howard M. Lewis Ship
060 * @see org.apache.hivemind.lib.util.StrategyRegistryImpl
061 * @since 1.1
062 */
063public interface StrategyRegistry
064{
065    /**
066     * Registers an adapter for a registration class.
067     * 
068     * @throws IllegalArgumentException
069     *             if a strategy has already been registered for the given class.
070     */
071    public void register(Class registrationClass, Object strategy);
072
073    /**
074     * Gets the stategy object for the specified subjectClass.
075     * 
076     * @throws IllegalArgumentException
077     *             if no strategy could be found.
078     */
079    public Object getStrategy(Class subjectClass);
080}