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