TableParsers.java
package org.jbehave.core.model;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import org.apache.commons.lang3.StringUtils;
import org.jbehave.core.configuration.Keywords;
import org.jbehave.core.i18n.LocalizedKeywords;
import org.jbehave.core.model.ExamplesTable.TableProperties;
import org.jbehave.core.model.ExamplesTable.TablePropertiesQueue;
import org.jbehave.core.model.ExamplesTable.TableRows;
import org.jbehave.core.steps.ParameterConverters;
public class TableParsers {
private static final String ROW_SEPARATOR_PATTERN = "\r?\n";
private final Keywords keywords;
private final ParameterConverters parameterConverters;
private final Optional<String> defaultNullPlaceholder;
public TableParsers(ParameterConverters parameterConverters) {
this(new LocalizedKeywords(), parameterConverters);
}
public TableParsers(Keywords keywords, ParameterConverters parameterConverters) {
this(keywords, parameterConverters, Optional.empty());
}
public TableParsers(Keywords keywords, ParameterConverters parameterConverters,
Optional<String> defaultNullPlaceholder) {
this.keywords = keywords;
this.parameterConverters = parameterConverters;
this.defaultNullPlaceholder = defaultNullPlaceholder;
}
public TablePropertiesQueue parseProperties(String tableAsString) {
Deque<TableProperties> properties = new LinkedList<>();
String tableWithoutProperties = tableAsString.trim();
Matcher matcher = ExamplesTable.INLINED_PROPERTIES_PATTERN.matcher(tableWithoutProperties);
while (matcher.matches()) {
String propertiesAsString = matcher.group(1);
propertiesAsString = StringUtils.replace(propertiesAsString, "\\{", "{");
propertiesAsString = StringUtils.replace(propertiesAsString, "\\}", "}");
properties.add(new TableProperties(propertiesAsString, keywords, parameterConverters));
tableWithoutProperties = matcher.group(2).trim();
matcher = ExamplesTable.INLINED_PROPERTIES_PATTERN.matcher(tableWithoutProperties);
}
if (properties.isEmpty()) {
properties.add(new TableProperties("", keywords, parameterConverters));
}
return new TablePropertiesQueue(tableWithoutProperties, properties);
}
public TableRows parseRows(String tableAsString, TableProperties properties) {
List<String> headers = new ArrayList<>();
List<Map<String, String>> data = new ArrayList<>();
String[] rows = tableAsString.split(ROW_SEPARATOR_PATTERN);
for (String row : rows) {
String trimmedRow = row.trim();
if (trimmedRow.startsWith(properties.getIgnorableSeparator()) || trimmedRow.isEmpty()) {
// skip ignorable or empty lines
continue;
} else if (headers.isEmpty()) {
headers.addAll(parseRow(trimmedRow, true, properties));
} else {
List<String> columns = parseRow(trimmedRow, false, properties);
Map<String, String> map = new LinkedHashMap<>();
for (int column = 0; column < columns.size(); column++) {
if (column < headers.size()) {
map.put(headers.get(column), columns.get(column));
}
}
data.add(map);
}
}
return new TableRows(headers, data);
}
public List<String> parseRow(String rowAsString, boolean header, TableProperties properties) {
String separator = header ? properties.getHeaderSeparator() : properties.getValueSeparator();
String commentSeparator = properties.getCommentSeparator();
Optional<String> nullPlaceholder = properties.getNullPlaceholder().map(Optional::of).orElse(
defaultNullPlaceholder);
UnaryOperator<String> trimmer = properties.isTrim() ? String::trim : UnaryOperator.identity();
String[] cells = StringUtils.splitByWholeSeparatorPreserveAllTokens(rowAsString.trim(), separator);
List<String> row = new ArrayList<>(cells.length);
for (int i = 0; i < cells.length; i++) {
String cell = cells[i];
cell = StringUtils.substringBefore(cell, commentSeparator);
if ((i == 0 || i == cells.length - 1) && cell.isEmpty()) {
continue;
}
String trimmedCell = trimmer.apply(cell);
row.add(nullPlaceholder.filter(trimmedCell::equals).isPresent() ? null : trimmedCell);
}
return row;
}
}