mirror of https://github.com/alibaba/easyexcel
41 changed files with 2109 additions and 21 deletions
@ -0,0 +1,73 @@ |
|||||||
|
package com.alibaba.excel.util; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* 单元格变量工具 |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
* @version 1.0.0 |
||||||
|
* @since 2023/6/7 10:38 |
||||||
|
*/ |
||||||
|
public class CellVariableUtils { |
||||||
|
|
||||||
|
private static final String FILL_PREFIX = "{"; |
||||||
|
private static final String FILL_SUFFIX = "}"; |
||||||
|
private static final char IGNORE_CHAR = '\\'; |
||||||
|
private static final String COLLECTION_PREFIX = "."; |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据cell值获取单元格变量 |
||||||
|
* @author linfeng |
||||||
|
* @param cellValue 单元格值 |
||||||
|
* @return 变量集合 |
||||||
|
*/ |
||||||
|
public static List<String> getVariable(String cellValue) { |
||||||
|
|
||||||
|
List<String> varList = new ArrayList<>(); |
||||||
|
int startIndex = 0; |
||||||
|
int length = cellValue.length(); |
||||||
|
out: |
||||||
|
while (startIndex < length) { |
||||||
|
int prefixIndex = cellValue.indexOf(FILL_PREFIX, startIndex); |
||||||
|
if (prefixIndex < 0) { |
||||||
|
break; |
||||||
|
} |
||||||
|
if (prefixIndex != 0) { |
||||||
|
char prefixPrefixChar = cellValue.charAt(prefixIndex - 1); |
||||||
|
if (prefixPrefixChar == IGNORE_CHAR) { |
||||||
|
startIndex = prefixIndex + 1; |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
int suffixIndex = -1; |
||||||
|
while (suffixIndex == -1 && startIndex < length) { |
||||||
|
suffixIndex = cellValue.indexOf(FILL_SUFFIX, startIndex + 1); |
||||||
|
if (suffixIndex < 0) { |
||||||
|
break out; |
||||||
|
} |
||||||
|
startIndex = suffixIndex + 1; |
||||||
|
char prefixSuffixChar = cellValue.charAt(suffixIndex - 1); |
||||||
|
if (prefixSuffixChar == IGNORE_CHAR) { |
||||||
|
suffixIndex = -1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
String variable = cellValue.substring(prefixIndex + 1, suffixIndex); |
||||||
|
if (StringUtils.isEmpty(variable)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
int collectPrefixIndex = variable.indexOf(COLLECTION_PREFIX); |
||||||
|
if (collectPrefixIndex == 0) { |
||||||
|
variable = variable.substring(collectPrefixIndex + 1); |
||||||
|
if (StringUtils.isEmpty(variable)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
} |
||||||
|
varList.add(variable); |
||||||
|
} |
||||||
|
return varList; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,123 @@ |
|||||||
|
package com.alibaba.excel.util; |
||||||
|
|
||||||
|
import org.springframework.cglib.beans.BeanMap; |
||||||
|
import org.springframework.lang.Nullable; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
* @version 1.0.0 |
||||||
|
* @since 2023/5/27 22:51 |
||||||
|
*/ |
||||||
|
public class PipeFilterUtils { |
||||||
|
|
||||||
|
private static final String PIPELINE_FLAG = "|"; |
||||||
|
private static final String MULTI_PIPE_FLAG = "\\|"; |
||||||
|
private static final String FILTER_PARAM_FLAG = ":"; |
||||||
|
private static final String PARAM_FLAG = ","; |
||||||
|
|
||||||
|
private static final String VAR_FLAG = "\\."; |
||||||
|
|
||||||
|
/** |
||||||
|
* Return {@code true} if the supplied Collection is {@code null} or empty. |
||||||
|
* Otherwise, return {@code false}. |
||||||
|
* @param collection the Collection to check |
||||||
|
* @return whether the given Collection is empty |
||||||
|
*/ |
||||||
|
public static boolean isEmpty(@Nullable Collection<?> collection) { |
||||||
|
return (collection == null || collection.isEmpty()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return {@code true} if the supplied Map is {@code null} or empty. |
||||||
|
* Otherwise, return {@code false}. |
||||||
|
* @param map the Map to check |
||||||
|
* @return whether the given Map is empty |
||||||
|
*/ |
||||||
|
public static boolean isEmpty(@Nullable Map<?, ?> map) { |
||||||
|
return (map == null || map.isEmpty()); |
||||||
|
} |
||||||
|
|
||||||
|
public static String trim(String source) { |
||||||
|
return StringUtils.isBlank(source) ? "" : source.trim(); |
||||||
|
} |
||||||
|
|
||||||
|
public static String[] getPipelines(String pipelines) { |
||||||
|
return pipelines.split(MULTI_PIPE_FLAG); |
||||||
|
} |
||||||
|
|
||||||
|
public static String[] getPipeFilter(String pipeline) { |
||||||
|
return pipeline.split(FILTER_PARAM_FLAG); |
||||||
|
} |
||||||
|
|
||||||
|
public static String[] getPipeFilterParams(String pipeFilter) { |
||||||
|
return pipeFilter.split(PARAM_FLAG); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否是管道,是管道返回true,反之返回false |
||||||
|
* |
||||||
|
* @param variable 表达式 |
||||||
|
* @return 是否管道 |
||||||
|
*/ |
||||||
|
public static boolean isPipeline(String variable) { |
||||||
|
return Objects.nonNull(variable) && variable.contains(PIPELINE_FLAG); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取变量字符串的管道前面的变量 |
||||||
|
* |
||||||
|
* @param variable 包含管道的变量字符串 |
||||||
|
* @return 管道前面的变量字符串 |
||||||
|
*/ |
||||||
|
public static String getVariableName(String variable) { |
||||||
|
String[] varArray = PipeFilterUtils.getPipelines(variable); |
||||||
|
if (Objects.nonNull(varArray[0])) { |
||||||
|
return varArray[0].trim(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从map中获取值 |
||||||
|
* @param dataMap map |
||||||
|
* @param key 例如: demo.test.name |
||||||
|
* @return 返回值 |
||||||
|
*/ |
||||||
|
public static Object getValueOfMap(Map dataMap, String key) { |
||||||
|
|
||||||
|
if (StringUtils.isBlank(key)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
Map tempDataMap = dataMap; |
||||||
|
String[] keyArray = key.split(VAR_FLAG); |
||||||
|
for (int i = 0; i < keyArray.length; i++) { |
||||||
|
if (StringUtils.isBlank(keyArray[i])) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
Object obj = tempDataMap.get(keyArray[i]); |
||||||
|
if (Objects.isNull(obj)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (i == keyArray.length - 1) { |
||||||
|
return obj; |
||||||
|
} else { |
||||||
|
if (obj instanceof BeanMap) { |
||||||
|
tempDataMap = (BeanMap) obj; |
||||||
|
} else if (obj instanceof Map) { |
||||||
|
tempDataMap = (Map)obj; |
||||||
|
} else { |
||||||
|
tempDataMap = BeanMapUtils.create(obj); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,82 @@ |
|||||||
|
package com.alibaba.excel.write.handler; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* pipeline filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public abstract class BasePipeFilter<T, R> implements PipeFilter<T, R> { |
||||||
|
|
||||||
|
private final List<String> filterParams = new ArrayList<>(); |
||||||
|
protected int rowIndex; |
||||||
|
protected int columnIndex; |
||||||
|
|
||||||
|
/** |
||||||
|
* filter name |
||||||
|
* |
||||||
|
* @return filter name |
||||||
|
*/ |
||||||
|
protected abstract String filterName(); |
||||||
|
|
||||||
|
protected boolean isValidity(PipeDataWrapper<R> apply) { |
||||||
|
Object data = apply.getData(); |
||||||
|
if (Objects.nonNull(data)) { |
||||||
|
return !(data instanceof Collection || data instanceof Map); |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return Error message prefix |
||||||
|
*/ |
||||||
|
protected String errorPrefix() { |
||||||
|
return String.format("Column [%s], [%s] instruction error:", columnIndex + 1, filterName()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* filter params |
||||||
|
* |
||||||
|
* @return params collection |
||||||
|
*/ |
||||||
|
public List<String> params() { |
||||||
|
return filterParams; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* add param |
||||||
|
* |
||||||
|
* @param params collection |
||||||
|
* @return filter |
||||||
|
*/ |
||||||
|
public BasePipeFilter<T, R> addParams(String... params) { |
||||||
|
params().addAll(Arrays.asList(params)); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* set excel cell |
||||||
|
* |
||||||
|
* @param row row index |
||||||
|
* @param column column index |
||||||
|
* @return 过滤器 |
||||||
|
*/ |
||||||
|
public BasePipeFilter<T, R> setCell(int row, int column) { |
||||||
|
this.rowIndex = row; |
||||||
|
this.columnIndex = column; |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* verify |
||||||
|
* |
||||||
|
* @param wrapper data |
||||||
|
* @return true |
||||||
|
*/ |
||||||
|
protected boolean verify(PipeDataWrapper<T> wrapper) { |
||||||
|
return Objects.nonNull(wrapper) && wrapper.success(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
package com.alibaba.excel.write.handler; |
||||||
|
|
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* filter wrapper |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
@AllArgsConstructor |
||||||
|
public class PipeDataWrapper<R> implements Serializable { |
||||||
|
private int status; |
||||||
|
private String message; |
||||||
|
private R data; |
||||||
|
|
||||||
|
public static <R> PipeDataWrapper<R> success(R data) { |
||||||
|
return new PipeDataWrapper<>(200, "OK", data); |
||||||
|
} |
||||||
|
|
||||||
|
public static <R> PipeDataWrapper<R> error(String error, R data) { |
||||||
|
return new PipeDataWrapper<>(500, error, data); |
||||||
|
} |
||||||
|
|
||||||
|
public static <R> PipeDataWrapper<R> error(String error) { |
||||||
|
return new PipeDataWrapper<>(500, error, null); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean success() { |
||||||
|
return status == 200; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
package com.alibaba.excel.write.handler; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
import java.util.function.Function; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* pipe filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public interface PipeFilter<T, R> extends Function<PipeDataWrapper<T>, PipeDataWrapper<R>> { |
||||||
|
|
||||||
|
/** |
||||||
|
* apply |
||||||
|
* |
||||||
|
* @param wrapper the function argument |
||||||
|
* @return data wrapper |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
PipeDataWrapper<R> apply(PipeDataWrapper<T> wrapper); |
||||||
|
|
||||||
|
/** |
||||||
|
* filter params collection |
||||||
|
* |
||||||
|
* @return params collection |
||||||
|
*/ |
||||||
|
List<String> params(); |
||||||
|
|
||||||
|
/** |
||||||
|
* add param to pipe filter |
||||||
|
* |
||||||
|
* @param params param |
||||||
|
* @return pipe filter |
||||||
|
*/ |
||||||
|
default PipeFilter<T, R> addParams(String... params) { |
||||||
|
params().addAll(Arrays.asList(params)); |
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,139 @@ |
|||||||
|
package com.alibaba.excel.write.handler; |
||||||
|
|
||||||
|
import com.alibaba.excel.context.WriteContext; |
||||||
|
import com.alibaba.excel.exception.ExcelRuntimeException; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.write.handler.filter.*; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
import java.util.function.Function; |
||||||
|
import java.util.function.Supplier; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* pipe filter factory |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class PipeFilterFactory extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
private static final Map<String, Supplier<BasePipeFilter<Object, Object>>> PIPE_FILTER_MAP = new HashMap<>(); |
||||||
|
|
||||||
|
static { |
||||||
|
// 初始化内置管道过滤器
|
||||||
|
PIPE_FILTER_MAP.put("trim", TrimFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("equals", EqualsFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("prior-equals", PriorEqualsFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("ends-with", EndsWithFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("prior-ends-with", PriorEndsWithFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("starts-with", StartsWithFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("prior-starts-with", PriorStartsWithFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("pattern", PatternFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("prior-pattern", PriorPatternFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("date-format", DateFormatFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("contains", ContainsFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("prior-contains", PriorContainsFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("list-index", ListIndexFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("list-echo", ListEchoFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("list-range", ListRangeFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("echo", EchoFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("cal-add", AdditionFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("cal-sub", SubtractionFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("cal-mul", MultiplicationFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("cal-div", DivisionFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("substring", SubstringFilter::new); |
||||||
|
PIPE_FILTER_MAP.put("replace", ReplaceFilter::new); |
||||||
|
} |
||||||
|
|
||||||
|
private PipeFilterFactory(WriteContext writeContext) { |
||||||
|
if (Objects.nonNull(writeContext) |
||||||
|
&& Objects.nonNull(writeContext.writeWorkbookHolder()) |
||||||
|
&& Objects.nonNull(writeContext.writeWorkbookHolder().getWriteWorkbook()) |
||||||
|
&& !PipeFilterUtils.isEmpty(writeContext.writeWorkbookHolder().getWriteWorkbook().getCustomPipeFilterMap())) { |
||||||
|
PIPE_FILTER_MAP.putAll(writeContext.writeWorkbookHolder().getWriteWorkbook().getCustomPipeFilterMap()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create pipeline filters |
||||||
|
* |
||||||
|
* @param writeContext WriteContext |
||||||
|
* @return pipe filter factory |
||||||
|
*/ |
||||||
|
public static PipeFilterFactory createPipeFilter(WriteContext writeContext) { |
||||||
|
return new PipeFilterFactory(writeContext); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> value) { |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params())) { |
||||||
|
throw new ExcelRuntimeException("Incorrect format of instruction parameter string"); |
||||||
|
} |
||||||
|
|
||||||
|
String variable = params().get(0); |
||||||
|
if (StringUtils.isBlank(variable)) { |
||||||
|
throw new ExcelRuntimeException("The instruction parameter string cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
String[] pipeArray = PipeFilterUtils.getPipelines(variable); |
||||||
|
Objects.requireNonNull(pipeArray, "The instruction parameter string cannot be empty"); |
||||||
|
if (pipeArray.length <= 1) { |
||||||
|
throw new ExcelRuntimeException("Incorrect format of instruction parameter string"); |
||||||
|
} |
||||||
|
|
||||||
|
List<BasePipeFilter<Object, Object>> pipeFilterList = new ArrayList<>(); |
||||||
|
for (int i = 1; i < pipeArray.length; i++) { |
||||||
|
if (StringUtils.isBlank(pipeArray[i])) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
String[] expressArray = PipeFilterUtils.getPipeFilter(pipeArray[i]); |
||||||
|
if (StringUtils.isBlank(expressArray[0])) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
String filterName = PipeFilterUtils.trim(expressArray[0]).toLowerCase(); |
||||||
|
if (StringUtils.isBlank(filterName)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
Supplier<BasePipeFilter<Object, Object>> supplier = PIPE_FILTER_MAP.get(filterName); |
||||||
|
if (Objects.isNull(supplier)) { |
||||||
|
throw new ExcelRuntimeException(String.format("No pipeline filter for [%s]", filterName)); |
||||||
|
} |
||||||
|
BasePipeFilter<Object, Object> pipeFilter = supplier.get(); |
||||||
|
if (Objects.nonNull(pipeFilter)) { |
||||||
|
pipeFilterList.add(pipeFilter); |
||||||
|
} |
||||||
|
pipeFilter.setCell(rowIndex, columnIndex); |
||||||
|
|
||||||
|
if (expressArray.length > 1 && StringUtils.isNotBlank(expressArray[1])) { |
||||||
|
String[] paramArray = PipeFilterUtils.getPipeFilterParams(PipeFilterUtils.trim(expressArray[1])); |
||||||
|
pipeFilter.addParams(paramArray); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(pipeFilterList)) { |
||||||
|
return value; |
||||||
|
} |
||||||
|
// 构建pipeline
|
||||||
|
Function<PipeDataWrapper<Object>, PipeDataWrapper<Object>> currFilter = pipeFilterList.get(0); |
||||||
|
for (int i = 1; i < pipeFilterList.size(); i++) { |
||||||
|
currFilter = currFilter.andThen(pipeFilterList.get(i)); |
||||||
|
} |
||||||
|
PipeDataWrapper<Object> dataWrapper = currFilter.apply(value); |
||||||
|
if (isValidity(dataWrapper)) { |
||||||
|
return dataWrapper; |
||||||
|
} |
||||||
|
return PipeDataWrapper.error(String.format("column [%s], data error:%s", columnIndex + 1, "the input value cannot be a set or a Map")); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "factory"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,165 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.write.handler.BasePipeFilter; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
import java.math.BigDecimal; |
||||||
|
import java.math.RoundingMode; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* abstract calculator filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
public abstract class AbstractCalculatorFilter extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
public static final String INT = "int"; |
||||||
|
public static final String NUMBER = "number"; |
||||||
|
public static final String REGEX = "_"; |
||||||
|
|
||||||
|
public static class Calculator { |
||||||
|
|
||||||
|
public static double add(double a, double b) { |
||||||
|
return a + b; |
||||||
|
} |
||||||
|
|
||||||
|
public static double subtract(double a, double b) { |
||||||
|
return a - b; |
||||||
|
} |
||||||
|
|
||||||
|
public static double multiply(double a, double b) { |
||||||
|
return a * b; |
||||||
|
} |
||||||
|
|
||||||
|
public static double divide(double a, double b) { |
||||||
|
if (b == 0) { |
||||||
|
throw new IllegalArgumentException("Divider cannot be 0"); |
||||||
|
} |
||||||
|
return a / b; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
// 验证
|
||||||
|
if (!verify(wrapper)) { |
||||||
|
return wrapper; |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "incoming data cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params())) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "missing parameter for instruction"); |
||||||
|
} |
||||||
|
|
||||||
|
String params1 = params().get(0); |
||||||
|
if (StringUtils.isBlank(params1)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "instruction parameter is empty"); |
||||||
|
} |
||||||
|
|
||||||
|
double number1 = 0D; |
||||||
|
if (value instanceof Number) { |
||||||
|
number1 = ((Number) value).doubleValue(); |
||||||
|
} else if (value instanceof String) { |
||||||
|
try { |
||||||
|
number1 = Double.parseDouble((String) value); |
||||||
|
} catch (Exception e) { |
||||||
|
number1 = 0D; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
double number2; |
||||||
|
try { |
||||||
|
number2 = Double.parseDouble(params1); |
||||||
|
} catch (Exception e) { |
||||||
|
number2 = 0D; |
||||||
|
} |
||||||
|
|
||||||
|
double result = calculator(number1, number2); |
||||||
|
|
||||||
|
return showDataWrapper(result); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Construct pipeline data wrapping objects based on calculation results |
||||||
|
* |
||||||
|
* @param result Calculation results |
||||||
|
* @return Pipe Data Wrapper |
||||||
|
*/ |
||||||
|
private PipeDataWrapper<Object> showDataWrapper(double result) { |
||||||
|
if (params().size() <= 1) { |
||||||
|
return PipeDataWrapper.success(result); |
||||||
|
} else { |
||||||
|
String params2 = params().get(1); |
||||||
|
if (StringUtils.isBlank(params2)) { |
||||||
|
return PipeDataWrapper.success(result); |
||||||
|
} |
||||||
|
String[] params2Array = params2.split(REGEX); |
||||||
|
if (INT.equalsIgnoreCase(params2Array[0])) { |
||||||
|
|
||||||
|
return PipeDataWrapper.success(BigDecimal.valueOf(result).setScale(0, RoundingMode.HALF_UP).intValue()); |
||||||
|
} else if (NUMBER.equalsIgnoreCase(params2Array[0])) { |
||||||
|
if (params2Array.length > 1) { |
||||||
|
if (StringUtils.isNumeric(params2Array[1])) { |
||||||
|
int scale = Integer.parseInt(params2Array[1]); |
||||||
|
BigDecimal bigDecimal = BigDecimal.valueOf(result).setScale(scale, RoundingMode.HALF_UP); |
||||||
|
if (scale == 0) { |
||||||
|
return PipeDataWrapper.success(bigDecimal.intValue()); |
||||||
|
} else { |
||||||
|
return PipeDataWrapper.success(bigDecimal.doubleValue()); |
||||||
|
} |
||||||
|
} else { |
||||||
|
log.warn("The digit parameter passed by the Calculator instruction [cal_add, cal_sub, cal_mul, cal_div] is not a number"); |
||||||
|
return PipeDataWrapper.success(result); |
||||||
|
} |
||||||
|
} else { |
||||||
|
return PipeDataWrapper.success(result); |
||||||
|
} |
||||||
|
} else { |
||||||
|
return PipeDataWrapper.success(result); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* calculator |
||||||
|
* |
||||||
|
* @param number1 number |
||||||
|
* @param number2 number |
||||||
|
* @return Calculation results |
||||||
|
*/ |
||||||
|
private double calculator(double number1, double number2) { |
||||||
|
double result; |
||||||
|
switch (filterName()) { |
||||||
|
case "cal-add": |
||||||
|
result = Calculator.add(number1, number2); |
||||||
|
break; |
||||||
|
case "cal-sub": |
||||||
|
result = Calculator.subtract(number1, number2); |
||||||
|
break; |
||||||
|
case "cal-mul": |
||||||
|
result = Calculator.multiply(number1, number2); |
||||||
|
break; |
||||||
|
case "cal-div": |
||||||
|
if (number2 == 0) { |
||||||
|
throw new RuntimeException("The cal_div instruction with a divisor of 0 is not supported"); |
||||||
|
} |
||||||
|
result = Calculator.divide(number1, number2); |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new RuntimeException("The Calculator instruction is not supported"); |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.write.handler.BasePipeFilter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* abstract echo |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public abstract class AbstractEchoFilter extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
protected enum Delimiter { |
||||||
|
/** |
||||||
|
* blank |
||||||
|
*/ |
||||||
|
BLANK("blank", " "), |
||||||
|
/** |
||||||
|
* enter |
||||||
|
*/ |
||||||
|
WRAP("wrap", "\n"), |
||||||
|
/** |
||||||
|
* comma |
||||||
|
*/ |
||||||
|
COMMA("comma", ","); |
||||||
|
|
||||||
|
private final String value; |
||||||
|
private final String delimiter; |
||||||
|
|
||||||
|
Delimiter(String value, String delimiter) { |
||||||
|
this.value = value; |
||||||
|
this.delimiter = delimiter; |
||||||
|
} |
||||||
|
|
||||||
|
public static Delimiter ofValue(String value) { |
||||||
|
for (Delimiter delim : Delimiter.values()) { |
||||||
|
if (delim.value.equalsIgnoreCase(value)) { |
||||||
|
return delim; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public String getValue() { |
||||||
|
return value; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDelimiter() { |
||||||
|
return delimiter; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,164 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.util.BeanMapUtils; |
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.write.handler.BasePipeFilter; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* abstract match filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public abstract class AbstractMatchFilter extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
/** |
||||||
|
* String Matching |
||||||
|
* |
||||||
|
* @param source source string |
||||||
|
* @param match Match String |
||||||
|
* @return Match or not |
||||||
|
*/ |
||||||
|
protected abstract boolean strMatch(String source, String match); |
||||||
|
|
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
// 验证
|
||||||
|
if (!verify(wrapper)) { |
||||||
|
return wrapper; |
||||||
|
} |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params())) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "missing parameter for instruction"); |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "Incoming data cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
Object dataObj; |
||||||
|
if (value instanceof String || value instanceof Collection || value instanceof Map) { |
||||||
|
dataObj = value; |
||||||
|
} else { |
||||||
|
dataObj = BeanMapUtils.create(value); |
||||||
|
} |
||||||
|
|
||||||
|
if (params().size() == 1) { |
||||||
|
|
||||||
|
return singleParamsHandle(dataObj); |
||||||
|
} else { |
||||||
|
|
||||||
|
return moreParamsHandle(dataObj); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 单参数处理 |
||||||
|
* |
||||||
|
* @param value 待处理数据 |
||||||
|
* @return 处理后的数据 |
||||||
|
*/ |
||||||
|
private PipeDataWrapper<Object> singleParamsHandle(Object value) { |
||||||
|
String center = params().get(0); |
||||||
|
if (StringUtils.isBlank(center)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "instruction parameter cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
return instructHandle(value, center); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 多参数处理 |
||||||
|
* |
||||||
|
* @param value 待处理数据 |
||||||
|
* @return 处理后的数据 |
||||||
|
*/ |
||||||
|
protected PipeDataWrapper<Object> moreParamsHandle(Object value) { |
||||||
|
List<Object> result = new ArrayList<>(); |
||||||
|
List<String> error = new ArrayList<>(); |
||||||
|
for (String center : params()) { |
||||||
|
if (Objects.isNull(center)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
PipeDataWrapper<Object> itemDataWrapper = instructHandle(value, center); |
||||||
|
if (itemDataWrapper.success()) { |
||||||
|
result.add(itemDataWrapper.getData()); |
||||||
|
} else { |
||||||
|
error.add(itemDataWrapper.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
if (PipeFilterUtils.isEmpty(error)) { |
||||||
|
return PipeDataWrapper.success(result); |
||||||
|
} else { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + String.join(",", error), result); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 指令处理 |
||||||
|
* |
||||||
|
* @param value 待处理的值 |
||||||
|
* @param center 待匹配的字符串 |
||||||
|
* @return 数据包裹 |
||||||
|
*/ |
||||||
|
protected PipeDataWrapper<Object> instructHandle(Object value, String center) { |
||||||
|
|
||||||
|
if (value instanceof Collection) { |
||||||
|
String result = null; |
||||||
|
//noinspection unchecked
|
||||||
|
Collection<Object> collection = (Collection<Object>) value; |
||||||
|
for (Object col : collection) { |
||||||
|
if (Objects.isNull(col)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (col instanceof String) { |
||||||
|
String cel = (String) col; |
||||||
|
if (strMatch(cel, center)) { |
||||||
|
result = cel; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (StringUtils.isBlank(result)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + String.format("No data containing [%s]", center)); |
||||||
|
} else { |
||||||
|
return PipeDataWrapper.success(result); |
||||||
|
} |
||||||
|
} else if (value instanceof String) { |
||||||
|
String col = (String) value; |
||||||
|
if (strMatch(col, center)) { |
||||||
|
return PipeDataWrapper.success(col); |
||||||
|
} else { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + String.format("No data containing [%s]", center)); |
||||||
|
} |
||||||
|
} else if (value instanceof Map) { |
||||||
|
|
||||||
|
//noinspection unchecked
|
||||||
|
Map<Object, Object> colMap = (Map<Object, Object>) value; |
||||||
|
for (Map.Entry<Object, Object> entry : colMap.entrySet()) { |
||||||
|
if (Objects.isNull(entry.getKey())) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (strMatch(entry.getKey().toString(), center)) { |
||||||
|
if (Objects.nonNull(entry.getValue())) { |
||||||
|
return PipeDataWrapper.success(entry.getValue().toString()); |
||||||
|
} else { |
||||||
|
return PipeDataWrapper.success(""); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return PipeDataWrapper.error(errorPrefix() + String.format("No data containing [%s]", center)); |
||||||
|
} else { |
||||||
|
|
||||||
|
return PipeDataWrapper.error(errorPrefix() + "the incoming data is not a collection or string", value.toString()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* Priority matching filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public abstract class AbstractPriorMatchFilter extends AbstractMatchFilter { |
||||||
|
|
||||||
|
/** |
||||||
|
* Multi parameter processing, priority processing |
||||||
|
* |
||||||
|
* @param value Pending data |
||||||
|
* @return processed data |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
protected PipeDataWrapper<Object> moreParamsHandle(Object value) { |
||||||
|
for (String center : params()) { |
||||||
|
if (Objects.isNull(center)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
PipeDataWrapper<Object> itemDataWrapper = instructHandle(value, center); |
||||||
|
if (itemDataWrapper.success()) { |
||||||
|
return itemDataWrapper; |
||||||
|
} |
||||||
|
} |
||||||
|
return PipeDataWrapper.error(errorPrefix() + String.format("The instruction did not match the result of [%s]", String.join(",", params()))); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* add |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class AdditionFilter extends AbstractCalculatorFilter { |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "cal-add"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* Contains Filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class ContainsFilter extends AbstractMatchFilter { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "contains"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return source.contains(match); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.util.DateUtils; |
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.write.handler.BasePipeFilter; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
|
||||||
|
import java.util.Date; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* Date Format Filter |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class DateFormatFilter extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
private static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss"; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "date-format"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
// 验证
|
||||||
|
if (!verify(wrapper)) { |
||||||
|
return wrapper; |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "Incoming data cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
if (value instanceof Date) { |
||||||
|
|
||||||
|
String format; |
||||||
|
if (PipeFilterUtils.isEmpty(params())) { |
||||||
|
format = DEFAULT_FORMAT; |
||||||
|
} else { |
||||||
|
format = StringUtils.isBlank(params().get(0)) ? DEFAULT_FORMAT : params().get(0); |
||||||
|
} |
||||||
|
Date date = (Date) value; |
||||||
|
return PipeDataWrapper.success(DateUtils.format(date, format)); |
||||||
|
} else if (value instanceof String) { |
||||||
|
|
||||||
|
return PipeDataWrapper.success(value); |
||||||
|
} |
||||||
|
|
||||||
|
return PipeDataWrapper.error(errorPrefix() + "The data passed in by the instruction is not a Date or string"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* Division Filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class DivisionFilter extends AbstractCalculatorFilter { |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "cal-div"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* echo filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class EchoFilter extends AbstractEchoFilter { |
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "echo"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
if (Objects.isNull(wrapper)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "missing parameter for instruction"); |
||||||
|
} |
||||||
|
|
||||||
|
if (!wrapper.success()) { |
||||||
|
return PipeDataWrapper.error(wrapper.getMessage()); |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.success(""); |
||||||
|
} |
||||||
|
|
||||||
|
if (!(value instanceof String)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "The incoming data is not a string"); |
||||||
|
} |
||||||
|
|
||||||
|
String val = (String) value; |
||||||
|
if (StringUtils.isBlank(val)) { |
||||||
|
return PipeDataWrapper.success(""); |
||||||
|
} |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params())) { |
||||||
|
return PipeDataWrapper.success(""); |
||||||
|
} |
||||||
|
|
||||||
|
String delimiter = params().get(0); |
||||||
|
|
||||||
|
Delimiter delimiterEnum = Delimiter.ofValue(delimiter); |
||||||
|
if (Objects.nonNull(delimiterEnum)) { |
||||||
|
return PipeDataWrapper.success(val + delimiterEnum.getDelimiter()); |
||||||
|
} |
||||||
|
|
||||||
|
return PipeDataWrapper.success(val + delimiter); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* ends-with filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class EndsWithFilter extends AbstractMatchFilter { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "ends-with"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return source.endsWith(match); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* equals Filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class EqualsFilter extends AbstractMatchFilter { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "equals"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return source.equalsIgnoreCase(match); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Objects; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* list-echo |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
* @version 1.0.0 |
||||||
|
* @since 2023/5/30 16:52 |
||||||
|
*/ |
||||||
|
public class ListEchoFilter extends AbstractEchoFilter { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "list-echo"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
// 验证
|
||||||
|
if (!verify(wrapper)) { |
||||||
|
return wrapper; |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.success(""); |
||||||
|
} |
||||||
|
|
||||||
|
if (!(value instanceof Collection)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "The incoming data is not a collection"); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
List<Object> collection = (List<Object>) value; |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(collection)) { |
||||||
|
return PipeDataWrapper.success(""); |
||||||
|
} |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params())) { |
||||||
|
return PipeDataWrapper.success(collection.stream().map(String::valueOf).collect(Collectors.joining(Delimiter.WRAP.getDelimiter()))); |
||||||
|
} |
||||||
|
|
||||||
|
String delimiter = params().get(0); |
||||||
|
|
||||||
|
Delimiter delimiterEnum = Delimiter.ofValue(delimiter); |
||||||
|
if (Objects.nonNull(delimiterEnum)) { |
||||||
|
return PipeDataWrapper.success(collection.stream().map(String::valueOf).collect(Collectors.joining(delimiterEnum.getDelimiter()))); |
||||||
|
} |
||||||
|
|
||||||
|
return PipeDataWrapper.success(collection.stream().map(String::valueOf).collect(Collectors.joining(delimiter))); |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,92 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.write.handler.BasePipeFilter; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.util.CollectionUtils; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Objects; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
* @version 1.0.0 |
||||||
|
* @since 2023/5/30 16:52 |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
public class ListIndexFilter extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 参数格式 list-index:n n表示下标,从1开始 |
||||||
|
* |
||||||
|
* @param wrapper the function argument |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
// 验证
|
||||||
|
if (!verify(wrapper)) { |
||||||
|
return wrapper; |
||||||
|
} |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params())) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "missing parameter for instruction"); |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "Incoming data cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
if (!(value instanceof Collection)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "The incoming data is not a collection"); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
List<Object> collection = (List<Object>) value; |
||||||
|
|
||||||
|
if (CollectionUtils.isEmpty(collection)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "Incoming data cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params()) || params().size() > 1) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "The index of the passed in parameter is empty or exceeds one"); |
||||||
|
} |
||||||
|
|
||||||
|
String index = params().get(0); |
||||||
|
if (StringUtils.isBlank(index)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "The index of the incoming parameter is empty"); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
int ind = Integer.parseInt(index); |
||||||
|
if (ind < 0) { |
||||||
|
ind = 0; |
||||||
|
} |
||||||
|
if (ind >= 1) { |
||||||
|
ind -= 1; |
||||||
|
} |
||||||
|
if (ind >= collection.size() - 1) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "The index of the passed in parameter exceeds the maximum length of the set"); |
||||||
|
} |
||||||
|
List<String> collect = collection.stream().map(Object::toString).collect(Collectors.toList()); |
||||||
|
return PipeDataWrapper.success(collect.get(ind)); |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
|
||||||
|
log.warn(e.getMessage(), e); |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "Index conversion error"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "list-index"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,99 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.write.handler.BasePipeFilter; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Objects; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
* @version 1.0.0 |
||||||
|
* @since 2023/5/30 16:52 |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
public class ListRangeFilter extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
private static final int PARAMS_NUM = 2; |
||||||
|
|
||||||
|
/** |
||||||
|
* list-range:index,count Starting from index, obtain count quantity |
||||||
|
* |
||||||
|
* @param wrapper the function argument |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
// 验证
|
||||||
|
if (!verify(wrapper)) { |
||||||
|
return wrapper; |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "Incoming data cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
if (!(value instanceof Collection)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "The incoming data is not a collection"); |
||||||
|
} |
||||||
|
|
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
List<Object> collection = (List<Object>) value; |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params()) || params().size() > PARAMS_NUM) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[list-range:index,count] the input parameter subscript is empty or exceeds two"); |
||||||
|
} |
||||||
|
|
||||||
|
String index = params().get(0); |
||||||
|
if (StringUtils.isBlank(index)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[list-range:index,count] the parameter index passed in is empty"); |
||||||
|
} |
||||||
|
|
||||||
|
String count = params().get(1); |
||||||
|
if (StringUtils.isBlank(count)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[list-range:index,count] the parameter count passed in is empty"); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
int fromIndex = Integer.parseInt(index); |
||||||
|
if (fromIndex < 0) { |
||||||
|
fromIndex = 0; |
||||||
|
} |
||||||
|
if (fromIndex >= 1) { |
||||||
|
fromIndex -= 1; |
||||||
|
} |
||||||
|
|
||||||
|
int countInt = Integer.parseInt(count); |
||||||
|
if (countInt < 1) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[list-range:index,count] count parameter must be greater than 0"); |
||||||
|
} |
||||||
|
|
||||||
|
int toIndex = countInt + fromIndex; |
||||||
|
int size = collection.size(); |
||||||
|
if (toIndex > size) { |
||||||
|
log.warn("error:[list-range:index,count] the count parameter value is greater than the size of the input set"); |
||||||
|
toIndex = size; |
||||||
|
} |
||||||
|
|
||||||
|
List<String> collect = collection.stream().map(Object::toString).collect(Collectors.toList()); |
||||||
|
return PipeDataWrapper.success(collect.subList(fromIndex, toIndex)); |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
log.warn(e.getMessage(), e); |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[list-range:index,count] Index or count parameter conversion error"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "list-range"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* cal-mul |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class MultiplicationFilter extends AbstractCalculatorFilter { |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "cal-mul"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* pattern |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class PatternFilter extends AbstractMatchFilter { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "pattern"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return Pattern.matches(match, source); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* prior-contains |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class PriorContainsFilter extends AbstractPriorMatchFilter { |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "prior-contains"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return source.contains(match); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* prior-ends-with |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class PriorEndsWithFilter extends AbstractPriorMatchFilter { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "prior-ends-with"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return source.endsWith(match); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* prior-equals |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class PriorEqualsFilter extends AbstractPriorMatchFilter { |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "prior-equals"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return source.equalsIgnoreCase(match); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import java.util.regex.Pattern; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* prior-pattern |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class PriorPatternFilter extends AbstractPriorMatchFilter { |
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "prior-pattern"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return Pattern.matches(match, source); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* starts-with |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class PriorStartsWithFilter extends AbstractPriorMatchFilter { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "starts-with"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return source.startsWith(match); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,77 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.write.handler.BasePipeFilter; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* replace |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
public class ReplaceFilter extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
private static final int PARAMS_NUM = 3; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "replace"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
// 验证
|
||||||
|
if (!verify(wrapper)) { |
||||||
|
return wrapper; |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "incoming data cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params()) || params().size() != PARAMS_NUM) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[replace:oldChar,newChar,all] the input parameter is empty or exceeds two"); |
||||||
|
} |
||||||
|
|
||||||
|
String oldChar = params().get(0); |
||||||
|
if (StringUtils.isBlank(oldChar)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[replace:oldChar,newChar,all] the parameter 'oldChar' passed in is empty"); |
||||||
|
} |
||||||
|
|
||||||
|
String newChar = params().get(1); |
||||||
|
if (StringUtils.isBlank(newChar)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[replace:oldChar,newChar,all] the parameter 'newChar' passed in is empty"); |
||||||
|
} |
||||||
|
|
||||||
|
String all = params().get(2); |
||||||
|
if (StringUtils.isBlank(all)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[replace:oldChar,newChar,all] the parameter 'all' passed in is empty, not 1/0"); |
||||||
|
} |
||||||
|
if (!StringUtils.isNumeric(all)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[replace:oldChar,newChar,all] the parameter 'all' passed in, not 1/0"); |
||||||
|
} |
||||||
|
|
||||||
|
if (!(value instanceof String)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "the instruction input data is not a string"); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
int allInt = Integer.parseInt(all); |
||||||
|
if (1 == allInt) { |
||||||
|
return PipeDataWrapper.success(((String) value).replaceAll(oldChar, newChar)); |
||||||
|
} else { |
||||||
|
return PipeDataWrapper.success(((String) value).replace(oldChar, newChar)); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
log.warn(e.getMessage()); |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[replace:oldChar,newChar,all] the parameter 'all' conversion error"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* starts-with |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class StartsWithFilter extends AbstractMatchFilter { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "starts-with"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean strMatch(String source, String match) { |
||||||
|
return source.startsWith(match); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,74 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.util.PipeFilterUtils; |
||||||
|
import com.alibaba.excel.util.StringUtils; |
||||||
|
import com.alibaba.excel.write.handler.BasePipeFilter; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* Substring |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
@Slf4j |
||||||
|
public class SubstringFilter extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
private static final int PARAMS_NUM = 2; |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "substring"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
// 验证
|
||||||
|
if (!verify(wrapper)) { |
||||||
|
return wrapper; |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "incoming data cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
if (PipeFilterUtils.isEmpty(params()) || params().size() != PARAMS_NUM) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[substring:beginIndex,endIndex] the input parameter is empty or exceeds two"); |
||||||
|
} |
||||||
|
|
||||||
|
String begin = params().get(0); |
||||||
|
if (StringUtils.isBlank(begin)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[substring:beginIndex,endIndex] the incoming parameter 'beginIndex' is empty"); |
||||||
|
} |
||||||
|
|
||||||
|
String end = params().get(1); |
||||||
|
if (StringUtils.isBlank(end)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "[substring:beginIndex,endIndex] the parameter 'endIndex' is empty"); |
||||||
|
} |
||||||
|
|
||||||
|
if (!(value instanceof String)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "the instruction input data is not a string"); |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
int length = ((String) value).length(); |
||||||
|
int beginIndex = Integer.parseInt(begin); |
||||||
|
int endIndex = Integer.parseInt(end); |
||||||
|
if (endIndex > length) { |
||||||
|
endIndex = length; |
||||||
|
} |
||||||
|
int subLen = endIndex - beginIndex; |
||||||
|
if (subLen < 0) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "index error,beginIndex==endIndex"); |
||||||
|
} |
||||||
|
return PipeDataWrapper.success(((String) value).substring(beginIndex, endIndex)); |
||||||
|
} catch (NumberFormatException e) { |
||||||
|
log.warn(e.getMessage(), e); |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "index conversion error"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* sub |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class SubtractionFilter extends AbstractCalculatorFilter { |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "cal-sub"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
package com.alibaba.excel.write.handler.filter; |
||||||
|
|
||||||
|
import com.alibaba.excel.write.handler.BasePipeFilter; |
||||||
|
import com.alibaba.excel.write.handler.PipeDataWrapper; |
||||||
|
import org.springframework.util.CollectionUtils; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
import java.util.Objects; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* trim pipe filter |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
*/ |
||||||
|
public class TrimFilter extends BasePipeFilter<Object, Object> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public PipeDataWrapper<Object> apply(PipeDataWrapper<Object> wrapper) { |
||||||
|
|
||||||
|
// 验证
|
||||||
|
if (!verify(wrapper)) { |
||||||
|
return wrapper; |
||||||
|
} |
||||||
|
|
||||||
|
Object value = wrapper.getData(); |
||||||
|
if (Objects.isNull(value)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "incoming data cannot be empty"); |
||||||
|
} |
||||||
|
|
||||||
|
if (value instanceof String) { |
||||||
|
|
||||||
|
return PipeDataWrapper.success(value.toString().trim()); |
||||||
|
} else if (value instanceof Collection) { |
||||||
|
//noinspection unchecked
|
||||||
|
Collection<Object> valList = (Collection<Object>) value; |
||||||
|
if (CollectionUtils.isEmpty(valList)) { |
||||||
|
return PipeDataWrapper.error(errorPrefix() + "incoming data cannot be empty"); |
||||||
|
} |
||||||
|
return PipeDataWrapper.success(valList.stream().filter(Objects::nonNull).map(str -> str.toString().trim()).collect(Collectors.toList())); |
||||||
|
} |
||||||
|
|
||||||
|
return PipeDataWrapper.error(errorPrefix() + "the instruction input data is not a string or set"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected String filterName() { |
||||||
|
return "trim"; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,155 @@ |
|||||||
|
package com.alibaba.excel.write.handler; |
||||||
|
|
||||||
|
import com.alibaba.easyexcel.test.demo.fill.FillData; |
||||||
|
import com.alibaba.excel.util.ListUtils; |
||||||
|
import lombok.val; |
||||||
|
import org.junit.jupiter.api.Test; |
||||||
|
import org.springframework.util.Assert; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Description: |
||||||
|
* |
||||||
|
* @author linfeng |
||||||
|
* @version 1.0.0 |
||||||
|
* @since 2023/6/21 14:00 |
||||||
|
*/ |
||||||
|
class PipeFilterFactoryTest { |
||||||
|
|
||||||
|
private List<FillData> dataPipe() { |
||||||
|
List<FillData> list = ListUtils.newArrayList(); |
||||||
|
for (int i = 0; i < 10; i++) { |
||||||
|
FillData fillData = new FillData(); |
||||||
|
list.add(fillData); |
||||||
|
fillData.setName(" 张三 "); |
||||||
|
fillData.setNumber(5.2); |
||||||
|
fillData.setDate(new Date()); |
||||||
|
if (i == 0) { |
||||||
|
fillData.setImages(Arrays.asList("http://www.baidu.com/images/m100-1.1.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.2.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.3.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.4.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.5.jpg")); |
||||||
|
} else { |
||||||
|
fillData.setImages(Arrays.asList("http://www.baidu.com/images/m100-1.1.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.2.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.3.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.4.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.5.jpg" |
||||||
|
, "http://www.baidu.com/images/K100-1.2.jpg")); |
||||||
|
} |
||||||
|
} |
||||||
|
return list; |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testEndsWithError() { |
||||||
|
PipeFilterFactory pipeFilterFactory = PipeFilterFactory.createPipeFilter(null); |
||||||
|
pipeFilterFactory.addParams("test | ends-with : "); |
||||||
|
val apply = pipeFilterFactory.apply(PipeDataWrapper.success(Arrays.asList("http://www.baidu.com/images/m100-1.1.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.2.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.3.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.4.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.5.jpg" |
||||||
|
, "http://www.baidu.com/images/K100-1.2.jpg"))); |
||||||
|
System.out.println(apply.getMessage()); |
||||||
|
Assert.isTrue(!apply.success(), "成功"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testEndsWith() { |
||||||
|
PipeFilterFactory pipeFilterFactory = PipeFilterFactory.createPipeFilter(null); |
||||||
|
pipeFilterFactory.addParams("test | ends-with : m100-1.3.jpg,m100-1.5.jpg,m100-1.4.jpg "); |
||||||
|
val apply = pipeFilterFactory.apply(PipeDataWrapper.success(Arrays.asList("http://www.baidu.com/images/m100-1.1.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.2.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.3.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.4.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.5.jpg" |
||||||
|
, "http://www.baidu.com/images/K100-1.2.jpg"))); |
||||||
|
Assert.isTrue(!apply.success(), "测试输出多个数字,不能为集合"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testProEndsWith() { |
||||||
|
PipeFilterFactory pipeFilterFactory = PipeFilterFactory.createPipeFilter(null); |
||||||
|
pipeFilterFactory.addParams("test | prior-ends-with : m100-1.3.jpg,m100-1.5.jpg,m100-1.4.jpg "); |
||||||
|
val apply = pipeFilterFactory.apply(PipeDataWrapper.success(Arrays.asList("http://www.baidu.com/images/m100-1.1.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.2.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.3.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.4.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.5.jpg" |
||||||
|
, "http://www.baidu.com/images/K100-1.2.jpg"))); |
||||||
|
Assert.isTrue(apply.success(), "失败"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Test |
||||||
|
void testSubstr() { |
||||||
|
PipeFilterFactory pipeFilterFactory = PipeFilterFactory.createPipeFilter(null); |
||||||
|
pipeFilterFactory.addParams("test | substring : 0,10 "); |
||||||
|
val apply = pipeFilterFactory.apply(PipeDataWrapper.success("这个示例程序创建了两个 double 类型的变量 a 和 b,分别赋值为 10 和 5,然后调用 Calculator 类中的四个方法,输出运算结果。其中,divide 方法在除数为0时会抛出异常,这里使用了 try-catch 语句捕获异常,并输出错误信息。")); |
||||||
|
Assert.isTrue(apply.success(), "失败"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testEquals() { |
||||||
|
//
|
||||||
|
Map<String, Object> titleMap = new HashMap<>(2); |
||||||
|
titleMap.put("eBayTitle", "eBayTitle这个示例程序创建了两个 double 类型的变量 a 和 b,分别赋值为 10 和 5,然后调用 Calculator 类中的四个方法,输出运算结果"); |
||||||
|
titleMap.put("amazonTitle", "amazonTitle其中,divide 方法在除数为0时会抛出异常,这里使用了 try-catch 语句捕获异常,并输出错误信息。"); |
||||||
|
PipeFilterFactory pipeFilterFactory = PipeFilterFactory.createPipeFilter(null); |
||||||
|
pipeFilterFactory.addParams("PublishCenter.titleMap | prior-equals:amazonTitle,eBayTitle "); |
||||||
|
val apply = pipeFilterFactory.apply(PipeDataWrapper.success(titleMap)); |
||||||
|
Assert.isTrue(apply.success() && apply.getData().toString().startsWith("amazonTitle"), "失败"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testNumber() { |
||||||
|
// ebayManno.price | cal-mul:1.4,int | cal-add:0.99,number_2
|
||||||
|
PipeFilterFactory pipeFilterFactory = PipeFilterFactory.createPipeFilter(null); |
||||||
|
pipeFilterFactory.addParams("ebayManno.price | cal-mul:2,int | cal-add:0.99,number_2"); |
||||||
|
val apply = pipeFilterFactory.apply(PipeDataWrapper.success("100")); |
||||||
|
Assert.isTrue(apply.success() && apply.getData().toString().equals("200.99"), "失败"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testEcho() { |
||||||
|
// PhotoStore.attach | prior-ends-with:m100-8.jpg | echo:wrap
|
||||||
|
PipeFilterFactory pipeFilterFactory = PipeFilterFactory.createPipeFilter(null); |
||||||
|
pipeFilterFactory.addParams("ebayManno.price | prior-ends-with:m100-1.4.jpg | echo:wrap"); |
||||||
|
val apply = pipeFilterFactory.apply(PipeDataWrapper.success(Arrays.asList("http://www.baidu.com/images/m100-1.1.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.2.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.3.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.4.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.5.jpg" |
||||||
|
, "http://www.baidu.com/images/K100-1.2.jpg"))); |
||||||
|
Assert.isTrue(apply.success() && apply.getData().toString().endsWith("\n"), "失败"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testEchoNone() { |
||||||
|
PipeFilterFactory pipeFilterFactory = PipeFilterFactory.createPipeFilter(null); |
||||||
|
pipeFilterFactory.addParams("ebayManno.price | prior-ends-with:m100-1.5.jpg | echo:wrap"); |
||||||
|
val apply = pipeFilterFactory.apply(PipeDataWrapper.success(Arrays.asList("http://www.baidu.com/images/m100-1.1.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.2.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.3.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.5.jpg" |
||||||
|
, "http://www.baidu.com/images/K100-1.2.jpg"))); |
||||||
|
Assert.isTrue(apply.success() && apply.getData().toString().endsWith("\n"), "失败"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
void testListEcho() { |
||||||
|
PipeFilterFactory pipeFilterFactory = PipeFilterFactory.createPipeFilter(null); |
||||||
|
pipeFilterFactory.addParams("ebayManno.price | list-echo:wrap"); |
||||||
|
val apply = pipeFilterFactory.apply(PipeDataWrapper.success(Arrays.asList("http://www.baidu.com/images/m100-1.1.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.2.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.3.jpg" |
||||||
|
, "http://www.baidu.com/images/m100-1.5.jpg" |
||||||
|
, "http://www.baidu.com/images/K100-1.2.jpg"))); |
||||||
|
Assert.isTrue(apply.success(), "失败"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue