Skip to content

Commit

Permalink
datatable: Improve handling of tables withouth header (#540)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpkorstanje authored Aug 1, 2019
1 parent c3b7aa6 commit e837d8b
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import static io.cucumber.datatable.UndefinedDataTableTypeException.mapsNoConverterDefined;
import static io.cucumber.datatable.UndefinedDataTableTypeException.listNoConverterDefined;
import static io.cucumber.datatable.UndefinedDataTableTypeException.listsNoConverterDefined;
import static io.cucumber.datatable.UndefinedDataTableTypeException.listTableTooWide;
import static io.cucumber.datatable.UndefinedDataTableTypeException.singletonTableTooWide;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.nCopies;
Expand Down Expand Up @@ -103,6 +105,10 @@ private <T> T toSingleton(DataTable dataTable, Type type) {

List<T> singletonList = toListOrNull(dataTable, type);
if (singletonList == null) {
DataTableType cellValueType = registry.lookupTableTypeByType(aListOf(aListOf(type)));
if (cellValueType != null) {
throw singletonTableTooWide(type, "TableEntryConverter or TableCellConverter", type);
}
throw singletonNoConverterDefined(type);
}

Expand All @@ -127,39 +133,49 @@ public <T> List<T> toList(DataTable dataTable, Type itemType) {
return unmodifiableList(list);
}

if (dataTable.width() > 1) {
throw listNoConverterDefined(itemType, "TableEntryTransformer or TableRowTransformer", itemType);
if (dataTable.width() == 1) {
throw listNoConverterDefined(itemType, "TableEntryTransformer, TableRowTransformer or TableCellTransformer", itemType);
}

throw listNoConverterDefined(itemType, "TableEntryTransformer, TableRowTransformer or TableCellTransformer", itemType);
}
DataTableType cellValueType = registry.lookupTableTypeByType(aListOf(aListOf(itemType)));
if (cellValueType != null) {
throw listTableTooWide(itemType, "TableEntryTransformer or TableRowTransformer", itemType);
}

private <T> List<T> toListOrNull(DataTable dataTable, Type itemType) {
return toListOrNull(dataTable.cells(), itemType);
throw listNoConverterDefined(itemType, "TableEntryTransformer or TableRowTransformer", itemType);
}

@SuppressWarnings("unchecked")
private <T> List<T> toListOrNull(List<List<String>> cells, Type itemType) {
private <T> List<T> toListOrNull(DataTable dataTable, Type itemType) {
DataTableType tableType = registry.lookupTableTypeByType(aListOf(itemType));
List<List<String>> cells = dataTable.cells();
if (tableType != null) {
return (List<T>) tableType.transform(cells);
}

DataTableType cellValueType = registry.lookupTableTypeByType(aListOf(aListOf(itemType)));
if (cellValueType != null) {
return unpack((List<List<T>>) cellValueType.transform(cells));
if (dataTable.width() == 1) {
DataTableType cellValueType = registry.lookupTableTypeByType(aListOf(aListOf(itemType)));
if (cellValueType != null) {
return unpack((List<List<T>>) cellValueType.transform(cells));
}
}

if (cells.size() > 1) {
if (dataTable.height() > 1) {
DataTableType defaultTableType = registry.getDefaultTableEntryTransformer(itemType);
if (defaultTableType != null) {
return (List<T>) defaultTableType.transform(cells);
}
}

DataTableType defaultCellValueType = registry.getDefaultTableCellTransformer(itemType);
if (defaultCellValueType != null) {
return unpack((List<List<T>>) defaultCellValueType.transform(cells));
if (dataTable.width() == 1) {
DataTableType defaultCellValueType = registry.getDefaultTableCellTransformer(itemType);
if (defaultCellValueType != null) {
return unpack((List<List<T>>) defaultCellValueType.transform(cells));
}
}

DataTableType defaultTableType = registry.getDefaultTableEntryTransformer(itemType);
if (defaultTableType != null) {
return (List<T>) defaultTableType.transform(cells);
}

return null;
Expand Down Expand Up @@ -199,7 +215,7 @@ public <K, V> Map<K, V> toMap(DataTable dataTable, Type keyType, Type valueType)

String firstHeaderCell = keyColumn.cell(0, 0);
boolean firstHeaderCellIsBlank = firstHeaderCell == null || firstHeaderCell.isEmpty();
List<K> keys = convertEntryKeys(keyType, keyColumn.cells(), valueType, firstHeaderCellIsBlank);
List<K> keys = convertEntryKeys(keyType, keyColumn, valueType, firstHeaderCellIsBlank);

if (valueColumns.isEmpty()) {
return createMap(keyType, keys, valueType, nCopies(keys.size(), (V) null));
Expand Down Expand Up @@ -232,7 +248,7 @@ private static <K, V> Map<K, V> createMap(Type keyType, List<K> keys, Type value
}

@SuppressWarnings("unchecked")
private <K> List<K> convertEntryKeys(Type keyType, List<List<String>> keyColumn, Type valueType, boolean firstHeaderCellIsBlank) {
private <K> List<K> convertEntryKeys(Type keyType, DataTable keyColumn, Type valueType, boolean firstHeaderCellIsBlank) {
if (firstHeaderCellIsBlank) {
DataTableType keyConverter;
keyConverter = registry.lookupTableTypeByType(aListOf(aListOf(keyType)));
Expand All @@ -242,7 +258,7 @@ private <K> List<K> convertEntryKeys(Type keyType, List<List<String>> keyColumn,
if (keyConverter == null) {
throw mapNoConverterDefined(keyType, valueType, "TableCellTransformer", keyType);
}
return unpack((List<List<K>>) keyConverter.transform(keyColumn.subList(1, keyColumn.size())));
return unpack((List<List<K>>) keyConverter.transform(keyColumn.rows(1, keyColumn.height()).cells()));
}

List<K> list = toListOrNull(keyColumn, keyType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ static UndefinedDataTableTypeException singletonNoConverterDefined(Type type) {
);
}

static CucumberDataTableException singletonTableTooWide(Type itemType, String missingConverter, Type typeToRegister) {
return new UndefinedDataTableTypeException(
format("Can't convert DataTable to %s.\n" +
"There was a table cell converter but the table was too wide to use it.\n" +
"Please reduce the table width or register a %s for %s.\n" ,
typeName(itemType), missingConverter, typeName(typeToRegister))
);
}

static UndefinedDataTableTypeException mapNoConverterDefined(Type keyType, Type valueType, String missingConverter, Type typeToRegister) {
return new UndefinedDataTableTypeException(
format("Can't convert DataTable to Map<%s, %s>.\n" +
Expand Down Expand Up @@ -46,6 +55,14 @@ static CucumberDataTableException listNoConverterDefined(Type itemType, String m
);
}

static CucumberDataTableException listTableTooWide(Type itemType, String missingConverter, Type typeToRegister) {
return new UndefinedDataTableTypeException(
format("Can't convert DataTable to List<%s>.\n" +
"There was a table cell converter but the table was too wide to use it.\n" +
"Please reduce the table width or register a %s for %s.\n" ,
typeName(itemType), missingConverter, typeName(typeToRegister))
);
}

static CucumberDataTableException listsNoConverterDefined(Type itemType) {
return new UndefinedDataTableTypeException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,15 @@ public void convert_to_empty_lists__empty_table() {
assertEquals(emptyList(), converter.convert(table, LIST_OF_LIST_OF_INT));
}

@Test
public void convert_to_empty_list__only_header() {
final DataTable table = parse("",
" | firstName | lastName | birthDate |"
);
registry.defineDataTableType(new DataTableType(Author.class, AUTHOR_TABLE_ENTRY_TRANSFORMER));
assertEquals(emptyList(), converter.convert(table, LIST_OF_AUTHOR));
}

@Test
public void convert_to_empty_map__blank_first_cell() {
DataTable table = parse("| |");
Expand Down Expand Up @@ -253,6 +262,17 @@ public void convert_to_list__single_column() {
assertEquals(expected, converter.convert(table, LIST_OF_INT));
}

@Test
public void convert_to_list__double_column__throws_exception() {
DataTable table = parse("",
"| 3 | 5 |",
"| 6 | 7 | "
);

expectedException.expectMessage("Can't convert DataTable to List<java.lang.Integer>");
converter.toList(table, Integer.class);
}

@Test
public void convert_to_list_of_map() {
DataTable table = parse("",
Expand Down Expand Up @@ -369,20 +389,6 @@ public void convert_to_list_of_object__using_object_mapper() {
assertEquals(expected, converter.convert(table, LIST_OF_AUTHOR));
}


@Test
public void convert_to_list_of_primitive() {
DataTable table = parse("",
"| 3 | 5 |",
"| 6 | 7 | "
);

List<Integer> expected = asList(3, 5, 6, 7);

assertEquals(expected, converter.toList(table, Integer.class));
assertEquals(expected, converter.convert(table, LIST_OF_INT));
}

@Test
public void convert_to_list_of_unknown_type__throws_exception__register_transformer() {
expectedException.expectMessage(listNoConverterDefined(Author.class, "TableEntryTransformer or TableRowTransformer", Author.class).getMessage());
Expand Down Expand Up @@ -632,8 +638,6 @@ public void to_map_of_object_to_object__without_implied_entries__prefers__defaul
assertEquals(expected, converter.convert(table, MAP_OF_AIR_PORT_CODE_TO_AIR_PORT_CODE));
}



@Test
public void convert_to_map_of_object_to_object_using_entry_and_cell() {
DataTable table = parse("",
Expand Down Expand Up @@ -963,6 +967,24 @@ public void convert_to_object__more_then_one_item__throws_exception() {
"The table contained more then one item: [♘, ♝]",
typeName(Piece.class)));

DataTable table = parse("",
"| ♘ |",
"| ♝ |"
);

registry.defineDataTableType(new DataTableType(Piece.class, PIECE_TABLE_CELL_TRANSFORMER));
converter.convert(table, Piece.class);
}


@Test
public void convert_to_object__too_wide__throws_exception() {
expectedException.expectMessage(format("" +
"Can't convert DataTable to %s.\n" +
"There was a table cell converter but the table was too wide to use it.\n" +
"Please reduce the table width or register a TableEntryConverter or TableCellConverter for %s.",
typeName(Piece.class), typeName(Piece.class)));

DataTable table = parse("",
"| ♘ | ♝ |"
);
Expand Down

0 comments on commit e837d8b

Please sign in to comment.