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    
015    package 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     */
063    public 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    }