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