Compare commits
10 Commits
1ceafba8f1
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| bbaacfb439 | |||
| b105c63c7e | |||
| bc9f2a7451 | |||
| ff8f71abf4 | |||
| f8ee09c97a | |||
| 3806797041 | |||
| d570e04087 | |||
| 0cc2304ad8 | |||
| caa1e4b8f8 | |||
| 861633d373 |
Generated
+1
-1
@@ -74,7 +74,7 @@
|
|||||||
</profile-state>
|
</profile-state>
|
||||||
</entry>
|
</entry>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="homebrew-17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="homebrew-17" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -6,10 +6,11 @@ import com.fasterxml.jackson.databind.SerializationFeature;
|
|||||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import org.apache.poi.ss.usermodel.DateUtil;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ public class FlowableExcelMapper {
|
|||||||
|
|
||||||
// excelPath defines the location of the Excel file
|
// excelPath defines the location of the Excel file
|
||||||
// FlowableExcelParser is used to create an ArrayList from the Excel file
|
// FlowableExcelParser is used to create an ArrayList from the Excel file
|
||||||
// The first row of every sheet contains the path of the variables to be created in the JsonNode
|
// The 1st row of every sheet contains the path of the variables to be created in the JsonNode
|
||||||
// Delimiter is "." for an ObjectNode and "*" for an ArrayNode
|
// Delimiter is "." for an ObjectNode and "*" for an ArrayNode
|
||||||
// The 2nd row contains tht type of the variable. Supported types are:
|
// The 2nd row contains tht type of the variable. Supported types are:
|
||||||
// - String
|
// - String
|
||||||
@@ -39,29 +40,29 @@ public class FlowableExcelMapper {
|
|||||||
// All sheets are added to an ArrayNode
|
// All sheets are added to an ArrayNode
|
||||||
// All rows are added to an ArrayNode in the sheets ArrayNode
|
// All rows are added to an ArrayNode in the sheets ArrayNode
|
||||||
// All cell values are added to an ObjectNode in the rows ArrayNode
|
// All cell values are added to an ObjectNode in the rows ArrayNode
|
||||||
public ArrayNode excelBookToJsonNode(String excelPath) {
|
public ArrayNode excelBookResourceToJsonNode(String resourcePath) {
|
||||||
ArrayList<ArrayList<ArrayList<Object>>> book = flowableExcelParser.parseExcelBook(excelPath);
|
ArrayList<ArrayList<ArrayList<String>>> book = flowableExcelParser.parseExcelBookFromResource(resourcePath);
|
||||||
return bookToJsonNode(book);
|
return bookToJsonNode(book);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ArrayNode bookToJsonNode(ArrayList<ArrayList<ArrayList<Object>>> book) {
|
protected ArrayNode bookToJsonNode(ArrayList<ArrayList<ArrayList<String>>> book) {
|
||||||
ArrayNode bookNode = objectMapper.createArrayNode();
|
ArrayNode bookNode = objectMapper.createArrayNode();
|
||||||
for (ArrayList<ArrayList<Object>> sheet : book) {
|
for (ArrayList<ArrayList<String>> sheet : book) {
|
||||||
bookNode.add(sheetToJsonNode(sheet));
|
bookNode.add(sheetToJsonNode(sheet));
|
||||||
}
|
}
|
||||||
return bookNode;
|
return bookNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ArrayNode sheetToJsonNode(ArrayList<ArrayList<Object>> rows) {
|
protected ArrayNode sheetToJsonNode(ArrayList<ArrayList<String>> rows) {
|
||||||
ArrayList<Object> paths = new ArrayList<>();
|
ArrayList<String> paths = new ArrayList<>();
|
||||||
ArrayList<Object> types = new ArrayList<>();
|
ArrayList<String> types = new ArrayList<>();
|
||||||
ArrayNode arrayNode = objectMapper.createArrayNode();
|
ArrayNode arrayNode = objectMapper.createArrayNode();
|
||||||
for (int rowNum = 0; rowNum < rows.size(); rowNum++) {
|
for (int rowNum = 0; rowNum < rows.size(); rowNum++) {
|
||||||
if (rowNum == 0) {
|
if (rowNum == 0) {
|
||||||
// The 1st row contains the paths
|
// The 1st row contains the paths
|
||||||
paths.addAll(rows.get(rowNum));
|
paths.addAll(rows.get(rowNum));
|
||||||
} else if (rowNum == 1) {
|
} else if (rowNum == 1) {
|
||||||
// The 1st row contains the types of the variables
|
// The 2nd row contains the types of the variables
|
||||||
types.addAll(rows.get(rowNum));
|
types.addAll(rows.get(rowNum));
|
||||||
} else {
|
} else {
|
||||||
// All other rows contain the values of the variables
|
// All other rows contain the values of the variables
|
||||||
@@ -71,25 +72,47 @@ public class FlowableExcelMapper {
|
|||||||
return arrayNode;
|
return arrayNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JsonNode rowToJsonNode(ArrayList<Object> types, ArrayList<Object> paths, ArrayList<Object> row, JsonNode jsonNode) {
|
protected JsonNode rowToJsonNode(ArrayList<String> types, ArrayList<String> paths, ArrayList<String> row, JsonNode jsonNode) {
|
||||||
for (int cellNum = 0; cellNum < row.size(); cellNum++) {
|
for (int cellNum = 0; cellNum < row.size(); cellNum++) {
|
||||||
Object content = row.get(cellNum);
|
String cellValue = row.get(cellNum);
|
||||||
if (content != null) {
|
// Empty cells are not added to node
|
||||||
String type = types.get(cellNum).toString();
|
if (cellValue != null && !cellValue.isEmpty()) {
|
||||||
switch (type) {
|
String type = types.get(cellNum);
|
||||||
case "String": content = content.toString(); break;
|
Object content;
|
||||||
case "Boolean": content = Boolean.parseBoolean(content.toString()); break;
|
switch (cellValue) {
|
||||||
case "Integer": content = (int) Double.parseDouble(content.toString()); break;
|
case "__NULL": content = null; break;
|
||||||
case "Double": content = Double.parseDouble(content.toString()); break;
|
case "__N_A": content = "__N_A"; break;
|
||||||
case "Date":
|
default:
|
||||||
// Excel considers dates as local dates, but we want them as UTC
|
switch (type) {
|
||||||
Date dateTime = DateUtil.getJavaDate(Double.parseDouble(content.toString()));
|
case "String":
|
||||||
content = dateTime.toInstant().plusSeconds(ZonedDateTime.now().getOffset().getTotalSeconds());
|
switch (cellValue) {
|
||||||
break;
|
case "__EMPTY": content = ""; break;
|
||||||
default: break;
|
case "__BLANK": content = " "; break;
|
||||||
|
default: content = cellValue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "Boolean": content = Boolean.parseBoolean(cellValue); break;
|
||||||
|
case "Integer": content = Integer.parseInt(cellValue); break;
|
||||||
|
case "Double": content = Double.parseDouble(cellValue); break;
|
||||||
|
case "Long": content = Long.parseLong(cellValue); break;
|
||||||
|
case "Date":
|
||||||
|
// Excel considers dates as local dates, but we want them as UTC
|
||||||
|
Instant instant;
|
||||||
|
try {
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
|
||||||
|
} catch (DateTimeParseException e) {
|
||||||
|
LocalDate localDate = LocalDate.parse(cellValue, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
||||||
|
instant = localDate.atStartOfDay(ZoneId.systemDefault()).toInstant();
|
||||||
|
}
|
||||||
|
content = instant.plusSeconds(ZonedDateTime.now().getOffset().getTotalSeconds());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new RuntimeException("Variable type not supported: " + type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
jsonNode = addNode(jsonNode, paths.get(cellNum), content);
|
||||||
}
|
}
|
||||||
jsonNode = addNode(jsonNode, paths.get(cellNum).toString(), content);
|
|
||||||
}
|
}
|
||||||
return jsonNode;
|
return jsonNode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -15,16 +17,16 @@ public class FlowableExcelParser {
|
|||||||
|
|
||||||
// excelPath defines the location of the Excel file
|
// excelPath defines the location of the Excel file
|
||||||
// Return all cells in all sheets with the following restrictions:
|
// Return all cells in all sheets with the following restrictions:
|
||||||
// - Max columns per sheet is defined in the first row
|
// - Max column count per sheet is defined in the first row
|
||||||
// - Max column count starts with the 1st cell and ends with the 1st empty cell
|
// - Max column count starts with the 1st cell and ends with the 1st empty cell
|
||||||
// - Parsing the sheet stops after the 1st empty row
|
// - Parsing the sheet stops after the 1st empty row
|
||||||
// All sheets are added to an ArrayList
|
// All sheets are added to an ArrayList
|
||||||
// All rows are added to an ArrayList in the sheets ArrayList
|
// All rows are added to an ArrayList in the sheets ArrayList
|
||||||
// All cell values are added to an ArrayList in the rows ArrayList
|
// All cell values are added to an ArrayList in the rows ArrayList
|
||||||
// Formulas in cells are evaluated
|
// Formulas in cells are evaluated
|
||||||
// Excel values can have only 3 types: String, boolean, double
|
// All values are returned as String
|
||||||
public ArrayList<ArrayList<ArrayList<Object>>> parseExcelBook(String excelPath) {
|
public ArrayList<ArrayList<ArrayList<String>>> parseExcelBookFromResource(String excelResourcePath) {
|
||||||
try (FileInputStream fileInputStream = new FileInputStream(excelPath)) {
|
try (FileInputStream fileInputStream = new FileInputStream(getResourcePath(excelResourcePath))) {
|
||||||
Workbook workBook = new XSSFWorkbook(fileInputStream);
|
Workbook workBook = new XSSFWorkbook(fileInputStream);
|
||||||
return parseBook(workBook);
|
return parseBook(workBook);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -32,8 +34,9 @@ public class FlowableExcelParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<ArrayList<Object>> parseExcelSheet(String excelPath) {
|
@Deprecated
|
||||||
try (FileInputStream fileInputStream = new FileInputStream(excelPath)) {
|
public ArrayList<ArrayList<String>> parseExcelSheetFromResource(String excelResourcePath) {
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(getResourcePath(excelResourcePath))) {
|
||||||
Workbook workBook = new XSSFWorkbook(fileInputStream);
|
Workbook workBook = new XSSFWorkbook(fileInputStream);
|
||||||
FormulaEvaluator formulaEvaluator = workBook.getCreationHelper().createFormulaEvaluator();
|
FormulaEvaluator formulaEvaluator = workBook.getCreationHelper().createFormulaEvaluator();
|
||||||
Sheet workSheet = workBook.getSheetAt(0);
|
Sheet workSheet = workBook.getSheetAt(0);
|
||||||
@@ -43,8 +46,17 @@ public class FlowableExcelParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ArrayList<ArrayList<ArrayList<Object>>> parseBook(Workbook workBook ) {
|
private String getResourcePath(String resourcePath) {
|
||||||
ArrayList<ArrayList<ArrayList<Object>>> book = new ArrayList<>();
|
ClassLoader classLoader = FlowableExcelParser.class.getClassLoader();
|
||||||
|
URL resourceUrl = classLoader.getResource(resourcePath);
|
||||||
|
if (resourceUrl == null) {
|
||||||
|
throw new RuntimeException("Resource not found: " + resourcePath);
|
||||||
|
}
|
||||||
|
return resourceUrl.getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<ArrayList<ArrayList<String>>> parseBook(Workbook workBook ) {
|
||||||
|
ArrayList<ArrayList<ArrayList<String>>> book = new ArrayList<>();
|
||||||
FormulaEvaluator formulaEvaluator = workBook.getCreationHelper().createFormulaEvaluator();
|
FormulaEvaluator formulaEvaluator = workBook.getCreationHelper().createFormulaEvaluator();
|
||||||
for (Sheet workSheet : workBook) {
|
for (Sheet workSheet : workBook) {
|
||||||
book.add(parseSheet(workSheet, formulaEvaluator));
|
book.add(parseSheet(workSheet, formulaEvaluator));
|
||||||
@@ -52,14 +64,13 @@ public class FlowableExcelParser {
|
|||||||
return book;
|
return book;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ArrayList<ArrayList<Object>> parseSheet(Sheet workSheet, FormulaEvaluator formulaEvaluator) {
|
private ArrayList<ArrayList<String>> parseSheet(Sheet workSheet, FormulaEvaluator formulaEvaluator) {
|
||||||
ArrayList<ArrayList<Object>> sheet = new ArrayList<>();
|
ArrayList<ArrayList<String>> sheet = new ArrayList<>();
|
||||||
// Count columns of first row
|
// Count columns of first row
|
||||||
int maxCols = getMaxCols(workSheet.getRow(0));
|
int maxCols = getMaxCols(workSheet.getRow(0));
|
||||||
int lastRowNum = workSheet.getLastRowNum();
|
DataFormatter dataFormatter = new DataFormatter();
|
||||||
for (int rowIndex = 0; rowIndex < lastRowNum; rowIndex++) {
|
for (Row workRow : workSheet) {
|
||||||
Row workRow = workSheet.getRow(rowIndex);
|
ArrayList<String> row = parseRow(workRow, maxCols, formulaEvaluator, dataFormatter);
|
||||||
ArrayList<Object> row = parseRow(workRow, maxCols, formulaEvaluator);
|
|
||||||
if (row == null) {
|
if (row == null) {
|
||||||
// Take all rows until the first empty row
|
// Take all rows until the first empty row
|
||||||
break;
|
break;
|
||||||
@@ -70,34 +81,19 @@ public class FlowableExcelParser {
|
|||||||
return sheet;
|
return sheet;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ArrayList<Object> parseRow(Row workRow, int maxCols, FormulaEvaluator formulaEvaluator) {
|
private ArrayList<String> parseRow(Row workRow, int maxCols, FormulaEvaluator formulaEvaluator, DataFormatter dataFormatter) {
|
||||||
if (workRow == null) {
|
if (workRow == null) {
|
||||||
// Row is empty
|
// Row is empty
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ArrayList<Object> row = new ArrayList<>();
|
ArrayList<String> row = new ArrayList<>();
|
||||||
boolean allCellsNull = true;
|
boolean allCellsNull = true;
|
||||||
for (int colIndex = 0; colIndex < maxCols; colIndex++) {
|
for (int colIndex = 0; colIndex < maxCols; colIndex++) {
|
||||||
Object content = null;
|
|
||||||
Cell workCell = workRow.getCell(colIndex);
|
Cell workCell = workRow.getCell(colIndex);
|
||||||
if (workCell != null) {
|
formulaEvaluator.evaluate(workCell);
|
||||||
CellType workCellType = workCell.getCellType();
|
String content = dataFormatter.formatCellValue(workCell, formulaEvaluator);
|
||||||
if (workCellType != CellType.BLANK && workCellType != CellType._NONE) {
|
if (content != null && !content.isEmpty()) {
|
||||||
allCellsNull = false;
|
allCellsNull = false;
|
||||||
switch (workCellType) {
|
|
||||||
case STRING : content = workCell.getStringCellValue(); break;
|
|
||||||
case BOOLEAN : content = workCell.getBooleanCellValue(); break;
|
|
||||||
case NUMERIC : content = workCell.getNumericCellValue(); break;
|
|
||||||
case FORMULA :
|
|
||||||
CellValue evaluatedValue = formulaEvaluator.evaluate(workCell);
|
|
||||||
switch (evaluatedValue.getCellType()) {
|
|
||||||
case STRING : content = evaluatedValue.getStringValue(); break;
|
|
||||||
case BOOLEAN : content = evaluatedValue.getBooleanValue(); break;
|
|
||||||
case NUMERIC : content = evaluatedValue.getNumberValue(); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
row.add(content);
|
row.add(content);
|
||||||
}
|
}
|
||||||
@@ -109,7 +105,7 @@ public class FlowableExcelParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getMaxCols(Row workRow) {
|
private int getMaxCols(Row workRow) {
|
||||||
int maxCol = workRow.getLastCellNum();
|
int maxCol = workRow.getLastCellNum();
|
||||||
for (int colIndex = 0; colIndex < maxCol; colIndex++) {
|
for (int colIndex = 0; colIndex < maxCol; colIndex++) {
|
||||||
Cell workCell = workRow.getCell(colIndex);
|
Cell workCell = workRow.getCell(colIndex);
|
||||||
@@ -120,4 +116,33 @@ public class FlowableExcelParser {
|
|||||||
}
|
}
|
||||||
return maxCol;
|
return maxCol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
public ArrayList<LinkedHashMap<String, Object>> parseExcelFromResource(String resourcePath) {
|
||||||
|
try (FileInputStream fileInputStream = new FileInputStream(getResourcePath(resourcePath))) {
|
||||||
|
Workbook workBook = new XSSFWorkbook(fileInputStream);
|
||||||
|
FormulaEvaluator formulaEvaluator = workBook.getCreationHelper().createFormulaEvaluator();
|
||||||
|
ArrayList<ArrayList<String>> sheet = parseSheet(workBook.getSheetAt(0), formulaEvaluator);
|
||||||
|
ArrayList<String> colHeaders = new ArrayList<>();
|
||||||
|
ArrayList<LinkedHashMap<String, Object>> rowList = new ArrayList<>();
|
||||||
|
for (int rowIndex = 0; rowIndex < sheet.size(); rowIndex++) {
|
||||||
|
ArrayList<String> row = sheet.get(rowIndex);
|
||||||
|
if (rowIndex == 0) {
|
||||||
|
// Header row
|
||||||
|
for (Object cell : row) {
|
||||||
|
colHeaders.add(String.valueOf(cell));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LinkedHashMap<String, Object> rowMap = new LinkedHashMap<>();
|
||||||
|
for (int colIndex = 0; colIndex < row.size(); colIndex++) {
|
||||||
|
rowMap.put(colHeaders.get(colIndex), row.get(colIndex));
|
||||||
|
}
|
||||||
|
rowList.add(rowMap);
|
||||||
|
}
|
||||||
|
return rowList;
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@@ -29,12 +28,8 @@ public class ParserApp {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
URL resourceUrl = ParserApp.class.getClassLoader().getResource("flowableExcelParserExampleData.xlsx");
|
logger.info("parsed excel={}", flowableExcelParser.parseExcelBookFromResource("flowableExcelParserExampleData.xlsx"));
|
||||||
assert resourceUrl != null;
|
|
||||||
logger.info("parsed excel={}", flowableExcelParser.parseExcelBook(resourceUrl.getPath()));
|
|
||||||
|
|
||||||
resourceUrl = ParserApp.class.getClassLoader().getResource("flowableExcelMapperExampleData.xlsx");
|
logger.info("mapped excel={}", flowableExcelMapper.excelBookResourceToJsonNode("flowableExcelMapperExampleData.xlsx"));
|
||||||
assert resourceUrl != null;
|
|
||||||
logger.info("mapped excel={}", flowableExcelMapper.excelBookToJsonNode(resourceUrl.getPath()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
@@ -2,18 +2,15 @@ package com.example.parser;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import org.assertj.core.api.Assertions;
|
import org.assertj.core.api.Assertions;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.junit.jupiter.api.TestInstance;
|
import org.junit.jupiter.api.TestInstance;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
||||||
@@ -24,19 +21,70 @@ class FlowableExcelMapperTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private FlowableExcelMapper flowableExcelMapper;
|
private FlowableExcelMapper flowableExcelMapper;
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(FlowableExcelMapperTest.class);
|
|
||||||
|
|
||||||
|
public boolean isSubset(JsonNode root, JsonNode test) {
|
||||||
protected String getResourcePath(String path) {
|
// If test is null, it is always a subset of root
|
||||||
ClassLoader classLoader = FlowableExcelMapperTest.class.getClassLoader();
|
if (test == null) {
|
||||||
URL resourceUrl = classLoader.getResource(path);
|
return true;
|
||||||
Assertions.assertThat(resourceUrl).isNotNull();
|
}
|
||||||
return resourceUrl.getPath();
|
// If test is a value node, compare values
|
||||||
|
if (test.isValueNode()) {
|
||||||
|
if (test.isTextual() && "__N_A".equals(test.asText())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (root == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return root.isValueNode() && root.asText().equals(test.asText());
|
||||||
|
}
|
||||||
|
// If test is an array node, check if all elements of test exist in root
|
||||||
|
if(test.isArray()){
|
||||||
|
for (int i = 0; i < test.size(); i++) {
|
||||||
|
JsonNode testElement = test.get(i);
|
||||||
|
JsonNode rootElement = null;
|
||||||
|
if (root != null) {
|
||||||
|
rootElement = root.get(i);
|
||||||
|
}
|
||||||
|
if (testElement.isTextual() && "__N_A".equals(testElement.asText())) {
|
||||||
|
if (rootElement != null && !rootElement.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isSubset(rootElement, testElement)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If test is an object node, check if all fields in test exist in root
|
||||||
|
if (test.isObject()){
|
||||||
|
for (Iterator<String> iterator = test.fieldNames(); iterator.hasNext(); ) {
|
||||||
|
String fieldName = iterator.next();
|
||||||
|
JsonNode testValue = test.get(fieldName);
|
||||||
|
JsonNode rootValue = null;
|
||||||
|
if (root != null) {
|
||||||
|
rootValue = root.get(fieldName);
|
||||||
|
}
|
||||||
|
if (testValue.isTextual() && "__N_A".equals(testValue.asText())) {
|
||||||
|
if (root != null && root.has(fieldName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isSubset(rootValue, testValue)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If none of the above matches, return false
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Stream<Arguments> getArgumentsFromExcel(String path) {
|
protected Stream<Arguments> getArgumentsFromExcel(String path) {
|
||||||
ArrayList<Arguments> argumentList = new ArrayList<>();
|
ArrayList<Arguments> argumentList = new ArrayList<>();
|
||||||
JsonNode book = flowableExcelMapper.excelBookToJsonNode(getResourcePath(path));
|
JsonNode book = flowableExcelMapper.excelBookResourceToJsonNode(path);
|
||||||
for (JsonNode sheet : book) {
|
for (JsonNode sheet : book) {
|
||||||
for (JsonNode row : sheet) {
|
for (JsonNode row : sheet) {
|
||||||
argumentList.add(Arguments.of(row));
|
argumentList.add(Arguments.of(row));
|
||||||
@@ -45,13 +93,27 @@ class FlowableExcelMapperTest {
|
|||||||
return argumentList.stream();
|
return argumentList.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
protected Stream<Arguments> excelMapperTestOk() {
|
||||||
protected Stream<Arguments> excelMapperTestData() {
|
return getArgumentsFromExcel("flowableExcelMapperTestData_ok.xlsx");
|
||||||
return getArgumentsFromExcel("flowableExcelMapperTestData.xlsx");
|
|
||||||
}
|
}
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("excelMapperTestData")
|
@MethodSource
|
||||||
public void excelMapperTest(JsonNode sheet) {
|
public void excelMapperTestOk(JsonNode row) {
|
||||||
logger.info("node2={}{}", System.lineSeparator(), sheet.toPrettyString());
|
JsonNode root = row.get("root");
|
||||||
|
JsonNode test = row.get("test");
|
||||||
|
Assertions.assertThat(isSubset(root, test))
|
||||||
|
.withFailMessage(System.lineSeparator() + "test :" + test + System.lineSeparator() + "root :" + root).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Stream<Arguments> excelMapperTestFail() {
|
||||||
|
return getArgumentsFromExcel("flowableExcelMapperTestData_fail.xlsx");
|
||||||
|
}
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource
|
||||||
|
public void excelMapperTestFail(JsonNode row) {
|
||||||
|
JsonNode root = row.get("root");
|
||||||
|
JsonNode test = row.get("test");
|
||||||
|
Assertions.assertThat(isSubset(root, test))
|
||||||
|
.withFailMessage(System.lineSeparator() + "test :" + test + System.lineSeparator() + "root :" + root).isFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import org.junit.jupiter.params.provider.MethodSource;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@@ -21,49 +20,42 @@ class FlowableExcelParserTest {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private FlowableExcelParser flowableExcelParser;
|
private FlowableExcelParser flowableExcelParser;
|
||||||
|
|
||||||
protected String getResourcePath(String path) {
|
protected Stream<Arguments> getArgumentsFromExcelBook(String resourcePath) {
|
||||||
ClassLoader classLoader = FlowableExcelParserTest.class.getClassLoader();
|
|
||||||
URL resourceUrl = classLoader.getResource(path);
|
|
||||||
Assertions.assertThat(resourceUrl).isNotNull();
|
|
||||||
return resourceUrl.getPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Stream<Arguments> getArgumentsFromExcel(String path) {
|
|
||||||
ArrayList<Arguments> argumentList = new ArrayList<>();
|
ArrayList<Arguments> argumentList = new ArrayList<>();
|
||||||
ArrayList<ArrayList<ArrayList<Object>>> book = flowableExcelParser.parseExcelBook(getResourcePath(path));
|
ArrayList<ArrayList<ArrayList<String>>> book = flowableExcelParser.parseExcelBookFromResource(resourcePath);
|
||||||
for (ArrayList<ArrayList<Object>> sheet : book) {
|
for (ArrayList<ArrayList<String>> sheet : book) {
|
||||||
for (ArrayList<Object> row : sheet) {
|
for (ArrayList<String> row : sheet) {
|
||||||
argumentList.add(Arguments.of(row));
|
argumentList.add(Arguments.of(row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrayList<ArrayList<Object>> sheet = flowableExcelParser.parseExcelSheet(getResourcePath(path));
|
ArrayList<ArrayList<String>> sheet = flowableExcelParser.parseExcelSheetFromResource(resourcePath);
|
||||||
for (ArrayList<Object> row : sheet) {
|
for (ArrayList<String> row : sheet) {
|
||||||
argumentList.add(Arguments.of(row));
|
argumentList.add(Arguments.of(row));
|
||||||
}
|
}
|
||||||
return argumentList.stream();
|
return argumentList.stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected Stream<Arguments> booleanExcelParserTestData() {
|
protected Stream<Arguments> booleanExcelParserTest() {
|
||||||
return getArgumentsFromExcel("flowableExcelParserTestData1.xlsx");
|
return getArgumentsFromExcelBook("flowableExcelParserTestDataBoolean.xlsx");
|
||||||
}
|
}
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("booleanExcelParserTestData")
|
@MethodSource
|
||||||
void booleanExcelParserTest(ArrayList<Object> row) {
|
public void booleanExcelParserTest(ArrayList<Object> row) {
|
||||||
Boolean valOr = (Boolean) row.get(0) || (Boolean) row.get(1) || (Boolean) row.get(2);
|
Boolean valOr = Boolean.parseBoolean(row.get(0).toString()) || Boolean.parseBoolean(row.get(1).toString()) || Boolean.parseBoolean(row.get(2).toString());
|
||||||
Assertions.assertThat(row.get(3)).isEqualTo(valOr);
|
Assertions.assertThat(Boolean.parseBoolean(row.get(3).toString())).isEqualTo(valOr);
|
||||||
|
|
||||||
Boolean valAnd = (Boolean) row.get(0) && (Boolean) row.get(1) && (Boolean) row.get(2);
|
Boolean valAnd = Boolean.parseBoolean(row.get(0).toString()) && Boolean.parseBoolean(row.get(1).toString()) && Boolean.parseBoolean(row.get(2).toString());
|
||||||
Assertions.assertThat(row.get(4)).isEqualTo(valAnd);
|
Assertions.assertThat(Boolean.parseBoolean(row.get(4).toString())).isEqualTo(valAnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected Stream<Arguments> stringExcelParserTestData() {
|
protected Stream<Arguments> stringExcelParserTest() {
|
||||||
return getArgumentsFromExcel("flowableExcelParserTestData2.xlsx");
|
return getArgumentsFromExcelBook("flowableExcelParserTestDataString.xlsx");
|
||||||
}
|
}
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("stringExcelParserTestData")
|
@MethodSource
|
||||||
void stringExcelParserTest(ArrayList<Object> row) {
|
public void stringExcelParserTest(ArrayList<Object> row) {
|
||||||
String val12 = row.get(0).toString() + row.get(1).toString();
|
String val12 = row.get(0).toString() + row.get(1).toString();
|
||||||
Assertions.assertThat(row.get(3)).isEqualTo(val12);
|
Assertions.assertThat(row.get(3)).isEqualTo(val12);
|
||||||
|
|
||||||
@@ -75,19 +67,108 @@ class FlowableExcelParserTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
protected Stream<Arguments> numberExcelParserTestData() {
|
protected Stream<Arguments> numberExcelParserTest() {
|
||||||
return getArgumentsFromExcel("flowableExcelParserTestData3.xlsx");
|
return getArgumentsFromExcelBook("flowableExcelParserTestDataInteger.xlsx");
|
||||||
}
|
}
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("numberExcelParserTestData")
|
@MethodSource
|
||||||
void numberExcelParserTest(ArrayList<Object> row) {
|
public void numberExcelParserTest(ArrayList<Object> row) {
|
||||||
Double val12 = (Double) row.get(0) + (Double) row.get(1);
|
Integer val12 = Integer.parseInt(row.get(0).toString()) + Integer.parseInt(row.get(1).toString());
|
||||||
Assertions.assertThat(row.get(3)).isEqualTo(val12);
|
Assertions.assertThat(Integer.parseInt(row.get(3).toString())).isEqualTo(val12);
|
||||||
|
|
||||||
Double val23 = (Double) row.get(1) + (Double) row.get(2);
|
Integer val23 = Integer.parseInt(row.get(1).toString()) + Integer.parseInt(row.get(2).toString());
|
||||||
Assertions.assertThat(row.get(4)).isEqualTo(val23);
|
Assertions.assertThat(Integer.parseInt(row.get(4).toString())).isEqualTo(val23);
|
||||||
|
|
||||||
Double val123 = (Double) row.get(0) + (Double) row.get(1) + (Double) row.get(2);
|
Integer val123 = Integer.parseInt(row.get(0).toString()) + Integer.parseInt(row.get(1).toString()) + Integer.parseInt(row.get(2).toString());
|
||||||
Assertions.assertThat(row.get(5)).isEqualTo(val123);
|
Assertions.assertThat(Integer.parseInt(row.get(5).toString())).isEqualTo(val123);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
protected Stream<Arguments> getArgumentsFromExcel(String resourcePath) {
|
||||||
|
ArrayList<Arguments> argumentList = new ArrayList<>();
|
||||||
|
ArrayList<LinkedHashMap<String, Object>> rowList = flowableExcelParser.parseExcelFromResource(resourcePath);
|
||||||
|
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", "output3").contains(key)) {
|
||||||
|
outputMap.put(key, entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argumentList.add(Arguments.of(inputMap, outputMap));
|
||||||
|
}
|
||||||
|
return argumentList.stream();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected Stream<Arguments> booleanOldExcelParserTest() {
|
||||||
|
return getArgumentsFromExcel("flowableExcelParserTestDataBooleanOld.xlsx");
|
||||||
|
}
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource
|
||||||
|
public void booleanOldExcelParserTest(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.parseBoolean(inputMap.get("input1").toString()) || Boolean.parseBoolean(inputMap.get("input2").toString()) || Boolean.parseBoolean(inputMap.get("input3").toString());
|
||||||
|
Assertions.assertThat(Boolean.parseBoolean(entry.getValue().toString())).isEqualTo(val);
|
||||||
|
}
|
||||||
|
if (key.equals("output2")) {
|
||||||
|
Boolean val = Boolean.parseBoolean(inputMap.get("input1").toString()) && Boolean.parseBoolean(inputMap.get("input2").toString()) && Boolean.parseBoolean(inputMap.get("input3").toString());
|
||||||
|
Assertions.assertThat(Boolean.parseBoolean(entry.getValue().toString())).isEqualTo(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected Stream<Arguments> stringOldExcelParserTest() {
|
||||||
|
return getArgumentsFromExcel("flowableExcelParserTestDataStringOld.xlsx");
|
||||||
|
}
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource
|
||||||
|
public void stringOldExcelParserTest(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected Stream<Arguments> numberOldExcelParserTest() {
|
||||||
|
return getArgumentsFromExcel("flowableExcelParserTestDataIntegerOld.xlsx");
|
||||||
|
}
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource
|
||||||
|
public void numberOldExcelParserTest(LinkedHashMap<String, Object> inputMap, LinkedHashMap<String, Object> outputMap) {
|
||||||
|
for (Map.Entry<String, Object> entry : outputMap.entrySet()) {
|
||||||
|
String key = entry.getKey();
|
||||||
|
if (key.equals("output1")) {
|
||||||
|
Integer val12 = Integer.parseInt(inputMap.get("input1").toString()) + Integer.parseInt(inputMap.get("input2").toString());
|
||||||
|
Assertions.assertThat(Integer.parseInt(entry.getValue().toString())).isEqualTo(val12);
|
||||||
|
}
|
||||||
|
if (key.equals("output2")) {
|
||||||
|
Integer val23 = Integer.parseInt(inputMap.get("input2").toString()) + Integer.parseInt(inputMap.get("input3").toString());
|
||||||
|
Assertions.assertThat(Integer.parseInt(entry.getValue().toString())).isEqualTo(val23);
|
||||||
|
}
|
||||||
|
if (key.equals("output3")) {
|
||||||
|
Integer val12 = Integer.parseInt(inputMap.get("input1").toString()) + Integer.parseInt(inputMap.get("input2").toString()) + Integer.parseInt(inputMap.get("input3").toString());
|
||||||
|
Assertions.assertThat(Integer.parseInt(entry.getValue().toString())).isEqualTo(val12);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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