    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    }