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øy
024 * @author Jon Tirsé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 }