[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);
     }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.