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