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 *****************************************************************************/
008package org.picocontainer;
009
010import java.lang.reflect.Type;
011
012/**
013 * A component adapter is responsible for providing a specific component
014 * instance of type <T>. An instance of an implementation of this interface is
015 * used inside a {@link PicoContainer} for every registered component or
016 * instance. Each <code>ComponentAdapter</code> instance has to have a key
017 * which is unique within that container. The key itself is either a class type
018 * (normally an interface) or an identifier.
019 * <p>In a overly simplistic sense, the ComponentAdapter can be thought of us a type of
020 * an object factory.  If you need to modify how your object is constructed, use and appropriate
021 * ComponentAdapter or roll your own since the API is purposely kept rather simple.  See
022 * <a href="http://www.picocontainer.org/adapters.html">http://www.picocontainer.org/adapters.html</a>
023 * for more information.</p>
024 *
025 * @author Jon Tirs&eacute;n
026 * @author Paul Hammant
027 * @author Aslak Helles&oslash;y
028 */
029public interface ComponentAdapter<T> {
030
031    public class NOTHING {
032        private NOTHING(){
033        }
034    };
035
036    /**
037     * Retrieve the key associated with the component.
038     *
039     * @return the component's key. Should either be a class type (normally an interface) or an identifier that is
040     *         unique (within the scope of the current PicoContainer).
041     */
042    Object getComponentKey();
043
044    /**
045     * Retrieve the class of the component.
046     *
047     * @return the component's implementation class. Should normally be a concrete class (ie, a class that can be
048     *         instantiated).
049     */
050    Class<? extends T> getComponentImplementation();
051
052    /**
053     * Retrieve the component instance. This method will usually create a new instance each time it is called, but that
054     * is not required. For example, {@link org.picocontainer.behaviors.Cached} will always return the
055     * same instance.
056     *
057     * @param container the {@link PicoContainer}, that is used to resolve any possible dependencies of the instance.
058     * @return the component instance.
059     * @throws PicoCompositionException  if the component has dependencies which could not be resolved, or
060     *                                     instantiation of the component lead to an ambigous situation within the
061     *                                     container.
062     * @deprecated since PicoContainer 2.2.  Use {@link getComponentInstance(PicoContainer,Type)} with {@link ComponentAdapter.NOTHING.class} as type
063     * if no type available.
064     */
065    T getComponentInstance(PicoContainer container) throws PicoCompositionException;
066
067    /**
068     * Retrieve the component instance. This method will usually create a new instance each time it is called, but that
069     * is not required. For example, {@link org.picocontainer.behaviors.Cached} will always return the
070     * same instance.
071     *
072     * @param container the {@link org.picocontainer.PicoContainer}, that is used to resolve any possible dependencies of the instance.
073     * @param into the class that is about to be injected into. Use ComponentAdapter.NOTHING.class if this is not important to you.
074     * @return the component instance.
075     * @throws PicoCompositionException  if the component has dependencies which could not be resolved, or
076     *                                     instantiation of the component lead to an ambiguous situation within the
077     *                                     container.
078     */
079    T getComponentInstance(PicoContainer container, Type into) throws PicoCompositionException;
080
081    /**
082     * Verify that all dependencies for this adapter can be satisfied. Normally, the adapter should verify this by
083     * checking that the associated PicoContainer contains all the needed dependencies.
084     *
085     * @param container the {@link PicoContainer}, that is used to resolve any possible dependencies of the instance.
086     * @throws PicoCompositionException if one or more dependencies cannot be resolved.
087     */
088    void verify(PicoContainer container) throws PicoCompositionException;
089
090    /**
091     * Accepts a visitor for this ComponentAdapter. The method is normally called by visiting a {@link PicoContainer}, that
092     * cascades the visitor also down to all its ComponentAdapter instances.
093     *
094     * @param visitor the visitor.
095     */
096    void accept(PicoVisitor visitor);
097
098    /**
099     * Component adapters may be nested in a chain, and this method is used to grab the next ComponentAdapter in the chain.
100     * @return the next component adapter in line or null if there is no delegate ComponentAdapter.
101     */
102    ComponentAdapter<T> getDelegate();
103
104    /**
105     * Locates a component adapter of type <em>componentAdapterType</em> in the ComponentAdapter chain.  Will return null
106     * if there is no adapter of the given type.
107     * @param <U> the type of ComponentAdapter being located.
108     * @param adapterType the class of the adapter type being located.  Never null.
109     * @return the appropriate component adapter of type <em>U</em>.  May return null if the component adapter type is not
110     * returned.
111     */
112    <U extends ComponentAdapter> U findAdapterOfType(Class<U> adapterType);
113
114    /**
115     * Get a string key descriptor of the component adapter for use in toString()
116     * @return the descriptor
117     */
118    String getDescriptor();
119
120}