001package org.picocontainer.adapters;
002
003import static org.picocontainer.BindKey.bindKey;
004
005import java.lang.annotation.ElementType;
006import java.lang.annotation.Retention;
007import java.lang.annotation.RetentionPolicy;
008import java.lang.annotation.Target;
009
010import org.junit.Assert;
011import org.junit.Test;
012import static org.junit.Assert.assertNotNull;
013import static org.junit.Assert.assertEquals;
014import org.picocontainer.DefaultPicoContainer;
015import org.picocontainer.MutablePicoContainer;
016import org.picocontainer.annotations.Bind;
017import org.picocontainer.annotations.Inject;
018import org.picocontainer.injectors.AbstractInjector;
019import org.picocontainer.injectors.AnnotatedFieldInjection;
020import org.picocontainer.injectors.ConstructorInjection;
021import org.picocontainer.injectors.MethodInjection;
022import org.picocontainer.injectors.SetterInjection;
023
024/** @author Paul Hammant */
025public 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}