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