    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     * Idea by Rachel Davies, Original code by Jon Tirsen                        *
    009     *****************************************************************************/
    010
    011    package org.picocontainer;
    012
    013    import org.picocontainer.parameters.ComponentParameter;
    014    import org.picocontainer.parameters.DefaultConstructorParameter;
    015
    016    import java.lang.annotation.Annotation;
    017    import java.lang.reflect.Type;
    018
    019    /**
    020     * This class provides control over the arguments that will be passed to a constructor. It can be used for finer control over
    021     * what arguments are passed to a particular constructor.
    022     *
    023     * @author Jon Tirs&eacute;n
    024     * @author Aslak Helles&oslash;y
    025     * @author Thomas Heller
    026     * @see MutablePicoContainer#addComponent(Object,Object,Parameter[]) a method on the
    027     *      {@link MutablePicoContainer} interface which allows passing in of an array of {@linkplain Parameter Parameters}.
    028     * @see org.picocontainer.parameters.ComponentParameter an implementation of this interface that allows you to specify the key
    029     *      used for resolving the parameter.
    030     * @see org.picocontainer.parameters.ConstantParameter an implementation of this interface that allows you to specify a constant
    031     *      that will be used for resolving the parameter.
    032     */
    033    public interface Parameter {
    034
    035            /**
    036             * Zero parameter is used when you wish a component to be instantiated with its default constructor.  Ex:
    037             * <div class="source">
    038             *      <pre>
    039             *              MutablePicoContainer mpc = new PicoBuilder().build();
    040             *              mpc.addComponent(Map.class, HashMap.class, Parameter.ZERO);
    041             *              mpc.addComponent(List.class, ArrayList.class, Parameter.ZERO);
    042             *      </pre>
    043             * </div>
    044             * <p>By specifying the default constructor in this example code, you allow PicoContainer to recognize
    045             * that HashMap(Collection) should <em>not</em> be used and avoid a CircularDependencyException.</p>
    046             */
    047        Parameter[] ZERO =  new Parameter[] {DefaultConstructorParameter.INSTANCE};
    048
    049        Parameter[] DEFAULT = new Parameter[]{ ComponentParameter.DEFAULT };
    050
    051
    052        /**
    053         * Check if the Parameter can satisfy the expected type using the container.
    054         *
    055         * @param container             the container from which dependencies are resolved.
    056         * @param forAdapter            the {@link org.picocontainer.ComponentAdapter} that is asking for the instance
    057         * @param injecteeAdapter
    058         * @param expectedType          the required type
    059         * @param expectedNameBinding Expected parameter name
    060         * @param useNames
    061         * @param binding @return <code>true</code> if the component parameter can be resolved.
    062         *
    063         */
    064        Resolver resolve(PicoContainer container, ComponentAdapter<?> forAdapter,
    065                         ComponentAdapter<?> injecteeAdapter, Type expectedType, NameBinding expectedNameBinding,
    066                         boolean useNames, Annotation binding);
    067
    068        /**
    069         * Verify that the Parameter can satisfy the expected type using the container
    070         *
    071         * @param container             the container from which dependencies are resolved.
    072         * @param adapter               the {@link ComponentAdapter} that is asking for the verification
    073         * @param expectedType          the required type
    074         * @param expectedNameBinding Expected parameter name
    075         *
    076         * @param useNames
    077         * @param binding
    078         * @throws PicoCompositionException if parameter and its dependencies cannot be resolved
    079         */
    080        void verify(PicoContainer container, ComponentAdapter<?> adapter,
    081                    Type expectedType, NameBinding expectedNameBinding,
    082                    boolean useNames, Annotation binding);
    083
    084        /**
    085         * Accepts a visitor for this Parameter. The method is normally called by visiting a {@link ComponentAdapter}, that
    086         * cascades the {@linkplain PicoVisitor visitor} also down to all its {@linkplain Parameter Parameters}.
    087         *
    088         * @param visitor the visitor.
    089         *
    090         */
    091        void accept(PicoVisitor visitor);
    092
    093        /**
    094         * Resolver is used transitarily during resolving of Parameters.
    095         * isResolvable() and resolveInstance() in series do not cause resolveAdapter() twice
    096         */
    097        public static interface Resolver {
    098
    099            /**
    100             * @return can the parameter be resolved
    101             */
    102            public boolean isResolved();
    103
    104            /**
    105             * @return the instance to be used to inject as a parameter
    106             */
    107            public Object resolveInstance();
    108
    109            /**
    110             * @return the ComponentAdapter for the parameter in question
    111             */
    112            public ComponentAdapter<?> getComponentAdapter();
    113
    114        }
    115
    116        /**
    117         * The Parameter cannot (ever) be resolved
    118         */
    119        public static class NotResolved implements Resolver {
    120            public boolean isResolved() {
    121                return false;
    122            }
    123
    124            public Object resolveInstance() {
    125                return null;
    126            }
    127
    128            public ComponentAdapter<?> getComponentAdapter() {
    129                return null;
    130            }
    131        }
    132
    133        /**
    134         * Delegate to another reolver
    135         */
    136        public abstract static class DelegateResolver implements Resolver {
    137            private final Resolver delegate;
    138
    139            public DelegateResolver(Resolver delegate) {
    140                this.delegate = delegate;
    141            }
    142
    143            public boolean isResolved() {
    144                return delegate.isResolved();
    145            }
    146
    147            public Object resolveInstance() {
    148                return delegate.resolveInstance();
    149            }
    150
    151            public ComponentAdapter<?> getComponentAdapter() {
    152                return delegate.getComponentAdapter();
    153            }
    154        }
    155
    156        /**
    157         * A fixed value wrapped as a Resolver
    158         */
    159        public static class ValueResolver implements Resolver {
    160
    161            private final boolean resolvable;
    162            private final Object value;
    163            private final ComponentAdapter<?> adapter;
    164
    165            public ValueResolver(boolean resolvable, Object value, ComponentAdapter<?> adapter) {
    166                this.resolvable = resolvable;
    167                this.value = value;
    168                this.adapter = adapter;
    169            }
    170
    171            public boolean isResolved() {
    172                return resolvable;
    173            }
    174
    175            public Object resolveInstance() {
    176                return value;
    177            }
    178
    179            public ComponentAdapter<?> getComponentAdapter() {
    180                return adapter;
    181            }
    182        }
    183
    184    }