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     *****************************************************************************/
009    package org.picocontainer.injectors;
010    
011    import org.junit.Test;
012    import static org.junit.Assert.assertNotNull;
013    import static org.junit.Assert.assertEquals;
014    import org.picocontainer.MutablePicoContainer;
015    import org.picocontainer.DefaultPicoContainer;
016    import org.picocontainer.PicoContainer;
017    import org.picocontainer.PicoCompositionException;
018    import org.picocontainer.annotations.Inject;
019    
020    import java.lang.reflect.Type;
021    import java.util.Map;
022    
023    public class FactoryInjectorTestCase {
024    
025        public static interface Swede {
026        }
027    
028        public static class Turnip2 extends Turnip {
029            public Turnip2(String foo, Swede swede) {
030                super(foo);
031                assertNotNull(swede);
032                super.swede = swede;
033            }
034        }
035    
036        public static class Turnip {
037            @Inject
038            Swede swede;
039            private final String foo;
040    
041            public Turnip(String foo) {
042                this.foo = foo;
043            }
044    
045            public Swede getSwede() {
046                return swede;
047            }
048    
049            public String getFoo() {
050                return foo;
051            }
052        }
053    
054        @Test
055        public void testThatComponentCanHaveAProvidedDependency() {
056            MutablePicoContainer container = new DefaultPicoContainer(new MultiInjection());
057            container.addComponent(String.class, "foo");
058            container.addComponent(Turnip.class);
059            container.addAdapter(new SwedeFactoryInjector());
060            Turnip t = container.getComponent(Turnip.class);
061            assertNotNull(t);
062            assertEquals("Swede for " + Turnip.class.getName(), t.getSwede().toString());
063            assertEquals("foo", t.getFoo());
064    
065        }
066    
067        @Test
068        public void testThatComponentCanHaveAProvidedDependencyWithInlinedFactoryInjector() {
069            MutablePicoContainer container = new DefaultPicoContainer(new MultiInjection());
070            container.addComponent(String.class, "foo");
071            container.addComponent(Turnip.class);
072            container.addAdapter(new FactoryInjector<Swede>() {
073                public Swede getComponentInstance(PicoContainer container, final Type into) {
074                    return new Swede() {
075                        public String toString() {
076                            return "Swede for " + ((Class) into).getName();
077                        }
078                    };
079                }
080            });
081            Turnip t = container.getComponent(Turnip.class);
082            assertNotNull(t);
083            assertEquals("Swede for " + Turnip.class.getName(), t.getSwede().toString());
084            assertEquals("foo", t.getFoo());
085    
086        }
087    
088        @Test
089        public void testThatComponentCanHaveAProvidedDependencyWithInlinedFactoryInjector2() {
090            MutablePicoContainer container = new DefaultPicoContainer(new MultiInjection());
091            container.addComponent(String.class, "foo");
092            container.addComponent(Turnip.class);
093            container.addAdapter(new FactoryInjector(Swede.class) {
094                public Swede getComponentInstance(PicoContainer container, final Type into) {
095                    return new Swede() {
096                        public String toString() {
097                            return "Swede for " + ((Class) into).getName();
098                        }
099                    };
100                }
101            });
102            Turnip t = container.getComponent(Turnip.class);
103            assertNotNull(t);
104            assertEquals("Swede for " + Turnip.class.getName(), t.getSwede().toString());
105            assertEquals("foo", t.getFoo());
106    
107        }
108    
109        @Test
110        public void testThatComponentCanHaveAProvidedDependencyWithInlinedFactoryInjector3() {
111            MutablePicoContainer container = new DefaultPicoContainer(new MultiInjection());
112            container.addComponent(String.class, "foo");
113            container.addComponent(Turnip.class);
114            container.addAdapter(new FactoryInjector(Swede.class) {
115                public Swede getComponentInstance(PicoContainer container, final Type into) {
116                    return new Swede() {
117                        public String toString() {
118                            return "Swede for " + ((Class) into).getName();
119                        }
120                    };
121                }
122            });
123            Turnip t = container.getComponent(Turnip.class);
124            assertNotNull(t);
125            assertEquals("Swede for " + Turnip.class.getName(), t.getSwede().toString());
126            assertEquals("foo", t.getFoo());
127    
128        }
129    
130    
131        @Test
132        public void testThatComponentCanHaveAProvidedDependencyViaConstructor() {
133            MutablePicoContainer container = new DefaultPicoContainer();
134            container.addComponent(String.class, "foo");
135            container.addComponent(Turnip2.class);
136            container.addAdapter(new SwedeFactoryInjector());
137            Turnip2 t = container.getComponent(Turnip2.class);
138            assertNotNull(t);
139            assertEquals("Swede for " + Turnip2.class.getName(), t.getSwede().toString());
140            assertEquals("foo", t.getFoo());
141    
142        }
143    
144        @Test
145        public void testThatComponentCanHaveAProvidedDependencyViaConstructorADifferentWay() {
146            MutablePicoContainer container = new DefaultPicoContainer();
147            container.addComponent(String.class, "foo");
148            container.addComponent(Turnip2.class);
149            container.addAdapter(new Swede2FactoryInjector()); // this injector defines Swede2 as key in its ctor
150            Turnip2 t = container.getComponent(Turnip2.class);
151            assertNotNull(t);
152            assertEquals("Swede for " + Turnip2.class.getName(), t.getSwede().toString());
153            assertEquals("foo", t.getFoo());
154    
155        }
156    
157        private static class SwedeFactoryInjector extends FactoryInjector<Swede> {
158            public Swede getComponentInstance(PicoContainer container, final Type into) throws PicoCompositionException {
159                // Mauro: you can do anything in here by way of startegy for injecting a specific logger :-)
160                return new Swede() {
161                    public String toString() {
162                        return "Swede for " + ((Class) into).getName();
163                    }
164                };
165            }
166        }
167    
168        private static class Swede2FactoryInjector extends FactoryInjector {
169            private Swede2FactoryInjector() {
170                super(Swede.class);
171            }
172    
173            public Swede getComponentInstance(PicoContainer container, final Type into) throws PicoCompositionException {
174                // Mauro: you can do anything in here by way of startegy for injecting a specific logger :-)
175                return new Swede() {
176                    public String toString() {
177                        return "Swede for " + ((Class) into).getName();
178                    }
179                };
180            }
181        }
182    
183        private abstract class Footle<T> {
184            private class ServiceConnectionInjector extends FactoryInjector<T> {
185                public T getComponentInstance(PicoContainer container, Type into) {
186                    System.out.println("**** injector called for " + into);
187                    return null;
188                }
189            }
190    
191            private void addAdapter(MutablePicoContainer mpc) {
192                mpc.addAdapter(new ServiceConnectionInjector());
193            }
194        }
195    
196    
197    
198        public static interface Tree {
199            String leafColor();
200        }
201        public static class OakTree implements Tree {
202            private String leafColor;
203    
204            public OakTree(String leafColor) {
205                this.leafColor = leafColor;
206            }
207    
208            public String leafColor() {
209                return leafColor;
210            }
211        }
212    
213        @Test public void ensureSophistcatedFactorInjectorCaseIsPossible() {
214    
215            DefaultPicoContainer pico = new DefaultPicoContainer();
216            pico.addConfig("leafColor", "green");
217            pico.addComponent(Tree.class, OakTree.class);
218    
219            Footle<Map> ft = new Footle<Map>(){};
220    
221            ft.addAdapter(pico);
222    
223            Tree tree = pico.getComponent(Tree.class);
224        }
225    
226    }