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.
*
* @param value 表达式
* @return {@link PartMatcher}
*/
public PartMatcher parse(String value) {
// 是否是查询最后一天
if (isMatchAllStr(value)) {
//兼容Quartz的"?"表达式,不会出现互斥情况,与"*"作用相同
return new AlwaysTrueMatcher();
}
final List values = parseArray(value);
if (values.isEmpty()) {
throw new CronException("Invalid part value: [{}]", value);
}
switch (this.part) {
case DAY_OF_MONTH:
return new DayOfMonthMatcher(values);
case YEAR:
return new YearValueMatcher(values);
default:
return new BoolArrayMatcher(values);
}
}
/**
* 处理数组形式表达式
* 处理的形式包括:
*
*
a 或 *
*
a,b,c,d
*
*
* @param value 子表达式值
* @return 值列表
*/
private List parseArray(String value) {
final List values = new ArrayList<>();
final List parts = StrUtil.split(value, StrUtil.C_COMMA);
for (String part : parts) {
CollUtil.addAllIfNotContains(values, parseStep(part));
}
return values;
}
/**
* 处理间隔形式的表达式
* 处理的形式包括:
*
*
a 或 *
*
a/b 或 */b
*
a-b/2
*
*
* @param value 表达式值
* @return List
*/
private List parseStep(String value) {
final List parts = StrUtil.split(value, StrUtil.C_SLASH);
int size = parts.size();
List results;
if (size == 1) {// 普通形式
results = parseRange(value, -1);
} else if (size == 2) {// 间隔形式
// issue#I7SMP7,步进不检查范围
final int step = parseNumber(parts.get(1), false);
if (step < 1) {
throw new CronException("Non positive divisor for field: [{}]", value);
}
results = parseRange(parts.get(0), step);
} else {
throw new CronException("Invalid syntax of field: [{}]", value);
}
return results;
}
/**
* 处理表达式中范围表达式 处理的形式包括:
*
*
*
*
2
*
3-8
*
8-3
*
3-3
*
*
* @param value 范围表达式
* @param step 步进
* @return List
*/
private List parseRange(String value, int step) {
final List results = new ArrayList<>();
// 全部匹配形式
if (value.length() <= 2) {
//根据步进的第一个数字确定起始时间,类似于 12/3则从12(秒、分等)开始
int minValue = part.getMin();
if (false == isMatchAllStr(value)) {
minValue = Math.max(minValue, parseNumber(value, true));
} else {
//在全匹配模式下,如果步进不存在,表示步进为1
if (step < 1) {
step = 1;
}
}
if (step > 0) {
final int maxValue = part.getMax();
if (minValue > maxValue) {
throw new CronException("Invalid value {} > {}", minValue, maxValue);
}
//有步进
for (int i = minValue; i <= maxValue; i += step) {
results.add(i);
}
} else {
//固定时间
results.add(minValue);
}
return results;
}
//Range模式
List parts = StrUtil.split(value, '-');
int size = parts.size();
if (size == 1) {// 普通值
final int v1 = parseNumber(value, true);
if (step > 0) {//类似 20/2的形式
NumberUtil.appendRange(v1, part.getMax(), step, results);
} else {
results.add(v1);
}
} else if (size == 2) {// range值
final int v1 = parseNumber(parts.get(0), true);
final int v2 = parseNumber(parts.get(1), true);
if (step < 1) {
//在range模式下,如果步进不存在,表示步进为1
step = 1;
}
if (v1 <= v2) {// 正常范围,例如:2-5,3-3
NumberUtil.appendRange(v1, v2, step, results);
} else {// 逆向范围,反选模式,例如:5-2
NumberUtil.appendRange(v1, part.getMax(), step, results);
NumberUtil.appendRange(part.getMin(), v2, step, results);
}
} else {
throw new CronException("Invalid syntax of field: [{}]", value);
}
return results;
}
/**
* 是否为全匹配符
* 全匹配符指 * 或者 ?
*
* @param value 被检查的值
* @return 是否为全匹配符
* @since 4.1.18
*/
private static boolean isMatchAllStr(String value) {
return (1 == value.length()) && ("*".equals(value) || "?".equals(value));
}
/**
* 解析单个int值,支持别名
*
* @param value 被解析的值
* @param checkValue 是否检查值在有效范围内
* @return 解析结果
* @throws CronException 当无效数字或无效别名时抛出
*/
private int parseNumber(String value, boolean checkValue) throws CronException {
int i;
try {
i = Integer.parseInt(value);
} catch (NumberFormatException ignore) {
i = parseAlias(value);
}
// 支持负数
if(i < 0){
i += part.getMax();
}
// 周日可以用0或7表示,统一转换为0
if(Part.DAY_OF_WEEK.equals(this.part) && Week.SUNDAY.getIso8601Value() == i){
i = Week.SUNDAY.ordinal();
}
return checkValue ? part.checkValue(i) : i;
}
/**
* 解析别名支持包括:
*
*
L 表示最大值
*
{@link Part#MONTH}和{@link Part#DAY_OF_WEEK}别名
*
*
* @param name 别名
* @return 解析int值
* @throws CronException 无匹配别名时抛出异常
*/
private int parseAlias(String name) throws CronException {
if ("L".equalsIgnoreCase(name)) {
// L表示最大值
return part.getMax();
}
switch (this.part) {
case MONTH:
// 月份从1开始
return Month.of(name).getValueBaseOne();
case DAY_OF_WEEK:
// 周从0开始,0表示周日
return Week.of(name).ordinal();
}
throw new CronException("Invalid alias value: [{}]", name);
}
}