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