since AnnotationFactory now uses a single StubFactory instance internally, the annotationType() handling can be handled therein.  Having taken away AnnotationStubConfigurer's only reason for being, it is deleted.

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/proxy/branches/version-2.0-work@997852 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java b/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
index 4769fa1..570342a 100644
--- a/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
+++ b/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
@@ -26,9 +26,9 @@
 
 /**
  * {@link AnnotationFactory} provides a simplified API over {@link StubProxyFactory}
- * to stub a Java {@link Annotation}.  Non-stubbed methods will return the values
- * that would have been returned from a "real" annotation whose methods' values
- * were unspecified.
+ * to stub a Java {@link Annotation}.  Non-stubbed methods including
+ * {@link Annotation#annotationType()} will return the values that would have been
+ * returned from a "real" annotation whose methods' values were unspecified.
  *
  * @author Matt Benson
  */
@@ -49,7 +49,8 @@
 
     private static final ThreadLocal<Object> CONFIGURER = new ThreadLocal<Object>();
 
-    private static final AnnotationStubConfigurer<Annotation> SHARED_CONFIGURER = new AnnotationStubConfigurer<Annotation>() {
+    private static final StubConfigurer<Annotation> SHARED_CONFIGURER = new StubConfigurer<Annotation>() {
+        
         /**
          * {@inheritDoc}
          */
@@ -62,11 +63,12 @@
          * {@inheritDoc}
          */
         @Override
-        protected void configureAnnotation(Annotation stub) {
+        protected void configure(Annotation stub) {
+            when(stub.annotationType()).thenReturn(getStubType());
             Object o = CONFIGURER.get();
-            if (o instanceof AnnotationStubConfigurer<?>) {
+            if (o instanceof StubConfigurer<?>) {
                 @SuppressWarnings("unchecked")
-                final AnnotationStubConfigurer<Annotation> configurer = (AnnotationStubConfigurer<Annotation>) o;
+                final StubConfigurer<Annotation> configurer = (StubConfigurer<Annotation>) o;
                 configurer.configure(requireStubInterceptor(), stub);
             }
         }
@@ -98,13 +100,13 @@
      * @return stubbed annotation proxy
      */
     public <A extends Annotation> A create(
-            AnnotationStubConfigurer<A> configurer) {
+        StubConfigurer<A> configurer) {
         @SuppressWarnings("unchecked")
         final A result = (A) createInternal(Thread.currentThread()
-                .getContextClassLoader(), configurer);
+            .getContextClassLoader(), configurer);
         return result;
     }
-
+    
     /**
      * Create an annotation of the type supported by <code>configurer</code> in the specified classpath.
      * @param <A>
@@ -113,12 +115,12 @@
      * @return stubbed annotation proxy
      */
     public <A extends Annotation> A create(ClassLoader classLoader,
-            AnnotationStubConfigurer<A> configurer) {
+        StubConfigurer<A> configurer) {
         @SuppressWarnings("unchecked")
         final A result = (A) createInternal(classLoader, configurer);
         return result;
     }
-
+    
     /**
      * Create an annotation of <code>annotationType</code> with fully default behavior.
      * @param <A>
@@ -149,6 +151,7 @@
 
     private <A extends Annotation> A createInternal(ClassLoader classLoader,
             Object configurer) {
+        final Object existingConfigurer = CONFIGURER.get();
         try {
             CONFIGURER.set(configurer);
             @SuppressWarnings("unchecked")
@@ -156,7 +159,11 @@
                     ANNOTATION_INVOKER, getStubType());
             return result;
         } finally {
-            CONFIGURER.remove();
+            if (existingConfigurer == null) {
+                CONFIGURER.remove();
+            } else {
+                CONFIGURER.set(existingConfigurer);
+            }
         }
     }
 
@@ -168,7 +175,7 @@
             return result;
         }
         @SuppressWarnings("unchecked")
-        final AnnotationStubConfigurer<A> configurer = (AnnotationStubConfigurer<A>) o;
+        final StubConfigurer<A> configurer = (StubConfigurer<A>) o;
         return configurer.getStubType();
     }
 }
diff --git a/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationStubConfigurer.java b/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationStubConfigurer.java
deleted file mode 100644
index 663dbe5..0000000
--- a/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationStubConfigurer.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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;
-
-/**
- * {@link StubConfigurer} for annotation types:  handles <code>{@link Annotation#annotationType()}</code>.
- */
-public class AnnotationStubConfigurer<T extends Annotation> extends
-        StubConfigurer<T> {
-
-    /**
-     * Create a new AnnotationStubConfigurer instance.
-     */
-    public AnnotationStubConfigurer() {
-        super();
-    }
-
-    /**
-     * Create a new AnnotationStubConfigurer instance.
-     */
-    public AnnotationStubConfigurer(Class<T> stubType) {
-        super(stubType);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected final void configure(T stub) {
-        when(stub.annotationType()).thenReturn(getStubType());
-        configureAnnotation(stub);
-    };
-
-    /**
-     * Configure stub as usual. Default implementation is a noop.
-     * @param stub
-     */
-    protected void configureAnnotation(T stub) {
-    }
-
-    /**
-     * Factory method.
-     * @param <T>
-     * @param type
-     * @return {@link AnnotationStubConfigurer} for type
-     */
-    public static <T extends Annotation> AnnotationStubConfigurer<T> forType(Class<T> type) {
-        return new AnnotationStubConfigurer<T>(type);
-    }
-}
diff --git a/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java b/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java
index 39b711f..378e660 100644
--- a/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java
+++ b/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java
@@ -20,8 +20,6 @@
 import static org.junit.Assert.*;
 
 import org.apache.commons.proxy2.ProxyFactory;
-import org.apache.commons.proxy2.stub.AnnotationFactory;
-import org.apache.commons.proxy2.stub.AnnotationStubConfigurer;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -50,10 +48,10 @@
 
     @Test
     public void testStubbedAnnotation() {
-        CustomAnnotation customAnnotation = annotationFactory.create(new AnnotationStubConfigurer<CustomAnnotation>() {
+        CustomAnnotation customAnnotation = annotationFactory.create(new StubConfigurer<CustomAnnotation>() {
 
             @Override
-            protected void configureAnnotation(CustomAnnotation stub) {
+            protected void configure(CustomAnnotation stub) {
                 when(stub.someType()).thenReturn(Object.class).when(stub.finiteValues())
                     .thenReturn(FiniteValues.ONE, FiniteValues.THREE).when(stub.annString()).thenReturn("hey");
             }
@@ -65,6 +63,28 @@
         assertEquals(Object.class, customAnnotation.someType());
     }
 
+    @Test
+    public void testNestedStubbedAnnotation() {
+        NestingAnnotation nestingAnnotation =
+            annotationFactory.create(new StubConfigurer<NestingAnnotation>() {
+                @Override
+                protected void configure(NestingAnnotation stub) {
+                    when(stub.child()).thenReturn(annotationFactory.create(CustomAnnotation.class))
+                        .when(stub.somethingElse()).thenReturn("somethingElse");
+                }
+            });
+        assertEquals("", nestingAnnotation.child().annString());
+        assertEquals(0, nestingAnnotation.child().finiteValues().length);
+        assertEquals(null, nestingAnnotation.child().someType());
+        assertEquals("somethingElse", nestingAnnotation.somethingElse());
+    }
+
+    public @interface NestingAnnotation {
+        CustomAnnotation child();
+
+        String somethingElse();
+    }
+
     public @interface CustomAnnotation {
         String annString() default "";