package er.chronic.repeaters; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; import er.chronic.tags.Pointer; import er.chronic.tags.Pointer.PointerType; import er.chronic.utils.Span; import er.chronic.utils.Time; import er.chronic.utils.Token; public class RepeaterMonthName extends Repeater<RepeaterMonthName.MonthName> { private static final Pattern JAN_PATTERN = Pattern.compile("^jan\\.?(uary)?$"); private static final Pattern FEB_PATTERN = Pattern.compile("^feb\\.?(ruary)?$"); private static final Pattern MAR_PATTERN = Pattern.compile("^mar\\.?(ch)?$"); private static final Pattern APR_PATTERN = Pattern.compile("^apr\\.?(il)?$"); private static final Pattern MAY_PATTERN = Pattern.compile("^may$"); private static final Pattern JUN_PATTERN = Pattern.compile("^jun\\.?e?$"); private static final Pattern JUL_PATTERN = Pattern.compile("^jul\\.?y?$"); private static final Pattern AUG_PATTERN = Pattern.compile("^aug\\.?(ust)?$"); private static final Pattern SEP_PATTERN = Pattern.compile("^sep\\.?(t\\.?|tember)?$"); private static final Pattern OCT_PATTERN = Pattern.compile("^oct\\.?(ober)?$"); private static final Pattern NOV_PATTERN = Pattern.compile("^nov\\.?(ember)?$"); private static final Pattern DEC_PATTERN = Pattern.compile("^dec\\.?(ember)?$"); private static final int MONTH_SECONDS = 2592000; // 30 * 24 * 60 * 60 public static enum MonthName { _ZERO_MONTH, JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER } private Calendar _currentMonthBegin; public RepeaterMonthName(MonthName type) { super(type); } public int getIndex() { return getType().ordinal(); } @Override protected Span _nextSpan(PointerType pointer) { if (_currentMonthBegin == null) { int targetMonth = getType().ordinal(); int nowMonth = getNow().get(Calendar.MONTH) + 1; if (pointer == PointerType.FUTURE) { if (nowMonth < targetMonth) { _currentMonthBegin = Time.y(getNow(), targetMonth); } else if (nowMonth > targetMonth) { _currentMonthBegin = Time.cloneAndAdd(Time.y(getNow(), targetMonth), Calendar.YEAR, 1); } } else if (pointer == PointerType.NONE) { if (nowMonth <= targetMonth) { _currentMonthBegin = Time.y(getNow(), targetMonth); } else if (nowMonth > targetMonth) { _currentMonthBegin = Time.cloneAndAdd(Time.y(getNow(), targetMonth), Calendar.YEAR, 1); } } else if (pointer == PointerType.PAST) { if (nowMonth > targetMonth) { _currentMonthBegin = Time.y(getNow(), targetMonth); } else if (nowMonth < targetMonth) { _currentMonthBegin = Time.cloneAndAdd(Time.y(getNow(), targetMonth), Calendar.YEAR, -1); } } else { throw new IllegalArgumentException("Unable to handle pointer " + pointer + "."); } if (_currentMonthBegin == null) { throw new IllegalStateException("Current month should be set by now."); } } else { if (pointer == PointerType.FUTURE) { _currentMonthBegin = Time.cloneAndAdd(_currentMonthBegin, Calendar.YEAR, 1); } else if (pointer == PointerType.PAST) { _currentMonthBegin = Time.cloneAndAdd(_currentMonthBegin, Calendar.YEAR, -1); } else { throw new IllegalArgumentException("Unable to handle pointer " + pointer + "."); } } return new Span(_currentMonthBegin, Calendar.MONTH, 1); } @Override protected Span _thisSpan(PointerType pointer) { Span span; if (pointer == Pointer.PointerType.PAST) { span = nextSpan(pointer); } else if (pointer == Pointer.PointerType.FUTURE || pointer == Pointer.PointerType.NONE) { span = nextSpan(Pointer.PointerType.NONE); } else { throw new IllegalArgumentException("Unable to handle pointer " + pointer + "."); } return span; } @Override public Span getOffset(Span span, float amount, PointerType pointer) { throw new IllegalStateException("Not implemented."); } @Override public int getWidth() { // WARN: Does not use Calendar return RepeaterMonthName.MONTH_SECONDS; } @Override public String toString() { return super.toString() + "-monthname-" + getType(); } public static RepeaterMonthName scan(Token token) { Map<Pattern, RepeaterMonthName.MonthName> scanner = new HashMap<>(); scanner.put(RepeaterMonthName.JAN_PATTERN, RepeaterMonthName.MonthName.JANUARY); scanner.put(RepeaterMonthName.FEB_PATTERN, RepeaterMonthName.MonthName.FEBRUARY); scanner.put(RepeaterMonthName.MAR_PATTERN, RepeaterMonthName.MonthName.MARCH); scanner.put(RepeaterMonthName.APR_PATTERN, RepeaterMonthName.MonthName.APRIL); scanner.put(RepeaterMonthName.MAY_PATTERN, RepeaterMonthName.MonthName.MAY); scanner.put(RepeaterMonthName.JUN_PATTERN, RepeaterMonthName.MonthName.JUNE); scanner.put(RepeaterMonthName.JUL_PATTERN, RepeaterMonthName.MonthName.JULY); scanner.put(RepeaterMonthName.AUG_PATTERN, RepeaterMonthName.MonthName.AUGUST); scanner.put(RepeaterMonthName.SEP_PATTERN, RepeaterMonthName.MonthName.SEPTEMBER); scanner.put(RepeaterMonthName.OCT_PATTERN, RepeaterMonthName.MonthName.OCTOBER); scanner.put(RepeaterMonthName.NOV_PATTERN, RepeaterMonthName.MonthName.NOVEMBER); scanner.put(RepeaterMonthName.DEC_PATTERN, RepeaterMonthName.MonthName.DECEMBER); for (Pattern scannerItem : scanner.keySet()) { if (scannerItem.matcher(token.getWord()).matches()) { return new RepeaterMonthName(scanner.get(scannerItem)); } } return null; } }