Skip to content
Permalink
Browse files
make annotationType available as early as possible for stubbed annota…
…tions; implement stubbed annotation arrays as nested annotation members

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/proxy/branches/version-2.0-work@1554962 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
mbenson committed Jan 2, 2014
1 parent a2190ff commit 408a446eb17de9e56ef2aef275dfe82a91c6a7ff
Showing 5 changed files with 142 additions and 25 deletions.
@@ -235,18 +235,21 @@ private AnnotationBuilder(Class<A> type, Invoker invoker)
{
super(PROXY_FACTORY, type, invoker);
this.annotationType = type;
train(new AnnotationTypeTrainer<A>(type));
}

private AnnotationBuilder(Class<A> type, ObjectProvider<? extends A> provider)
{
super(PROXY_FACTORY, type, provider);
this.annotationType = type;
train(new AnnotationTypeTrainer<A>(type));
}

private AnnotationBuilder(Class<A> type, A target)
{
super(PROXY_FACTORY, type, target);
this.annotationType = type;
train(new AnnotationTypeTrainer<A>(type));
}

public AnnotationBuilder<A> withMembers(Map<String, ?> members)
@@ -259,18 +262,4 @@ public <O> AnnotationBuilder<A> train(BaseTrainer<?, O> trainer)
{
return (AnnotationBuilder<A>) super.train(trainer);
}

@Override
public A build()
{
train(new AnnotationTrainer<A>(annotationType)
{
@Override
protected void train(A trainee)
{
when(trainee.annotationType()).thenReturn(annotationType);
}
});
return super.build();
}
}
@@ -0,0 +1,36 @@
/*
* 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;

class AnnotationTypeTrainer<R extends Annotation> extends AnnotationTrainer<R>
{

AnnotationTypeTrainer(Class<R> annotationType)
{
super(annotationType);
}

@Override
protected void train(R trainee)
{
when(trainee.annotationType()).thenReturn(traineeType);
}

}
@@ -21,36 +21,91 @@

import org.apache.commons.proxy2.interceptor.InterceptorUtils;

public abstract class BaseAnnotationTrainer<S extends BaseAnnotationTrainer<S, A>, A extends Annotation> extends BaseTrainer<S, A>
public abstract class BaseAnnotationTrainer<S extends BaseAnnotationTrainer<S, A>, A extends Annotation> extends
BaseTrainer<S, A>
{
protected BaseAnnotationTrainer() {
protected BaseAnnotationTrainer()
{
super();
}

protected BaseAnnotationTrainer(Class<A> traineeType) {
protected BaseAnnotationTrainer(Class<A> traineeType)
{
super(traineeType);
}

protected class WhenAnnotation<R> extends WhenObject<R>
{
public S thenStub(Class<R> type) {
public S thenStub(Class<R> type)
{
trainingContext().push(type);
trainingContext().then(InterceptorUtils.constant(trainingContext().pop(AnnotationInvoker.INSTANCE)));
return self();
}

@Override
public S thenStub(BaseTrainer<?, R> trainer) {
public S thenStub(BaseTrainer<?, R> trainer)
{
final R trainee = trainingContext().push(trainer.traineeType);
trainer.train(trainee);
trainingContext().then(InterceptorUtils.constant(trainingContext().pop(AnnotationInvoker.INSTANCE)));
return self();
}
}

protected class WhenAnnotationArray<R> extends WhenObjectArray<R>
{
protected WhenAnnotationArray(Class<? extends R> componentType)
{
super(componentType);
}

@Override
public StubAnnotationArrayBuilder<R> thenBuildArray()
{
return new StubAnnotationArrayBuilder<R>(componentType);
}
}

protected class StubAnnotationArrayBuilder<R> extends StubArrayBuilder<R>
{
private final BaseTrainer<?, R> annotationTypeTrainer;

private <N extends Annotation> StubAnnotationArrayBuilder(final Class<? extends R> componentType)
{
super(componentType);
@SuppressWarnings("unchecked")
final Class<N> annotationType = (Class<N>) componentType;
@SuppressWarnings("unchecked")
final BaseTrainer<?, R> annotationTypeTrainer = (BaseTrainer<?, R>) new AnnotationTypeTrainer<N>(
annotationType);
this.annotationTypeTrainer = annotationTypeTrainer;
}

@Override
public StubAnnotationArrayBuilder<R> addElement(BaseTrainer<?, R> trainer)
{
final R trainee = trainingContext().push(trainer.traineeType);

annotationTypeTrainer.train(trainee);
trainer.train(trainee);

elements.add(trainingContext().<R> pop());
return this;
}
}

@Override
public <R> WhenAnnotation<R> when(R expression) {
public <R> WhenAnnotation<R> when(R expression)
{
return new WhenAnnotation<R>();
}

@Override
public <R> WhenAnnotationArray<R> when(R[] expression)
{
@SuppressWarnings("unchecked")
final Class<? extends R> componentType = (Class<? extends R>) expression.getClass().getComponentType();
return new WhenAnnotationArray<R>(componentType);
}
}
@@ -300,9 +300,9 @@ public S thenReturn(Class<?> value)

protected class WhenObjectArray<R> extends BaseWhen<R[]>
{
private final Class<? extends R> componentType;
protected final Class<? extends R> componentType;

private WhenObjectArray(Class<? extends R> componentType)
protected WhenObjectArray(Class<? extends R> componentType)
{
this.componentType = componentType;
}
@@ -321,10 +321,10 @@ public StubArrayBuilder<R> thenBuildArray()

protected class StubArrayBuilder<R>
{
private final Class<? extends R> componentType;
private final List<R> elements = new ArrayList<R>();
protected final List<R> elements = new ArrayList<R>();
protected final Class<? extends R> componentType;

private StubArrayBuilder(Class<? extends R> componentType)
protected StubArrayBuilder(Class<? extends R> componentType)
{
this.componentType = componentType;
}
@@ -102,6 +102,41 @@ public void testMemberMap()
assertEquals(Object.class, customAnnotation.someType());
}

@Test
public void testNestedStubbedAnnotationArray()
{
final NestingAnnotation nestingAnnotation = AnnotationBuilder.of(NestingAnnotation.class)
.train(new AnnotationTrainer<NestingAnnotation>()
{

@Override
protected void train(NestingAnnotation trainee)
{
when(trainee.children()).thenBuildArray().addElement(new AnnotationTrainer<CustomAnnotation>()
{
@Override
protected void train(CustomAnnotation trainee)
{
when(trainee.finiteValues()).thenReturn(FiniteValues.ONE, FiniteValues.THREE);
}
}).addElement(new AnnotationTrainer<CustomAnnotation>()
{
@Override
protected void train(CustomAnnotation trainee)
{
when(trainee.finiteValues()).thenReturn(FiniteValues.TWO);
}
}).build();
}
}).build();

assertNull(nestingAnnotation.child());
assertEquals(2, nestingAnnotation.children().length);
assertArrayEquals(new FiniteValues[] { FiniteValues.ONE, FiniteValues.THREE },
nestingAnnotation.children()[0].finiteValues());
assertArrayEquals(new FiniteValues[] { FiniteValues.TWO }, nestingAnnotation.children()[1].finiteValues());
}

@Test(expected = IllegalArgumentException.class)
public void testBadMemberMap()
{
@@ -114,6 +149,8 @@ public void testBadMemberMap()
CustomAnnotation child();

String somethingElse();

CustomAnnotation[] children() default {};
}

public @interface CustomAnnotation

0 comments on commit 408a446

Please sign in to comment.