001 package org.picocontainer.defaults; 002 003 import org.picocontainer.ComponentAdapter; 004 import org.picocontainer.MutablePicoContainer; 005 import org.picocontainer.Parameter; 006 import org.picocontainer.PicoContainer; 007 import org.picocontainer.PicoIntrospectionException; 008 import org.picocontainer.testmodel.SimpleTouchable; 009 import org.picocontainer.testmodel.Touchable; 010 011 import org.jmock.Mock; 012 import org.jmock.MockObjectTestCase; 013 014 import java.util.Arrays; 015 import java.util.Collection; 016 import java.util.Collections; 017 import java.util.HashSet; 018 import java.util.List; 019 import java.util.Map; 020 import java.util.Set; 021 import java.util.SortedMap; 022 import java.util.SortedSet; 023 024 025 /** 026 * @author Aslak Hellesøy 027 * @author Jörg Schaible 028 * @version $Revision: 2789 $ 029 */ 030 public class CollectionComponentParameterTestCase 031 extends MockObjectTestCase { 032 033 public void testShouldInstantiateArrayOfStrings() { 034 CollectionComponentParameter ccp = new CollectionComponentParameter(); 035 036 Mock componentAdapterMock = mock(ComponentAdapter.class); 037 componentAdapterMock.expects(atLeastOnce()).method("getComponentKey").will(returnValue("x")); 038 Mock containerMock = mock(PicoContainer.class); 039 containerMock.expects(once()).method("getComponentAdapters").withNoArguments().will(returnValue(new HashSet())); 040 containerMock.expects(once()).method("getComponentAdaptersOfType").with(eq(String.class)).will( 041 returnValue(Arrays.asList(new ComponentAdapter[]{ 042 new InstanceComponentAdapter("y", "Hello"), new InstanceComponentAdapter("z", "World")}))); 043 containerMock.expects(once()).method("getComponentInstance").with(eq("z")).will(returnValue("World")); 044 containerMock.expects(once()).method("getComponentInstance").with(eq("y")).will(returnValue("Hello")); 045 containerMock.expects(once()).method("getParent").withNoArguments().will(returnValue(null)); 046 047 List expected = Arrays.asList(new String[]{"Hello", "World"}); 048 Collections.sort(expected); 049 List actual = Arrays.asList((Object[]) ccp.resolveInstance( 050 (PicoContainer) containerMock.proxy(), (ComponentAdapter) componentAdapterMock.proxy(), String[].class)); 051 Collections.sort(actual); 052 assertEquals(expected, actual); 053 } 054 055 static public interface Fish { 056 } 057 058 static public class Cod 059 implements Fish { 060 public String toString() { 061 return "Cod"; 062 } 063 } 064 065 static public class Shark 066 implements Fish { 067 public String toString() { 068 return "Shark"; 069 } 070 } 071 072 static public class Bowl { 073 private final Cod[] cods; 074 private final Fish[] fishes; 075 076 public Bowl(Cod cods[], Fish fishes[]) { 077 this.cods = cods; 078 this.fishes = fishes; 079 } 080 } 081 082 private MutablePicoContainer getDefaultPicoContainer() { 083 MutablePicoContainer mpc = new DefaultPicoContainer(); 084 mpc.registerComponentImplementation(Bowl.class); 085 mpc.registerComponentImplementation(Cod.class); 086 mpc.registerComponentImplementation(Shark.class); 087 return mpc; 088 } 089 090 public void testNativeArrays() { 091 MutablePicoContainer mpc = getDefaultPicoContainer(); 092 Cod cod = (Cod) mpc.getComponentInstanceOfType(Cod.class); 093 Bowl bowl = (Bowl) mpc.getComponentInstance(Bowl.class); 094 assertEquals(1, bowl.cods.length); 095 assertEquals(2, bowl.fishes.length); 096 assertSame(cod, bowl.cods[0]); 097 assertNotSame(bowl.fishes[0], bowl.fishes[1]); 098 } 099 100 public void testCollectionsAreGeneratedOnTheFly() { 101 MutablePicoContainer mpc = new DefaultPicoContainer(); 102 mpc.registerComponent(new ConstructorInjectionComponentAdapter(Bowl.class, Bowl.class)); 103 mpc.registerComponentImplementation(Cod.class); 104 Bowl bowl = (Bowl) mpc.getComponentInstance(Bowl.class); 105 assertEquals(1, bowl.cods.length); 106 mpc.registerComponentInstance("Nemo", new Cod()); 107 bowl = (Bowl) mpc.getComponentInstance(Bowl.class); 108 assertEquals(2, bowl.cods.length); 109 assertNotSame(bowl.cods[0], bowl.cods[1]); 110 } 111 112 static public class CollectedBowl { 113 private final Cod[] cods; 114 private final Fish[] fishes; 115 116 public CollectedBowl(Collection cods, Collection fishes) { 117 this.cods = (Cod[]) cods.toArray(new Cod[cods.size()]); 118 this.fishes = (Fish[]) fishes.toArray(new Fish[fishes.size()]); 119 } 120 } 121 122 public void testCollections() { 123 MutablePicoContainer mpc = new DefaultPicoContainer(); 124 mpc.registerComponentImplementation(CollectedBowl.class, CollectedBowl.class, new Parameter[]{ 125 new ComponentParameter(Cod.class, false), new ComponentParameter(Fish.class, false)}); 126 mpc.registerComponentImplementation(Cod.class); 127 mpc.registerComponentImplementation(Shark.class); 128 Cod cod = (Cod) mpc.getComponentInstanceOfType(Cod.class); 129 CollectedBowl bowl = (CollectedBowl) mpc.getComponentInstance(CollectedBowl.class); 130 assertEquals(1, bowl.cods.length); 131 assertEquals(2, bowl.fishes.length); 132 assertSame(cod, bowl.cods[0]); 133 assertNotSame(bowl.fishes[0], bowl.fishes[1]); 134 } 135 136 static public class MappedBowl { 137 private final Fish[] fishes; 138 139 public MappedBowl(Map map) { 140 Collection collection = map.values(); 141 this.fishes = (Fish[]) collection.toArray(new Fish[collection.size()]); 142 } 143 } 144 145 public void testMaps() { 146 MutablePicoContainer mpc = new DefaultPicoContainer(); 147 mpc.registerComponentImplementation(MappedBowl.class, MappedBowl.class, new Parameter[]{new ComponentParameter( 148 Fish.class, false)}); 149 mpc.registerComponentImplementation(Cod.class); 150 mpc.registerComponentImplementation(Shark.class); 151 MappedBowl bowl = (MappedBowl) mpc.getComponentInstance(MappedBowl.class); 152 assertEquals(2, bowl.fishes.length); 153 assertNotSame(bowl.fishes[0], bowl.fishes[1]); 154 } 155 156 public static class UngenericCollectionBowl { 157 public UngenericCollectionBowl(Collection fish) { 158 } 159 } 160 161 public void testShouldNotInstantiateCollectionForUngenericCollectionParameters() { 162 MutablePicoContainer pico = getDefaultPicoContainer(); 163 pico.registerComponentImplementation(UngenericCollectionBowl.class); 164 try { 165 pico.getComponentInstance(UngenericCollectionBowl.class); 166 fail(); 167 } catch (UnsatisfiableDependenciesException e) { 168 // expected 169 } 170 } 171 172 public static class AnotherGenericCollectionBowl { 173 private final String[] strings; 174 175 public AnotherGenericCollectionBowl(String[] strings) { 176 this.strings = strings; 177 } 178 179 public String[] getStrings() { 180 return strings; 181 } 182 } 183 184 public void testShouldFailWhenThereAreNoComponentsToPutInTheArray() { 185 MutablePicoContainer pico = getDefaultPicoContainer(); 186 pico.registerComponentImplementation(AnotherGenericCollectionBowl.class); 187 try { 188 pico.getComponentInstance(AnotherGenericCollectionBowl.class); 189 fail(); 190 } catch (UnsatisfiableDependenciesException e) { 191 // expected 192 } 193 } 194 195 public void testAllowsEmptyArraysIfEspeciallySet() { 196 MutablePicoContainer pico = getDefaultPicoContainer(); 197 pico.registerComponentImplementation( 198 AnotherGenericCollectionBowl.class, AnotherGenericCollectionBowl.class, 199 new Parameter[]{ComponentParameter.ARRAY_ALLOW_EMPTY}); 200 AnotherGenericCollectionBowl bowl = (AnotherGenericCollectionBowl) pico 201 .getComponentInstance(AnotherGenericCollectionBowl.class); 202 assertNotNull(bowl); 203 assertEquals(0, bowl.strings.length); 204 } 205 206 public static class TouchableObserver 207 implements Touchable { 208 private final Touchable[] touchables; 209 210 public TouchableObserver(Touchable[] touchables) { 211 this.touchables = touchables; 212 213 } 214 215 public void touch() { 216 for (int i = 0; i < touchables.length; i++) { 217 touchables[i].touch(); 218 } 219 } 220 } 221 222 public void testWillOmitSelfFromCollection() { 223 MutablePicoContainer pico = getDefaultPicoContainer(); 224 pico.registerComponentImplementation(SimpleTouchable.class); 225 pico.registerComponentImplementation(TouchableObserver.class); 226 Touchable observer = (Touchable) pico.getComponentInstanceOfType(TouchableObserver.class); 227 assertNotNull(observer); 228 observer.touch(); 229 SimpleTouchable touchable = (SimpleTouchable) pico.getComponentInstanceOfType(SimpleTouchable.class); 230 assertTrue(touchable.wasTouched); 231 } 232 233 public void testWillRemoveComponentsWithMatchingKeyFromParent() { 234 MutablePicoContainer parent = new DefaultPicoContainer(); 235 parent.registerComponentImplementation("Tom", Cod.class); 236 parent.registerComponentImplementation("Dick", Cod.class); 237 parent.registerComponentImplementation("Harry", Cod.class); 238 MutablePicoContainer child = new DefaultPicoContainer(parent); 239 child.registerComponentImplementation("Dick", Shark.class); 240 child.registerComponentImplementation(Bowl.class); 241 Bowl bowl = (Bowl) child.getComponentInstance(Bowl.class); 242 assertEquals(3, bowl.fishes.length); 243 assertEquals(2, bowl.cods.length); 244 } 245 246 public void testBowlWithoutTom() { 247 MutablePicoContainer mpc = new DefaultPicoContainer(); 248 mpc.registerComponentImplementation("Tom", Cod.class); 249 mpc.registerComponentImplementation("Dick", Cod.class); 250 mpc.registerComponentImplementation("Harry", Cod.class); 251 mpc.registerComponentImplementation(Shark.class); 252 mpc.registerComponentImplementation(CollectedBowl.class, CollectedBowl.class, new Parameter[]{ 253 new CollectionComponentParameter(Cod.class, false) { 254 protected boolean evaluate(ComponentAdapter adapter) { 255 return !"Tom".equals(adapter.getComponentKey()); 256 } 257 }, 258 new CollectionComponentParameter(Fish.class, false) 259 }); 260 CollectedBowl bowl = (CollectedBowl) mpc.getComponentInstance(CollectedBowl.class); 261 Cod tom = (Cod) mpc.getComponentInstance("Tom"); 262 assertEquals(4, bowl.fishes.length); 263 assertEquals(2, bowl.cods.length); 264 assertFalse(Arrays.asList(bowl.cods).contains(tom)); 265 } 266 267 public static class DependsOnAll { 268 public DependsOnAll(Set set, SortedSet sortedSet, Collection collection, List list, SortedMap sortedMap, Map map 269 // , ConcurrentMap concurrentMap, Queue queue, BlockingQueue blockingQueue 270 ) { 271 assertNotNull(set); 272 assertNotNull(sortedSet); 273 assertNotNull(collection); 274 assertNotNull(list); 275 assertNotNull(sortedMap); 276 assertNotNull(map); 277 // assertNotNull(concurrentMap); 278 // assertNotNull(queue); 279 // assertNotNull(blockingQueue); 280 } 281 } 282 283 public void testDifferentCollectiveTypesAreResolved() { 284 MutablePicoContainer pico = new DefaultPicoContainer(); 285 CollectionComponentParameter parameter = new CollectionComponentParameter(Fish.class, true); 286 pico.registerComponentImplementation(DependsOnAll.class, DependsOnAll.class, new Parameter[]{ 287 parameter, parameter, parameter, parameter, parameter, parameter, 288 // parameter, parameter, parameter, 289 }); 290 assertNotNull(pico.getComponentInstance(DependsOnAll.class)); 291 } 292 293 public void testVerify() { 294 MutablePicoContainer pico = new DefaultPicoContainer(); 295 CollectionComponentParameter parameterNonEmpty = CollectionComponentParameter.ARRAY; 296 pico.registerComponentImplementation(Shark.class); 297 parameterNonEmpty.verify(pico, null, Fish[].class); 298 try { 299 parameterNonEmpty.verify(pico, null, Cod[].class); 300 fail("(PicoIntrospectionException expected"); 301 } catch (PicoIntrospectionException e) { 302 assertTrue(e.getMessage().indexOf(Cod.class.getName())>0); 303 } 304 CollectionComponentParameter parameterEmpty = CollectionComponentParameter.ARRAY_ALLOW_EMPTY; 305 parameterEmpty.verify(pico, null, Fish[].class); 306 parameterEmpty.verify(pico, null, Cod[].class); 307 } 308 309 // PICO-243 : this test will fail if executed on jdk1.3 without commons-collections 310 public void testOrderOfElementsOfAnArrayDependencyIsPreserved() { 311 MutablePicoContainer pico = new DefaultPicoContainer(); 312 pico.registerComponentInstance("first", "first"); 313 pico.registerComponentInstance("second", "second"); 314 pico.registerComponentInstance("third", "third"); 315 pico.registerComponentInstance("fourth", "fourth"); 316 pico.registerComponentInstance("fifth", "fifth"); 317 pico.registerComponentImplementation(Truc.class); 318 319 final List strings = pico.getComponentInstancesOfType(String.class); 320 assertEquals("first", strings.get(0)); 321 assertEquals("second", strings.get(1)); 322 assertEquals("third", strings.get(2)); 323 assertEquals("fourth", strings.get(3)); 324 assertEquals("fifth", strings.get(4)); 325 326 pico.getComponentInstanceOfType(Truc.class); 327 } 328 329 public static final class Truc { 330 public Truc(String[] s) { 331 assertEquals("first", s[0]); 332 assertEquals("second", s[1]); 333 assertEquals("third", s[2]); 334 assertEquals("fourth", s[3]); 335 assertEquals("fifth", s[4]); 336 } 337 } 338 339 }