diff --git a/CHANGELOG.md b/CHANGELOG.md
index 88aad4b570..736afc04c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Core] Update dependency io.cucumber:html-formatter to v22.1.0
- [Core] Update dependency io.cucumber:junit-xml-formatter to v0.11.0
- [Core] Update dependency io.cucumber:pretty-formatter to v2.4.1
+- [Java] Any custom method declared as `@DefaultParameterTransformer` can now have a `Locale` argument to optionally consider the locale declaration of the current Feature ([cucumber/cucumber-expressions#376](https://github.com/cucumber/cucumber-expressions/issues/376) Stefan Gasterstädt)
### Fixed
- [Core] Add OS version to `Meta` message ([#3108](https://github.com/cucumber/cucumber-jvm/pull/3108))
diff --git a/cucumber-core/src/main/java/io/cucumber/core/backend/DefaultParameterTransformerDefinition.java b/cucumber-core/src/main/java/io/cucumber/core/backend/DefaultParameterTransformerDefinition.java
index ddc9248701..4cbac1736c 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/backend/DefaultParameterTransformerDefinition.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/backend/DefaultParameterTransformerDefinition.java
@@ -3,9 +3,15 @@
import io.cucumber.cucumberexpressions.ParameterByTypeTransformer;
import org.apiguardian.api.API;
+import java.util.Locale;
+
@API(status = API.Status.STABLE)
public interface DefaultParameterTransformerDefinition extends Located {
ParameterByTypeTransformer parameterByTypeTransformer();
+ default ParameterByTypeTransformer parameterByTypeTransformer(Locale locale) {
+ return this.parameterByTypeTransformer();
+ }
+
}
diff --git a/cucumber-core/src/main/java/io/cucumber/core/runner/CachingGlue.java b/cucumber-core/src/main/java/io/cucumber/core/runner/CachingGlue.java
index fbdbd66d52..26a1f4a461 100644
--- a/cucumber-core/src/main/java/io/cucumber/core/runner/CachingGlue.java
+++ b/cucumber-core/src/main/java/io/cucumber/core/runner/CachingGlue.java
@@ -277,7 +277,7 @@ void prepareGlue(Locale locale) throws DuplicateStepDefinitionException {
if (defaultParameterTransformers.size() == 1) {
DefaultParameterTransformerDefinition definition = defaultParameterTransformers.get(0);
- ParameterByTypeTransformer transformer = definition.parameterByTypeTransformer();
+ ParameterByTypeTransformer transformer = definition.parameterByTypeTransformer(locale);
stepTypeRegistry.setDefaultParameterTransformer(transformer);
} else if (defaultParameterTransformers.size() > 1) {
throw new DuplicateDefaultParameterTransformers(defaultParameterTransformers);
diff --git a/cucumber-java/src/main/java/io/cucumber/java/DefaultParameterTransformer.java b/cucumber-java/src/main/java/io/cucumber/java/DefaultParameterTransformer.java
index 1986fe5fa9..7d8d2fdbf6 100644
--- a/cucumber-java/src/main/java/io/cucumber/java/DefaultParameterTransformer.java
+++ b/cucumber-java/src/main/java/io/cucumber/java/DefaultParameterTransformer.java
@@ -14,6 +14,8 @@
*
* - {@code String, Type -> Object}
* - {@code Object, Type -> Object}
+ * - {@code String, Type, Locale -> Object}
+ * - {@code Object, Type, Locale -> Object}
*
*
* @see io.cucumber.cucumberexpressions.ParameterByTypeTransformer
diff --git a/cucumber-java/src/main/java/io/cucumber/java/JavaDefaultParameterTransformerDefinition.java b/cucumber-java/src/main/java/io/cucumber/java/JavaDefaultParameterTransformerDefinition.java
index 873e03562d..59609c587c 100644
--- a/cucumber-java/src/main/java/io/cucumber/java/JavaDefaultParameterTransformerDefinition.java
+++ b/cucumber-java/src/main/java/io/cucumber/java/JavaDefaultParameterTransformerDefinition.java
@@ -6,6 +6,7 @@
import java.lang.reflect.Method;
import java.lang.reflect.Type;
+import java.util.Locale;
import static io.cucumber.java.InvalidMethodSignatureException.builder;
@@ -13,12 +14,10 @@ class JavaDefaultParameterTransformerDefinition extends AbstractGlueDefinition
implements DefaultParameterTransformerDefinition {
private final Lookup lookup;
- private final ParameterByTypeTransformer transformer;
JavaDefaultParameterTransformerDefinition(Method method, Lookup lookup) {
super(requireValidMethod(method), lookup);
this.lookup = lookup;
- this.transformer = this::execute;
}
private static Method requireValidMethod(Method method) {
@@ -28,7 +27,7 @@ private static Method requireValidMethod(Method method) {
}
Class>[] parameterTypes = method.getParameterTypes();
- if (parameterTypes.length != 2) {
+ if ((parameterTypes.length != 2) || (parameterTypes.length != 3)) {
throw createInvalidSignatureException(method);
}
@@ -40,11 +39,19 @@ private static Method requireValidMethod(Method method) {
throw createInvalidSignatureException(method);
}
+ if ((parameterTypes.length == 3) && !Locale.class.equals(parameterTypes[2])) {
+ throw createInvalidSignatureException(method);
+ }
return method;
}
- private Object execute(String fromValue, Type toValueType) {
- return Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, fromValue, toValueType);
+ private Object execute(String fromValue, Type toValueType, Locale locale) {
+ if (method.getParameterTypes().length == 2) {
+ return Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, fromValue, toValueType);
+ } else {
+ return Invoker.invoke(this, lookup.getInstance(method.getDeclaringClass()), method, fromValue, toValueType,
+ locale);
+ }
}
private static InvalidMethodSignatureException createInvalidSignatureException(Method method) {
@@ -52,12 +59,19 @@ private static InvalidMethodSignatureException createInvalidSignatureException(M
.addAnnotation(DefaultParameterTransformer.class)
.addSignature("public Object defaultDataTableEntry(String fromValue, Type toValueType)")
.addSignature("public Object defaultDataTableEntry(Object fromValue, Type toValueType)")
+ .addSignature("public Object defaultDataTableEntry(String fromValue, Type toValueType, Locale locale)")
+ .addSignature("public Object defaultDataTableEntry(Object fromValue, Type toValueType, Locale locale)")
.build();
}
@Override
public ParameterByTypeTransformer parameterByTypeTransformer() {
- return transformer;
+ return this.parameterByTypeTransformer(null);
+ }
+
+ @Override
+ public ParameterByTypeTransformer parameterByTypeTransformer(Locale locale) {
+ return (fromValue, toValueType) -> execute(fromValue, toValueType, locale);
}
}
diff --git a/cucumber-java/src/test/java/io/cucumber/java/JavaDefaultParameterTransformerDefinitionTest.java b/cucumber-java/src/test/java/io/cucumber/java/JavaDefaultParameterTransformerDefinitionTest.java
index fe7b184eec..bbad1f86ba 100644
--- a/cucumber-java/src/test/java/io/cucumber/java/JavaDefaultParameterTransformerDefinitionTest.java
+++ b/cucumber-java/src/test/java/io/cucumber/java/JavaDefaultParameterTransformerDefinitionTest.java
@@ -5,6 +5,7 @@
import java.lang.reflect.Method;
import java.lang.reflect.Type;
+import java.util.Locale;
import java.util.Map;
import static org.hamcrest.CoreMatchers.startsWith;
@@ -33,10 +34,34 @@ void can_transform_string_to_type() throws Throwable {
assertThat(transformed, is("transform_string_to_type"));
}
+ @Test
+ void can_transform_string_to_type_ignoring_locale() throws Throwable {
+ Method method = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("transform_string_to_type",
+ String.class, Type.class);
+ JavaDefaultParameterTransformerDefinition definition = new JavaDefaultParameterTransformerDefinition(method,
+ lookup);
+ Object transformed = definition.parameterByTypeTransformer(Locale.ENGLISH).transform("something", String.class);
+ assertThat(transformed, is("transform_string_to_type"));
+ }
+
public Object transform_string_to_type(String fromValue, Type toValueType) {
return "transform_string_to_type";
}
+ @Test
+ void can_transform_string_to_type_using_locale() throws Throwable {
+ Method method = JavaDefaultParameterTransformerDefinitionTest.class.getMethod(
+ "transform_string_to_type_with_locale", String.class, Type.class, Locale.class);
+ JavaDefaultParameterTransformerDefinition definition = new JavaDefaultParameterTransformerDefinition(method,
+ lookup);
+ Object transformed = definition.parameterByTypeTransformer(Locale.ENGLISH).transform("something", String.class);
+ assertThat(transformed, is("transform_string_to_type_with_locale_en"));
+ }
+
+ public Object transform_string_to_type_with_locale(String fromValue, Type toValueType, Locale locale) {
+ return "transform_string_to_type_with_locale_" + locale.getLanguage();
+ }
+
@Test
void can_transform_object_to_type() throws Throwable {
Method method = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("transform_object_to_type",
@@ -47,10 +72,36 @@ void can_transform_object_to_type() throws Throwable {
assertThat(transformed, is("transform_object_to_type"));
}
+ @Test
+ void can_transform_object_to_type_ignoring_locale() throws Throwable {
+ Method method = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("transform_object_to_type",
+ Object.class, Type.class);
+ JavaDefaultParameterTransformerDefinition definition = new JavaDefaultParameterTransformerDefinition(method,
+ lookup);
+ String transformed = (String) definition.parameterByTypeTransformer(Locale.ENGLISH).transform("something",
+ String.class);
+ assertThat(transformed, is("transform_object_to_type"));
+ }
+
public Object transform_object_to_type(Object fromValue, Type toValueType) {
return "transform_object_to_type";
}
+ @Test
+ void can_transform_object_to_type_using_locale() throws Throwable {
+ Method method = JavaDefaultParameterTransformerDefinitionTest.class.getMethod(
+ "transform_object_to_type_with_locale", Object.class, Type.class, Locale.class);
+ JavaDefaultParameterTransformerDefinition definition = new JavaDefaultParameterTransformerDefinition(method,
+ lookup);
+ String transformed = (String) definition.parameterByTypeTransformer(Locale.ENGLISH).transform("something",
+ String.class);
+ assertThat(transformed, is("transform_object_to_type_with_locale_en"));
+ }
+
+ public Object transform_object_to_type_with_locale(Object fromValue, Type toValueType, Locale locale) {
+ return "transform_object_to_type_with_locale_" + locale.getLanguage();
+ }
+
@Test
void must_have_non_void_return() throws Throwable {
Method method = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("transforms_string_to_void",
@@ -61,6 +112,8 @@ void must_have_non_void_return() throws Throwable {
"A @DefaultParameterTransformer annotated method must have one of these signatures:\n" +
" * public Object defaultDataTableEntry(String fromValue, Type toValueType)\n" +
" * public Object defaultDataTableEntry(Object fromValue, Type toValueType)\n" +
+ " * public Object defaultDataTableEntry(Object fromValue, Type toValueType, Locale locale)\n" +
+ " * public Object defaultDataTableEntry(Object fromValue, Type toValueType, Locale locale)\n" +
"at io.cucumber.java.JavaDefaultParameterTransformerDefinitionTest.transforms_string_to_void(java.lang.String,java.lang.reflect.Type)"));
}
@@ -68,28 +121,32 @@ public void transforms_string_to_void(String fromValue, Type toValueType) {
}
@Test
- void must_have_two_arguments() throws Throwable {
+ void must_have_two_or_three_arguments() throws Throwable {
Method oneArg = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("one_argument", String.class);
assertThrows(InvalidMethodSignatureException.class,
() -> new JavaDefaultParameterTransformerDefinition(oneArg, lookup));
- Method threeArg = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("three_arguments", String.class,
+ Method fourArg = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("four_arguments", String.class,
Type.class, Object.class);
assertThrows(InvalidMethodSignatureException.class,
- () -> new JavaDefaultParameterTransformerDefinition(threeArg, lookup));
+ () -> new JavaDefaultParameterTransformerDefinition(fourArg, lookup));
}
public Object one_argument(String fromValue) {
- return "one_arguments";
+ return "one_argument";
}
- public Object three_arguments(String fromValue, Type toValueType, Object extra) {
- return "three_arguments";
+ public Object four_arguments(String fromValue, Type toValueType, Locale locale, Object extra) {
+ return "four_arguments";
}
@Test
void must_have_string_or_object_as_from_value() throws Throwable {
- Method threeArg = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("map_as_from_value", Map.class,
+ Method twoArg = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("map_as_from_value", Map.class,
Type.class);
+ assertThrows(InvalidMethodSignatureException.class,
+ () -> new JavaDefaultParameterTransformerDefinition(twoArg, lookup));
+ Method threeArg = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("map_as_from_value_with_locale",
+ Map.class, Type.class, Locale.class);
assertThrows(InvalidMethodSignatureException.class,
() -> new JavaDefaultParameterTransformerDefinition(threeArg, lookup));
}
@@ -98,10 +155,18 @@ public Object map_as_from_value(Map fromValue, Type toValueType)
return "map_as_from_value";
}
+ public Object map_as_from_value_with_locale(Map fromValue, Type toValueType, Locale locale) {
+ return "map_as_from_value_with_locale";
+ }
+
@Test
void must_have_type_as_to_value_type() throws Throwable {
- Method threeArg = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("object_as_to_value_type",
+ Method twoArg = JavaDefaultParameterTransformerDefinitionTest.class.getMethod("object_as_to_value_type",
String.class, Object.class);
+ assertThrows(InvalidMethodSignatureException.class,
+ () -> new JavaDefaultParameterTransformerDefinition(twoArg, lookup));
+ Method threeArg = JavaDefaultParameterTransformerDefinitionTest.class.getMethod(
+ "object_as_to_value_type_with_locale", String.class, Object.class, Locale.class);
assertThrows(InvalidMethodSignatureException.class,
() -> new JavaDefaultParameterTransformerDefinition(threeArg, lookup));
}
@@ -110,4 +175,8 @@ public Object object_as_to_value_type(String fromValue, Object toValueType) {
return "object_as_to_value_type";
}
+ public Object object_as_to_value_type_with_locale(String fromValue, Object toValueType, Locale locale) {
+ return "object_as_to_value_type_with_locale";
+ }
+
}