In our project we often have to parse JBehave tables that might look like this one:
Given currencies are truncated to these decimal places
| Currency | Decimal places |
| USD | 2 |
| JPY | 0 |
| LYD | 3 |
The standard approach is to write something like this
@Given("currencies are truncated to these decimal places $currencyDecimalPlaces")
public void currencyDecimalPlaces(ExamplesTable currencyDecimalPlacesTable) {
...
for (Parameters row : currencyDecimalPlacesTable.getRowsAsParameters()) {
// read row data
}
...
}
where reading row data may look like this:
CurrencyCode currencyCode = row.valueAs("Currency", CurrencyCode.class);
Integer decimalPlaces = row.valueAs("Decimal places", Integer.class);
or we can make it a little more readable like this:
CurrencyCode currencyCode = Currency.in(row);
Integer decimalPlaces = DecimalPlaces.in(row);
To make the readable code we define a new Column class:
public class Column<T> {
private final String label;
private final Class<T> defaultType;
public Column(String label, Class<T> defaultType) {
this.label = label;
this.defaultType = defaultType;
}
public <T> T in(Parameters row, Class<T> type) {
return row.valueAs(label, type);
}
public T in(Parameters row) {
return in(row, defaultType);
}
public String asString(Parameters row) {
return in(row, String.class);
}
public static <T> Column<T> column(String label, Class<T> defaultType) {
return new Column<T>(label, defaultType);
}
public static Column<String> column(String label) {
return new Column<String>(label, String.class);
}
}
and registering custom columns:
public interface Columns {
...
public static final Column<CurrencyCode> Currency = column("Currency", CurrencyCode.class);
public static final Column<Integer> DecimalPlaces = column("Decimal places", Integer.class);
...
}
now we can convert the column to the default registered class
CurrencyCode currencyCode = Currency.in(row);
or to a specified class:
String currencyCode = Currency.in(row, String.class);