Skip to content

Commit

Permalink
JBEHAVE-900 Honor order in @UsingSteps instances
Browse files Browse the repository at this point in the history
  • Loading branch information
Jonas Olsson authored and Jonas Olsson committed Apr 13, 2013
1 parent 946a651 commit 4ee794d
Show file tree
Hide file tree
Showing 4 changed files with 312 additions and 143 deletions.
Original file line number Diff line number Diff line change
@@ -1,100 +1,127 @@
package org.jbehave.core.configuration;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;

/**
* Helper class to find and retrieve annotated values
*
* @author Cristiano Gavião
* @author Brian Repko
* @author Mauro Talevi
*/
public class AnnotationFinder {

private final Class<?> annotatedClass;

public AnnotationFinder(Class<?> annotatedClass) {
this.annotatedClass = annotatedClass;
}

public <A extends Annotation> boolean isAnnotationPresent(Class<A> annotationClass) {
return getAnnotation(annotationClass) != null;
}

public <A extends Annotation> boolean isAnnotationValuePresent(Class<A> annotationClass, String memberName) {
Annotation annotation = getAnnotation(annotationClass);
return annotation != null && getAnnotationValue(annotation, memberName) != null;
}

@SuppressWarnings("unchecked")
public <T, A extends Annotation> T getAnnotatedValue(Class<A> annotationClass, Class<T> memberType,
String memberName) {
Annotation annotation = getAnnotation(annotationClass);
if (annotation != null) {
return (T) getAnnotationValue(annotation, memberName);
}
throw new AnnotationRequired(annotatedClass, annotationClass);
}

@SuppressWarnings("unchecked")
public <T, A extends Annotation> List<T> getAnnotatedValues(Class<A> annotationClass, Class<T> type,
String memberName) {
Set<T> set = new HashSet<T>();
if (!isAnnotationPresent(annotationClass)) {
return new ArrayList<T>(set);
}
Object[] values = getAnnotatedValue(annotationClass, Object[].class, memberName);
for (Object value : values) {
set.add((T) value);
}
boolean inheritValues = true;
String inheritMemberName = createInheritMemberName(memberName);
if (isAnnotationValuePresent(annotationClass, inheritMemberName)) {
inheritValues = getAnnotatedValue(annotationClass, boolean.class, inheritMemberName);
}
if (inheritValues) {
Class<?> superClass = annotatedClass.getSuperclass();
if (superClass != null && superClass != Object.class) {
set.addAll(new AnnotationFinder(superClass).getAnnotatedValues(annotationClass, type, memberName));
}
}
return new ArrayList<T>(set);
}

/**
* Creates the inherit member name by prefixing "inherit" to the capitalized
* member name.
*
* @param memberName
* @return The inherit member name
*/
protected String createInheritMemberName(String memberName) {
return "inherit" + StringUtils.capitalize(memberName);
}

@SuppressWarnings("unchecked")
public <T, A extends Annotation> List<Class<T>> getAnnotatedClasses(Class<A> annotationClass, Class<T> type,
String memberName) {
return (List<Class<T>>) getAnnotatedValues(annotationClass, type.getClass(), memberName);
}

protected <A extends Annotation> Annotation getAnnotation(Class<A> annotationClass) {
return annotatedClass.getAnnotation(annotationClass);
}

protected Object getAnnotationValue(Annotation annotation, String attributeName) {
try {
Method method = annotation.annotationType().getDeclaredMethod(attributeName, new Class[0]);
return method.invoke(annotation);
} catch (Exception e) {
return null;
}
}
}
package org.jbehave.core.configuration;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

