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 * Original code by * 009 *****************************************************************************/ 010 package org.picocontainer.defaults; 011 012 import static org.junit.Assert.assertEquals; 013 import static org.junit.Assert.assertNotSame; 014 import static org.junit.Assert.assertSame; 015 016 import java.util.HashMap; 017 import java.util.Map; 018 import java.lang.reflect.Type; 019 020 import org.junit.Test; 021 import org.picocontainer.Characteristics; 022 import org.picocontainer.DefaultPicoContainer; 023 import org.picocontainer.MutablePicoContainer; 024 import org.picocontainer.PicoCompositionException; 025 import org.picocontainer.PicoContainer; 026 import org.picocontainer.adapters.AbstractAdapter; 027 import org.picocontainer.injectors.ConstructorInjection; 028 029 /** 030 * This class can be used to test out various things asked on the mailing list. 031 * Or to answer questions. 032 * 033 * @author Aslak Hellesøy 034 */ 035 @SuppressWarnings("serial") 036 public final class UserQuestionTestCase { 037 038 // From Scott Farquahsr 039 public static final class CheeseAdapter extends AbstractAdapter { 040 private final Map bla; 041 042 public CheeseAdapter(Object componentKey, Class componentImplementation, Map cheeseMap) throws PicoCompositionException { 043 super(componentKey, componentImplementation); 044 this.bla = cheeseMap; 045 } 046 047 public Object getComponentInstance(PicoContainer pico, Type into) throws PicoCompositionException { 048 return bla.get("cheese"); 049 } 050 051 public void verify(PicoContainer pico) { 052 } 053 054 public String getDescriptor() { 055 return null; 056 } 057 } 058 059 public static interface Cheese { 060 String getName(); 061 } 062 063 public static class Gouda implements Cheese { 064 public String getName() { 065 return "Gouda"; 066 } 067 } 068 069 public static class Roquefort implements Cheese { 070 public String getName() { 071 return "Roquefort"; 072 } 073 } 074 075 public static class Omelette { 076 private final Cheese cheese; 077 078 public Omelette(Cheese cheese) { 079 this.cheese = cheese; 080 } 081 082 public Cheese getCheese() { 083 return cheese; 084 } 085 } 086 087 @Test public void testOmeletteCanHaveDifferentCheeseWithAFunnyComponentAdapter() { 088 Map<String,Cheese> cheeseMap = new HashMap<String,Cheese>(); 089 090 MutablePicoContainer pico = new DefaultPicoContainer(new ConstructorInjection()); 091 pico.addComponent(Omelette.class); 092 pico.addAdapter(new CheeseAdapter("scott", Gouda.class, cheeseMap)); 093 094 Cheese gouda = new Gouda(); 095 cheeseMap.put("cheese", gouda); 096 Omelette goudaOmelette = pico.getComponent(Omelette.class); 097 assertSame(gouda, goudaOmelette.getCheese()); 098 099 Cheese roquefort = new Roquefort(); 100 cheeseMap.put("cheese", roquefort); 101 Omelette roquefortOmelette = pico.getComponent(Omelette.class); 102 assertSame(roquefort, roquefortOmelette.getCheese()); 103 } 104 105 public static interface InterfaceX { 106 String getIt(); 107 } 108 109 public static class Enabled implements InterfaceX { 110 public String getIt() { 111 return "Enabled"; 112 } 113 } 114 115 public static class Disabled implements InterfaceX { 116 public String getIt() { 117 return "Disabled"; 118 } 119 } 120 121 public static class Something implements InterfaceX { 122 private final Disabled disabled; 123 private final Enabled enabled; 124 private final Map map; 125 126 public Something(Disabled disabled, Enabled enabled, Map map) { 127 this.disabled = disabled; 128 this.enabled = enabled; 129 this.map = map; 130 } 131 132 public String getIt() { 133 if (map.get("enabled") == null) { 134 return disabled.getIt(); 135 } else { 136 return enabled.getIt(); 137 } 138 } 139 } 140 141 public static class NeedsInterfaceX { 142 private final InterfaceX interfaceX; 143 144 public NeedsInterfaceX(InterfaceX interfaceX) { 145 this.interfaceX = interfaceX; 146 } 147 148 public String getIt() { 149 return interfaceX.getIt(); 150 } 151 } 152 153 @Test public void testMoreWeirdness() { 154 MutablePicoContainer pico = new DefaultPicoContainer(); 155 Map<String,String> map = new HashMap<String,String>(); 156 pico.addComponent(map); 157 // See class level javadoc in DefaultPicoContainer - about precedence. 158 pico.addComponent(InterfaceX.class, Something.class); 159 pico.addComponent(Disabled.class); 160 pico.addComponent(Enabled.class); 161 pico.addComponent(NeedsInterfaceX.class); 162 163 NeedsInterfaceX needsInterfaceX = pico.getComponent(NeedsInterfaceX.class); 164 assertEquals("Disabled", needsInterfaceX.getIt()); 165 map.put("enabled", "blah"); 166 assertEquals("Enabled", needsInterfaceX.getIt()); 167 } 168 169 // From John Tal 23/03/2004 170 public static interface ABC { 171 } 172 173 public static interface DEF { 174 } 175 176 public static class ABCImpl implements ABC { 177 public ABCImpl(DEF def) { 178 } 179 } 180 181 public static class DEFImpl implements DEF { 182 public DEFImpl() { 183 } 184 } 185 186 @Test public void testJohnTalOne() { 187 MutablePicoContainer picoContainer = new DefaultPicoContainer(); 188 189 picoContainer.addComponent("ABC", ABCImpl.class); 190 picoContainer.addComponent("DEF", DEFImpl.class); 191 192 assertEquals(ABCImpl.class, picoContainer.getComponent("ABC").getClass()); 193 } 194 195 public static interface Foo { 196 } 197 198 public static interface Bar { 199 } 200 201 public static class FooBar implements Foo, Bar { 202 } 203 204 public static class NeedsFoo { 205 private final Foo foo; 206 207 public NeedsFoo(Foo foo) { 208 this.foo = foo; 209 } 210 211 public Foo getFoo() { 212 return foo; 213 } 214 } 215 216 public static class NeedsBar { 217 private final Bar bar; 218 219 public NeedsBar(Bar bar) { 220 this.bar = bar; 221 } 222 223 public Bar getBar() { 224 return bar; 225 } 226 } 227 228 @Test public void testShouldBeAbleShareSameReferenceForDifferentTypes() { 229 MutablePicoContainer pico = new DefaultPicoContainer(); 230 pico.as(Characteristics.CACHE).addComponent(FooBar.class); 231 pico.addComponent(NeedsFoo.class); 232 pico.addComponent(NeedsBar.class); 233 NeedsFoo needsFoo = pico.getComponent(NeedsFoo.class); 234 NeedsBar needsBar = pico.getComponent(NeedsBar.class); 235 assertSame(needsFoo.getFoo(), needsBar.getBar()); 236 } 237 238 @Test public void testSeveralDifferentInstancesCanBeCreatedWithOnePreconfiguredContainer() { 239 // create a container that doesn't cache instances 240 MutablePicoContainer container = new DefaultPicoContainer(new ConstructorInjection()); 241 container.addComponent(NeedsBar.class); 242 243 Bar barOne = new FooBar(); 244 container.addComponent(Bar.class, barOne); 245 NeedsBar needsBarOne = container.getComponent(NeedsBar.class); 246 assertSame(barOne, needsBarOne.getBar()); 247 248 // reuse the same container - just flip out the existing foo. 249 Bar barTwo = new FooBar(); 250 container.removeComponent(Bar.class); 251 container.addComponent(Bar.class, barTwo); 252 NeedsBar needsBarTwo = container.getComponent(NeedsBar.class); 253 assertSame(barTwo, needsBarTwo.getBar()); 254 255 assertNotSame(needsBarOne, needsBarTwo); 256 } 257 }