-
Notifications
You must be signed in to change notification settings - Fork 265
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
4 changed files
with
325 additions
and
9 deletions.
There are no files selected for viewing
94 changes: 94 additions & 0 deletions
94
src/main/java/com/cronutils/descriptor/refactor/CronDescriptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package com.cronutils.descriptor.refactor; | ||
|
||
import com.cronutils.model.Cron; | ||
import com.cronutils.model.field.CronField; | ||
import com.cronutils.model.field.CronFieldName; | ||
import com.cronutils.model.field.constraint.FieldConstraintsBuilder; | ||
import com.cronutils.model.field.expression.Always; | ||
import com.cronutils.model.field.expression.On; | ||
import com.cronutils.model.field.value.IntegerFieldValue; | ||
import com.google.common.collect.Range; | ||
import org.apache.commons.lang3.Validate; | ||
|
||
import java.util.Locale; | ||
import java.util.Map; | ||
import java.util.ResourceBundle; | ||
|
||
class CronDescriptor { | ||
public static final Locale DEFAULT_LOCALE = Locale.UK; | ||
private static final String BUNDLE = "cron-descI18N"; | ||
private ResourceBundle bundle; | ||
|
||
/** | ||
* Constructor creating a descriptor for given Locale | ||
* @param locale - Locale in which descriptions are given | ||
*/ | ||
private CronDescriptor(Locale locale) { | ||
bundle = ResourceBundle.getBundle(BUNDLE, locale); | ||
} | ||
|
||
/** | ||
* Default constructor. Considers Locale.UK as default locale | ||
*/ | ||
private CronDescriptor() { | ||
bundle = ResourceBundle.getBundle(BUNDLE, DEFAULT_LOCALE); | ||
} | ||
|
||
/** | ||
* Provide a description of given CronFieldParseResult list | ||
* @param cron - Cron instance, never null | ||
* if null, will throw NullPointerException | ||
* @return description - String | ||
*/ | ||
public String describe(Cron cron) { | ||
Validate.notNull(cron, "Cron must not be null"); | ||
Map<CronFieldName, CronField> expressions = cron.retrieveFieldsAsMap(); | ||
FieldDescriptor descriptor = new FieldDescriptor(bundle); | ||
StringBuilder builder = new StringBuilder(); | ||
|
||
CronField year; | ||
Range<Integer> yearRange; | ||
if(expressions.containsKey(CronFieldName.YEAR)){ | ||
year = expressions.get(CronFieldName.YEAR); | ||
yearRange = cron.getCronDefinition().getFieldDefinition(CronFieldName.YEAR).getConstraints().getValidRange(); | ||
} else { | ||
year = new CronField(CronFieldName.YEAR, new Always(FieldConstraintsBuilder.instance().createConstraintsInstance())); | ||
yearRange = Range.all(); | ||
} | ||
CronField month = expressions.get(CronFieldName.MONTH); | ||
Range<Integer> monthRange = cron.getCronDefinition().getFieldDefinition(CronFieldName.MONTH).getConstraints().getValidRange(); | ||
CronField dom = expressions.get(CronFieldName.DAY_OF_MONTH); | ||
Range<Integer> domRange = cron.getCronDefinition().getFieldDefinition(CronFieldName.DAY_OF_MONTH).getConstraints().getValidRange(); | ||
CronField dow = expressions.get(CronFieldName.DAY_OF_WEEK); | ||
Range<Integer> dowRange = cron.getCronDefinition().getFieldDefinition(CronFieldName.DAY_OF_WEEK).getConstraints().getValidRange(); | ||
CronField hour = expressions.get(CronFieldName.HOUR); | ||
Range<Integer> hourRange = cron.getCronDefinition().getFieldDefinition(CronFieldName.HOUR).getConstraints().getValidRange(); | ||
CronField minute = expressions.get(CronFieldName.MINUTE); | ||
Range<Integer> minuteRange = cron.getCronDefinition().getFieldDefinition(CronFieldName.MINUTE).getConstraints().getValidRange(); | ||
CronField second; | ||
Range<Integer> secondRange; | ||
if(expressions.containsKey(CronFieldName.SECOND)){ | ||
second = expressions.get(CronFieldName.SECOND); | ||
secondRange = cron.getCronDefinition().getFieldDefinition(CronFieldName.SECOND).getConstraints().getValidRange(); | ||
} else { | ||
second = new CronField( | ||
CronFieldName.SECOND, | ||
new On( | ||
FieldConstraintsBuilder.instance() | ||
.forField(CronFieldName.SECOND).createConstraintsInstance(), | ||
new IntegerFieldValue(0)) | ||
); | ||
secondRange = Range.all(); | ||
} | ||
|
||
return new StringBuilder() | ||
.append(descriptor.describe(null, second, secondRange)).append(" ") | ||
.append(descriptor.describe(second, minute, minuteRange)).append(" ") | ||
.append(descriptor.describe(minute, hour, hourRange)).append(" ") | ||
.append(descriptor.describe(hour, dow, dowRange)).append(" ") | ||
.append(descriptor.describe(dow, dom, domRange)).append(" ") | ||
.append(descriptor.describe(dom, month, monthRange)).append(" ") | ||
.append(descriptor.describe(month, year, yearRange)) | ||
.toString().replaceAll("\\s+", " ").trim(); | ||
} | ||
} |
184 changes: 184 additions & 0 deletions
184
src/main/java/com/cronutils/descriptor/refactor/FieldDescriptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
package com.cronutils.descriptor.refactor; | ||
|
||
import com.cronutils.model.field.CronField; | ||
import com.cronutils.model.field.expression.*; | ||
import com.cronutils.model.field.value.IntegerFieldValue; | ||
import com.cronutils.model.field.value.SpecialChar; | ||
import com.cronutils.model.field.value.SpecialCharFieldValue; | ||
import com.google.common.collect.Lists; | ||
import com.google.common.collect.Range; | ||
import com.google.common.collect.RangeSet; | ||
import com.google.common.collect.TreeRangeSet; | ||
import org.apache.commons.lang3.Validate; | ||
|
||
import java.text.MessageFormat; | ||
import java.util.List; | ||
import java.util.Locale; | ||
import java.util.ResourceBundle; | ||
import java.util.Set; | ||
|
||
class FieldDescriptor { | ||
protected ResourceBundle bundle; | ||
private MessageFormat formatter; | ||
|
||
public FieldDescriptor(ResourceBundle bundle) { | ||
this.bundle = bundle; | ||
formatter = new MessageFormat("", Locale.US);//TODO extract | ||
} | ||
|
||
protected String describe(CronField previous, CronField current, Range<Integer> range) { | ||
Validate.notNull(current, "CronField must not be null!"); | ||
FieldExpression pexpression = null; | ||
if (previous != null) { | ||
pexpression = previous.getExpression(); | ||
} | ||
FieldExpression expression = current.getExpression(); | ||
switch (current.getField()) { | ||
case YEAR: | ||
return describeYear(pexpression, expression, range); | ||
case MONTH: | ||
return describeMonth(pexpression, expression, range); | ||
case DAY_OF_MONTH: | ||
return describeDayOfMonth(pexpression, expression, range); | ||
case DAY_OF_WEEK: | ||
return describeDayOfWeek(pexpression, expression, range); | ||
case HOUR: | ||
return describeHour(pexpression, expression, range); | ||
case MINUTE: | ||
return describeMinute(pexpression, expression, range); | ||
case SECOND: | ||
return describeSecond(pexpression, expression, range); | ||
} | ||
return ""; | ||
} | ||
|
||
protected String describeYear(FieldExpression previous, FieldExpression current, Range<Integer> range) { | ||
return describe(previous, current, range, "every_year", "between_x_and_y_year", "every_x_years", "on_x_year"); | ||
} | ||
|
||
protected String describeMonth(FieldExpression previous, FieldExpression current, Range<Integer> range) { | ||
return describe(previous, current, range, "every_month", "between_x_and_y_month", "every_x_months", "on_x_month");//TODO add nominal transform | ||
} | ||
|
||
protected String describeDayOfMonth(FieldExpression previous, FieldExpression current, Range<Integer> range) { | ||
return describe(previous, current, range, "every_dom", "between_x_and_y_dom", "every_x_dom", "on_x_dom"); | ||
} | ||
|
||
protected String describeDayOfWeek(FieldExpression previous, FieldExpression current, Range<Integer> range) { | ||
return describe(previous, current, range, "every_dow", "between_x_and_y_dow", "every_x_dow", "on_x_dow"); | ||
} | ||
|
||
protected String describeHour(FieldExpression previous, FieldExpression current, Range<Integer> range) { | ||
return describe(previous, current, range, "every_hour", "between_x_and_y_hour", "every_x_hour", "on_x_hour"); | ||
} | ||
|
||
protected String describeMinute(FieldExpression previous, FieldExpression current, Range<Integer> range) { | ||
return describe(previous, current, range, "every_minute", "between_x_and_y_minute", "every_x_minute", "on_x_minute"); | ||
} | ||
|
||
protected String describeSecond(FieldExpression previous, FieldExpression current, Range<Integer> range) { | ||
return describe(previous, current, range, "every_second", "between_x_and_y_second", "every_x_second", "on_x_second"); | ||
} | ||
|
||
protected String describe(FieldExpression previous, FieldExpression current, Range<Integer> range, | ||
String always, String between, String everyX, String onX) { | ||
if (current instanceof Always) { | ||
return describeAlways(previous, current, always); | ||
} | ||
if (current instanceof Between) { | ||
return describeBetween(previous, (Between)current, between); | ||
} | ||
if (current instanceof Every) { | ||
if(((Every)current).getTime().getValue()==1) { | ||
return describeAlways(previous, current, always); | ||
}else { | ||
return describeEveryX(previous, (Every)current, everyX); | ||
} | ||
} | ||
if (current instanceof On) { | ||
return describeOnX(previous, (On)current, onX); | ||
} | ||
if (current instanceof And) { | ||
And and = (And)current; | ||
StringBuilder builder = new StringBuilder(); | ||
RangeSet<Integer> ranges = TreeRangeSet.create(); | ||
List<SpecialChar> onSpecialCharValues = Lists.newArrayList(); | ||
for(FieldExpression expression : and.getExpressions()){ | ||
if(expression instanceof On){ | ||
On on = (On)expression; | ||
if(SpecialChar.NONE.equals(on.getSpecialChar().getValue())){ | ||
ranges.add(Range.closed(on.getTime().getValue(), on.getTime().getValue())); | ||
}else{ | ||
onSpecialCharValues.add(on.getSpecialChar().getValue()); | ||
} | ||
} | ||
if(expression instanceof Between){ | ||
Between betweenExp = (Between)expression; | ||
if(betweenExp.getFrom() instanceof IntegerFieldValue && betweenExp.getTo() instanceof IntegerFieldValue){ | ||
int from = ((IntegerFieldValue)betweenExp.getFrom()).getValue(); | ||
int to = ((IntegerFieldValue)betweenExp.getTo()).getValue(); | ||
int every = betweenExp.getEvery().getTime().getValue(); | ||
if(every==1){ | ||
ranges.add(Range.closed(from, to)); | ||
}else{ | ||
for(int j=from; j<=to; j+=every){ | ||
ranges.add(Range.closed(j, j)); | ||
} | ||
} | ||
} else { | ||
SpecialChar specialChar; | ||
int from; | ||
if(betweenExp.getFrom() instanceof SpecialCharFieldValue){ | ||
specialChar = ((SpecialCharFieldValue)betweenExp.getFrom()).getValue(); | ||
from = ((IntegerFieldValue)betweenExp.getTo()).getValue(); | ||
} else { | ||
from = ((IntegerFieldValue)betweenExp.getFrom()).getValue(); | ||
specialChar = ((SpecialCharFieldValue)betweenExp.getTo()).getValue(); | ||
} | ||
//TODO manage case where one of values is special char | ||
} | ||
} | ||
if(expression instanceof Every){ | ||
Every every = (Every)expression; | ||
if(every.getTime().getValue()==1){ | ||
return describeAlways(previous, current, always); | ||
}else{ | ||
//TODO we need the range, to calculate times in range | ||
ranges.add(Range.closed(every.getTime().getValue(), every.getTime().getValue())); | ||
} | ||
} | ||
Set<Range<Integer>> sortedDisconnectedRanges = ranges.asRanges(); | ||
if(sortedDisconnectedRanges.size()==1 &&//TODO update Range.closed(1, 1) with correct value | ||
range.equals(sortedDisconnectedRanges.iterator().next())){ | ||
return always; | ||
} | ||
for(Range consolidatedRange : sortedDisconnectedRanges){ | ||
//TODO describe ranges | ||
} | ||
} | ||
} | ||
return ""; | ||
} | ||
|
||
protected String describeAlways(FieldExpression previous, FieldExpression current, String always){ | ||
if(previous instanceof Always){ | ||
return ""; | ||
} | ||
return bundle.getString(always); | ||
} | ||
|
||
protected String describeBetween(FieldExpression previous, Between current, String between){ | ||
formatter.applyPattern(bundle.getString(between)); | ||
return formatter.format(new Object[]{current.getFrom().getValue(), current.getTo().getValue()}); | ||
} | ||
|
||
protected String describeEveryX(FieldExpression previous, Every current, String everyX){ | ||
formatter.applyPattern(bundle.getString(everyX)); | ||
return formatter.format(new Object[]{current.getTime()}); | ||
} | ||
|
||
protected String describeOnX(FieldExpression previous, On current, String onX){ | ||
formatter.applyPattern(bundle.getString(onX)); | ||
return formatter.format(new Object[]{current.getTime()}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
every_year=every year | ||
between_x_and_y_year=between {0} and {1} | ||
every_x_year=every {0} years | ||
on_x_year=on {0} | ||
|
||
every_month=every month | ||
between_x_and_y_month=between {0} and {1} month | ||
every_x_month=every {0} months | ||
on_x_month=on {0} | ||
|
||
every_dom=every day of month | ||
between_x_and_y_dom=between days {0} and {1} | ||
every_x_dom=every {0} days of month | ||
on_x_dom=on day {0} | ||
|
||
every_dow=every day of week | ||
between_x_and_y_dow=between {0} and {1} | ||
every_x_dow=every {0} days of week | ||
on_x_dow=on {0} | ||
|
||
every_hour=every hour | ||
between_x_and_y_hour=between {0} and {1} hours | ||
every_x_hour=every {0} hours | ||
on_x_hour=at {0} hs | ||
|
||
every_minute=every minute | ||
between_x_and_y_minute=between {0} and {1} minutes | ||
every_x_minute=between {0} minute | ||
on_x_minute=on minute {0} | ||
|
||
every_second=every second | ||
between_x_and_y_second=between {0} and {1} seconds | ||
every_x_second=every {0} seconds | ||
on_x_second=on {0} second |