/**
* Helper class to find and retrieve annotated values
*
* @author Cristiano Gavião
* @author Brian Repko
* @author Mauro Talevi
*/
public class AnnotationFinder
{

private final Class<?> annotatedClass;

public AnnotationFinder(Class<?> annotatedClass)
{
this.annotatedClass = annotatedClass;
}

public <A extends Annotation> boolean isAnnotationPresent(
Class<A> annotationClass)
{
return getAnnotation(annotationClass) != null;
}

public <A extends Annotation> boolean isAnnotationValuePresent(
Class<A> annotationClass, String memberName)
{
Annotation annotation = getAnnotation(annotationClass);
return annotation != null
&& getAnnotationValue(annotation, memberName) != null;
}

@SuppressWarnings("unchecked")
public <T, A extends Annotation> T getAnnotatedValue(
Class<A> annotationClass, Class<T> memberType, String memberName)
{
Annotation annotation = getAnnotation(annotationClass);
if (annotation != null)
{
return (T) getAnnotationValue(annotation, memberName);
}
throw new AnnotationRequired(annotatedClass, annotationClass);
}

@SuppressWarnings("unchecked")
public <T, A extends Annotation> List<T> getAnnotatedValues(
Class<A> annotationClass, Class<T> type, String memberName)
{
List<T> list = new LinkedList<T>();
if (!isAnnotationPresent(annotationClass))
{
return list;
}
Object[] values = getAnnotatedValue(annotationClass, Object[].class,
memberName);
for (Object value : values)
{
list.add((T) value);
}
boolean inheritValues = true;
String inheritMemberName = createInheritMemberName(memberName);
if (isAnnotationValuePresent(annotationClass, inheritMemberName))
{
inheritValues = getAnnotatedValue(annotationClass, boolean.class,
inheritMemberName);
}
if (inheritValues)
{
Class<?> superClass = annotatedClass.getSuperclass();
if (superClass != null && superClass != Object.class)
{
list.addAll(new AnnotationFinder(superClass)
.getAnnotatedValues(annotationClass, type, memberName));
}
}
return list;
}

/**
* Creates the inherit member name by prefixing "inherit" to the capitalized
* member name.
*
* @param memberName
* @return The inherit member name
*/
protected String createInheritMemberName(String memberName)
{
return "inherit" + StringUtils.capitalize(memberName);
}

@SuppressWarnings("unchecked")
public <T, A extends Annotation> List<Class<T>> getAnnotatedClasses(
Class<A> annotationClass, Class<T> type, String memberName)
{
return (List<Class<T>>) getAnnotatedValues(annotationClass,
type.getClass(), memberName);
}

protected <A extends Annotation> Annotation getAnnotation(
Class<A> annotationClass)
{
return annotatedClass.getAnnotation(annotationClass);
}

protected Object getAnnotationValue(Annotation annotation,
String attributeName)
{
try
{
Method method = annotation.annotationType().getDeclaredMethod(
attributeName, new Class[0]);
return method.invoke(annotation);
}
catch (Exception e)
{
return null;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,43 +1,54 @@
package org.jbehave.core.steps;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jbehave.core.configuration.Configuration;

import static java.util.Arrays.asList;

/**
* An {@link InjectableStepsFactory} that is provided Object instances.
*/
public class InstanceStepsFactory extends AbstractStepsFactory {

private final Map<Class<?>,Object> stepsInstances = new HashMap<Class<?>, Object>();

public InstanceStepsFactory(Configuration configuration, Object... stepsInstances) {
this(configuration, asList(stepsInstances));
}

public InstanceStepsFactory(Configuration configuration, List<Object> stepsInstances) {
super(configuration);
for (Object instance : stepsInstances) {
this.stepsInstances.put(instance.getClass(), instance);
}
}

@Override
protected List<Class<?>> stepsTypes() {
return new ArrayList<Class<?>>(stepsInstances.keySet());
}

public Object createInstanceOfType(Class<?> type) {
Object instance = stepsInstances.get(type);
if ( instance == null ){
throw new StepsInstanceNotFound(type, this);
}
return instance;
}

}
package org.jbehave.core.steps;

import static java.util.Arrays.asList;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.jbehave.core.configuration.Configuration;

/**
* An {@link InjectableStepsFactory} that is provided Object instances.
*/
public class InstanceStepsFactory extends AbstractStepsFactory
{

private final List<Class<?>> stepsTypes = new LinkedList<Class<?>>();
private final Map<Class<?>, Object> stepsInstances = new HashMap<Class<?>, Object>();

public InstanceStepsFactory(Configuration configuration,
Object... stepsInstances)
{
this(configuration, asList(stepsInstances));
}

public InstanceStepsFactory(Configuration configuration,
List<Object> stepsInstances)
{
super(configuration);
for (Object instance : stepsInstances)
{
this.stepsTypes.add(instance.getClass());
this.stepsInstances.put(instance.getClass(), instance);
}
}

@Override
protected List<Class<?>> stepsTypes()
{
return stepsTypes;
}

public Object createInstanceOfType(Class<?> type)
{
Object instance = stepsInstances.get(type);
if (instance == null)
{
throw new StepsInstanceNotFound(type, this);
}
return instance;
}

}

0 comments on commit 4ee794d

Please sign in to comment.