001    package org.picocontainer.adapters;
002    
003    import static org.picocontainer.BindKey.bindKey;
004    
005    import java.lang.annotation.ElementType;
006    import java.lang.annotation.Retention;
007    import java.lang.annotation.RetentionPolicy;
008    import java.lang.annotation.Target;
009    
010    import org.junit.Assert;
011    import org.junit.Test;
012    import static org.junit.Assert.assertNotNull;
013    import static org.junit.Assert.assertEquals;
014    import org.picocontainer.DefaultPicoContainer;
015    import org.picocontainer.MutablePicoContainer;
016    import org.picocontainer.annotations.Bind;
017    import org.picocontainer.annotations.Inject;
018    import org.picocontainer.injectors.AbstractInjector;
019    import org.picocontainer.injectors.AnnotatedFieldInjection;
020    import org.picocontainer.injectors.ConstructorInjection;
021    import org.picocontainer.injectors.MethodInjection;
022    import org.picocontainer.injectors.SetterInjection;
023    
024    /** @author Paul Hammant */
025    public class TypedBindingAnnotationTestCase  {
026    
027            @Test public void testFieldInjectionWithBindings() {
028            MutablePicoContainer mpc = new DefaultPicoContainer(new AnnotatedFieldInjection());
029    
030            addFiveComponents(mpc);
031            FruitBasket fb = mpc.getComponent(FruitBasket.class);
032            assertFourMemberApplesAreRight(fb);
033            assertGettingOfAppleOneWorks(mpc);
034        }
035    
036        private void assertGettingOfAppleOneWorks(MutablePicoContainer mpc) {
037            try {
038                mpc.getComponent(Apple.class);
039                Assert.fail("should have barfed");
040            } catch (AbstractInjector.AmbiguousComponentResolutionException e) {
041                // expected
042            }
043            assertNotNull(mpc.getComponent(Apple.class, Bramley.class));
044        }
045    
046        @Test public void testBindingAnnotationsWithConstructorInjection() {
047            MutablePicoContainer mpc = new DefaultPicoContainer(new ConstructorInjection());
048    
049            addFiveComponents(mpc, FruitBasketViaConstructor.class);
050            FruitBasket fb = mpc.getComponent(FruitBasketViaConstructor.class);
051            assertFourMemberApplesAreRight(fb);
052            assertGettingOfAppleOneWorks(mpc);
053        }
054    
055        private void assertFourMemberApplesAreRight(FruitBasket fb) {
056            assertNotNull(fb);
057            assertEquals(fb.bramley.getX(), 1);
058            assertEquals(fb.cox.getX(), 2);
059            assertEquals(fb.granny.getX(), 3);
060            assertEquals(fb.braeburn.getX(), 4);
061        }
062    
063        @Test public void testBindingAnnotationsWithMethodInjection() {
064            MutablePicoContainer mpc = new DefaultPicoContainer(new MethodInjection("foo"));
065            addFiveComponents(mpc);
066            FruitBasket fb = mpc.getComponent(FruitBasket.class);
067            assertFourMemberApplesAreRight(fb);
068            assertGettingOfAppleOneWorks(mpc);
069    
070        }
071    
072        @Test public void testBindingAnnotationsWithSetterInjection() {
073            MutablePicoContainer mpc = new DefaultPicoContainer(new SetterInjection());
074            addFiveComponents(mpc);
075            FruitBasket fb = mpc.getComponent(FruitBasket.class);
076            assertFourMemberApplesAreRight(fb);
077            assertGettingOfAppleOneWorks(mpc);
078    
079        }
080    
081        private void addFiveComponents(MutablePicoContainer mpc) {
082            addFiveComponents(mpc, FruitBasket.class);
083        }
084    
085        private void addFiveComponents(MutablePicoContainer mpc, Class clazz) {
086            mpc.addComponent(clazz);
087            mpc.addComponent(bindKey(Apple.class, Bramley.class), AppleImpl1.class);
088            mpc.addComponent(bindKey(Apple.class, Cox.class), AppleImpl2.class);
089            mpc.addComponent(bindKey(Apple.class, Granny.class), AppleImpl3.class);
090            mpc.addComponent(bindKey(Apple.class, Braeburn.class), AppleImpl4.class);
091        }
092    
093        public interface Apple {
094            int getX();
095        }
096        public static class AppleImpl1 implements Apple {
097            public int getX() {
098                return 1;
099            }
100        }
101        public static class AppleImpl2 implements Apple {
102            public int getX() {
103                return 2;
104            }
105        }
106        public static class AppleImpl3 implements Apple {
107            public int getX() {
108                return 3;
109            }
110        }
111        public static class AppleImpl4 implements Apple {
112            public int getX() {
113                return 4;
114            }
115        }
116    
117        @Retention(RetentionPolicy.RUNTIME)
118        @Target({ElementType.FIELD, ElementType.PARAMETER})
119        @Bind
120        public static @interface Bramley {}
121    
122        @Retention(RetentionPolicy.RUNTIME)
123        @Target({ElementType.FIELD, ElementType.PARAMETER})
124        @Bind
125        public static @interface Cox {}
126    
127        @Retention(RetentionPolicy.RUNTIME)
128        @Target({ElementType.FIELD, ElementType.PARAMETER})
129        @Bind
130        public static @interface Granny {}
131    
132        @Retention(RetentionPolicy.RUNTIME)
133        @Target({ElementType.FIELD, ElementType.PARAMETER})
134        @Bind
135        public static @interface Braeburn {}
136    
137        public static class FruitBasketViaConstructor extends FruitBasket {
138            // used in testBindingAnnotationsWithConstructorInjection()
139            public FruitBasketViaConstructor(@Bramley Apple bramley, @Cox Apple cox, @Granny Apple granny, @Braeburn Apple braeburn) {
140                foo(bramley, cox, granny, braeburn);
141            }
142    
143        }
144        public static class FruitBasket {
145            @Inject
146            private @Bramley Apple bramley;
147            @Inject
148            private @Cox Apple cox;
149            @Inject
150            private @Granny Apple granny;
151            @Inject
152            private @Braeburn Apple braeburn;
153    
154            public FruitBasket() {
155            }
156    
157    
158            // used in testBindingAnnotationsWithMethodInjection()
159            public void foo(@Bramley Apple bramley, @Cox Apple cox, @Granny Apple granny, @Braeburn Apple braeburn) {
160                this.bramley = bramley;
161                this.cox = cox;
162                this.granny = granny;
163                this.braeburn = braeburn;
164            }
165    
166            public void setOne(@Bramley Apple bramley) {
167                this.bramley = bramley;
168            }
169    
170            public void setTwo(@Cox Apple cox) {
171                this.cox = cox;
172            }
173    
174            public void setThree(@Granny Apple granny) {
175                this.granny = granny;
176            }
177    
178            public void setFour(@Braeburn Apple braeburn) {
179                this.braeburn = braeburn;
180            }
181        }
182    
183    
184    }