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();