Skip to content

Commit

Permalink
Added ability to define custom annotations. Closes #628.
Browse files Browse the repository at this point in the history
  • Loading branch information
aslakhellesoy committed Mar 16, 2014
2 parents 3745fd6 + ae0b2e2 commit 41490a1
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 25 deletions.
1 change: 1 addition & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## [1-1-6-SNAPSHOT (Git master)](https://github.com/cucumber/cucumber-jvm/compare/v1.1.5...master)

* [Java] Added ability to define custom annotations. ([#628](https://github.com/cucumber/cucumber-jvm/pull/628) slowikps)
* [Core] Added support for SVG images in HTML output ([#624](https://github.com/cucumber/cucumber-jvm/pull/624) agattiker)
* [Scala] Transforming Gherkin tables into java.util.List<T> broken in Scala DSL ([#668](https://github.com/cucumber/cucumber-jvm/issues/668), [#669](https://github.com/cucumber/cucumber-jvm/pull/669) chriswhelan)
* [Clojure] Add tagged Before/After hook support ([#676](https://github.com/cucumber/cucumber-jvm/pull/676) Jeremy Anderson)
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/cucumber/api/Delimiter.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
public @interface Delimiter {
String value();
}
2 changes: 1 addition & 1 deletion core/src/main/java/cucumber/api/Format.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
public @interface Format {
String value();
}
11 changes: 7 additions & 4 deletions core/src/main/java/cucumber/api/Transform.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package cucumber.api;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* An annotation to specify how a Step Definition argument is transformed.
*
* @see Transformer
*/
@java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
@java.lang.annotation.Target({ElementType.PARAMETER})
@java.lang.annotation.Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Documented
public @interface Transform {
Class<? extends Transformer> value();
Class<? extends Transformer<?>> value();
}
37 changes: 28 additions & 9 deletions core/src/main/java/cucumber/runtime/ParameterInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class ParameterInfo {
private final String format;
private final String delimiter;
private final boolean transposed;
private final Transformer transformer;
private final Transformer<?> transformer;

public static List<ParameterInfo> fromMethod(Method method) {
List<ParameterInfo> result = new ArrayList<ParameterInfo>();
Expand All @@ -36,32 +36,51 @@ public static List<ParameterInfo> fromMethod(Method method) {
String format = null;
String delimiter = DEFAULT_DELIMITER;
boolean transposed = false;
Transformer transformer = null;
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) {
try {
transformer = ((Transform) annotation).value().newInstance();
} catch (InstantiationException e) {
throw new CucumberException(e);
} catch (IllegalAccessException e) {
throw new CucumberException(e);
}
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<? extends Annotation> requiredAnnotation) {
return getAnnotationForAnnotation(source, requiredAnnotation) != null;
}

private static <T extends Annotation> T getAnnotationForAnnotation(Annotation source, Class<T> 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);
}
Expand Down
55 changes: 45 additions & 10 deletions core/src/test/java/cucumber/runtime/ParameterInfoTest.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
package cucumber.runtime;

import cucumber.api.Delimiter;
import cucumber.api.Format;
import cucumber.api.Transform;
import cucumber.api.Transformer;
import cucumber.runtime.xstream.LocalizedXStreams;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.junit.Test;
import static org.junit.Assert.assertEquals;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static org.junit.Assert.assertEquals;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.junit.Test;

import cucumber.api.Delimiter;
import cucumber.api.Format;
import cucumber.api.Transform;
import cucumber.api.Transformer;
import cucumber.runtime.annotations.CustomDelimiter;
import cucumber.runtime.annotations.SampleDateFormat;
import cucumber.runtime.annotations.TransformToFortyTwo;
import cucumber.runtime.xstream.LocalizedXStreams;

public class ParameterInfoTest {

Expand Down Expand Up @@ -114,4 +121,32 @@ public void converts_list_with_no_type_argument() throws NoSuchMethodException {
ParameterInfo pt = ParameterInfo.fromMethod(getClass().getMethod("listWithNoTypeArgument", List.class)).get(0);
assertEquals(Arrays.asList("hello", "world"), pt.convert("hello, world", US));
}

public void intWithCustomTransformAnnotation(@TransformToFortyTwo int n) {
}

@Test
public void converts_int_with_custom_annotation() throws NoSuchMethodException{
ParameterInfo pt = ParameterInfo.fromMethod(getClass().getMethod("intWithCustomTransformAnnotation", Integer.TYPE)).get(0);
assertEquals(42, pt.convert("hello", US));
}

public void listWithCustomAnnotationDelimiter(@CustomDelimiter List<String> list) {
}

@Test
public void converts_list_with_custom_annotation_delimiter() throws NoSuchMethodException {
ParameterInfo pt = ParameterInfo.fromMethod(getClass().getMethod("listWithCustomAnnotationDelimiter", List.class)).get(0);
assertEquals(Arrays.asList("hello", "world"), pt.convert("hello,!,world", US));
}

public void withDateAndAnnotationFormat(@SampleDateFormat Date date) {
}

@Test
public void converts_with_custom_format_annotation() throws NoSuchMethodException, ParseException {
ParameterInfo parameterInfo = ParameterInfo.fromMethod(getClass().getMethod("withDateAndAnnotationFormat", Date.class)).get(0);
Date sampleDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse("1985-02-12T16:05:12");
assertEquals(sampleDate, parameterInfo.convert("1985-02-12T16:05:12", US));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cucumber.runtime.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import cucumber.api.Delimiter;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
@Documented
@Delimiter(",!,")
public @interface CustomDelimiter {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package cucumber.runtime.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import cucumber.api.Format;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
@Documented
@Format("yyyy-MM-dd'T'HH:mm:ss")
public @interface SampleDateFormat {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cucumber.runtime.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import cucumber.api.Transform;
import cucumber.runtime.ParameterInfoTest.FortyTwoTransformer;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
@Documented
@Transform(FortyTwoTransformer.class)
public @interface TransformToFortyTwo {

}

0 comments on commit 41490a1

Please sign in to comment.