All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cucumber.runtime.ParameterInfo Maven / Gradle / Ivy

There is a newer version: 1.2.6
Show newest version
package cucumber.runtime;

import cucumber.api.Delimiter;
import cucumber.api.Format;
import cucumber.api.Transform;
import cucumber.api.Transformer;
import cucumber.api.Transpose;
import cucumber.deps.com.thoughtworks.xstream.annotations.XStreamConverter;
import cucumber.deps.com.thoughtworks.xstream.converters.SingleValueConverter;
import cucumber.runtime.xstream.LocalizedXStreams;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * This class composes all interesting parameter information into one object.
 */
public class ParameterInfo {
    public static final String DEFAULT_DELIMITER = ",\\s?";

    private final Type type;
    private final String format;
    private final String delimiter;
    private final boolean transposed;
    private final Transformer transformer;

    public static List fromMethod(Method method) {
        List result = new ArrayList();
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        Annotation[][] annotations = method.getParameterAnnotations();
        for (int i = 0; i < genericParameterTypes.length; i++) {
            String format = null;
            String delimiter = DEFAULT_DELIMITER;
            boolean transposed = false;
            Transformer transformer = null;
            for (Annotation annotation : annotations[i]) {
                if (annotation instanceof Format) {
                    format = ((Format) annotation).value();
                } else if (isAnnotatedWith(annotation, Format.class)) {
                    format = getAnnotationForAnnotation(annotation, Format.class).value();
                }

                if (annotation instanceof Delimiter) {
                    delimiter = ((Delimiter) annotation).value();
                } else if (isAnnotatedWith(annotation, Delimiter.class)) {
                    delimiter = getAnnotationForAnnotation(annotation, Delimiter.class).value();
                }
                if (annotation instanceof Transpose) {
                    transposed = ((Transpose) annotation).value();
                }
                if (annotation instanceof Transform) {
                    transformer = getTransformer(annotation);
                } else if (isAnnotatedWith(annotation, Transform.class)) {
                    transformer = getTransformer(getAnnotationForAnnotation(annotation, Transform.class));
                }
            }
            result.add(new ParameterInfo(genericParameterTypes[i], format, delimiter, transposed, transformer));
        }
        return result;
    }

    private static boolean isAnnotatedWith(Annotation source, Class requiredAnnotation) {
        return getAnnotationForAnnotation(source, requiredAnnotation) != null;
    }

    private static  T getAnnotationForAnnotation(Annotation source, Class requiredAnnotation) {
        return source.annotationType().getAnnotation(requiredAnnotation);
    }

    private static Transformer getTransformer(Annotation annotation) {
        try {
            return ((Transform) annotation).value().newInstance();
        } catch (InstantiationException e) {
            throw new CucumberException(e);
        } catch (IllegalAccessException e) {
            throw new CucumberException(e);
        }
    }

    public ParameterInfo(Type type, String format, String delimiter, Transformer transformer) {
        this(type, format, delimiter, false, transformer);
    }

    public ParameterInfo(Type type, String format, String delimiter, boolean transposed, Transformer transformer) {
        this.type = type;
        this.format = format;
        this.delimiter = delimiter;
        this.transposed = transposed;
        this.transformer = transformer;
    }

    public Class getRawType() {
        return getRawType(type);
    }

    private Class getRawType(Type type) {
        if (type instanceof ParameterizedType) {
            return (Class) ((ParameterizedType) type).getRawType();
        } else {
            return (Class) type;
        }
    }

    public Type getType() {
        return type;
    }

    public boolean isTransposed() {
        return transposed;
    }

    @Override
    public String toString() {
        return type.toString();
    }

    public Object convert(String value, LocalizedXStreams.LocalizedXStream xStream) {
        try {
            xStream.setParameterInfo(this);
            SingleValueConverter converter;
            xStream.processAnnotations(getRawType());
            xStream.autodetectAnnotations(true); // Needed to unlock annotation processing

            if (transformer != null) {
                transformer.setParameterInfoAndLocale(this, xStream.getLocale());
                converter = transformer;
            } else {
                if (List.class.isAssignableFrom(getRawType())) {
                    converter = getListConverter(type, xStream);
                } else {
                    converter = getConverter(getRawType(), xStream);
                }
                if (converter == null) {
                    throw new CucumberException(String.format(
                            "Don't know how to convert \"%s\" into %s.\n" +
                                    "Try writing your own converter:\n" +
                                    "\n" +
                                    "@%s(%sConverter.class)\n" +
                                    "public class %s {}\n",
                            value,
                            getRawType().getName(),
                            XStreamConverter.class.getName(),
                            getRawType().getSimpleName(),
                            getRawType().getSimpleName()
                    ));
                }
            }
            return converter.fromString(value);
        } finally {
            xStream.unsetParameterInfo();
        }
    }

    private SingleValueConverter getListConverter(Type type, LocalizedXStreams.LocalizedXStream xStream) {
        Class elementType = type instanceof ParameterizedType
                ? getRawType(((ParameterizedType) type).getActualTypeArguments()[0])
                : Object.class;

        SingleValueConverter elementConverter = getConverter(elementType, xStream);
        if (elementConverter == null) {
            return null;
        } else {
            return xStream.createListConverter(delimiter, elementConverter);
        }
    }

    private SingleValueConverter getConverter(Class type, LocalizedXStreams.LocalizedXStream xStream) {
        if (type.isEnum()) {
            return xStream.createEnumConverter((Class) type);
        } else {
            return xStream.getSingleValueConverter(type);
        }
    }

    public String getFormat() {
        return format;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy