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    }