Author: mbenson
Date: Thu Sep 23 03:20:41 2010
New Revision: 1000298

URL: http://svn.apache.org/viewvc?rev=1000298&view=rev
Log:
(re-)add notion of a special Annotation-specific StubConfigurer subclass, 
AnnotationConfigurer.  Not required for use, but if used, provides methods to 
simplify the creation of nested annotations a bit

Added:
    
commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java
   (with props)
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

Added: 
commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java
URL: 
http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java?rev=1000298&view=auto
==============================================================================
--- 
commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java
 (added)
+++ 
commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java
 Thu Sep 23 03:20:41 2010
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.proxy2.stub;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * Special {...@link StubConfigurer} subclass that makes creating nested 
annotations (somewhat more) convenient.
+ *
+ * @param <A>
+ */
+public abstract class AnnotationConfigurer<A extends Annotation> extends 
StubConfigurer<A> {
+    AnnotationFactory annotationFactory;
+
+    /**
+     * Create a child annotation of the specified type using a StubConfigurer.
+     * @param <T>
+     * @param configurer, should not be <code>this</code>
+     * @return T
+     * @throws IllegalStateException if called other than when an {...@link 
AnnotationFactory} is executing {...@link #configure(Object)}
+     * @throws IllegalArgumentException if <code>configurer == this</code>
+     */
+    protected final <T extends Annotation> T child(StubConfigurer<T> 
configurer) {
+        if (configurer == this) {
+            throw new IllegalArgumentException("An AnnotationConfigurer cannot 
configure its own child annotation");
+        }
+        return requireAnnotationFactory().create(configurer);
+    }
+
+    /**
+     * Create a child annotation of the specified type with default behavior.
+     * @param <T>
+     * @param annotationType
+     * @return T
+     * @throws IllegalStateException if called other than when an {...@link 
AnnotationFactory} is executing {...@link #configure(Object)}
+     */
+    protected final <T extends Annotation> T child(Class<T> annotationType) {
+        return requireAnnotationFactory().create(annotationType);
+    }
+
+    /**
+     * Get the registered annotationFactory.
+     * @return AnnotationFactory
+     * @throws IllegalStateException if no ongoing annotation stubbing could 
be detected
+     */
+    synchronized AnnotationFactory requireAnnotationFactory() throws 
IllegalStateException {
+        if (annotationFactory == null) {
+            throw new IllegalStateException("Could not detect ongoing 
annotation stubbing");
+        }
+        return annotationFactory;
+    }
+}
\ No newline at end of file

Propchange: 
commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=1000298&r1=1000297&r2=1000298&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 03:20:41 2010
@@ -155,7 +155,7 @@ public class AnnotationFactory {
 
     private static final ThreadLocal<Object> CONFIGURER = new 
ThreadLocal<Object>();
 
-    private static final StubConfigurer<Annotation> SHARED_CONFIGURER = new 
StubConfigurer<Annotation>() {
+    private final StubConfigurer<Annotation> sharedConfigurer = new 
StubConfigurer<Annotation>() {
 
         /**
          * {...@inheritdoc}
@@ -175,7 +175,21 @@ public class AnnotationFactory {
             if (o instanceof StubConfigurer<?>) {
                 @SuppressWarnings("unchecked")
                 final StubConfigurer<Annotation> configurer = 
(StubConfigurer<Annotation>) o;
-                configurer.configure(requireStubInterceptor(), stub);
+                boolean deregisterFactory = false;
+                synchronized (configurer) {
+                    try {
+                        if (configurer instanceof AnnotationConfigurer<?>) {
+                            AnnotationConfigurer<?> annotationConfigurer = 
(AnnotationConfigurer<?>) configurer;
+                            deregisterFactory = true;
+                            annotationConfigurer.annotationFactory = 
AnnotationFactory.this;
+                        }
+                        configurer.configure(requireStubInterceptor(), stub);
+                    } finally {
+                        if (deregisterFactory) {
+                            ((AnnotationConfigurer<?>) 
configurer).annotationFactory = null;
+                        }
+                    }
+                }
             }
         }
     };
@@ -186,7 +200,7 @@ public class AnnotationFactory {
      * Create a new AnnotationFactory instance.
      */
     public AnnotationFactory() {
-        this.proxyFactory = new StubProxyFactory(PROXY_FACTORY, 
SHARED_CONFIGURER);
+        this.proxyFactory = new StubProxyFactory(PROXY_FACTORY, 
sharedConfigurer);
     }
 
     /**

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=1000298&r1=1000297&r2=1000298&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 03:20:41 2010
@@ -19,6 +19,8 @@ package org.apache.commons.proxy2.stub;
 
 import static org.junit.Assert.*;
 
+import java.lang.annotation.Annotation;
+
 import org.junit.Before;
 import org.junit.Test;
 
@@ -36,11 +38,11 @@ public class AnnotationFactoryTest {
     @Test
     public void testDefaultAnnotation() {
         CustomAnnotation customAnnotation = 
annotationFactory.create(CustomAnnotation.class);
+        assertNotNull(customAnnotation);
         assertEquals(CustomAnnotation.class, 
customAnnotation.annotationType());
         assertEquals("", customAnnotation.annString());
         assertEquals(0, customAnnotation.finiteValues().length);
         assertNull(customAnnotation.someType());
-
     }
 
     @Test
@@ -54,6 +56,7 @@ public class AnnotationFactoryTest {
             }
 
         });
+        assertNotNull(customAnnotation);
         assertEquals(CustomAnnotation.class, 
customAnnotation.annotationType());
         assertEquals("hey", customAnnotation.annString());
         assertArrayEquals(new FiniteValues[] { FiniteValues.ONE, 
FiniteValues.THREE }, customAnnotation.finiteValues());
@@ -61,21 +64,103 @@ public class AnnotationFactoryTest {
     }
 
     @Test
-    public void testNestedStubbedAnnotation() {
+    public void testStubbedAnnotationWithDefaultChild() {
         NestingAnnotation nestingAnnotation =
-            annotationFactory.create(new StubConfigurer<NestingAnnotation>() {
+            annotationFactory.create(new 
AnnotationConfigurer<NestingAnnotation>() {
                 @Override
                 protected void configure(NestingAnnotation stub) {
-                    
when(stub.child()).thenReturn(annotationFactory.create(CustomAnnotation.class))
+                    
when(stub.child()).thenReturn(child(CustomAnnotation.class))
                         
.when(stub.somethingElse()).thenReturn("somethingElse");
                 }
             });
+        assertNotNull(nestingAnnotation);
+        assertNotNull(nestingAnnotation.child());
         assertEquals("", nestingAnnotation.child().annString());
         assertEquals(0, nestingAnnotation.child().finiteValues().length);
         assertEquals(null, nestingAnnotation.child().someType());
         assertEquals("somethingElse", nestingAnnotation.somethingElse());
     }
 
+    @Test
+    public void testStubbedAnnotationWithConfiguredChild() {
+        NestingAnnotation nestingAnnotation = annotationFactory.create(new 
AnnotationConfigurer<NestingAnnotation>() {
+            @Override
+            protected void configure(NestingAnnotation stub) {
+                when(stub.child()).thenReturn(child(new 
StubConfigurer<CustomAnnotation>() {
+
+                    @Override
+                    protected void configure(CustomAnnotation stub) {
+                        
when(stub.annString()).thenReturn("wow").when(stub.finiteValues())
+                            
.thenReturn(FiniteValues.values()).when(stub.someType()).thenReturn(Class.class);
+                    }
+                })).when(stub.somethingElse()).thenReturn("somethingElse");
+            }
+        });
+        assertNotNull(nestingAnnotation);
+        assertNotNull(nestingAnnotation.child());
+        assertEquals("wow", nestingAnnotation.child().annString());
+        assertEquals(3, nestingAnnotation.child().finiteValues().length);
+        assertEquals(Class.class, nestingAnnotation.child().someType());
+        assertEquals("somethingElse", nestingAnnotation.somethingElse());
+    }
+
+    @Test
+    public void testStubbedAnnotationWithDoubleNesting() {
+        OuterContainer outerContainer = annotationFactory.create(new 
AnnotationConfigurer<OuterContainer>() {
+
+            @Override
+            protected void configure(OuterContainer stub) {
+                when(stub.nest()).thenReturn(child(new 
AnnotationConfigurer<NestingAnnotation>() {
+
+                    @Override
+                    protected void configure(NestingAnnotation stub) {
+                        when(stub.child()).thenReturn(child(new 
AnnotationConfigurer<CustomAnnotation>() {
+
+                            @Override
+                            protected void configure(CustomAnnotation stub) {
+                                
when(stub.annString()).thenReturn("wow").when(stub.finiteValues())
+                                
.thenReturn(FiniteValues.values()).when(stub.someType()).thenReturn(Class.class);
+                            }
+
+                        
})).when(stub.somethingElse()).thenReturn("somethingElse");
+                    }
+                }));
+            }
+        });
+        assertNotNull(outerContainer);
+        NestingAnnotation nestingAnnotation = outerContainer.nest();
+        assertNotNull(nestingAnnotation);
+        assertNotNull(nestingAnnotation.child());
+        assertEquals("wow", nestingAnnotation.child().annString());
+        assertEquals(3, nestingAnnotation.child().finiteValues().length);
+        assertEquals(Class.class, nestingAnnotation.child().someType());
+        assertEquals("somethingElse", nestingAnnotation.somethingElse());
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testCannotConfigureOwnChild() {
+        annotationFactory.create(new AnnotationConfigurer<NestingAnnotation>() 
{
+
+            @Override
+            protected void configure(NestingAnnotation stub) {
+                child(this);
+            }
+        });
+    }
+
+    @Test(expected=IllegalStateException.class)
+    public void testChildRequiresOngoingStubbing() {
+        new AnnotationConfigurer<Annotation>() {
+            {
+                child(CustomAnnotation.class);
+            }
+
+            @Override
+            protected void configure(Annotation stub) {
+            }
+        };
+    }
+
     public @interface NestingAnnotation {
         CustomAnnotation child();
 
@@ -90,6 +175,10 @@ public class AnnotationFactoryTest {
         Class<?> someType();
     }
 
+    public @interface OuterContainer {
+        NestingAnnotation nest();
+    }
+
     public enum FiniteValues {
         ONE, TWO, THREE;
     }


Reply via email to