All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.intelie.pipes.cron.CronParsingHelper Maven / Gradle / Ivy

There is a newer version: 0.25.5
Show newest version
package net.intelie.pipes.cron;

import java.time.DayOfWeek;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

class CronParsingHelper {
    private static final Map MONTHS =
            aliases("JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC");
    private static final Map DAYS_OF_WEEK =
            aliases("MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN");

    private static Map aliases(String... values) {
        return Collections.unmodifiableMap(IntStream.range(0, values.length)
                .boxed().collect(Collectors.toMap(x -> values[x], x -> (x + 1))));
    }

    public static List parse(String expr) {
        expr = alias(expr, "@yearly", "0 0 1 1 *");
        expr = alias(expr, "@annually", "0 0 1 1 *");
        expr = alias(expr, "@monthly", "0 0 1 * *");
        expr = alias(expr, "@weekly", "0 0 * * 0");
        expr = alias(expr, "@daily", "0 0 * * *");
        expr = alias(expr, "@midnight", "0 0 * * *");
        expr = alias(expr, "@hourly", "0 * * * *");

        String[] fields = expr.split("\\s+");
        CronException.check(fields.length == 5 || fields.length == 6,
                "Expression '%s' must define 5 or 6 fields. It has: %d.", expr, fields.length);

        int offset = fields.length - 5;
        return Arrays.asList(
                offset == 1 ? parseOther(FieldType.SECOND, fields[0]) : new ValueField(FieldType.SECOND, 0),
                parseOther(FieldType.MINUTE, fields[offset]),
                parseOther(FieldType.HOUR, fields[offset + 1]),
                parseOther(FieldType.DAY, fields[offset + 2]),
                parseMonth(fields[offset + 3]),
                parseDayOfWeek(fields[offset + 4]));
    }

    private static String alias(String expression, String from, String to) {
        if (from.equalsIgnoreCase(expression))
            return to;
        return expression;
    }

    public static Field parseDayOfWeek(String field) {
        return parseField(FieldType.DAY_OF_WEEK, field, DAYS_OF_WEEK);
    }

    public static Field parseMonth(String field) {
        return parseField(FieldType.MONTH, field, MONTHS);
    }

    public static Field parseOther(FieldType type, String expr) {
        return parseField(type, expr, Collections.emptyMap());
    }

    private static Field parseField(FieldType type, String expr, Map aliases) {
        try {
            List list = new ArrayList<>();
            for (String field : expr.split(","))
                list.add(parseSingle(type, field, aliases));
            if (list.size() == 1)
                return list.get(0);
            return new FieldList(list);
        } catch (CronException e) {
            throw new CronException("%s (%s = '%s')", e.getMessage(), type.toString().toLowerCase(Locale.ROOT), expr);
        }
    }

    private static Field parseSingle(FieldType type, String expr, Map aliases) {
        String[] slashed = expr.split("/", 2);
        String[] dashed = slashed[0].split("-", 2);

        String start = dashed[0];
        String end = dashed.length == 2 ? dashed[1] : null;
        String step = slashed.length == 2 ? slashed[1] : null;

        if (step != null || end != null) {
            Integer startValue = parseValue(type, start, aliases);
            Integer endValue = parseValue(type, end, aliases);
            Integer stepValue = parseValue(type, step, null);

            if (startValue != null && endValue != null && startValue > endValue)
                return new FieldList(
                        new RangeField(type, null, endValue, stepValue),
                        new RangeField(type, startValue, null, stepValue));
            return new RangeField(type, startValue, endValue, stepValue);
        } else {
            Integer value = parseValue(type, start, aliases);
            if (value == null)
                return new StarField();
            return new ValueField(type, value);
        }
    }

    private static Integer parseValue(FieldType type, String expr, Map aliases) {
        if (expr == null) return null;
        if ("*".equals(expr) || "".equals(expr)) return null;
        if (aliases != null) {
            Integer value = aliases.get(expr.toUpperCase(Locale.ROOT));
            if (value != null) return value;
        }

        try {
            int parsed = Integer.parseInt(expr);
            if (type == FieldType.DAY_OF_WEEK && parsed == 0)
                return DayOfWeek.SUNDAY.getValue();
            return parsed;
        } catch (Exception e) {
            throw new CronException(String.format((Locale) null, "Invalid expression: '%s'", expr));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy