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 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 }