com.viaoa.process.OACron Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of oa Show documentation
Show all versions of oa Show documentation
Object Automation library
The newest version!
package com.viaoa.process;
import java.util.Arrays;
import java.util.Calendar;
import com.viaoa.hub.HubEvent;
import com.viaoa.util.OAArray;
import com.viaoa.util.OAConv;
import com.viaoa.util.OADate;
import com.viaoa.util.OADateTime;
import com.viaoa.util.OAString;
/**
* Used to define and find the next time a Cron-like entry should be ran.
* * * * * command to be executed
- - - - -
| | | | |
| | | | +----- day of week (0-6) (Sunday=0) - Java: 1-7 (Sunday=1)
| | | +---------- month (1-12) - Java: 0-11
| | +-------------- day of month (1-31), also allows "last"
| +-------------------- hour (0 - 23)
+-------------------------- min (0 - 59)
Each field needs to be separate by space or tab.
Field values can use a single number, "-" for a range, and commas to separate more then one.
see OACronProcessor# to register cron to be processed
@author vvia
*/
public abstract class OACron {
// NOTE: all values are stored as cron values
private OADateTime dtFrom;
private String strMins;
private String strHours;
private String strDayOfMonth;
private String strMonth;
private String strDayOfWeek;
// store sorted cron values (not Java)
private int[] mins;
private int[] hrs;
private int[] monthDays;
private int[] daysOfWeek;
private int[] months;
private boolean bIncludeLastDayOfMonth;
private boolean bValid;
private String name;
private String description;
private boolean bEnabled = true;
private OADateTime dtCreated;
private OADateTime dtLast;
public OACron(String strMins, String strHours, String strDayOfMonth, String strMonth, String strDayOfWeek) {
this.dtCreated = new OADateTime();
this.strMins = strMins;
this.strHours = strHours;
this.strDayOfMonth = strDayOfMonth;
this.strMonth = strMonth;
this.strDayOfWeek = strDayOfWeek;
// set to default, can get changed when calling getInts
bValid = true;
bIncludeLastDayOfMonth = false;
mins = getInts(strMins);
hrs = getInts(strHours);
monthDays = getInts(strDayOfMonth, true);
daysOfWeek = getInts(strDayOfWeek);
months = getInts(strMonth);
if (bValid) {
for (int x : mins) {
if (x < 0 || x > 59) bValid = false;
}
for (int x : hrs) {
if (x < 0 || x > 23) bValid = false;
}
for (int x : monthDays) {
if (x < 1 || x > 31) bValid = false;
}
for (int x : daysOfWeek) {
if (x < 0 || x > 6) bValid = false;
}
if (months == null || months.length == 0) { // any month
months = new int[12];
for (int i=0; i<12; i++) months[i] = i+1; // store as cron month is 1-12, java is 0-11
}
for (int x : months) {
if (x < 1 || x > 12) bValid = false;
}
}
}
/**
* Called when it's time to process.
*/
public abstract void process(final boolean bManuallyCalled);
public int[] getMinutes() {
return mins;
}
public int[] getHours() {
return hrs;
}
public int[] getMonthDays() {
return monthDays;
}
public int[] getDaysOfWeek() {
return daysOfWeek;
}
public int[] getMonths() {
return months;
}
public boolean getIncludeLastDayOfMonth() {
return bIncludeLastDayOfMonth;
}
public boolean isValid() {
return bValid;
}
public String getDescription() {
if (description != null) return description;
description = "";
int x;
if (months.length == 12) {
//if (description.length() > 0) description += "; and ";
//else description += "all months";
}
else if (months.length > 0) {
if (description.length() > 0) description += "; and";
else description += "when";
description += " month is ";
for (int i=0; i 0) description += " or ";
if (x < 1 || x > 12) {
description += "Invalid:"+x;
}
else {
OADate d = new OADate(2017, x-1, 1);
description += d.toString("MMM");
}
}
}
if (monthDays.length > 0 || bIncludeLastDayOfMonth) {
if (description.length() > 0) description += "; and";
else description += "when";
description += " day of month is ";
for (int i=0; i 0) description += " or ";
if (x < 0 || x > 31) description += "Invalid:"+x;
else description += ""+x;
}
if (bIncludeLastDayOfMonth) {
if (monthDays.length > 0) description += " or ";
description += "last day";
}
}
if (daysOfWeek.length > 0) {
if (description.length() > 0) description += "; and";
else description += "when";
description += " day of week is ";
for (int i=0; i 0) description += " or ";
if (x < 0 || x > 6) description += "Invalid:"+x;
else {
String s;
for (int j=0; j<7; j++) {
OADate d = new OADate(2017, 0, 1+j);
if (d.getDayOfWeek() != x+1) continue;
description += d.toString("EEE");
break;
}
}
}
}
if (hrs.length > 0) {
if (description.length() > 0) description += "; and";
else description += "when";
description += " hour is ";
for (int i=0; i 0) description += " or ";
if (x < 0 || x > 23) description += "Invalid:"+x;
else description += ""+x;
}
}
if (mins.length > 0) {
if (description.length() > 0) description += "; and";
else description += "when";
description += " minute is ";
for (int i=0; i 0) description += ", ";
if (x < 0 || x > 59) description += "Invalid:"+x;
else description += ""+x;
}
}
else {
if (description.length() > 0) description += "; and ";
description += "every minute";
}
if (!isValid()) description = "INVALID: "+description;
return description;
}
public OADateTime getLast() {
return dtLast;
}
public void setLast(OADateTime dt) {
this.dtLast = dt;
}
public OADateTime getNext() {
return findNext(new OADateTime());
}
public OADateTime getNext(OADateTime dtFrom) {
return findNext(dtFrom);
}
public OADateTime findNext() {
return findNext(new OADateTime());
}
public OADateTime findNext(OADateTime dtFrom) {
if (!isValid()) return null;
if (dtFrom == null) dtFrom = new OADateTime();
this.dtFrom = dtFrom;
OADateTime dtFound = findNextMonth();
return dtFound;
}
private OADateTime findNextMonth() {
OADateTime dtFound = null;
final int fromMonth = dtFrom.getMonth();
OADateTime dtCheck = new OADateTime(dtFrom.getTime());
for (int i=0; ;i++) {
if (i > 0) dtCheck = dtCheck.addYears(1);
for (int m : months) {
m--; // cron month is 1-12, java is 0-11
if (i == 0 && m < dtFrom.getMonth()) continue;
dtCheck.setDay(1);
dtCheck.setMonth(m);
dtCheck.clearTime();
if (dtFound != null && dtFound.before(dtCheck)) continue;
OADateTime dtTo = dtCheck.addMonths(1);
if (dtCheck.before(dtFrom)) dtCheck = new OADateTime(dtFrom);
dtFound = findNextMonthDay(dtFound, dtTo, dtCheck);
}
if (dtFound != null) break;
}
if (dtFound != null) {
dtFound.clearSecondAndMilliSecond();
}
return dtFound;
}
private OADateTime findNextMonthDay(OADateTime dtFound, OADateTime dtTo, OADateTime dtCheck) {
if (!bIncludeLastDayOfMonth && (monthDays == null || monthDays.length == 0)) {
dtFound = findClosestDayOfWeek(dtFound, dtTo, dtCheck);
}
else {
OADateTime dtx = new OADateTime(dtFrom);
dtx.clearTime();
int max = dtCheck.getDaysInMonth();
for (int i=0; i<=monthDays.length; i++) {
int md;
if (i == monthDays.length) {
if (!bIncludeLastDayOfMonth) continue;
md = max;
}
else md = monthDays[i];
if (md > max) continue;
dtCheck.setDay(md);
if (dtCheck.before(dtx)) continue;
if (dtFound != null && dtFound.before(dtCheck)) continue;
OADateTime dtTo2 = dtCheck.addDays(1);
dtTo2.clearTime();
dtFound = findClosestDayOfWeek(dtFound, dtTo2, dtCheck);
}
}
return dtFound;
}
// Java Sunday=1, cron Sunday=0
private OADateTime findClosestDayOfWeek(OADateTime dtFound, OADateTime dtTo, OADateTime dtCheck) {
if (daysOfWeek == null || daysOfWeek.length == 0) { // any dayOfWeek
for (;;) {
dtFound = findClosestHour(dtFound, dtTo, dtCheck);
if (dtFound != null) break;
dtCheck = dtCheck.addDays(1);
dtCheck.clearTime();
if (dtTo != null && dtTo.compareTo(dtCheck) <= 0) break;
}
}
else {
int fromDayOfWeek = dtCheck.getDayOfWeek();
OADateTime dtHold = dtCheck;
int fromWd = dtHold.getDayOfWeek();
for (int i=0; i<2; i++) {
for (int wd : daysOfWeek) {
wd++; // cron day is 0 based, java 1 based
int diff;
if (i > 0) {
if (wd != fromWd) continue;
diff = 7;
}
else {
if (fromWd > wd) diff = (wd+7) - fromWd;
else diff = wd - fromWd;
}
if (diff != 0) dtCheck = dtHold.addDays(diff);
dtCheck.clearTime();
if (dtTo != null && dtTo.compareTo(dtCheck) <= 0) continue;
if (dtFound != null && dtFound.before(dtCheck)) continue;
dtFound = findClosestHour(dtFound, dtTo, dtCheck);
}
if (dtFound != null) break;
}
}
return dtFound;
}
private OADateTime findClosestHour(OADateTime dtFound, OADateTime dtTo, OADateTime dtCheck) {
if (hrs == null || hrs.length == 0) { // any hour
dtFound = findClosestMinute(dtFound, dtTo, dtCheck);
if (dtFound == null) {
dtCheck = dtCheck.addHours(1);
if (dtTo == null || dtTo.compareTo(dtCheck) > 0) {
dtFound = findClosestMinute(dtFound, dtTo, dtCheck);
}
}
}
else {
dtCheck.setMinute(0);
dtCheck.clearSecondAndMilliSecond();
OADateTime dtx = new OADateTime(dtFrom);
dtx.clearTime();
dtx.set24Hour(dtFrom.get24Hour());
for (int hr : hrs) {
dtCheck.set24Hour(hr);
if (dtCheck.before(dtx)) continue;
if (dtFound != null && dtFound.before(dtCheck)) continue;
dtFound = findClosestMinute(dtFound, dtTo, dtCheck);
}
}
return dtFound;
}
private OADateTime findClosestMinute(OADateTime dtFound, OADateTime dtTo, OADateTime dtCheck) {
if (mins == null || mins.length == 0) {
if (dtFound == null || dtCheck.before(dtFound)) {
dtFound = new OADateTime(dtCheck);
if (dtFound.equals(dtFrom)) dtFound = dtFound.addMinutes(1);
}
return dtFound;
}
else {
for (int m : mins) {
dtCheck.setMinute(m);
if (dtCheck.compareTo(dtFrom) <= 0) continue;
if (dtFound != null && dtFound.before(dtCheck)) continue;
if (dtCheck.before(dtFrom)) continue;
if (dtFound == null || dtCheck.before(dtFound)) {
dtFound = new OADateTime(dtCheck);
}
}
}
return dtFound;
}
/**
* parses values from String
* @param line
* @return values to include or [0]=all
*/
private int[] getInts(String line) {
return getInts(line, false);
}
private int[] getInts(String line, boolean bAllowLast) {
if (OAString.isEmpty(line)) return new int[0];
if (line.indexOf('*') >= 0) return new int[0]; // all
line = line.replace(',', ' ');
line = line.replace(':', ' ');
int[] ints = new int[0];
for (String s : line.split("\\s+")) {
String[] ss = s.split("\\-");
if (ss == null || ss.length == 0) continue;
s = ss[0];
if (!OAString.isInteger(s)) {
if (bAllowLast && s.equalsIgnoreCase("last")) {
bIncludeLastDayOfMonth = true;
}
else bValid = false;
continue;
}
int x = OAConv.toInt(s);
if (ss.length == 2) {
if (!OAString.isInteger(ss[1])) {
bValid = false;
if (!OAArray.contains(ints, x)) {
ints = OAArray.add(ints, x);
}
continue;
}
int x2 = OAConv.toInt(ss[1]);
for (int i=x; i<=x2; i++) {
if (!OAArray.contains(ints, i)) {
ints = OAArray.add(ints, i);
}
}
}
else {
ints = OAArray.add(ints, x);
}
}
Arrays.sort(ints);
return ints;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public boolean getIsValid() {
return bValid;
}
public void setEnabled(boolean b) {
this.bEnabled = b;
}
public boolean getEnabled() {
return bEnabled;
}
public OADateTime getCreated() {
return dtCreated;
}
}