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