Added types to FlowableExcelMapper
This commit is contained in:
@@ -2,35 +2,69 @@ package com.example.parser;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.apache.poi.ss.usermodel.DateUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@Component
|
||||
public class FlowableExcelMapper {
|
||||
|
||||
protected static ObjectMapper objectMapper = new ObjectMapper();
|
||||
protected static JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||
protected static FlowableExcelParser flowableExcelParser = new FlowableExcelParser();
|
||||
|
||||
public FlowableExcelMapper() {
|
||||
objectMapper.registerModule(javaTimeModule);
|
||||
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||
}
|
||||
|
||||
public ArrayNode excelToJsonNode(String excelPath) {
|
||||
ArrayList<LinkedHashMap<String, Object>> rowList = flowableExcelParser.parseExcel(excelPath);
|
||||
ArrayList<ArrayList<Object>> rawList = flowableExcelParser.parseExcel(excelPath);
|
||||
ArrayList<Object> paths = new ArrayList<>();
|
||||
ArrayList<Object> types = new ArrayList<>();
|
||||
ArrayNode arrayNode = objectMapper.createArrayNode();
|
||||
for (LinkedHashMap<String, Object> row : rowList) {
|
||||
JsonNode jsonNode = null;
|
||||
Set<Map.Entry<String, Object>> entries = row.entrySet();
|
||||
for (Map.Entry<String, Object> entry : entries) {
|
||||
jsonNode = addNode(jsonNode, entry.getKey(), entry.getValue());
|
||||
for (int rowNum = 0; rowNum < rawList.size(); rowNum++) {
|
||||
if (rowNum == 0) {
|
||||
// The 1st row contains the paths
|
||||
paths.addAll(rawList.get(rowNum));
|
||||
} else if (rowNum == 1) {
|
||||
// The 1st row contains the types of the variables
|
||||
types.addAll(rawList.get(rowNum));
|
||||
} else {
|
||||
// All other rows contain the values of the variables
|
||||
JsonNode jsonNode = null;
|
||||
ArrayList<Object> row = rawList.get(rowNum);
|
||||
for (int cellNum = 0; cellNum < row.size(); cellNum++) {
|
||||
Object content = row.get(cellNum);
|
||||
String type = types.get(cellNum).toString();
|
||||
switch (type) {
|
||||
case "String": content = content.toString(); break;
|
||||
case "Boolean": content = Boolean.parseBoolean(content.toString()); break;
|
||||
case "Integer": content = (int) Double.parseDouble(content.toString()); break;
|
||||
case "Double": content = Double.parseDouble(content.toString()); break;
|
||||
case "Date":
|
||||
// Excel considers dates as local dates, but we want them as UTC
|
||||
Date dateTime = DateUtil.getJavaDate(Double.parseDouble(content.toString()));
|
||||
content = dateTime.toInstant().plusSeconds(ZonedDateTime.now().getOffset().getTotalSeconds());
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
jsonNode = addNode(jsonNode, paths.get(cellNum).toString(), content);
|
||||
}
|
||||
arrayNode.add(jsonNode);
|
||||
}
|
||||
arrayNode.add(jsonNode);
|
||||
}
|
||||
return arrayNode;
|
||||
}
|
||||
|
||||
public JsonNode addNode(JsonNode parent, String path, Object value) {
|
||||
objectMapper = new ObjectMapper();
|
||||
|
||||
protected JsonNode addNode(JsonNode parent, String path, Object value) {
|
||||
if (parent == null) {
|
||||
parent = objectMapper.createObjectNode();
|
||||
}
|
||||
@@ -87,7 +121,7 @@ public class FlowableExcelMapper {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public static int indexOfFirstDelimiter(String str, String delimiters) {
|
||||
protected int indexOfFirstDelimiter(String str, String delimiters) {
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
for (char c : delimiters.toCharArray()) {
|
||||
if (str.charAt(i) == c) {
|
||||
|
||||
@@ -8,56 +8,63 @@ import org.springframework.stereotype.Component;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Component
|
||||
public class FlowableExcelParser {
|
||||
|
||||
public ArrayList<LinkedHashMap<String, Object>> parseExcel(String resourcePath) {
|
||||
ArrayList<LinkedHashMap<String, Object>> rowList = new ArrayList<>();
|
||||
// resourcePath defines the location of the Excel file
|
||||
// Return all cells in the 1st sheet which have values as objects (String, boolean or double)
|
||||
// The 1st row defines the amount of cells per row
|
||||
// Parsing the sheet stops after the 1st empty row
|
||||
public ArrayList<ArrayList<Object>> parseExcel(String resourcePath) {
|
||||
ArrayList<ArrayList<Object>> rows = new ArrayList<>();
|
||||
try (FileInputStream fileInputStream = new FileInputStream(resourcePath)) {
|
||||
Workbook workbook = new XSSFWorkbook(fileInputStream);
|
||||
Sheet sheet = workbook.getSheetAt(0);
|
||||
ArrayList<String> colHeaders = new ArrayList<>();
|
||||
for (Row row : sheet) {
|
||||
if (row.getRowNum() == 0) {
|
||||
// Header row
|
||||
for (int colNum = 0; colNum < row.getLastCellNum(); colNum++) {
|
||||
Cell cell = row.getCell(colNum);
|
||||
if (cell == null || cell.getCellType() == CellType.BLANK || cell.getCellType() == CellType._NONE) {
|
||||
// Take all columns until the first empty header cell
|
||||
break;
|
||||
} else {
|
||||
colHeaders.add(cell.getStringCellValue());
|
||||
}
|
||||
}
|
||||
continue;
|
||||
int maxCells = 0;
|
||||
for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
|
||||
Row row = sheet.getRow(rowNum);
|
||||
if (row == null) {
|
||||
break;
|
||||
}
|
||||
if (maxCells == 0) {
|
||||
maxCells = row.getLastCellNum();
|
||||
}
|
||||
boolean allCellsNull = true;
|
||||
LinkedHashMap<String, Object> rowMap = new LinkedHashMap<>();
|
||||
for (int colNum = 0; colNum < colHeaders.size(); colNum++) {
|
||||
Object content = null;
|
||||
Cell cell = row.getCell(colNum);
|
||||
CellValue cellValue = workbook.getCreationHelper().createFormulaEvaluator().evaluate(cell);
|
||||
if (cellValue != null && cell.getCellType() != CellType.BLANK && cell.getCellType() != CellType._NONE) {
|
||||
switch (cellValue.getCellType()) {
|
||||
case STRING : content = cellValue.getStringValue(); break;
|
||||
case BOOLEAN : content = cellValue.getBooleanValue(); break;
|
||||
case NUMERIC : content = cellValue.getNumberValue(); break;
|
||||
ArrayList<Object> cells = new ArrayList<>();
|
||||
for (int cellNum = 0; cellNum < maxCells; cellNum++) {
|
||||
Cell cell = row.getCell(cellNum);
|
||||
if(rowNum == 0) {
|
||||
if (cell == null || cell.getCellType() == CellType.BLANK || cell.getCellType() == CellType._NONE) {
|
||||
// Count cells of 1st row until the first empty cell
|
||||
maxCells = cellNum;
|
||||
break;
|
||||
}
|
||||
allCellsNull = false;
|
||||
}
|
||||
rowMap.put(colHeaders.get(colNum), content);
|
||||
CellValue cellValue = workbook.getCreationHelper().createFormulaEvaluator().evaluate(cell);
|
||||
Object content = null;
|
||||
if (cellValue != null) {
|
||||
CellType cellType = cell.getCellType();
|
||||
if (cellType != CellType.BLANK && cellType != CellType._NONE) {
|
||||
switch (cellValue.getCellType()) {
|
||||
case STRING : content = cellValue.getStringValue(); break;
|
||||
case BOOLEAN : content = cellValue.getBooleanValue(); break;
|
||||
case NUMERIC : content = cellValue.getNumberValue(); break;
|
||||
}
|
||||
allCellsNull = false;
|
||||
}
|
||||
}
|
||||
cells.add(content);
|
||||
}
|
||||
if (allCellsNull) {
|
||||
// Take all rows until the first empty row
|
||||
return rowList;
|
||||
return rows;
|
||||
}
|
||||
rowList.add(rowMap);
|
||||
rows.add(cells);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return rowList;
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ public class ParserApp {
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private static final FlowableJsonParser flowableJsonParser = new FlowableJsonParser();
|
||||
private static final FlowableExcelParser flowableExcelParser = new FlowableExcelParser();
|
||||
private static final FlowableExcelMapper flowableExcelMapper = new FlowableExcelMapper();
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ParserApp.class, args);
|
||||
@@ -28,9 +29,12 @@ public class ParserApp {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
ClassLoader classLoader = ParserApp.class.getClassLoader();
|
||||
URL resourceUrl = classLoader.getResource("flowableExcelParserExampleData.xlsx");
|
||||
URL resourceUrl = ParserApp.class.getClassLoader().getResource("flowableExcelParserExampleData.xlsx");
|
||||
assert resourceUrl != null;
|
||||
logger.info("parsed excel={}", flowableExcelParser.parseExcel(resourceUrl.getPath()));
|
||||
|
||||
resourceUrl = ParserApp.class.getClassLoader().getResource("flowableExcelMapperExampleData.xlsx");
|
||||
assert resourceUrl != null;
|
||||
logger.info("mapped excel={}", flowableExcelMapper.excelToJsonNode(resourceUrl.getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -18,23 +18,9 @@ class FlowableExcelMapperTest {
|
||||
@Autowired
|
||||
private FlowableExcelMapper flowableExcelMapper;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ParserApp.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(FlowableExcelMapperTest.class);
|
||||
|
||||
|
||||
@Test
|
||||
public void addNodeTest() {
|
||||
JsonNode node = null;
|
||||
node = flowableExcelMapper.addNode(node, "3*0*2", "String1");
|
||||
node = flowableExcelMapper.addNode(node, "3*0*3", "String1");
|
||||
node = flowableExcelMapper.addNode(node, "3*1.1", 234);
|
||||
node = flowableExcelMapper.addNode(node, "3*1.2", 234);
|
||||
node = flowableExcelMapper.addNode(node, "3*2", false);
|
||||
node = flowableExcelMapper.addNode(node, "4.5", "String1");
|
||||
node = flowableExcelMapper.addNode(node, "4.6", 234);
|
||||
node = flowableExcelMapper.addNode(node, "4.7", false);
|
||||
logger.info("node2={}{}", System.lineSeparator(), node.toPrettyString());
|
||||
}
|
||||
|
||||
protected String getResourcePath(String path) {
|
||||
ClassLoader classLoader = FlowableExcelMapperTest.class.getClassLoader();
|
||||
URL resourceUrl = classLoader.getResource(path);
|
||||
@@ -44,7 +30,7 @@ class FlowableExcelMapperTest {
|
||||
|
||||
@Test
|
||||
public void excelToJsonNodeTest() {
|
||||
JsonNode node = flowableExcelMapper.excelToJsonNode(getResourcePath("flowableExcelMapperTestData1.xlsx"));
|
||||
JsonNode node = flowableExcelMapper.excelToJsonNode(getResourcePath("flowableExcelMapperTestData.xlsx"));
|
||||
logger.info("node2={}{}", System.lineSeparator(), node.toPrettyString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,26 +20,18 @@ class FlowableExcelParserTest {
|
||||
@Autowired
|
||||
private FlowableExcelParser flowableExcelParser;
|
||||
|
||||
private Stream<Arguments> GetArgumentsFromExcel(String path) {
|
||||
ArrayList<Arguments> argumentList = new ArrayList<>();
|
||||
protected String getResourcePath(String path) {
|
||||
ClassLoader classLoader = FlowableExcelParserTest.class.getClassLoader();
|
||||
URL resourceUrl = classLoader.getResource(path);
|
||||
Assertions.assertThat(resourceUrl).isNotNull();
|
||||
ArrayList<LinkedHashMap<String, Object>> rowList = flowableExcelParser.parseExcel(resourceUrl.getPath());
|
||||
Assertions.assertThat(rowList).isNotNull();
|
||||
for (LinkedHashMap<String, Object> row : rowList) {
|
||||
LinkedHashMap<String, Object> inputMap = new LinkedHashMap<>();
|
||||
LinkedHashMap<String, Object> outputMap = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, Object> entry : row.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (List.of("input1", "input2", "input3").contains(key)) {
|
||||
inputMap.put(key, entry.getValue());
|
||||
}
|
||||
if (List.of("output1", "output2").contains(key)) {
|
||||
outputMap.put(key, entry.getValue());
|
||||
}
|
||||
}
|
||||
argumentList.add(Arguments.of(inputMap, outputMap));
|
||||
return resourceUrl.getPath();
|
||||
}
|
||||
|
||||
protected Stream<Arguments> GetArgumentsFromExcel(String path) {
|
||||
ArrayList<Arguments> argumentList = new ArrayList<>();
|
||||
ArrayList<ArrayList<Object>> rowList = flowableExcelParser.parseExcel(getResourcePath(path));
|
||||
for (ArrayList<Object> row : rowList) {
|
||||
argumentList.add(Arguments.of(row));
|
||||
}
|
||||
return argumentList.stream();
|
||||
}
|
||||
@@ -51,18 +43,12 @@ class FlowableExcelParserTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("booleanExcelParserTestDataProvider")
|
||||
void booleanExcelParserTest(LinkedHashMap<String, Object> inputMap, LinkedHashMap<String, Object> outputMap) {
|
||||
for (Map.Entry<String, Object> entry : outputMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (key.equals("output1")) {
|
||||
Boolean val = (Boolean)inputMap.get("input1") || (Boolean)inputMap.get("input2") || (Boolean)inputMap.get("input3");
|
||||
Assertions.assertThat(entry.getValue()).isEqualTo(val);
|
||||
}
|
||||
if (key.equals("output2")) {
|
||||
Boolean val = (Boolean)inputMap.get("input1") && (Boolean)inputMap.get("input2") && (Boolean)inputMap.get("input3");
|
||||
Assertions.assertThat(entry.getValue()).isEqualTo(val);
|
||||
}
|
||||
}
|
||||
void booleanExcelParserTest(ArrayList<Object> row) {
|
||||
Boolean valOr = (Boolean) row.get(0) || (Boolean) row.get(1) || (Boolean) row.get(2);
|
||||
Assertions.assertThat(row.get(3)).isEqualTo(valOr);
|
||||
|
||||
Boolean valAnd = (Boolean) row.get(0) && (Boolean) row.get(1) && (Boolean) row.get(2);
|
||||
Assertions.assertThat(row.get(4)).isEqualTo(valAnd);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -72,22 +58,15 @@ class FlowableExcelParserTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("stringExcelParserTestDataProvider")
|
||||
void stringExcelParserTest(LinkedHashMap<String, Object> inputMap, LinkedHashMap<String, Object> outputMap) {
|
||||
for (Map.Entry<String, Object> entry : outputMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (key.equals("output1")) {
|
||||
String val = inputMap.get("input1").toString() + inputMap.get("input2").toString();
|
||||
Assertions.assertThat(entry.getValue()).isEqualTo(val);
|
||||
}
|
||||
if (key.equals("output2")) {
|
||||
String val = inputMap.get("input2").toString() + inputMap.get("input3").toString();
|
||||
Assertions.assertThat(entry.getValue()).isEqualTo(val);
|
||||
}
|
||||
if (key.equals("output3")) {
|
||||
String val = inputMap.get("input1").toString() + inputMap.get("input2").toString() + inputMap.get("input3").toString();
|
||||
Assertions.assertThat(entry.getValue()).isEqualTo(val);
|
||||
}
|
||||
}
|
||||
void stringExcelParserTest(ArrayList<Object> row) {
|
||||
String val12 = row.get(0).toString() + row.get(1).toString();
|
||||
Assertions.assertThat(row.get(3)).isEqualTo(val12);
|
||||
|
||||
String val23 = row.get(1).toString() + row.get(2).toString();
|
||||
Assertions.assertThat(row.get(4)).isEqualTo(val23);
|
||||
|
||||
String val123 = row.get(0).toString() + row.get(1).toString() + row.get(2).toString();
|
||||
Assertions.assertThat(row.get(5)).isEqualTo(val123);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -97,21 +76,14 @@ class FlowableExcelParserTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("numberExcelParserTestDataProvider")
|
||||
void numberExcelParserTest(LinkedHashMap<String, Object> inputMap, LinkedHashMap<String, Object> outputMap) {
|
||||
for (Map.Entry<String, Object> entry : outputMap.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (key.equals("output1")) {
|
||||
Double val = (Double)inputMap.get("input1") + (Double)inputMap.get("input2");
|
||||
Assertions.assertThat(entry.getValue()).isEqualTo(val);
|
||||
}
|
||||
if (key.equals("output2")) {
|
||||
Double val = (Double)inputMap.get("input2") + (Double)inputMap.get("input3");
|
||||
Assertions.assertThat(entry.getValue()).isEqualTo(val);
|
||||
}
|
||||
if (key.equals("output3")) {
|
||||
Double val = (Double)inputMap.get("input1") + (Double)inputMap.get("input2") + (Double)inputMap.get("input3");
|
||||
Assertions.assertThat(entry.getValue()).isEqualTo(val);
|
||||
}
|
||||
}
|
||||
void numberExcelParserTest(ArrayList<Object> row) {
|
||||
Double val12 = (Double) row.get(0) + (Double) row.get(1);
|
||||
Assertions.assertThat(row.get(3)).isEqualTo(val12);
|
||||
|
||||
Double val23 = (Double) row.get(1) + (Double) row.get(2);
|
||||
Assertions.assertThat(row.get(4)).isEqualTo(val23);
|
||||
|
||||
Double val123 = (Double) row.get(0) + (Double) row.get(1) + (Double) row.get(2);
|
||||
Assertions.assertThat(row.get(5)).isEqualTo(val123);
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user