001 package org.picocontainer.defaults;
002
003 import junit.framework.TestCase;
004 import org.picocontainer.MutablePicoContainer;
005 import org.picocontainer.PicoContainer;
006 import org.picocontainer.PicoInitializationException;
007 import org.picocontainer.PicoIntrospectionException;
008
009 import java.util.HashMap;
010 import java.util.Map;
011
012 /**
013 * This class can be used to test out various things asked on the mailing list.
014 * Or to answer questions.
015 *
016 * @author Aslak Hellesøy
017 * @version $Revision: 1595 $
018 */
019 public class UserQuestionTestCase extends TestCase {
020
021 // From Scott Farquahsr
022 public static class CheeseComponentAdapter extends AbstractComponentAdapter {
023 private Map bla;
024
025 public CheeseComponentAdapter(Object componentKey, Class componentImplementation, Map cheeseMap) throws AssignabilityRegistrationException, NotConcreteRegistrationException {
026 super(componentKey, componentImplementation);
027 this.bla = cheeseMap;
028 }
029
030 public Object getComponentInstance(PicoContainer pico) throws PicoInitializationException, PicoIntrospectionException {
031 return bla.get("cheese");
032 }
033
034 public void verify(PicoContainer pico) throws UnsatisfiableDependenciesException {
035 }
036 }
037
038 public static interface Cheese {
039 String getName();
040 }
041
042 public static class Gouda implements Cheese {
043 public String getName() {
044 return "Gouda";
045 }
046 }
047
048 public static class Roquefort implements Cheese {
049 public String getName() {
050 return "Roquefort";
051 }
052 }
053
054 public static class Omelette {
055 private final Cheese cheese;
056
057 public Omelette(Cheese cheese) {
058 this.cheese = cheese;
059 }
060
061 public Cheese getCheese() {
062 return cheese;
063 }
064 }
065
066 public void testOmeletteCanHaveDifferentCheeseWithAFunnyComponentAdapter() {
067 Map cheeseMap = new HashMap();
068
069 MutablePicoContainer pico = new DefaultPicoContainer(new ConstructorInjectionComponentAdapterFactory());
070 pico.registerComponentImplementation(Omelette.class);
071 pico.registerComponent(new CheeseComponentAdapter("scott", Gouda.class, cheeseMap));
072
073 Cheese gouda = new Gouda();
074 cheeseMap.put("cheese", gouda);
075 Omelette goudaOmelette = (Omelette) pico.getComponentInstance(Omelette.class);
076 assertSame(gouda, goudaOmelette.getCheese());
077
078 Cheese roquefort = new Roquefort();
079 cheeseMap.put("cheese", roquefort);
080 Omelette roquefortOmelette = (Omelette) pico.getComponentInstance(Omelette.class);
081 assertSame(roquefort, roquefortOmelette.getCheese());
082 }
083
084 public static interface InterfaceX {
085 String getIt();
086 }
087
088 public static class Enabled implements InterfaceX {
089 public String getIt() {
090 return "Enabled";
091 }
092 }
093
094 public static class Disabled implements InterfaceX {
095 public String getIt() {
096 return "Disabled";
097 }
098 }
099
100 public static class Something implements InterfaceX {
101 private final Disabled disabled;
102 private final Enabled enabled;
103 private final Map map;
104
105 public Something(Disabled disabled, Enabled enabled, Map map) {
106 this.disabled = disabled;
107 this.enabled = enabled;
108 this.map = map;
109 }
110
111 public String getIt() {
112 if (map.get("enabled") == null) {
113 return disabled.getIt();
114 } else {
115 return enabled.getIt();
116 }
117 }
118 }
119
120 public static class NeedsInterfaceX {
121 private final InterfaceX interfaceX;
122
123 public NeedsInterfaceX(InterfaceX interfaceX) {
124 this.interfaceX = interfaceX;
125 }
126
127 public String getIt() {
128 return interfaceX.getIt();
129 }
130 }
131
132 public void testMoreWeirdness() {
133 MutablePicoContainer pico = new DefaultPicoContainer();
134 Map map = new HashMap();
135 pico.registerComponentInstance(map);
136 // See class level javadoc in DefaultPicoContainer - about precedence.
137 pico.registerComponentImplementation(InterfaceX.class, Something.class);
138 pico.registerComponentImplementation(Disabled.class);
139 pico.registerComponentImplementation(Enabled.class);
140 pico.registerComponentImplementation(NeedsInterfaceX.class);
141
142 NeedsInterfaceX needsInterfaceX = (NeedsInterfaceX) pico.getComponentInstance(NeedsInterfaceX.class);
143 assertEquals("Disabled", needsInterfaceX.getIt());
144 map.put("enabled", "blah");
145 assertEquals("Enabled", needsInterfaceX.getIt());
146 }
147
148 // From John Tal 23/03/2004
149 public static interface ABC {
150 }
151
152 public static interface DEF {
153 }
154
155 public static class ABCImpl implements ABC {
156 public ABCImpl(DEF def) {
157 }
158 }
159
160 public static class DEFImpl implements DEF {
161 public DEFImpl() {
162 }
163 }
164
165 public void testJohnTalOne() {
166 MutablePicoContainer picoContainer = new DefaultPicoContainer();
167
168 picoContainer.registerComponentImplementation("ABC", ABCImpl.class);
169 picoContainer.registerComponentImplementation("DEF", DEFImpl.class);
170
171 assertEquals(ABCImpl.class, picoContainer.getComponentInstance("ABC").getClass());
172 }
173
174 public static interface Foo {
175 }
176
177 public static interface Bar {
178 }
179
180 public static class FooBar implements Foo, Bar {
181 }
182
183 public static class NeedsFoo {
184 private final Foo foo;
185
186 public NeedsFoo(Foo foo) {
187 this.foo = foo;
188 }
189
190 public Foo getFoo() {
191 return foo;
192 }
193 }
194
195 public static class NeedsBar {
196 private final Bar bar;
197
198 public NeedsBar(Bar bar) {
199 this.bar = bar;
200 }
201
202 public Bar getBar() {
203 return bar;
204 }
205 }
206
207 public void testShouldBeAbleShareSameReferenceForDifferentTypes() {
208 MutablePicoContainer pico = new DefaultPicoContainer();
209 pico.registerComponentImplementation(FooBar.class);
210 pico.registerComponentImplementation(NeedsFoo.class);
211 pico.registerComponentImplementation(NeedsBar.class);
212 NeedsFoo needsFoo = (NeedsFoo) pico.getComponentInstance(NeedsFoo.class);
213 NeedsBar needsBar = (NeedsBar) pico.getComponentInstance(NeedsBar.class);
214 assertSame(needsFoo.getFoo(), needsBar.getBar());
215 }
216
217 public void testSeveralDifferentInstancesCanBeCreatedWithOnePreconfiguredContainer() {
218 // create a container that doesn't cache instances
219 MutablePicoContainer container = new DefaultPicoContainer(new ConstructorInjectionComponentAdapterFactory());
220 container.registerComponentImplementation(NeedsBar.class);
221
222 Bar barOne = new FooBar();
223 container.registerComponentInstance(Bar.class, barOne);
224 NeedsBar needsBarOne = (NeedsBar) container.getComponentInstance(NeedsBar.class);
225 assertSame(barOne, needsBarOne.getBar());
226
227 // reuse the same container - just flip out the existing foo.
228 Bar barTwo = new FooBar();
229 container.unregisterComponent(Bar.class);
230 container.registerComponentInstance(Bar.class, barTwo);
231 NeedsBar needsBarTwo = (NeedsBar) container.getComponentInstance(NeedsBar.class);
232 assertSame(barTwo, needsBarTwo.getBar());
233
234 assertNotSame(needsBarOne, needsBarTwo);
235 }
236 }