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é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     */
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    }