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