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    }