You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mb...@apache.org on 2010/09/23 20:23:21 UTC

svn commit: r1000566 - in /commons/proper/proxy/branches/version-2.0-work/stub/src: main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java test/java/org/apache/commons/proxy2/stub/AnnotationFactoryTest.java

Author: mbenson
Date: Thu Sep 23 18:23:21 2010
New Revision: 1000566

URL: http://svn.apache.org/viewvc?rev=1000566&view=rev
Log:
add the ability to program an annotation from (ugh) a string-keyed attribute map

Modified:
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AnnotationFactoryTest.java

Modified: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java?rev=1000566&r1=1000565&r2=1000566&view=diff
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java (original)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java Thu Sep 23 18:23:21 2010
@@ -23,6 +23,7 @@ import java.lang.reflect.InvocationHandl
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.util.Map;
 
 import org.apache.commons.lang3.AnnotationUtils;
 import org.apache.commons.lang3.Pair;
@@ -148,6 +149,41 @@ public class AnnotationFactory {
         }
     }
 
+    private static class MapBasedAnnotationConfigurer<A extends Annotation> extends StubConfigurer<A> {
+        final Map<String, Object> attributes;
+
+        /**
+         * Create a new {@link MapBasedAnnotationConfigurer} instance.
+         * @param stubType
+         * @param attributes
+         */
+        public MapBasedAnnotationConfigurer(Class<A> stubType, Map<String, Object> attributes) {
+            super(stubType);
+            this.attributes = attributes;
+        }
+
+        @Override
+        protected void configure(A stub) {
+            When<Object> bud;
+            StubConfiguration dy = this;
+            for (Map.Entry<String, Object> attr : attributes.entrySet()) {
+                Method m;
+                try {
+                    m = getStubType().getDeclaredMethod(attr.getKey());
+                } catch (Exception e1) {
+                    throw new IllegalArgumentException(String.format("Could not detect annotation attribute %1$s", attr.getKey()));
+                }
+                try {
+                    bud = dy.when(m.invoke(stub));
+                } catch (Exception e) {
+                    //it must have happened on the invoke, so we didn't call when... it shouldn't happen, but we'll simply skip:
+                    continue;
+                }
+                dy = bud.thenReturn(attr.getValue());
+            }
+        }
+    }
+
     private static final Invoker ANNOTATION_INVOKER = new Invoker() {
 
         /** Serialization version */
@@ -247,6 +283,32 @@ public class AnnotationFactory {
         return result;
     }
 
+    /**
+     * Create an annotation of <code>annotationType</code> with behavior specified by a {@link String}-keyed {@link Map}.
+     * @param <A>
+     * @param classLoader
+     * @param annotationType
+     * @param attributes
+     * @return stubbed annotation proxy
+     */
+    public <A extends Annotation> A create(Class<A> annotationType, Map<String, Object> attributes) {
+        return attributes == null || attributes.isEmpty() ? create(annotationType)
+            : create(new MapBasedAnnotationConfigurer<A>(annotationType, attributes));
+    }
+
+    /**
+     * Create an annotation of <code>annotationType</code> with behavior specified by a {@link String}-keyed {@link Map}.
+     * @param <A>
+     * @param classLoader
+     * @param annotationType
+     * @param attributes
+     * @return stubbed annotation proxy
+     */
+    public <A extends Annotation> A create(ClassLoader classLoader, Class<A> annotationType, Map<String, Object> attributes) {
+        return attributes == null || attributes.isEmpty() ? create(classLoader, annotationType) : create(classLoader,
+            new MapBasedAnnotationConfigurer<A>(annotationType, attributes));
+    }
+
     private <A extends Annotation> A createInternal(ClassLoader classLoader, Object configurer) {
         final Object existingConfigurer = CONFIGURER.get();
         final boolean outerContext = CONTEXT.get() == null;

Modified: commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AnnotationFactoryTest.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AnnotationFactoryTest.java?rev=1000566&r1=1000565&r2=1000566&view=diff
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AnnotationFactoryTest.java (original)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AnnotationFactoryTest.java Thu Sep 23 18:23:21 2010
@@ -20,6 +20,8 @@ package org.apache.commons.proxy2.stub;
 import static org.junit.Assert.*;
 
 import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -161,6 +163,26 @@ public class AnnotationFactoryTest {
         };
     }
 
+    @Test
+    public void testAttributes() {
+        Map<String, Object> attributes = new HashMap<String, Object>();
+        attributes.put("annString", "foo");
+        attributes.put("finiteValues", FiniteValues.values());
+        attributes.put("someType", Object.class);
+        CustomAnnotation customAnnotation = annotationFactory.create(CustomAnnotation.class, attributes);
+        assertNotNull(customAnnotation);
+        assertEquals("foo", customAnnotation.annString());
+        assertEquals(3, customAnnotation.finiteValues().length);
+        assertEquals(Object.class, customAnnotation.someType());
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testBadAttributes() {
+        Map<String, Object> attributes = new HashMap<String, Object>();
+        attributes.put("annString", 100);
+        annotationFactory.create(CustomAnnotation.class, attributes);
+    }
+    
     public @interface NestingAnnotation {
         CustomAnnotation child();