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.
com.supwisdom.spreadsheet.mapper.validation.engine.CellGroupValidationEngine Maven / Gradle / Ivy
package com.supwisdom.spreadsheet.mapper.validation.engine;
import com.supwisdom.spreadsheet.mapper.m2f.excel.ExcelMessageWriteStrategies;
import com.supwisdom.spreadsheet.mapper.model.core.Cell;
import com.supwisdom.spreadsheet.mapper.model.core.Row;
import com.supwisdom.spreadsheet.mapper.model.meta.FieldMeta;
import com.supwisdom.spreadsheet.mapper.model.meta.SheetMeta;
import com.supwisdom.spreadsheet.mapper.model.msg.Message;
import com.supwisdom.spreadsheet.mapper.model.msg.MessageBean;
import com.supwisdom.spreadsheet.mapper.validation.validator.Dependant;
import com.supwisdom.spreadsheet.mapper.validation.validator.cell.CellValidator;
import com.supwisdom.spreadsheet.mapper.validation.validator.unioncell.UnionCellValidator;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* 针对{@link Dependant}的两个实现{@link CellValidator}、{@link UnionCellValidator}的校验引擎。
* Created by hanwen on 2017/1/6.
*/
public class CellGroupValidationEngine {
private static final Logger LOGGER = LoggerFactory.getLogger(CellGroupValidationEngine.class);
private final List cellValidators;
private final SheetMeta sheetMeta;
// group -> validators
private transient LinkedHashMap> cellValidatorGroups = new LinkedHashMap<>();
// group -> dependsOn
private transient LinkedHashMap> dependencyTree = new LinkedHashMap<>();
// group -> validator -> columns
private transient Map>> group2Validator2Columns = new HashMap<>();
private transient Map result = new HashMap<>();
private transient List errorMessages = new ArrayList<>();
private enum ValidateResult {
PASS, FAIL, SKIP
}
public CellGroupValidationEngine(SheetMeta sheetMeta, List cellValidators) {
if (cellValidators != null) {
this.cellValidators = new ArrayList<>(cellValidators);
} else {
this.cellValidators = Collections.emptyList();
}
this.sheetMeta = sheetMeta;
}
/**
* 初始化工作,主要是计算哪些field对应哪些CellValidator/UnionCellValidator
*/
public void initialize() {
this.cellValidatorGroups = buildCellValidatorGroups(cellValidators);
this.dependencyTree = buildDependencyTree(cellValidatorGroups);
assertNoMissingGroup(dependencyTree);
assertNoCyclic(dependencyTree);
this.group2Validator2Columns = buildGroup2Validator2Columns(cellValidatorGroups);
}
/**
* 构建 CellValidator 分组
*
* @param cellValidators {@link CellValidator}或{@link UnionCellValidator}
* @return 分组
*/
protected LinkedHashMap> buildCellValidatorGroups(List cellValidators) {
LinkedHashMap> group2Validators = new LinkedHashMap<>();
for (Dependant cellValidator : cellValidators) {
String group = cellValidator.getGroup();
if (!group2Validators.containsKey(group)) {
group2Validators.put(group, new ArrayList());
}
group2Validators.get(group).add(cellValidator);
}
return group2Validators;
}
/**
* 构建分组依赖树
*
* @param group2Validators Validator分组
* @return 依赖关系
*/
protected LinkedHashMap> buildDependencyTree(
LinkedHashMap> group2Validators) {
LinkedHashMap> groupDependencies = new LinkedHashMap<>();
for (Map.Entry> entry : group2Validators.entrySet()) {
String key = entry.getKey();
groupDependencies.put(key, new LinkedHashSet());
for (Dependant dependant : entry.getValue()) {
Set dependsOn = dependant.getDependsOn();
if (CollectionUtils.isNotEmpty(dependsOn)) {
groupDependencies.get(key).addAll(dependsOn);
}
}
}
return groupDependencies;
}
/**
* 断言不存在丢失的group
*
* @param dependencyTree 依赖关系
*/
protected void assertNoMissingGroup(LinkedHashMap> dependencyTree) {
Set allGroups = dependencyTree.keySet();
for (Map.Entry> entry : dependencyTree.entrySet()) {
String group = entry.getKey();
Set dependsOn = entry.getValue();
Collection missingGroups = CollectionUtils.subtract(dependsOn, allGroups);
if (!missingGroups.isEmpty()) {
throw new CellGroupValidationEngineException(
"Group[" + group + "] depends on missing group(s)[" + StringUtils.join(missingGroups, ',') + "]");
}
}
}
/**
* 断言不存在循环依赖
*
* @param dependencyTree 依赖关系
*/
protected void assertNoCyclic(LinkedHashMap> dependencyTree) {
GraphCyclicChecker graphCyclicChecker = new GraphCyclicChecker(dependencyTree);
if (graphCyclicChecker.cycling()) {
throw new CellGroupValidationEngineException(
"Cyclic group dependency found: " + StringUtils.join(graphCyclicChecker.getCycle(), "->"));
}
}
protected Map>> buildGroup2Validator2Columns(
LinkedHashMap> cellValidatorGroups) {
Map>> group2validator2columns = new HashMap<>();
for (Map.Entry> entry : cellValidatorGroups.entrySet()) {
String group = entry.getKey();
List validators = entry.getValue();
Map> validator2columns = new HashMap<>();
group2validator2columns.put(group, validator2columns);
for (Dependant validator : validators) {
List columnIndices = new ArrayList<>(0);
if (CellValidator.class.isAssignableFrom(validator.getClass())) {
Integer columnIndex = getValidateColumnIndex(sheetMeta, (CellValidator) validator);
if (columnIndex != null) {
columnIndices.add(columnIndex);
}
} else if (UnionCellValidator.class.isAssignableFrom(validator.getClass())) {
LinkedHashSet indices = getValidateColumnIndices(sheetMeta, (UnionCellValidator) validator);
if (indices != null) {
columnIndices.addAll(indices);
}
}
validator2columns.put(validator, columnIndices);
}
}
return group2validator2columns;
}
private Integer getValidateColumnIndex(SheetMeta sheetMeta, CellValidator validator) {
String matchField = validator.getMatchField();
FieldMeta fieldMeta = sheetMeta.getUniqueFieldMeta(matchField);
if (fieldMeta == null) {
LOGGER.debug("Couldn't find field [{}] for CellValidator [{}]", matchField, validator.getClass().getName());
return null;
}
return fieldMeta.getColumnIndex();
}
private LinkedHashSet getValidateColumnIndices(SheetMeta sheetMeta, UnionCellValidator validator) {
LinkedHashSet columnIndices = new LinkedHashSet<>(validator.getMatchFields().size());
for (String matchField : validator.getMatchFields()) {
FieldMeta fieldMeta = sheetMeta.getUniqueFieldMeta(matchField);
if (fieldMeta == null) {
LOGGER
.debug("Couldn't find field [{}] for UnionCellValidator [{}]", matchField, validator.getClass().getName());
return null;
}
columnIndices.add(fieldMeta.getColumnIndex());
}
return columnIndices;
}
public boolean validate(Row row, SheetMeta sheetMeta) {
for (String group : dependencyTree.keySet()) {
if (!result.containsKey(group)) {
validateGroup(row, sheetMeta, group);
}
}
return !result.values().contains(ValidateResult.FAIL);
}
public List getErrorMessages() {
return errorMessages;
}
public void clearResults() {
this.errorMessages.clear();
this.result.clear();
}
private void validateGroup(Row row, SheetMeta sheetMeta, String group) {
LinkedHashSet upstreamGroups = dependencyTree.get(group);
// 上游group没有校验过的话,先校验上游group
for (String upstreamGroup : upstreamGroups) {
if (!result.containsKey(upstreamGroup)) {
validateGroup(row, sheetMeta, upstreamGroup);
}
}
// 判断上游group是否通过,如果没有通过则跳过
for (String upstreamGroup : upstreamGroups) {
if (result.get(upstreamGroup) == ValidateResult.SKIP) {
LOGGER.debug("Skip validation group [{}] because upstream group [{}] skip", group, upstreamGroup);
result.put(group, ValidateResult.SKIP);
return;
}
if (result.get(upstreamGroup) == ValidateResult.FAIL) {
LOGGER.debug("Skip validation group [{}] because upstream group [{}] failure", group, upstreamGroup);
result.put(group, ValidateResult.SKIP);
return;
}
}
// 执行本group校验
List dependants = cellValidatorGroups.get(group);
LOGGER.debug("Start validation group [{}] {} validator(s).", group, dependants.size());
boolean groupSucceeded = true;
for (Dependant dependant : dependants) {
List columnIndices = group2Validator2Columns.get(group).get(dependant);
// group内的validator按顺序执行,只要有一个失败了,那么后面的就不会再执行了
groupSucceeded = groupSucceeded && validateCell(row, sheetMeta, dependant, columnIndices);
if (!groupSucceeded) {
LOGGER.debug("validation group [{}] validation failed on [{}]", group, dependant.getClass().getName());
break;
}
}
result.put(group, groupSucceeded ? ValidateResult.PASS : ValidateResult.FAIL);
}
private boolean validateCell(Row row, SheetMeta sheetMeta, Dependant dependant, List columnIndices) {
if (UnionCellValidator.class.isAssignableFrom(dependant.getClass())) {
return executeValidator(columnIndices, sheetMeta, row, (UnionCellValidator) dependant);
} else if (CellValidator.class.isAssignableFrom(dependant.getClass())) {
return executeValidator(columnIndices, sheetMeta, row, (CellValidator) dependant);
}
LOGGER.debug("Unsupported Validator [{}]", dependant.getClass().getName());
return false;
}
private boolean executeValidator(List columnIndices, SheetMeta sheetMeta, Row row,
UnionCellValidator validator) {
if (CollectionUtils.isEmpty(columnIndices)) {
LOGGER.debug("Skip UnionCellValidator [{}]", validator.getClass().getName());
return true;
}
List cells = new ArrayList<>();
List fieldMetas = new ArrayList<>();
for (Integer columnIndex : columnIndices) {
cells.add(row.getCell(columnIndex));
fieldMetas.add(sheetMeta.getFieldMeta(columnIndex));
}
boolean result = validator.validate(cells, fieldMetas);
if (!result) {
String errorMessage = StringUtils.defaultIfBlank(validator.getErrorMessage(), "Invalid");
for (FieldMeta fieldMeta : fieldMetas) {
errorMessages.add(
new MessageBean(ExcelMessageWriteStrategies.COMMENT, StringUtils.defaultIfBlank(errorMessage, "Invalid"), row.getSheet().getIndex(),
row.getIndex(),
fieldMeta.getColumnIndex()));
}
}
return result;
}
private boolean executeValidator(List columnIndices, SheetMeta sheetMeta, Row row,
CellValidator validator) {
if (CollectionUtils.isEmpty(columnIndices)) {
LOGGER.debug("Skip CellValidator [{}]", validator.getClass().getName());
return true;
}
int columnIndex = columnIndices.get(0);
Cell cell = row.getCell(columnIndex);
FieldMeta fieldMeta = sheetMeta.getFieldMeta(columnIndex);
boolean result = validator.validate(cell, fieldMeta);
if (!result) {
String errorMessage = StringUtils.defaultIfBlank(validator.getErrorMessage(), "Invalid");
errorMessages.add(
new MessageBean(ExcelMessageWriteStrategies.COMMENT, errorMessage,
row.getSheet().getIndex(), row.getIndex(), fieldMeta.getColumnIndex()));
}
return result;
}
}
|