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.defaults;
011    
012    import org.picocontainer.ComponentMonitor;
013    import org.picocontainer.PicoVisitor;
014    
015    /**
016     * Base class for a ComponentAdapter with general functionality.
017     * This implementation provides basic checks for a healthy implementation of a ComponentAdapter.
018     * It does not allow to use <code>null</code> for the component key or the implementation, 
019     * ensures that the implementation is a concrete class and that the key is assignable from the 
020     * implementation if the key represents a type.   
021     *  
022     * @author Paul Hammant
023     * @author Aslak Helles&oslash;y
024     * @author Jon Tirs&eacute;n
025     * @version $Revision: 2654 $
026     * @since 1.0
027     */
028    public abstract class AbstractComponentAdapter extends MonitoringComponentAdapter {
029        private Object componentKey;
030        private Class componentImplementation;
031    
032        /**
033         * Constructs a new ComponentAdapter for the given key and implementation. 
034         * @param componentKey the search key for this implementation
035         * @param componentImplementation the concrete implementation
036         * @throws AssignabilityRegistrationException if the key is a type and the implementation cannot be assigned to.
037         */
038        protected AbstractComponentAdapter(Object componentKey, Class componentImplementation) throws AssignabilityRegistrationException {
039            this(componentKey, componentImplementation, new DelegatingComponentMonitor());
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         * @param monitor the component monitor used by this ComponentAdapter
047         * @throws AssignabilityRegistrationException if the key is a type and the implementation cannot be assigned to.
048         */
049        protected AbstractComponentAdapter(Object componentKey, Class componentImplementation, ComponentMonitor monitor) throws AssignabilityRegistrationException {
050            super(monitor);
051            if (componentImplementation == null) {
052                throw new NullPointerException("componentImplementation");
053            }
054            this.componentKey = componentKey;
055            this.componentImplementation = componentImplementation;
056            checkTypeCompatibility();
057        }
058    
059        /**
060         * {@inheritDoc}
061         * @see org.picocontainer.ComponentAdapter#getComponentKey()
062         */
063        public Object getComponentKey() {
064            if (componentKey == null) {
065                throw new NullPointerException("componentKey");
066            }
067            return componentKey;
068        }
069    
070        /**
071         * {@inheritDoc}
072         * @see org.picocontainer.ComponentAdapter#getComponentImplementation()
073         */
074        public Class getComponentImplementation() {
075            return componentImplementation;
076        }
077    
078        protected void checkTypeCompatibility() throws AssignabilityRegistrationException {
079            if (componentKey instanceof Class) {
080                Class componentType = (Class) componentKey;
081                if (!componentType.isAssignableFrom(componentImplementation)) {
082                    throw new AssignabilityRegistrationException(componentType, componentImplementation);
083                }
084            }
085        }
086    
087        /**
088         * @return Returns the ComponentAdapter's class name and the component's key.
089         * @see java.lang.Object#toString()
090         */
091        public String toString() {
092            return getClass().getName() + "[" + getComponentKey() + "]";
093        }
094    
095        public void accept(PicoVisitor visitor) {
096            visitor.visitComponentAdapter(this);
097        }
098        
099    }