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