[picocontainer-dev] patches for *full* binding-annotation capability
Paul Hammant <[email protected]>
| Newsgroups | gmane.comp.java.picocontainer.devel |
|---|---|
| Message-ID | <[email protected]> |
I'd apply them of course, but Konstantin has a precarious branch he
may want to merge back in the future <grin/>
I moved the goal post (as hinted in an email earlier).
Binding annotations are ugly but here to stay. The style that Guice
pioneers is illustrated in the following testcase :-
import static org.picocontainer.BindKey.bindKey;
import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.annotations.Bind;
import org.picocontainer.annotations.Inject;
import org.picocontainer.injectors.AbstractInjector;
import org.picocontainer.injectors.AnnotatedFieldInjection;
import org.picocontainer.injectors.MethodInjection;
import org.picocontainer.injectors.SetterInjection;
import org.picocontainer.parameters.ComponentParameter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import junit.framework.TestCase;
/** @author Paul Hammant */
public class JasonsTestCase extends TestCase {
public void testJasonsFieldInjectionWithBindingsNeed() {
MutablePicoContainer mpc = new DefaultPicoContainer(new
AnnotatedFieldInjection());
addFiveComponents(mpc);
FruitBasket fb = mpc.getComponent(FruitBasket.class);
assertFourMemberApplesAreRight(fb);
assertGettingOfAppleOneWorks(mpc);
}
private void assertGettingOfAppleOneWorks(MutablePicoContainer
mpc) {
try {
mpc.getComponent(Apple.class);
fail("should have barfed");
} catch
(AbstractInjector.AmbiguousComponentResolutionException e) {
// expected
}
assertNotNull(mpc.getComponent(Apple.class, BindOne.class));
}
public void testBindingAnnotationsWithConstructorInjection() {
MutablePicoContainer mpc = new DefaultPicoContainer();
addFiveComponents(mpc);
FruitBasket fb = mpc.getComponent(FruitBasket.class);
assertFourMemberApplesAreRight(fb);
assertGettingOfAppleOneWorks(mpc);
}
private void assertFourMemberApplesAreRight(FruitBasket fb) {
assertNotNull(fb);
assertEquals(fb.one.getX(), 1);
assertEquals(fb.two.getX(), 2);
assertEquals(fb.three.getX(), 3);
assertEquals(fb.four.getX(), 4);
}
public void testBindingAnnotationsWithMethodInjection() {
MutablePicoContainer mpc = new DefaultPicoContainer(new
MethodInjection("foo"));
addFiveComponents(mpc);
FruitBasket fb = mpc.getComponent(FruitBasket.class);
assertFourMemberApplesAreRight(fb);
assertGettingOfAppleOneWorks(mpc);
}
public void testBindingAnnotationsWithSetterInjection() {
MutablePicoContainer mpc = new DefaultPicoContainer(new
SetterInjection());
addFiveComponents(mpc);
FruitBasket fb = mpc.getComponent(FruitBasket.class);
assertFourMemberApplesAreRight(fb);
assertGettingOfAppleOneWorks(mpc);
}
private void addFiveComponents(MutablePicoContainer mpc) {
mpc.addComponent(FruitBasket.class);
mpc.addComponent(bindKey(Apple.class, BindOne.class),
AppleImpl1.class);
mpc.addComponent(bindKey(Apple.class, BindTwo.class),
AppleImpl2.class);
mpc.addComponent(bindKey(Apple.class, BindThree.class),
AppleImpl3.class);
mpc.addComponent(bindKey(Apple.class, BindFour.class),
AppleImpl4.class);
}
public interface Apple {
int getX();
}
public static class AppleImpl1 implements Apple {
public int getX() {
return 1;
}
}
public static class AppleImpl2 implements Apple {
public int getX() {
return 2;
}
}
public static class AppleImpl3 implements Apple {
public int getX() {
return 3;
}
}
public static class AppleImpl4 implements Apple {
public int getX() {
return 4;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Bind
public static @interface BindOne {}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Bind
public static @interface BindTwo {}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Bind
public static @interface BindThree {}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Bind
public static @interface BindFour {}
public static class FruitBasket {
@Inject
private @BindOne Apple one;
@Inject
private @BindTwo Apple two;
@Inject
private @BindThree Apple three;
@Inject
private @BindFour Apple four;
public FruitBasket() {
}
// used in testBindingAnnotationsWithConstructorInjection()
public FruitBasket(@BindOne Apple one, @BindTwo Apple two,
@BindThree Apple three, @BindFour Apple four) {
this.one = one;
this.two = two;
this.three = three;
this.four = four;
}
// used in testBindingAnnotationsWithMethodInjection()
public void foo(@BindOne Apple one, @BindTwo Apple two,
@BindThree Apple three, @BindFour Apple four) {
this.one = one;
this.two = two;
this.three = three;
this.four = four;
}
public void setOne(@BindOne Apple one) {
this.one = one;
}
public void setTwo(@BindTwo Apple two) {
this.two = two;
}
public void setThree(@BindThree Apple three) {
this.three = three;
}
public void setFour(@BindFour Apple four) {
this.four = four;
}
}
}
---------------------------------------------------------------------
To unsubscribe from this list please visit:
http://xircles.codehaus.org/manage_email
pico.patch
(application/octet-stream, 122.1 KB) - not displayed
nano.patch
(application/octet-stream, 10.1 KB)
Index: container/src/test/org/nanocontainer/script/xml/NonMutablePicoContainerContainerTestCase.java
===================================================================
--- container/src/test/org/nanocontainer/script/xml/NonMutablePicoContainerContainerTestCase.java (revision 4062)
+++ container/src/test/org/nanocontainer/script/xml/NonMutablePicoContainerContainerTestCase.java (working copy)
@@ -22,6 +22,7 @@
import java.io.StringReader;
import java.util.Collection;
import java.util.List;
+import java.lang.annotation.Annotation;
import javax.xml.parsers.ParserConfigurationException;
import org.nanocontainer.integrationkit.PicoCompositionException;
@@ -46,6 +47,10 @@
return null;
}
+ public <T> T getComponent(Class<T> componentType, Class<? extends Annotation> binding) {
+ return null;
+ }
+
public List getComponents() {
return null;
}
@@ -80,6 +85,14 @@
return null;
}
+ public <T> ComponentAdapter<T> getComponentAdapter(Class<T> componentType, Class<? extends Annotation> binding) {
+ return null;
+ }
+
+ public <T> List<ComponentAdapter<T>> getComponentAdapters(Class<T> componentType, Class<? extends Annotation> binding) {
+ return null;
+ }
+
public void start() {
}
Index: container/src/test/org/nanocontainer/script/xml/XStreamContainerBuilderTestCase.java
===================================================================
--- container/src/test/org/nanocontainer/script/xml/XStreamContainerBuilderTestCase.java (revision 4062)
+++ container/src/test/org/nanocontainer/script/xml/XStreamContainerBuilderTestCase.java (working copy)
@@ -15,6 +15,7 @@
import org.nanocontainer.testmodel.WebServerImpl;
import org.picocontainer.PicoContainer;
import org.picocontainer.ComponentAdapter;
+import org.picocontainer.ParameterName;
import org.picocontainer.behaviors.AbstractBehavior;
import org.picocontainer.behaviors.Cached;
@@ -86,7 +87,7 @@
"</container>");
PicoContainer pico = buildContainer(new XStreamContainerBuilder(script, getClass().getClassLoader()), null, "SOME_SCOPE");
- Cached ca = (Cached) pico.getComponentAdapter(TestAdapter.class, null);
+ Cached ca = (Cached) pico.getComponentAdapter(TestAdapter.class, (ParameterName) null);
assertNotNull((TestAdapter)ca.getDelegate());
}
Index: container/src/test/org/nanocontainer/script/xml/issues/Issue0170TestCase.java
===================================================================
--- container/src/test/org/nanocontainer/script/xml/issues/Issue0170TestCase.java (revision 4062)
+++ container/src/test/org/nanocontainer/script/xml/issues/Issue0170TestCase.java (working copy)
@@ -1,15 +1,17 @@
package org.nanocontainer.script.xml.issues;
+import org.picocontainer.ComponentAdapter;
+import org.picocontainer.ParameterName;
+import org.picocontainer.PicoContainer;
+import org.picocontainer.gems.behaviors.HotSwappable;
+
import java.io.Reader;
import java.io.StringReader;
+import java.util.ArrayList;
import java.util.List;
-import java.util.ArrayList;
import org.nanocontainer.script.AbstractScriptedContainerBuilderTestCase;
import org.nanocontainer.script.xml.XMLContainerBuilder;
-import org.picocontainer.PicoContainer;
-import org.picocontainer.ComponentAdapter;
-import org.picocontainer.gems.behaviors.HotSwappable;
//http://jira.codehaus.org/browse/NANO-170
public class Issue0170TestCase extends AbstractScriptedContainerBuilderTestCase {
@@ -35,7 +37,7 @@
List list = pico.getComponent(List.class);
assertNotNull(list);
- ComponentAdapter listCA = pico.getComponentAdapter(List.class, null);
+ ComponentAdapter listCA = pico.getComponentAdapter(List.class, (ParameterName) null);
assertTrue(listCA instanceof HotSwappable);
HotSwappable hsca = (HotSwappable) listCA;
Index: container/src/java/org/nanocontainer/DefaultNanoContainer.java
===================================================================
--- container/src/java/org/nanocontainer/DefaultNanoContainer.java (revision 4062)
+++ container/src/java/org/nanocontainer/DefaultNanoContainer.java (working copy)
@@ -40,7 +40,7 @@
import java.util.List;
import java.util.Map;
import java.util.Properties;
-import java.util.Enumeration;
+import java.lang.annotation.Annotation;
/**
* This is a MutablePicoContainer that also supports soft composition. i.e. assembly by class name rather that class
@@ -441,6 +441,10 @@
return DefaultNanoContainer.this.getComponent(componentType);
}
+ public <T> T getComponent(Class<T> componentType, Class<? extends Annotation> binding) {
+ return DefaultNanoContainer.this.getComponent(componentType, binding);
+ }
+
public List getComponents() {
return DefaultNanoContainer.this.getComponents();
}
@@ -457,6 +461,10 @@
return DefaultNanoContainer.this.getComponentAdapter(componentType, componentParameterName);
}
+ public <T> ComponentAdapter<T> getComponentAdapter(Class<T> componentType, Class<? extends Annotation> binding) {
+ return DefaultNanoContainer.this.getComponentAdapter(componentType, binding);
+ }
+
public Collection<ComponentAdapter<?>> getComponentAdapters() {
return DefaultNanoContainer.this.getComponentAdapters();
}
@@ -465,6 +473,11 @@
return DefaultNanoContainer.this.getComponentAdapters(componentType);
}
+ public <T> List<ComponentAdapter<T>> getComponentAdapters(Class<T> componentType, Class<? extends Annotation> binding) {
+ return DefaultNanoContainer.this.getComponentAdapters(componentType, binding);
+ }
+
+
public <T> List<T> getComponents(Class<T> componentType) {
return DefaultNanoContainer.this.getComponents();
}
Index: container-groovy/src/test/org/nanocontainer/script/groovy/GroovyNodeBuilderTestCase.java
===================================================================
--- container-groovy/src/test/org/nanocontainer/script/groovy/GroovyNodeBuilderTestCase.java (revision 4062)
+++ container-groovy/src/test/org/nanocontainer/script/groovy/GroovyNodeBuilderTestCase.java (working copy)
@@ -26,6 +26,7 @@
import org.picocontainer.ComponentMonitor;
import org.picocontainer.LifecycleStrategy;
import org.picocontainer.ComponentFactory;
+import org.picocontainer.ParameterName;
import org.picocontainer.behaviors.Caching;
import org.picocontainer.injectors.AbstractInjector;
import org.picocontainer.monitors.NullComponentMonitor;
@@ -492,7 +493,7 @@
NanoContainer parent = new DefaultNanoContainer(
buildContainer(script, null, new ParentAssemblyScope()));
- assertNotNull(parent.getComponentAdapter(A.class, null));
+ assertNotNull(parent.getComponentAdapter(A.class, (ParameterName) null));
script = new StringReader(scriptValue);
PicoContainer pico = buildContainer(script, parent, new SomeAssemblyScope());
@@ -529,7 +530,7 @@
MutablePicoContainer pico = (MutablePicoContainer)buildContainer(script, parent, ASSEMBLY_SCOPE);
// Should be able to get instance that was registered in the parent container
- ComponentAdapter componentAdapter = pico.addComponent(String.class).getComponentAdapter(String.class, null);
+ ComponentAdapter componentAdapter = pico.addComponent(String.class).getComponentAdapter(String.class, (ParameterName) null);
assertTrue("ComponentAdapter should be originally defined by parent" , componentAdapter instanceof SetterInjector);
}
Index: container-jruby/src/test/org/nanocontainer/script/jruby/JRubyContainerBuilderTestCase.java
===================================================================
--- container-jruby/src/test/org/nanocontainer/script/jruby/JRubyContainerBuilderTestCase.java (revision 4062)
+++ container-jruby/src/test/org/nanocontainer/script/jruby/JRubyContainerBuilderTestCase.java (working copy)
@@ -3,16 +3,17 @@
import org.picocontainer.ComponentAdapter;
import org.picocontainer.ComponentFactory;
import org.picocontainer.ComponentMonitor;
+import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.LifecycleStrategy;
import org.picocontainer.MutablePicoContainer;
+import org.picocontainer.ParameterName;
import org.picocontainer.PicoContainer;
-import org.picocontainer.DefaultPicoContainer;
-import org.picocontainer.monitors.NullComponentMonitor;
-import org.picocontainer.lifecycle.NullLifecycleStrategy;
import org.picocontainer.adapters.InstanceAdapter;
+import org.picocontainer.injectors.AbstractInjector;
+import org.picocontainer.injectors.SetterInjection;
import org.picocontainer.injectors.SetterInjector;
-import org.picocontainer.injectors.SetterInjection;
-import org.picocontainer.injectors.AbstractInjector;
+import org.picocontainer.lifecycle.NullLifecycleStrategy;
+import org.picocontainer.monitors.NullComponentMonitor;
import java.io.File;
import java.io.IOException;
@@ -422,7 +423,7 @@
Reader script = new StringReader(scriptValue);
NanoContainer parent = new DefaultNanoContainer(
buildContainer(script, null, new ParentAssemblyScope()));
- assertNotNull(parent.getComponentAdapter(A.class, null));
+ assertNotNull(parent.getComponentAdapter(A.class, (ParameterName) null));
script = new StringReader(scriptValue);
PicoContainer pico = buildContainer(script, parent, new SomeAssemblyScope());
@@ -435,7 +436,7 @@
MutablePicoContainer pico = (MutablePicoContainer) buildContainer(script, parent, ASSEMBLY_SCOPE);
// Should be able to get instance that was registered in the parent container
- ComponentAdapter componentAdapter = pico.addComponent(String.class).getComponentAdapter(String.class, null);
+ ComponentAdapter componentAdapter = pico.addComponent(String.class).getComponentAdapter(String.class, (ParameterName) null);
assertTrue("ComponentAdapter should be originally defined by parent",
componentAdapter instanceof SetterInjector);
}