Skip to content
This repository has been archived by the owner on Sep 13, 2021. It is now read-only.

Commit

Permalink
datatable/java: Allow Object and String datatable types to be redefin…
Browse files Browse the repository at this point in the history
…ed (#885)

This enables the following in Cucumber-JVM:

```feature
Feature: Whitespace
  Scenario: Whitespace in a table
   Given a blank value
     | key | value   |
     | a   | [blank] |
```

```java
@given("A blank value")
public void given_a_blank_value(Map<String, String> map){
    // map contains { "key":"a", "value": ""}
}

@DataTableType(replaceWithEmptyString = "[blank]")
public String listOfStringListsType(String cell) {
    return cell;
}
```

Note that this only applies to `String` and `Object` the other build in types
can not be redefined. Though this could be considered if a clear usecase is
presented.

See: cucumber/cucumber-jvm#1884
  • Loading branch information
mpkorstanje authored Feb 5, 2020
1 parent c8e4d6b commit 4ac2165
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 6 deletions.
24 changes: 24 additions & 0 deletions datatable/src/main/java/io/cucumber/datatable/DataTableType.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@ public final class DataTableType {
private final JavaType targetType;
private final RawTableTransformer<?> transformer;
private final Type elementType;
private final boolean replaceable;

private DataTableType(Type type, Type target, RawTableTransformer<?> transformer) {
this(type, target, transformer, false);
}
private DataTableType(Type type, Type target, RawTableTransformer<?> transformer, boolean replaceable) {
if (type == null) throw new NullPointerException("targetType cannot be null");
if (target == null) throw new NullPointerException("target cannot be null");
if (transformer == null) throw new NullPointerException("transformer cannot be null");
this.elementType = type;
this.targetType = constructType(target);
this.transformer = transformer;
this.replaceable = replaceable;
}

/**
Expand Down Expand Up @@ -74,6 +79,21 @@ public <T> DataTableType(Type type, TableEntryTransformer<T> transformer) {
this(type, aListOf(type), new TableEntryTransformerAdaptor<>(transformer));
}

/**
* Creates a data replaceable table type that transforms the entries of the
* table into a list of objects. An entry consists of the elements of the
* table header paired with the values of each subsequent row.
*
* @param type the type of the list items
* @param transformer a function that creates an instance of
* <code>type</code> from the data table entry
* @param replaceable can this datatable type be replaced with another for the same type
* @param <T> see <code>type</code>
*/
<T> DataTableType(Type type, TableCellTransformer<T> transformer, boolean replaceable) {
this(type, aListOf(aListOf(type)), new TableCellTransformerAdaptor<>(transformer), replaceable);
}

/**
* Creates a data table type that transforms the cells of the table into a
* list of list of objects.
Expand Down Expand Up @@ -141,6 +161,10 @@ Class<?> getTransformerType() {
return transformer.getOriginalTransformerType();
}

public boolean isReplaceable() {
return replaceable;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public DataTableTypeRegistry(Locale locale) {
final NumberParser numberParser = new NumberParser(locale);

TableCellTransformer<Object> objectTableCellTransformer = applyIfPresent(s -> s);
defineDataTableType(new DataTableType(Object.class, objectTableCellTransformer));
defineDataTableType(new DataTableType(Object.class, objectTableCellTransformer, true));
defineDataTableType(new DataTableType(String.class, objectTableCellTransformer, true));

TableCellTransformer<BigInteger> bigIntegerTableCellTransformer = applyIfPresent(BigInteger::new);
defineDataTableType(new DataTableType(BigInteger.class, bigIntegerTableCellTransformer));
Expand Down Expand Up @@ -56,10 +57,6 @@ public DataTableTypeRegistry(Locale locale) {
TableCellTransformer<Double> doubleTableCellTransformer = applyIfPresent(numberParser::parseDouble);
defineDataTableType(new DataTableType(Double.class, doubleTableCellTransformer));
defineDataTableType(new DataTableType(double.class, doubleTableCellTransformer));

TableCellTransformer<String> stringTableCellTransformer = (String cell) -> cell;
defineDataTableType(new DataTableType(String.class, stringTableCellTransformer));

}

private static <R> TableCellTransformer<R> applyIfPresent(Function<String, R> f) {
Expand All @@ -68,7 +65,7 @@ private static <R> TableCellTransformer<R> applyIfPresent(Function<String, R> f)

public void defineDataTableType(DataTableType dataTableType) {
DataTableType existing = tableTypeByType.get(dataTableType.getTargetType());
if (existing != null) {
if (existing != null && !existing.isReplaceable()) {
throw new DuplicateTypeException(format("" +
"There already is a data table type registered that can supply %s.\n" +
"You are trying to register a %s for %s.\n" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class DataTableTypeRegistryTest {
private static final Type LIST_OF_LIST_OF_FLOAT = aListOf(aListOf(Float.class));
private static final Type LIST_OF_LIST_OF_DOUBLE = aListOf(aListOf(Double.class));
private static final Type LIST_OF_LIST_OF_STRING = aListOf(aListOf(String.class));
private static final Type LIST_OF_LIST_OF_OBJECT = aListOf(aListOf(Object.class));

private static final TableCellByTypeTransformer PLACE_TABLE_CELL_TRANSFORMER =
(value, cellType) -> new Place(value);
Expand Down Expand Up @@ -235,6 +236,27 @@ void null_string_transformed_to_null() {
singletonList(singletonList(null)),
dataTableType.transform(singletonList(singletonList(null)))
);
}

@Test
void string_transformer_is_replaceable() {
DataTableTypeRegistry registry = new DataTableTypeRegistry(Locale.ENGLISH);
registry.defineDataTableType(new DataTableType(String.class, (String cell) -> "[blank]".equals(cell) ? "" : cell));
DataTableType dataTableType = registry.lookupTableTypeByType(LIST_OF_LIST_OF_STRING);
assertEquals(
singletonList(singletonList("")),
dataTableType.transform(singletonList(singletonList("[blank]")))
);
}

@Test
void object_transformer_is_replaceable() {
DataTableTypeRegistry registry = new DataTableTypeRegistry(Locale.ENGLISH);
registry.defineDataTableType(new DataTableType(Object.class, (String cell) -> "[blank]".equals(cell) ? "" : cell));
DataTableType dataTableType = registry.lookupTableTypeByType(LIST_OF_LIST_OF_OBJECT);
assertEquals(
singletonList(singletonList("")),
dataTableType.transform(singletonList(singletonList("[blank]")))
);
}
}

0 comments on commit 4ac2165

Please sign in to comment.