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
011package org.picocontainer;
012
013import org.picocontainer.parameters.ComponentParameter;
014import org.picocontainer.parameters.DefaultConstructorParameter;
015
016import java.lang.annotation.Annotation;
017import 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én
024 * @author Aslak Hellesø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 */
033public 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       the adapter to be injected into (null for N/A)
058     * @param expectedType          the required type
059     * @param expectedNameBinding Expected parameter name
060     * @param useNames              should use parameter names for disambiguation
061     * @param binding @return <code>true</code> if the component parameter can be resolved.
062     * @since 2.8.1
063     *
064     */
065    Resolver resolve(PicoContainer container, ComponentAdapter<?> forAdapter,
066                     ComponentAdapter<?> injecteeAdapter, Type expectedType, NameBinding expectedNameBinding,
067                     boolean useNames, Annotation binding);
068
069    /**
070     * Verify that the Parameter can satisfy the expected type using the container
071     *
072     * @param container             the container from which dependencies are resolved.
073     * @param adapter               the {@link ComponentAdapter} that is asking for the verification
074     * @param expectedType          the required type
075     * @param expectedNameBinding Expected parameter name
076     *
077     * @param useNames
078     * @param binding
079     * @throws PicoCompositionException if parameter and its dependencies cannot be resolved
080     */
081    void verify(PicoContainer container, ComponentAdapter<?> adapter,
082                Type expectedType, NameBinding expectedNameBinding,
083                boolean useNames, Annotation binding);
084
085    /**
086     * Accepts a visitor for this Parameter. The method is normally called by visiting a {@link ComponentAdapter}, that
087     * cascades the {@linkplain PicoVisitor visitor} also down to all its {@linkplain Parameter Parameters}.
088     *
089     * @param visitor the visitor.
090     *
091     */
092    void accept(PicoVisitor visitor);
093
094
095    @Deprecated
096    Object resolveInstance(PicoContainer container, ComponentAdapter<?> forAdapter,
097                           Type expectedType, NameBinding expectedNameBinding,
098                           boolean useNames, Annotation binding);
099
100    @Deprecated
101    boolean isResolvable(PicoContainer container, ComponentAdapter<?> forAdapter,
102                         Type expectedType, NameBinding expectedNameBinding,
103                         boolean useNames, Annotation binding);
104
105    /**
106     * Resolver is used transitarily during resolving of Parameters.
107     * isResolvable() and resolveInstance() in series do not cause resolveAdapter() twice
108     */
109    public static interface Resolver {
110
111        /**
112         * @return can the parameter be resolved
113         */
114        public boolean isResolved();
115
116        /**
117         * @return the instance to be used to inject as a parameter
118         */
119        public Object resolveInstance();
120
121        /**
122         * @return the ComponentAdapter for the parameter in question
123         */
124        public ComponentAdapter<?> getComponentAdapter();
125
126    }
127
128    /**
129     * The Parameter cannot (ever) be resolved
130     */
131    public static class NotResolved implements Resolver {
132        public boolean isResolved() {
133            return false;
134        }
135
136        public Object resolveInstance() {
137            return null;
138        }
139
140        public ComponentAdapter<?> getComponentAdapter() {
141            return null;
142        }
143    }
144
145    /**
146     * Delegate to another reolver
147     */
148    public abstract static class DelegateResolver implements Resolver {
149        private final Resolver delegate;
150
151        public DelegateResolver(Resolver delegate) {
152            this.delegate = delegate;
153        }
154
155        public boolean isResolved() {
156            return delegate.isResolved();
157        }
158
159        public Object resolveInstance() {
160            return delegate.resolveInstance();
161        }
162
163        public ComponentAdapter<?> getComponentAdapter() {
164            return delegate.getComponentAdapter();
165        }
166    }
167
168    /**
169     * A fixed value wrapped as a Resolver
170     */
171    public static class ValueResolver implements Resolver {
172
173        private final boolean resolvable;
174        private final Object value;
175        private final ComponentAdapter<?> adapter;
176
177        public ValueResolver(boolean resolvable, Object value, ComponentAdapter<?> adapter) {
178            this.resolvable = resolvable;
179            this.value = value;
180            this.adapter = adapter;
181        }
182
183        public boolean isResolved() {
184            return resolvable;
185        }
186
187        public Object resolveInstance() {
188            return value;
189        }
190
191        public ComponentAdapter<?> getComponentAdapter() {
192            return adapter;
193        }
194    }
195
196}