package com.hqyg.disjob.console.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import com.hqyg.disjob.common.exception.EjobCronException;
import com.hqyg.disjob.common.exception.EjobFrameWorkException;
import com.hqyg.disjob.register.domain.CronInfo;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
public class CronUtils {
public static final String ALL = "*";
public static final String COMMA = ",";
public static final String QUESTION_MARK = "?";
public static final String SPACE = " ";
public static final String defaultSpecial = CronInfo.defaultSpecial;
private static final BiMap<String, String> specialCronMap = HashBiMap.create(5);
static{
specialCronMap.put("hourly", "0 0 * * * ?");
specialCronMap.put("daily", "0 0 0 * * ?");
specialCronMap.put("weekly", "0 0 0 ? * SUN");
specialCronMap.put("monthly", "0 0 0 1 * ?");
specialCronMap.put("yearly", "0 0 0 1 1 ?");
}
private static final String[] dateFactor = new String[] { "seconds", "mins", "hours", "days", "months",
"weekdays" };
public static final String transferToCronExpression(CronInfo cronInfo) {
String minute,second,hour,day,month,weekday;
if(cronInfo.isChooseSpecial()){
return specialCronMap.get(cronInfo.getSpecial());
}else{
if(cronInfo.isAllMins()){
minute = ALL;
}else{
minute = transferToString(cronInfo.getMins());
}
if(cronInfo.isAllSeconds()){
second = ALL;
}else{
second = transferToString(cronInfo.getSeconds());
}
if(cronInfo.isAllHours()){
hour = ALL;
}else{
hour = transferToString(cronInfo.getHours());
}
if(cronInfo.isAllDays()){
day = ALL;
}else{
day = transferToString(cronInfo.getDays());
}
if(cronInfo.isAllMonths()){
month = ALL;
}else{
month = transferToString(cronInfo.getMonths());
}
if(cronInfo.isAllWeekdays()){
if(ALL.equals(day)){
weekday = QUESTION_MARK;
}else{
if(day.equals(QUESTION_MARK)){
weekday = ALL;
}else{
weekday = QUESTION_MARK;
}
}
}else{
weekday = transferToString(cronInfo.getWeekdays());
day = QUESTION_MARK;
}
}
String cronExpression = buidCron(second,minute,hour,day,month,weekday);
if(CronExpression.isValidExpression(cronExpression)){
return cronExpression;
}else{
throw new EjobFrameWorkException("CronUtils.transferToCronExpression transfer CronInfo to StringCronExpression , but [" + cronExpression + "] isUnValidExpression");
}
}
private static String buidCron(String...str) {
return StringUtils.join(str, SPACE);
}
private static String transferToString(String[] iArray){
return StringUtils.join(iArray, COMMA);
}
public static final CronInfo transferFromCronExpression(String cronExpression) {
if(StringUtils.isEmpty(cronExpression)){
return CronInfo.defaultValue();
}
cronExpression = cronExpression.trim();
CronInfo cronInfo = new CronInfo();
if(specialCronMap.containsValue(cronExpression)){
cronInfo.setChooseSpecial(true);
cronInfo.setSpecial(specialCronMap.inverse().get(cronExpression));
return cronInfo;
}
StringTokenizer exprsTok = new StringTokenizer(cronExpression, " \t", false);
int i = 0;
while (exprsTok.hasMoreTokens() && i < dateFactor.length){
String expr = exprsTok.nextToken().trim(); // 0 * * * * ? ...
if(!QUESTION_MARK.equals(expr) && !ALL.equals(expr)){
}
String factorName = dateFactor[i]; // seconds...
Class<CronInfo> clazz = CronInfo.class;
try {
Method methodSetAll = clazz.getDeclaredMethod("setAll" + captureName(factorName), boolean.class);
methodSetAll.setAccessible(true);
if(ALL.equals(expr) || QUESTION_MARK.equals(expr)){
methodSetAll.invoke(cronInfo, true);
}else{
Method method = clazz.getDeclaredMethod("set" + captureName(factorName), String[].class);
method.setAccessible(true);
method.invoke(cronInfo, new Object[]{transferArrayToString(expr)});
methodSetAll.invoke(cronInfo, false);
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
throw new EjobCronException(e);
}
i++;
}
return cronInfo;
}
private static String[] transferArrayToString(String str){
List<String> list = Lists.newArrayList();
for(String string : str.split(COMMA)){
String number = string.trim();
if(!NumberUtils.isNumber(number)){
throw new EjobCronException();
}
list.add(number);
}
String[] is = new String[0];
return list.toArray(is);
}
public static String captureName(String name) {
char[] cs = name.toCharArray();
cs[0] -= 32;
return String.valueOf(cs);
}
}