diff --git a/clojure/pom.xml b/clojure/pom.xml
old mode 100755
new mode 100644
index 23a1318608..2108e5048e
--- a/clojure/pom.xml
+++ b/clojure/pom.xml
@@ -12,7 +12,6 @@
clojure
- 0.4.3-SNAPSHOT
jar
Cucumber: Clojure
diff --git a/core/pom.xml b/core/pom.xml
old mode 100755
new mode 100644
index b10c0739b8..d2a6ebbdf0
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -12,7 +12,6 @@
core
- 0.4.3-SNAPSHOT
jar
Cucumber: Core
diff --git a/core/src/main/java/cucumber/runtime/CucumberException.java b/core/src/main/java/cucumber/runtime/CucumberException.java
index 669a619767..beaf2fdc0c 100644
--- a/core/src/main/java/cucumber/runtime/CucumberException.java
+++ b/core/src/main/java/cucumber/runtime/CucumberException.java
@@ -1,7 +1,12 @@
package cucumber.runtime;
public class CucumberException extends RuntimeException {
- public CucumberException(String message) {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1393513206771603671L;
+
+ public CucumberException(String message) {
super(message);
}
diff --git a/core/src/main/java/cucumber/runtime/Runtime.java b/core/src/main/java/cucumber/runtime/Runtime.java
index 7459368030..89f4133c55 100644
--- a/core/src/main/java/cucumber/runtime/Runtime.java
+++ b/core/src/main/java/cucumber/runtime/Runtime.java
@@ -1,9 +1,7 @@
package cucumber.runtime;
-import cucumber.classpath.Classpath;
-import gherkin.GherkinParser;
+import static java.util.Arrays.asList;
import gherkin.formatter.Argument;
-import gherkin.formatter.model.Feature;
import gherkin.formatter.model.Step;
import java.util.ArrayList;
@@ -11,11 +9,13 @@
import java.util.Comparator;
import java.util.List;
-import static java.util.Arrays.asList;
+import cucumber.classpath.Classpath;
+import cucumber.runtime.transformers.Transformer;
public class Runtime {
private final List backends;
private final List undefinedSteps = new ArrayList();
+ private Transformer transformer;
public Runtime(Backend... backends) {
this.backends = asList(backends);
@@ -45,7 +45,7 @@ private List stepDefinitionMatches(Step step) {
for (StepDefinition stepDefinition : backend.getStepDefinitions()) {
List arguments = stepDefinition.matchedArguments(step);
if (arguments != null) {
- result.add(new StepDefinitionMatch(arguments, stepDefinition, step));
+ result.add(new StepDefinitionMatch(arguments, stepDefinition, step, getTransformer()));
}
}
}
@@ -84,4 +84,15 @@ public int compare(Step a, Step b) {
public World newWorld() {
return new World(backends, this);
}
+
+ public Transformer getTransformer() {
+ if (this.transformer == null) {
+ this.transformer = new Transformer();
+ }
+ return this.transformer;
+ }
+
+ public void setTransformer(Transformer transformer) {
+ this.transformer = transformer;
+ }
}
diff --git a/core/src/main/java/cucumber/runtime/StepDefinitionMatch.java b/core/src/main/java/cucumber/runtime/StepDefinitionMatch.java
index b412bbf0c0..4c5649b8ef 100644
--- a/core/src/main/java/cucumber/runtime/StepDefinitionMatch.java
+++ b/core/src/main/java/cucumber/runtime/StepDefinitionMatch.java
@@ -6,17 +6,22 @@
import java.lang.reflect.InvocationTargetException;
import java.util.List;
+import java.util.Locale;
+
+import cucumber.runtime.transformers.Transformer;
import static java.util.Arrays.asList;
public class StepDefinitionMatch extends Match {
private final StepDefinition stepDefinition;
private final Step step;
+ private Transformer transformer;
- public StepDefinitionMatch(List arguments, StepDefinition stepDefinition, Step step) {
+ public StepDefinitionMatch(List arguments, StepDefinition stepDefinition, Step step, Transformer transformer) {
super(arguments, stepDefinition.getLocation());
this.stepDefinition = stepDefinition;
this.step = step;
+ this.transformer = transformer;
}
public void run(String path) throws Throwable {
@@ -39,13 +44,15 @@ private Object[] getTransformedArgs(Class>[] parameterTypes) {
Object[] result = new Object[getArguments().size()];
int n = 0;
for (Argument a : getArguments()) {
- // TODO: Use the Locale for transformation
- // TODO: Also use method signature to transform ints...
- result[n++] = a.getVal();
+ result[n] = this.transformer.transform(a, parameterTypes[n++], getLocale());
}
return result;
}
+ private Locale getLocale() {
+ return this.stepDefinition.getLocale();
+ }
+
private Throwable filterStacktrace(Throwable error, StackTraceElement stepLocation) {
StackTraceElement[] stackTraceElements = error.getStackTrace();
if (error.getCause() != null && error.getCause() != error) {
diff --git a/core/src/main/java/cucumber/runtime/World.java b/core/src/main/java/cucumber/runtime/World.java
index 268d23ef4e..97ab471608 100644
--- a/core/src/main/java/cucumber/runtime/World.java
+++ b/core/src/main/java/cucumber/runtime/World.java
@@ -40,7 +40,7 @@ public void runStep(Step step, String path, Reporter reporter) {
} finally {
long duration = System.nanoTime() - start;
String status = e == null ? Result.PASSED : Result.FAILED;
- Result result = new Result(status, duration, e);
+ Result result = new Result(status, duration, e, null);
reporter.result(result);
}
} else {
diff --git a/core/src/main/java/cucumber/runtime/transformers/BigDecimalTransformable.java b/core/src/main/java/cucumber/runtime/transformers/BigDecimalTransformable.java
new file mode 100644
index 0000000000..ded02d6f37
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/BigDecimalTransformable.java
@@ -0,0 +1,14 @@
+package cucumber.runtime.transformers;
+
+import java.math.BigDecimal;
+
+public class BigDecimalTransformable extends
+ TransformableWithNumberFormat {
+
+ @Override
+ protected BigDecimal doTransform(Number number) {
+ // See http://java.sun.com/j2se/6/docs/api/java/math/BigDecimal.html#BigDecimal%28double%29
+ return new BigDecimal(Double.toString(number.doubleValue()));
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/BigIntegerTransformable.java b/core/src/main/java/cucumber/runtime/transformers/BigIntegerTransformable.java
new file mode 100644
index 0000000000..b34660bb63
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/BigIntegerTransformable.java
@@ -0,0 +1,12 @@
+package cucumber.runtime.transformers;
+
+import java.math.BigInteger;
+
+public class BigIntegerTransformable extends TransformableWithNumberFormat {
+
+ @Override
+ protected BigInteger doTransform(Number argument) {
+ return BigInteger.valueOf(argument.longValue());
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/BooleanTransformable.java b/core/src/main/java/cucumber/runtime/transformers/BooleanTransformable.java
new file mode 100644
index 0000000000..2b16029270
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/BooleanTransformable.java
@@ -0,0 +1,15 @@
+package cucumber.runtime.transformers;
+
+import java.util.Locale;
+
+public class BooleanTransformable implements Transformable {
+
+ public Boolean transform(String argument, Locale locale) {
+ if ("false".equalsIgnoreCase(argument) || "true".equalsIgnoreCase(argument)) {
+ return Boolean.parseBoolean(argument);
+ } else {
+ throw new TransformationException(String.format(locale, "Could not convert %s to Boolean", argument));
+ }
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/ByteTransformable.java b/core/src/main/java/cucumber/runtime/transformers/ByteTransformable.java
new file mode 100644
index 0000000000..c8294d4eda
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/ByteTransformable.java
@@ -0,0 +1,10 @@
+package cucumber.runtime.transformers;
+
+public class ByteTransformable extends TransformableWithNumberFormat {
+
+ @Override
+ protected Byte doTransform(Number value) {
+ return Byte.valueOf(value.byteValue());
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/CharacterTransformable.java b/core/src/main/java/cucumber/runtime/transformers/CharacterTransformable.java
new file mode 100644
index 0000000000..11529bd227
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/CharacterTransformable.java
@@ -0,0 +1,14 @@
+package cucumber.runtime.transformers;
+
+import java.util.Locale;
+
+public class CharacterTransformable implements Transformable {
+
+ public Character transform(String argument, Locale locale) {
+ if (argument.length() < 1) {
+ return null;
+ }
+ return Character.valueOf(argument.charAt(0));
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/DateTransformable.java b/core/src/main/java/cucumber/runtime/transformers/DateTransformable.java
new file mode 100644
index 0000000000..30d59080b4
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/DateTransformable.java
@@ -0,0 +1,17 @@
+package cucumber.runtime.transformers;
+
+import java.text.DateFormat;
+import java.text.Format;
+import java.util.Date;
+import java.util.Locale;
+
+public class DateTransformable extends TransformableWithFormat {
+
+ public Format getFormat(Locale locale) {
+ DateFormat format = DateFormat
+ .getDateInstance(DateFormat.SHORT, locale);
+ format.setLenient(false);
+ return format;
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/DoubleTransformable.java b/core/src/main/java/cucumber/runtime/transformers/DoubleTransformable.java
new file mode 100644
index 0000000000..03c2ab7a9f
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/DoubleTransformable.java
@@ -0,0 +1,10 @@
+package cucumber.runtime.transformers;
+
+public class DoubleTransformable extends TransformableWithNumberFormat {
+
+ @Override
+ protected Double doTransform(Number transform) {
+ return Double.valueOf(transform.doubleValue());
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/FloatTransformable.java b/core/src/main/java/cucumber/runtime/transformers/FloatTransformable.java
new file mode 100644
index 0000000000..0668b38764
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/FloatTransformable.java
@@ -0,0 +1,10 @@
+package cucumber.runtime.transformers;
+
+public class FloatTransformable extends TransformableWithNumberFormat {
+
+ @Override
+ protected Float doTransform(Number argument) {
+ return Float.valueOf(argument.floatValue());
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/IntegerTransformable.java b/core/src/main/java/cucumber/runtime/transformers/IntegerTransformable.java
new file mode 100644
index 0000000000..97a4aa861d
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/IntegerTransformable.java
@@ -0,0 +1,10 @@
+package cucumber.runtime.transformers;
+
+public class IntegerTransformable extends TransformableWithNumberFormat {
+
+ @Override
+ protected Integer doTransform(Number number) {
+ return Integer.valueOf(number.intValue());
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/LongTransformable.java b/core/src/main/java/cucumber/runtime/transformers/LongTransformable.java
new file mode 100644
index 0000000000..229f1d1763
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/LongTransformable.java
@@ -0,0 +1,10 @@
+package cucumber.runtime.transformers;
+
+public class LongTransformable extends TransformableWithNumberFormat {
+
+ @Override
+ protected Long doTransform(Number argument) {
+ return Long.valueOf(argument.longValue());
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/ShortTransformable.java b/core/src/main/java/cucumber/runtime/transformers/ShortTransformable.java
new file mode 100644
index 0000000000..64464f9d54
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/ShortTransformable.java
@@ -0,0 +1,10 @@
+package cucumber.runtime.transformers;
+
+public class ShortTransformable extends TransformableWithNumberFormat {
+
+ @Override
+ protected Short doTransform(Number argument) {
+ return Short.valueOf(argument.shortValue());
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/StringTransformable.java b/core/src/main/java/cucumber/runtime/transformers/StringTransformable.java
new file mode 100644
index 0000000000..88fe93d3f3
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/StringTransformable.java
@@ -0,0 +1,11 @@
+package cucumber.runtime.transformers;
+
+import java.util.Locale;
+
+public class StringTransformable implements Transformable {
+
+ public String transform(String argument, Locale locale) {
+ return argument;
+ }
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/Transformable.java b/core/src/main/java/cucumber/runtime/transformers/Transformable.java
new file mode 100644
index 0000000000..6ed96e493d
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/Transformable.java
@@ -0,0 +1,7 @@
+package cucumber.runtime.transformers;
+
+import java.util.Locale;
+
+public interface Transformable {
+ public T transform(String argument, Locale locale);
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/TransformableWithFormat.java b/core/src/main/java/cucumber/runtime/transformers/TransformableWithFormat.java
new file mode 100644
index 0000000000..8b3b171f22
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/TransformableWithFormat.java
@@ -0,0 +1,45 @@
+package cucumber.runtime.transformers;
+
+import java.text.Format;
+import java.text.ParsePosition;
+import java.util.Locale;
+
+public abstract class TransformableWithFormat implements Transformable {
+
+ public T transform(String argument, Locale locale) {
+ return transform(getFormat(locale), argument, locale);
+ }
+
+ /**
+ *
+ * @param locale
+ * The locale used to parse
+ * @return A Format to parse the argument
+ */
+ public abstract Format getFormat(Locale locale);
+
+ /**
+ * Parses a value using one of the java.util.text format classes.
+ *
+ * @param format
+ * The format to use
+ * @param argument
+ * The object to parse
+ * @param locale
+ * The locale used to parse
+ * @return The object
+ * @throws TransformationException
+ * Thrown if parsing fails
+ */
+ @SuppressWarnings("unchecked")
+ protected T transform(final Format format, final String argument,
+ Locale locale) {
+ ParsePosition position = new ParsePosition(0);
+ Object result = format.parseObject(argument, position);
+ if (position.getErrorIndex() != -1) {
+ throw new TransformationException("Can't parse '" + argument
+ + "' using format " + format);
+ }
+ return (T) result;
+ }
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/TransformableWithNumberFormat.java b/core/src/main/java/cucumber/runtime/transformers/TransformableWithNumberFormat.java
new file mode 100644
index 0000000000..1ccf9f51a8
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/TransformableWithNumberFormat.java
@@ -0,0 +1,22 @@
+package cucumber.runtime.transformers;
+
+import java.text.Format;
+import java.text.NumberFormat;
+import java.util.Locale;
+
+public abstract class TransformableWithNumberFormat extends
+ TransformableWithFormat {
+
+ @Override
+ public T transform(String argument, Locale locale) {
+ return doTransform(super.transform(argument, locale));
+ }
+
+ @Override
+ public Format getFormat(Locale locale) {
+ return NumberFormat.getNumberInstance(locale);
+ }
+
+ protected abstract T doTransform(Number argument);
+
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/TransformationException.java b/core/src/main/java/cucumber/runtime/transformers/TransformationException.java
new file mode 100644
index 0000000000..8c61fdd182
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/TransformationException.java
@@ -0,0 +1,21 @@
+package cucumber.runtime.transformers;
+
+public class TransformationException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3893851462286949513L;
+
+ public TransformationException(Throwable t) {
+ super(t);
+ }
+
+ public TransformationException(String message, Throwable t) {
+ super (message, t);
+ }
+
+ public TransformationException(String message) {
+ super (message);
+ }
+}
diff --git a/core/src/main/java/cucumber/runtime/transformers/Transformer.java b/core/src/main/java/cucumber/runtime/transformers/Transformer.java
new file mode 100644
index 0000000000..7e26370439
--- /dev/null
+++ b/core/src/main/java/cucumber/runtime/transformers/Transformer.java
@@ -0,0 +1,78 @@
+package cucumber.runtime.transformers;
+
+import gherkin.formatter.Argument;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+/**
+ *
+ * Class for transforming argument to a certain type using a Locale
+ *
+ */
+public class Transformer {
+ private Map, Transformable>> transformables;
+
+ @SuppressWarnings("unchecked")
+ public T transform(Argument argument, Class> clazz, Locale locale) {
+ Transformable> transformable = getTransformable(clazz);
+ if (transformable == null) {
+ throw new TransformationException("Can't transform " + argument.getVal() + " to: " + clazz.getName() + ". No transformable found.");
+ }
+ return (T) transformable.transform(argument.getVal(), locale);
+ }
+
+ private Transformable> getTransformable(Class> clazz) {
+ return getTransformables().get(clazz);
+ }
+
+ public Map, Transformable>> getTransformables() {
+ if (this.transformables == null) {
+ this.transformables = registerDefaultTransformables();
+ }
+ return this.transformables;
+ }
+
+ protected Map, Transformable>> registerDefaultTransformables() {
+ HashMap, Transformable>> hashMap = new HashMap, Transformable>>();
+ hashMap.put(String.class, new StringTransformable());
+ hashMap.put(Date.class, new DateTransformable());
+ hashMap.put(BigDecimal.class, new BigDecimalTransformable());
+ hashMap.put(BigIntegerTransformable.class, new BigIntegerTransformable());
+ BooleanTransformable booleanTransformable = new BooleanTransformable();
+ hashMap.put(Boolean.TYPE, booleanTransformable);
+ hashMap.put(Boolean.class, booleanTransformable);
+ ByteTransformable byteTransformable = new ByteTransformable();
+ hashMap.put(Byte.TYPE, byteTransformable);
+ hashMap.put(Byte.class, byteTransformable);
+ CharacterTransformable characterTransformable = new CharacterTransformable();
+ hashMap.put(Character.TYPE, characterTransformable);
+ hashMap.put(Character.class, characterTransformable);
+ DoubleTransformable doubleTransformable = new DoubleTransformable();
+ hashMap.put(Double.TYPE, doubleTransformable);
+ hashMap.put(Double.class, doubleTransformable);
+ FloatTransformable floatTransformable = new FloatTransformable();
+ hashMap.put(Float.TYPE, floatTransformable);
+ hashMap.put(Float.class, floatTransformable);
+ IntegerTransformable integerTransformable = new IntegerTransformable();
+ hashMap.put(Integer.TYPE, integerTransformable);
+ hashMap.put(Integer.class, integerTransformable);
+ LongTransformable longTransformable = new LongTransformable();
+ hashMap.put(Long.TYPE, longTransformable);
+ hashMap.put(Long.class, longTransformable);
+ ShortTransformable shortTransformable = new ShortTransformable();
+ hashMap.put(Short.TYPE, shortTransformable);
+ hashMap.put(Short.class, shortTransformable);
+ return hashMap;
+ }
+
+ public void addTransformable(Class> clazz, Transformable> transformable) {
+ getTransformables().put(clazz, transformable);
+ }
+
+ public void setTransformables(Map, Transformable>> transformables) {
+ this.transformables = transformables;
+ }
+}
diff --git a/core/src/main/java/cuke4duke/internal/Utils.java b/core/src/main/java/cuke4duke/internal/Utils.java
index bee2aa56b2..31b9d7bb3d 100644
--- a/core/src/main/java/cuke4duke/internal/Utils.java
+++ b/core/src/main/java/cuke4duke/internal/Utils.java
@@ -20,4 +20,15 @@ public static Locale localeFor(String isoString) {
return new Locale(languageAndCountry[0], languageAndCountry[1]);
}
}
+
+ public static String join(Object[] objects, String separator) {
+ StringBuilder sb = new StringBuilder();
+ int i = 0;
+ for (Object o : objects) {
+ if (i != 0) sb.append(separator);
+ sb.append(o);
+ i++;
+ }
+ return sb.toString();
+ }
}
diff --git a/core/src/main/java/cuke4duke/internal/jvmclass/DefaultJvmTransforms.java b/core/src/main/java/cuke4duke/internal/jvmclass/DefaultJvmTransforms.java
deleted file mode 100644
index 002081a6f1..0000000000
--- a/core/src/main/java/cuke4duke/internal/jvmclass/DefaultJvmTransforms.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package cuke4duke.internal.jvmclass;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.text.NumberFormat;
-import java.text.ParseException;
-import java.util.Locale;
-
-public class DefaultJvmTransforms {
- public static Object transformStringToObject(String argument, Locale locale) {
- return argument;
- }
-
- public static int transformStringToInt(String argument, Locale locale) throws ParseException {
- return NumberFormat.getInstance(locale).parse(argument).intValue();
- }
-
- public static Integer transformStringToInteger(String argument, Locale locale) throws ParseException {
- return transformStringToInt(argument, locale);
- }
-
- public static long transformStringToLongPrimitive(String argument, Locale locale) throws ParseException {
- return NumberFormat.getInstance(locale).parse(argument).longValue();
- }
-
- public static Long transformStringToLong(String argument, Locale locale) throws ParseException {
- return transformStringToLongPrimitive(argument, locale);
- }
-
- public static double transformStringToDoublePrimitive(String argument, Locale locale) throws ParseException {
- return NumberFormat.getInstance(locale).parse(argument).doubleValue();
- }
-
- public static Double transformStringToDouble(String argument, Locale locale) throws ParseException {
- return transformStringToDoublePrimitive(argument, locale);
- }
-
- public static float transformStringToFloatPrimitive(String argument, Locale locale) throws ParseException {
- return NumberFormat.getInstance(locale).parse(argument).floatValue();
- }
-
- public static Float transformStringToFloat(String argument, Locale locale) throws ParseException {
- return transformStringToFloatPrimitive(argument, locale);
- }
-
- public static short transformStringToShortPrimitive(String argument, Locale locale) throws ParseException {
- return NumberFormat.getInstance(locale).parse(argument).shortValue();
- }
-
- public static Short transformStringToShort(String argument, Locale locale) throws ParseException {
- return transformStringToShortPrimitive(argument, locale);
- }
-
- public static byte transformStringToBytePrimitive(String argument, Locale locale) throws ParseException {
- return NumberFormat.getInstance(locale).parse(argument).byteValue();
- }
-
- public static Byte transformStringToByte(String argument, Locale locale) throws ParseException {
- return transformStringToBytePrimitive(argument, locale);
- }
-
- public static char transformStringToChar(String argument, Locale locale) {
- return argument.charAt(0);
- }
-
- public static Character transformStringToCharacters(String argument, Locale locale) {
- return argument.charAt(0);
- }
-
- public static BigDecimal transformStringToBigDecimal(String argument, Locale locale) throws ParseException {
- return BigDecimal.valueOf(transformStringToDoublePrimitive(argument, locale));
- }
-
- public static BigInteger transformStringToBigInteger(String argument, Locale locale) throws ParseException {
- return BigInteger.valueOf(transformStringToLongPrimitive(argument, locale));
- }
-
- public static boolean transformStringToBooleanPrimitive(String argument, Locale locale) {
- return Boolean.valueOf(argument);
- }
-
- public static Boolean transformStringToBoolean(String argument, Locale locale) {
- return Boolean.valueOf(argument);
- }
-}
diff --git a/core/src/test/java/cucumber/runtime/StepDefinitionMatchTest.java b/core/src/test/java/cucumber/runtime/StepDefinitionMatchTest.java
new file mode 100644
index 0000000000..57571f254a
--- /dev/null
+++ b/core/src/test/java/cucumber/runtime/StepDefinitionMatchTest.java
@@ -0,0 +1,29 @@
+package cucumber.runtime;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import gherkin.formatter.Argument;
+import gherkin.formatter.model.Step;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+import org.junit.Test;
+
+import cucumber.runtime.transformers.Transformer;
+public class StepDefinitionMatchTest {
+ @Test
+ public void shouldConvertParameters() throws Throwable {
+ List arguments = Arrays.asList(new Argument(0, "5"));
+ StepDefinition stepDefinition = mock(StepDefinition.class);
+ when(stepDefinition.getLocale()).thenReturn(Locale.ENGLISH);
+ Class>[] parameterTypes = {Integer.TYPE};
+ when(stepDefinition.getParameterTypes()).thenReturn(parameterTypes );
+ StepDefinitionMatch stepDefinitionMatch = new StepDefinitionMatch(arguments, stepDefinition, mock(Step.class), new Transformer());
+ stepDefinitionMatch.run("step-definition-match-test");
+ Object[] args = {5};
+ verify(stepDefinition).execute(args);
+ }
+}
diff --git a/core/src/test/java/cucumber/runtime/transformers/StandardTransformersTest.java b/core/src/test/java/cucumber/runtime/transformers/StandardTransformersTest.java
new file mode 100644
index 0000000000..d2a0b94bc7
--- /dev/null
+++ b/core/src/test/java/cucumber/runtime/transformers/StandardTransformersTest.java
@@ -0,0 +1,133 @@
+package cucumber.runtime.transformers;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import cuke4duke.internal.Utils;
+
+public class StandardTransformersTest {
+ @Test
+ public void shouldTransformBoolean() {
+ Boolean transformFalse = new BooleanTransformable().transform("false", Locale.ENGLISH);
+ Boolean transformTrue = new BooleanTransformable().transform("true", Locale.ENGLISH);
+ Assert.assertFalse(transformFalse);
+ Assert.assertTrue(transformTrue);
+ }
+
+ @Test(expected = TransformationException.class)
+ public void shouldThrowTransformationExceptionWhenConvertingBoolean() {
+ new BooleanTransformable().transform("vrai", Locale.ENGLISH);
+ }
+
+ @Test
+ public void shouldTransformBigDecimal() {
+ BigDecimal englishBigDecimal = new BigDecimalTransformable().transform("300.15",
+ Locale.ENGLISH);
+ BigDecimal englishBigDecimal2 = new BigDecimalTransformable().transform("30000000.15",
+ Locale.ENGLISH);
+ BigDecimal englishInteger = new BigDecimalTransformable().transform("300", Locale.ENGLISH);
+ BigDecimal frenchBigDecimal = new BigDecimalTransformable().transform("300,15",
+ Locale.FRENCH);
+ Assert.assertEquals(new BigDecimal("300.15"), englishBigDecimal);
+ Assert.assertEquals(new BigDecimal("30000000.15"), englishBigDecimal2);
+ Assert.assertEquals(new BigDecimal("300.15"), frenchBigDecimal);
+ Assert.assertEquals(new BigDecimal("300.0"), englishInteger);
+ }
+
+ @Test
+ public void shouldTransformDate() {
+ Assert.assertEquals(getDateToTest(),
+ new DateTransformable().transform("11/29/2011", Locale.ENGLISH));
+ Assert.assertEquals(getDateToTest(),
+ new DateTransformable().transform("29/11/2011", Locale.FRENCH));
+ }
+
+ @Test(expected = TransformationException.class)
+ public void shouldThrowTransformationExceptionWhenConvertingInvalidDate() {
+ Assert.assertEquals(getDateToTest(),
+ new DateTransformable().transform("29/11/2011", Locale.ENGLISH));
+ }
+
+ private Date getDateToTest() {
+ Calendar calendar = Calendar.getInstance();
+ calendar.set(2011, 10, 29, 0, 0, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ return calendar.getTime();
+ }
+
+ @Test
+ public void shouldTransformIntegers() {
+ Integer expected = Integer.valueOf(1000);
+ Assert.assertEquals(expected, new IntegerTransformable().transform("1000", Locale.ENGLISH));
+ Assert.assertEquals(expected, new IntegerTransformable().transform("1,000", Locale.ENGLISH));
+ Assert.assertEquals(expected,
+ new IntegerTransformable().transform("1.000", Utils.localeFor("pt")));
+ }
+
+ @Test
+ public void shouldTransformDoubles() {
+ Double expected = Double.valueOf(3000.15);
+ Assert.assertEquals(expected,
+ new DoubleTransformable().transform("3000.15", Locale.ENGLISH));
+ Assert.assertEquals(expected,
+ new DoubleTransformable().transform("3,000.15", Locale.ENGLISH));
+ Assert.assertEquals(expected,
+ new DoubleTransformable().transform("3.000,15", Utils.localeFor("pt")));
+ Assert.assertEquals(expected,
+ new DoubleTransformable().transform("3000,15", Locale.FRENCH));
+ }
+
+ @Test
+ public void shouldTransformLongs() {
+ Long expected = Long.valueOf(8589934592L);
+ Assert.assertEquals(expected, new LongTransformable().transform("8589934592", Locale.ENGLISH));
+ Assert.assertEquals(expected, new LongTransformable().transform("8,589,934,592", Locale.ENGLISH));
+ }
+
+ @Test
+ public void shouldTransformShorts() {
+ short exp = 32767;
+ short exp2 = -32768;
+ Short expected = Short.valueOf(exp);
+ Short expected2 = Short.valueOf(exp2);
+ Assert.assertEquals(expected, new ShortTransformable().transform("32767", Locale.ENGLISH));
+ Assert.assertEquals(expected, new ShortTransformable().transform("32,767", Locale.ENGLISH));
+ Assert.assertEquals(expected2, new ShortTransformable().transform("-32,768", Locale.ENGLISH));
+ }
+
+ @Test
+ public void shouldTransformBytes() {
+ byte exp = 127;
+ Byte expected = Byte.valueOf(exp);
+ Assert.assertEquals(expected, new ByteTransformable().transform("127", Locale.ENGLISH));
+ Assert.assertEquals(expected, new ByteTransformable().transform("127", Locale.ENGLISH));
+ }
+
+ @Test
+ public void shouldTransformChars() {
+ Character expected = Character.valueOf('C');
+ Assert.assertEquals(expected, new CharacterTransformable().transform("Cedric", Locale.ENGLISH));
+ Assert.assertEquals(expected, new CharacterTransformable().transform("C", Locale.ENGLISH));
+ }
+
+ @Test
+ public void shouldTransformFloats() {
+ Float expected = Float.valueOf(3000.15f);
+ Assert.assertEquals(expected, new FloatTransformable().transform("3000.15", Locale.ENGLISH));
+ Assert.assertEquals(expected, new FloatTransformable().transform("3,000.15", Locale.ENGLISH));
+ }
+
+ @Test
+ public void shouldTransformBigInteger() {
+ BigInteger expected = BigInteger.valueOf(8589934592L);
+ Assert.assertEquals(expected, new BigIntegerTransformable().transform("8589934592", Locale.ENGLISH));
+ Assert.assertEquals(expected, new BigIntegerTransformable().transform("8,589,934,592", Locale.ENGLISH));
+ }
+
+}
diff --git a/core/src/test/java/cucumber/runtime/transformers/TransformerTest.java b/core/src/test/java/cucumber/runtime/transformers/TransformerTest.java
new file mode 100644
index 0000000000..890d499c16
--- /dev/null
+++ b/core/src/test/java/cucumber/runtime/transformers/TransformerTest.java
@@ -0,0 +1,25 @@
+package cucumber.runtime.transformers;
+
+import gherkin.formatter.Argument;
+
+import java.math.BigDecimal;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TransformerTest {
+ @Test
+ public void shouldTransformToTheRightType() {
+ Argument argument = new Argument(0, "true");
+ Transformer transformer = new Transformer();
+ Locale english = Locale.ENGLISH;
+ Boolean transformBool = transformer.transform(argument, Boolean.class, english);
+ Assert.assertTrue(transformBool);
+ boolean transformBoolPrimitive = transformer.transform(argument, Boolean.TYPE, english);
+ Assert.assertTrue("Boolean primitive transformation", transformBoolPrimitive);
+ Assert.assertEquals("Float class transformation", Float.valueOf(3000.15f), transformer.transform(new Argument(0, "3000.15"), Float.class, english));
+ Assert.assertEquals("Float primitive transformation", Float.valueOf(3000.15f), transformer.transform(new Argument(0, "3000.15"), Float.TYPE, english));
+ Assert.assertEquals("BigDecimal transformation", new BigDecimal("3000.15"), transformer.transform(new Argument(0, "3000.15"), BigDecimal.class, english));
+ }
+}
diff --git a/cucumber-ant/pom.xml b/cucumber-ant/pom.xml
index 5f8cfd7a00..6a3f9a8932 100644
--- a/cucumber-ant/pom.xml
+++ b/cucumber-ant/pom.xml
@@ -12,7 +12,6 @@
cucumber-ant
- 0.4.3-SNAPSHOT
jar
Cucumber: Ant
diff --git a/groovy/pom.xml b/groovy/pom.xml
old mode 100755
new mode 100644
index 523f0e1413..d7432aa10f
--- a/groovy/pom.xml
+++ b/groovy/pom.xml
@@ -12,7 +12,6 @@
groovy
- 0.4.3-SNAPSHOT
jar
Cucumber: Groovy
diff --git a/guice/pom.xml b/guice/pom.xml
old mode 100755
new mode 100644
index 75d2ea95d6..5d11b7f7a5
--- a/guice/pom.xml
+++ b/guice/pom.xml
@@ -12,7 +12,6 @@
guice
- 0.4.3-SNAPSHOT
jar
Cucumber: Guice
diff --git a/ioke/pom.xml b/ioke/pom.xml
old mode 100755
new mode 100644
index 6fff81e07b..8a94b643b6
--- a/ioke/pom.xml
+++ b/ioke/pom.xml
@@ -12,7 +12,6 @@
ioke
- 0.4.3-SNAPSHOT
jar
Cucumber: Ioke
diff --git a/java/pom.xml b/java/pom.xml
old mode 100755
new mode 100644
index 8a398e917b..1e25af7eaa
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -12,7 +12,6 @@
java
- 0.4.3-SNAPSHOT
jar
Cucumber: Java
@@ -26,5 +25,11 @@
junit
test
+
+ org.mockito
+ mockito-all
+ test
+ true
+
diff --git a/java/src/main/java/cucumber/runtime/java/ClasspathMethodScanner.java b/java/src/main/java/cucumber/runtime/java/ClasspathMethodScanner.java
index bd90ff58a6..426a8f5d7e 100644
--- a/java/src/main/java/cucumber/runtime/java/ClasspathMethodScanner.java
+++ b/java/src/main/java/cucumber/runtime/java/ClasspathMethodScanner.java
@@ -49,7 +49,7 @@ private void scan(Method method, Collection> cucumbe
if (isHookAnnotation(annotation)) {
// TODO Add hook
}
-
+ //TODO: scan cucumber.annotation.Transform annotations
Locale locale = Utils.localeFor(annotation.annotationType().getAnnotation(CucumberAnnotation.class).value());
try {
Method regexpMethod = annotation.getClass().getMethod("value");
diff --git a/java/src/main/java/cucumber/runtime/java/JavaBackend.java b/java/src/main/java/cucumber/runtime/java/JavaBackend.java
index 71cab99ec5..a906704ff4 100644
--- a/java/src/main/java/cucumber/runtime/java/JavaBackend.java
+++ b/java/src/main/java/cucumber/runtime/java/JavaBackend.java
@@ -1,10 +1,14 @@
package cucumber.runtime.java;
+import cucumber.annotation.Pending;
import cucumber.classpath.Classpath;
import cucumber.runtime.Backend;
+import cucumber.runtime.CucumberException;
import cucumber.runtime.StepDefinition;
+import cuke4duke.internal.Utils;
import gherkin.formatter.model.Step;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
@@ -19,6 +23,11 @@ public JavaBackend(String packagePrefix) {
this.objectFactory = Classpath.instantiateSubclass(ObjectFactory.class);
new ClasspathMethodScanner().scan(this, packagePrefix);
}
+
+ public JavaBackend(ObjectFactory objectFactory, List stepDefinitions) {
+ this.objectFactory = objectFactory;
+ this.stepDefinitions = stepDefinitions;
+ }
public List getStepDefinitions() {
return stepDefinitions;
@@ -41,4 +50,22 @@ void addStepDefinition(Pattern pattern, Method method, Locale locale) {
objectFactory.addClass(clazz);
stepDefinitions.add(new JavaStepDefinition(pattern, method, objectFactory, locale));
}
+
+ public Object invoke(Method method, Object[] javaArgs) {
+ try {
+ if (method.isAnnotationPresent(Pending.class)) {
+ throw new CucumberException(method.getAnnotation(Pending.class).value());
+ } else {
+ return method.invoke(this.objectFactory.getInstance(method.getDeclaringClass()), javaArgs);
+ }
+ } catch (IllegalArgumentException e) {
+ String m = "Couldn't invokeWithArgs " + method.toGenericString() + " with "
+ + Utils.join(javaArgs, ",");
+ throw new CucumberException(m);
+ } catch (InvocationTargetException e) {
+ throw new CucumberException("Couldn't invoke method", e.getTargetException());
+ } catch (IllegalAccessException e) {
+ throw new CucumberException("Couldn't invoke method", e);
+ }
+ }
}
diff --git a/java/src/main/java/cucumber/runtime/java/JavaMethodTransform.java b/java/src/main/java/cucumber/runtime/java/JavaMethodTransform.java
new file mode 100644
index 0000000000..9a9066d367
--- /dev/null
+++ b/java/src/main/java/cucumber/runtime/java/JavaMethodTransform.java
@@ -0,0 +1,23 @@
+package cucumber.runtime.java;
+
+import java.lang.reflect.Method;
+import java.util.Locale;
+
+import cucumber.runtime.transformers.Transformable;
+
+public class JavaMethodTransform implements Transformable