package com.taobao.tddl.rule.enumerator.handler;
import java.util.Calendar;
import java.util.Date;
import java.util.Set;
import com.taobao.tddl.common.utils.thread.ThreadLocalMap;
import com.taobao.tddl.rule.model.DateEnumerationParameter;
import com.taobao.tddl.rule.model.sqljep.Comparative;
/**
* 基于时间类型的枚举器
*
* @author jianghang 2013-10-29 下午5:23:01
* @since 5.0.0
*/
public class DatePartDiscontinousRangeEnumerator extends PartDiscontinousRangeEnumerator {
private static final long LIMIT_UNIT_OF_DATE = 1L;
private static final String DATE_ENUMERATOR = "DATE_ENUMERATOR";
private static final int DEFAULT_DATE_ATOMIC_VALUE = 1;
@Override
protected Comparative changeGreater2GreaterOrEq(Comparative from) {
if (from.getComparison() == Comparative.GreaterThan) {
Date gtDate = (Date) from.getValue();
long gtOrEqDate = gtDate.getTime() + LIMIT_UNIT_OF_DATE;
return new Comparative(Comparative.GreaterThanOrEqual, new Date(gtOrEqDate));
}
return from;
}
@Override
protected Comparative changeLess2LessOrEq(Comparative to) {
if (to.getComparison() == Comparative.LessThan) {
Date less = (Date) to.getValue();
long lessOrEqDate = less.getTime() - LIMIT_UNIT_OF_DATE;
return new Comparative(Comparative.LessThanOrEqual, new Date(lessOrEqDate));
}
return to;
}
@SuppressWarnings("rawtypes")
@Override
protected Comparable getOneStep(Comparable source, Comparable atomIncVal) {
DateEnumerationParameter dateEnumerationParameter = getDateEnumerationParameter(atomIncVal);
Calendar cal = getCalendar((Date) source);
cal.add(dateEnumerationParameter.calendarFieldType, dateEnumerationParameter.atomicIncreatementNumber);
return cal.getTime();
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
protected boolean inputCloseRangeGreaterThanMaxFieldOfDifination(Comparable from, Comparable to,
Integer cumulativeTimes,
Comparable<?> atomIncrValue) {
if (cumulativeTimes == null) {
return false;
}
Calendar cal = getCalendar((Date) from);
int rangeSet = cumulativeTimes;
if (atomIncrValue instanceof Integer) {
// 兼容老实现,对应#gmt,1,7#这种
cal.add(Calendar.DATE, rangeSet * (Integer) atomIncrValue);
} else if (atomIncrValue instanceof DateEnumerationParameter) {
// 对应#gmt,1_month,12这样的情况
DateEnumerationParameter dep = (DateEnumerationParameter) atomIncrValue;
cal.add(dep.calendarFieldType, rangeSet * dep.atomicIncreatementNumber);
} else if (atomIncrValue == null) {
// 兼容老实现,对应没有#gmt#.这种普通的情况,
cal.add(Calendar.DATE, rangeSet);
} else {
throwNotSupportIllegalArgumentException(atomIncrValue);
}
if (to.compareTo(cal.getTime()) >= 0) {
return true;
}
return false;
}
private void throwNotSupportIllegalArgumentException(Object arg) {
throw new IllegalArgumentException("不能识别的类型:" + arg + " .type is" + arg.getClass());
}
public void processAllPassableFields(Comparative begin, Set<Object> retValue, Integer cumulativeTimes,
Comparable<?> atomicIncreationValue) {
DateEnumerationParameter dateEnumerationParameter = getDateEnumerationParameter(atomicIncreationValue);
// 把> < 替换为>= <=
begin = changeGreater2GreaterOrEq(begin);
begin = changeLess2LessOrEq(begin);
Calendar cal = getCalendar((Date) begin.getValue());
int comparasion = begin.getComparison();
if (comparasion == Comparative.GreaterThanOrEqual) {
// 添加当前时间,因为当前时间内已经是大于等于了。
retValue.add(cal.getTime());
// 减少一次迭代,因为已经加了当前时间
for (int i = 0; i < cumulativeTimes - 1; i++) {
cal.add(dateEnumerationParameter.calendarFieldType, dateEnumerationParameter.atomicIncreatementNumber);
retValue.add(cal.getTime());
}
} else if (comparasion == Comparative.LessThanOrEqual) {
retValue.add(cal.getTime());
for (int i = 0; i < cumulativeTimes - 1; i++) {
cal.add(dateEnumerationParameter.calendarFieldType, -1
* dateEnumerationParameter.atomicIncreatementNumber);
retValue.add(cal.getTime());
}
}
}
/**
* 识别data自增参数
*/
protected DateEnumerationParameter getDateEnumerationParameter(Comparable<?> comparable) {
DateEnumerationParameter dateEnumerationParameter = null;
if (comparable == null) {
dateEnumerationParameter = new DateEnumerationParameter(DEFAULT_DATE_ATOMIC_VALUE);
} else if (comparable instanceof Integer) {
dateEnumerationParameter = new DateEnumerationParameter((Integer) comparable);
} else if (comparable instanceof DateEnumerationParameter) {
dateEnumerationParameter = (DateEnumerationParameter) comparable;
} else {
throwNotSupportIllegalArgumentException(comparable);
}
return dateEnumerationParameter;
}
private Calendar getCalendar(Date date2BeSet) {
// 优化重用一下Calendar
Calendar cal = (Calendar) ThreadLocalMap.get(DATE_ENUMERATOR);
if (cal == null) {
cal = Calendar.getInstance();
ThreadLocalMap.put(DATE_ENUMERATOR, cal);
}
cal.setTime(date2BeSet);
return cal;
}
}