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