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 }