    001    /*****************************************************************************
    002     * Copyright (C) PicoContainer Organization. All rights reserved.            *
    003     * ------------------------------------------------------------------------- *
    004     * The software in this package is published under the terms of the BSD      *
    005     * style license a copy of which has been included with this distribution in *
    006     * the LICENSE.txt file.                                                     *
    007     *                                                                           *
    008     * Original code by                                                          *
    009     *****************************************************************************/
    010    package org.picocontainer.adapters;
    011
    012    import org.picocontainer.ComponentMonitor;
    013    import org.picocontainer.PicoVisitor;
    014    import org.picocontainer.ComponentAdapter;
    015    import org.picocontainer.ComponentMonitorStrategy;
    016    import org.picocontainer.PicoContainer;
    017    import org.picocontainer.PicoCompositionException;
    018    import org.picocontainer.injectors.ProviderAdapter;
    019    import org.picocontainer.injectors.Provider;
    020    import org.picocontainer.monitors.AbstractComponentMonitor;
    021    import org.picocontainer.monitors.NullComponentMonitor;
    022
    023    import java.io.Serializable;
    024
    025    /**
    026     * Base class for a ComponentAdapter with general functionality.
    027     * This implementation provides basic checks for a healthy implementation of a ComponentAdapter.
    028     * It does not allow to use <code>null</code> for the component key or the implementation,
    029     * ensures that the implementation is a concrete class and that the key is assignable from the
    030     * implementation if the key represents a type.
    031     *
    032     * @author Paul Hammant
    033     * @author Aslak Helles&oslash;y
    034     * @author Jon Tirs&eacute;n
    035     */
    036    public abstract class AbstractAdapter<T> implements ComponentAdapter<T>, ComponentMonitorStrategy, Serializable {
    037        private Object componentKey;
    038        private Class<T> componentImplementation;
    039        private ComponentMonitor componentMonitor;
    040
    041
    042        /**
    043         * Constructs a new ComponentAdapter for the given key and implementation.
    044         * @param componentKey the search key for this implementation
    045         * @param componentImplementation the concrete implementation
    046         */
    047        public AbstractAdapter(Object componentKey, Class componentImplementation) {
    048            this(componentKey, componentImplementation, new AbstractComponentMonitor());
    049            this.componentMonitor = new NullComponentMonitor();
    050        }
    051
    052        /**
    053         * Constructs a new ComponentAdapter for the given key and implementation.
    054         * @param componentKey the search key for this implementation
    055         * @param componentImplementation the concrete implementation
    056         * @param monitor the component monitor used by this ComponentAdapter
    057         */
    058        public AbstractAdapter(Object componentKey, Class componentImplementation, ComponentMonitor monitor) {
    059            if (monitor == null) {
    060                throw new NullPointerException("ComponentMonitor==null");
    061            }
    062            this.componentMonitor = monitor;
    063            if (componentImplementation == null) {
    064                throw new NullPointerException("componentImplementation");
    065            }
    066            this.componentKey = componentKey;
    067            this.componentImplementation = componentImplementation;
    068            checkTypeCompatibility();
    069        }
    070
    071        /**
    072         * {@inheritDoc}
    073         * @see org.picocontainer.ComponentAdapter#getComponentKey()
    074         */
    075        public Object getComponentKey() {
    076            if (componentKey == null) {
    077                throw new NullPointerException("componentKey");
    078            }
    079            return componentKey;
    080        }
    081
    082        /**
    083         * {@inheritDoc}
    084         * @see org.picocontainer.ComponentAdapter#getComponentImplementation()
    085         */
    086        public Class<T> getComponentImplementation() {
    087            return componentImplementation;
    088        }
    089
    090        protected void checkTypeCompatibility() {
    091            if (componentKey instanceof Class) {
    092                Class<?> componentType = (Class) componentKey;
    093                if (Provider.class.isAssignableFrom(componentImplementation)) {
    094                    if (!componentType.isAssignableFrom(ProviderAdapter.getProvideMethod(componentImplementation).getReturnType())) {
    095                        throw newCCE(componentType);
    096                    }
    097                } else {
    098                    if (!componentType.isAssignableFrom(componentImplementation)) {
    099                        throw newCCE(componentType);
    100                    }
    101                }
    102            }
    103        }
    104
    105        private ClassCastException newCCE(Class<?> componentType) {
    106            return new ClassCastException(componentImplementation.getName() + " is not a " + componentType.getName());
    107        }
    108
    109        public T getComponentInstance(PicoContainer container) throws PicoCompositionException {
    110            return getComponentInstance(container, null);
    111        }
    112
    113        /**
    114         * @return Returns the ComponentAdapter's class name and the component's key.
    115         * @see java.lang.Object#toString()
    116         */
    117        public String toString() {
    118            return getDescriptor() + getComponentKey();
    119        }
    120
    121        public void accept(PicoVisitor visitor) {
    122            visitor.visitComponentAdapter(this);
    123        }
    124
    125        public void changeMonitor(ComponentMonitor monitor) {
    126            this.componentMonitor = monitor;
    127        }
    128
    129        /**
    130         * Returns the monitor currently used
    131         * @return The ComponentMonitor currently used
    132         */
    133        public ComponentMonitor currentMonitor(){
    134            return componentMonitor;
    135        }
    136
    137        public final ComponentAdapter<T> getDelegate() {
    138            return null;
    139        }
    140
    141        public final <U extends ComponentAdapter> U findAdapterOfType(Class<U> adapterType) {
    142            if (adapterType.isAssignableFrom(this.getClass())) {
    143                return (U) this;
    144            } else if (getDelegate() != null) {
    145                return getDelegate().findAdapterOfType(adapterType);
    146            }
    147            return null;
    148        }
    149
    150
    151    }