com.xiaoleilu.hutool.cron.pattern.matcher.ValueMatcherBuilder Maven / Gradle / Ivy
package com.xiaoleilu.hutool.cron.pattern.matcher;
import java.util.ArrayList;
import java.util.List;
import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaoleilu.hutool.cron.CronException;
import com.xiaoleilu.hutool.cron.pattern.parser.DayOfMonthValueParser;
import com.xiaoleilu.hutool.cron.pattern.parser.ValueParser;
import com.xiaoleilu.hutool.cron.pattern.parser.YearValueParser;
import com.xiaoleilu.hutool.util.NumberUtil;
import com.xiaoleilu.hutool.util.StrUtil;
/**
* {@link ValueMatcher} 构建器
* @author Looly
*
*/
public class ValueMatcherBuilder {
/**
* 处理定时任务表达式每个时间字段
* 多个时间使用逗号分隔
*
* @param value 某个时间字段
* @param parser 针对这个时间字段的解析器
* @return List
*/
public static ValueMatcher build(String value, ValueParser parser) {
if (1 == value.length() && ("*".equals(value) || "?".equals(value))) {
//兼容Quartz的"?"表达式,不会出现互斥情况,与"*"作用相同
return new AlwaysTrueValueMatcher();
}
List values = parseArray(value, parser);
if (values.size() == 0) {
throw new CronException("Invalid field: [{}]", value);
}
if (parser instanceof DayOfMonthValueParser) {
//考虑每月的天数不同,切存在闰年情况,日匹配单独使用
return new DayOfMonthValueMatcher(values);
}else if(parser instanceof YearValueParser){
//考虑年数字太大,不适合boolean数组,单独使用列表遍历匹配
return new YearValueMatcher(values);
}else {
return new BoolArrayValueMatcher(values);
}
}
/**
* 处理数组形式表达式
* 处理的形式包括:
*
* - a 或 *
* - a,b,c,d
*
* @param value 子表达式值
* @param parser 针对这个字段的解析器
* @return 值列表
*/
private static List parseArray(String value, ValueParser parser){
final List values = new ArrayList<>();
final List parts = StrUtil.split(value, StrUtil.C_COMMA);
for (String part : parts) {
CollectionUtil.addAllIfNotContains(values, parseStep(part, parser));
}
return values;
}
/**
* 处理间隔形式的表达式
* 处理的形式包括:
*
* - a 或 *
* - a/b 或 */b
* - a-b/2
*
*
* @param value 表达式值
* @param parser 针对这个时间字段的解析器
* @return List
*/
private static List parseStep(String value, ValueParser parser) {
List parts = StrUtil.split(value, StrUtil.C_SLASH);
int size = parts.size();
if (size == 1) {// 普通形式
return parseRange(value, parser);
} else if (size == 2) {// 间隔形式
final List rangeValues = parseRange(parts.get(0), parser);
int step = parser.parse(parts.get(1));
if (step < 1) {
throw new CronException("Non positive divisor for field: [{}]", value);
}
// 根据定义的间隔值,返回重新生成的时间值列表
List values2 = new ArrayList<>();
for (int i = 0; i < rangeValues.size(); i += step) {
values2.add(rangeValues.get(i));
}
return values2;
} else {
throw new CronException("Invalid syntax of field: [{}]", value);
}
}
/**
* 处理表达式中范围表达式 处理的形式包括:
*
* - *
* - 2
* - 3-8
* - 8-3
* - 3-3
*
*
* @param value 范围表达式
* @param parser 针对这个时间字段的解析器
* @return List
*/
private static List parseRange(String value, ValueParser parser) {
// 全部匹配形式
if (value.length() == 1 && value.equals("*")) {
List values = new ArrayList<>();
for (int i = parser.getMin(); i <= parser.getMax(); i++) {
values.add(i);
}
return values;
}
List parts = StrUtil.split(value, '-');
int size = parts.size();
List values = new ArrayList<>();
if (size == 1) {// 普通值
values.add(parser.parse(value));
return values;
} else if (size == 2) {// range值
int v1 = parser.parse(parts.get(0));
int v2 = parser.parse(parts.get(1));
if (v1 < v2) {// 正常范围,例如:2-5
NumberUtil.appendRange(v1, v2, values);
} else if (v1 > v2) {// 逆向范围,反选模式,例如:5-2
NumberUtil.appendRange(v1, parser.getMax(), values);
NumberUtil.appendRange(parser.getMin(), v2, values);
} else {// v1 == v2
values.add(v1);
}
} else {
throw new CronException("Invalid syntax of field: [{}]", value);
}
return values;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy