All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
cucumber.runtime.table.TableConverter Maven / Gradle / Ivy
package cucumber.runtime.table;
import cucumber.api.DataTable;
import cucumber.deps.com.thoughtworks.xstream.converters.ConversionException;
import cucumber.deps.com.thoughtworks.xstream.converters.SingleValueConverter;
import cucumber.deps.com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter;
import cucumber.deps.com.thoughtworks.xstream.io.HierarchicalStreamReader;
import cucumber.runtime.CucumberException;
import cucumber.runtime.ParameterInfo;
import cucumber.runtime.xstream.CellWriter;
import cucumber.runtime.xstream.ComplexTypeWriter;
import cucumber.runtime.xstream.ListOfComplexTypeReader;
import cucumber.runtime.xstream.ListOfSingleValueWriter;
import cucumber.runtime.xstream.LocalizedXStreams;
import gherkin.formatter.model.Comment;
import gherkin.formatter.model.DataTableRow;
import gherkin.util.Mapper;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static cucumber.runtime.Utils.listItemType;
import static cucumber.runtime.Utils.mapKeyType;
import static cucumber.runtime.Utils.mapValueType;
import static gherkin.util.FixJava.map;
import static java.util.Arrays.asList;
/**
* This class converts a {@link cucumber.api.DataTable to various other types}
*/
public class TableConverter {
private static final List NO_COMMENTS = Collections.emptyList();
private final LocalizedXStreams.LocalizedXStream xStream;
private final ParameterInfo parameterInfo;
public TableConverter(LocalizedXStreams.LocalizedXStream xStream, ParameterInfo parameterInfo) {
this.xStream = xStream;
this.parameterInfo = parameterInfo;
}
public T convert(Type type, DataTable dataTable) {
try {
xStream.setParameterType(parameterInfo);
if (type == null || (type instanceof Class && ((Class) type).isAssignableFrom(DataTable.class))) {
return (T) dataTable;
}
Type itemType = listItemType(type);
if (itemType == null) {
throw new CucumberException("Not a List type: " + type);
}
Type listItemType = listItemType(itemType);
if (listItemType == null) {
SingleValueConverter singleValueConverter = xStream.getSingleValueConverter(itemType);
if (singleValueConverter != null) {
return (T) toListOfSingleValue(dataTable, singleValueConverter);
} else {
if (itemType instanceof Class) {
if (Map.class.equals(itemType)) {
// Non-generic map
SingleValueConverter mapKeyConverter = xStream.getSingleValueConverter(String.class);
SingleValueConverter mapValueConverter = xStream.getSingleValueConverter(String.class);
return (T) toListOfSingleValueMap(dataTable, mapKeyConverter, mapValueConverter);
} else {
return (T) toListOfComplexType(dataTable, (Class) itemType);
}
} else {
SingleValueConverter mapKeyConverter = xStream.getSingleValueConverter(mapKeyType(itemType));
SingleValueConverter mapValueConverter = xStream.getSingleValueConverter(mapValueType(itemType));
if (mapKeyConverter != null && mapValueConverter != null) {
return (T) toListOfSingleValueMap(dataTable, mapKeyConverter, mapValueConverter);
} else {
throw new CucumberException("Can't convert a table to " + type + ". When using List, SomeComplexType must not be a generic type");
}
}
}
} else {
// List>
SingleValueConverter singleValueConverter = xStream.getSingleValueConverter(listItemType);
if (singleValueConverter != null) {
// List>
return (T) toListOfListOfSingleValue(dataTable, singleValueConverter);
} else {
// List>
throw new CucumberException("Can't convert to " + type.toString());
}
}
} finally {
xStream.unsetParameterInfo();
}
}
private List toListOfComplexType(DataTable dataTable, Class itemType) {
HierarchicalStreamReader reader = new ListOfComplexTypeReader(itemType, convertTopCellsToFieldNames(dataTable), dataTable.cells(1));
try {
return Collections.unmodifiableList((List) xStream.unmarshal(reader));
} catch (AbstractReflectionConverter.UnknownFieldException e) {
throw new CucumberException(e.getShortMessage());
} catch (ConversionException e) {
throw new CucumberException(String.format("Can't assign null value to one of the primitive fields in %s. Please use boxed types.", e.get("class")));
}
}
private List toListOfSingleValue(DataTable dataTable, SingleValueConverter singleValueConverter) {
List result = new ArrayList();
for (String cell : dataTable.flatten()) {
result.add(singleValueConverter.fromString(cell));
}
return Collections.unmodifiableList(result);
}
private List> toListOfListOfSingleValue(DataTable dataTable, SingleValueConverter singleValueConverter) {
List> result = new ArrayList>();
for (List row : dataTable.raw()) {
List convertedRow = new ArrayList();
for (String cell : row) {
convertedRow.add(singleValueConverter.fromString(cell));
}
result.add(Collections.unmodifiableList(convertedRow));
}
return Collections.unmodifiableList(result);
}
private List> toListOfSingleValueMap(DataTable dataTable, SingleValueConverter mapKeyConverter, SingleValueConverter mapValueConverter) {
List> result = new ArrayList>();
List keyStrings = dataTable.topCells();
List keys = new ArrayList();
for (String keyString : keyStrings) {
keys.add(mapKeyConverter.fromString(keyString));
}
List> valueRows = dataTable.cells(1);
for (List valueRow : valueRows) {
Map map = new HashMap();
int i = 0;
for (String cell : valueRow) {
map.put(keys.get(i), mapValueConverter.fromString(cell));
i++;
}
result.add(Collections.unmodifiableMap(map));
}
return Collections.unmodifiableList(result);
}
/**
* Converts a DataTable to a List of objects.
*/
public List toList(final Type type, DataTable dataTable) {
if (type == null) {
return convert(new GenericListType(new GenericListType(String.class)), dataTable);
}
return convert(new GenericListType(type), dataTable);
}
/**
* Converts a List of objects to a DataTable.
*
* @param objects the objects to convert
* @param columnNames an explicit list of column names (currently not used)
* @return a DataTable
*/
public DataTable toTable(List> objects, String... columnNames) {
try {
xStream.setParameterType(parameterInfo);
List header = null;
List> valuesList = new ArrayList>();
for (Object object : objects) {
CellWriter writer;
if (isListOfSingleValue(object)) {
// XStream needs this
object = new ArrayList((List) object);
writer = new ListOfSingleValueWriter();
} else {
writer = new ComplexTypeWriter(asList(columnNames));
}
xStream.marshal(object, writer);
if (header == null) {
header = writer.getHeader();
}
List values = writer.getValues();
valuesList.add(values);
}
return createDataTable(header, valuesList);
} finally {
xStream.unsetParameterInfo();
}
}
private DataTable createDataTable(List header, List> valuesList) {
List gherkinRows = new ArrayList();
if (header != null) {
gherkinRows.add(gherkinRow(header));
}
for (List values : valuesList) {
gherkinRows.add(gherkinRow(values));
}
return new DataTable(gherkinRows, this);
}
private DataTableRow gherkinRow(List cells) {
return new DataTableRow(NO_COMMENTS, cells, 0);
}
private List convertTopCellsToFieldNames(DataTable dataTable) {
final StringConverter mapper = new CamelCaseStringConverter();
return map(dataTable.topCells(), new Mapper() {
@Override
public String map(String attributeName) {
return mapper.map(attributeName);
}
});
}
private boolean isListOfSingleValue(Object object) {
if (object instanceof List) {
List list = (List) object;
boolean isSingleValue = xStream.getSingleValueConverter(list.get(0).getClass()) != null;
if (list.size() > 0 && isSingleValue) {
return true;
}
}
return false;
}
private static class GenericListType implements ParameterizedType {
private final Type type;
public GenericListType(Type type) {
this.type = type;
}
@Override
public Type[] getActualTypeArguments() {
return new Type[]{type};
}
@Override
public Type getRawType() {
return List.class;
}
@Override
public Type getOwnerType() {
throw new UnsupportedOperationException();
}
}
}