/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.rule.ruleengine.enumerator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import com.alipay.zdal.common.exception.runtime.NotSupportException;
import com.alipay.zdal.common.sqljep.function.Comparative;
import com.alipay.zdal.common.sqljep.function.ComparativeAND;
import com.alipay.zdal.common.sqljep.function.ComparativeBaseList;
import com.alipay.zdal.common.sqljep.function.ComparativeOR;
public class EnumeratorImp implements Enumerator {
private static final String DEFAULT_ENUMERATOR = "DEFAULT_ENUMERATOR";
protected static final Map<String, CloseIntervalFieldsEnumeratorHandler> enumeratorMap = new HashMap<String, CloseIntervalFieldsEnumeratorHandler>();
{
enumeratorMap.put(Integer.class.getName(), new IntegerPartDiscontinousRangeEnumerator());
enumeratorMap.put(Long.class.getName(), new LongPartDiscontinousRangeEnumerator());
enumeratorMap.put(Date.class.getName(), new DatePartDiscontinousRangeEnumerator());
enumeratorMap.put(java.sql.Date.class.getName(), new DatePartDiscontinousRangeEnumerator());
enumeratorMap.put(java.sql.Timestamp.class.getName(),
new DatePartDiscontinousRangeEnumerator());
enumeratorMap.put(DEFAULT_ENUMERATOR, new DefaultEnumerator());
}
private boolean isDebug = false;
/**
* ���ݴ���IJ�������ʹ������ö����
*
* TODO Ӧ�ý�ö��������Χ��С����ʵö�����ĺ������þ�����a > ? and a < ?�����ı��ʽ��
* ��������ʱ���Dz���Ҫ����������+ö�ٵķ�ʽ����ġ�
* @param comp
* @param needMergeValueInCloseInterval
* @return
*/
@SuppressWarnings("unchecked")
public CloseIntervalFieldsEnumeratorHandler getCloseIntervalEnumeratorHandlerByComparative(
Comparative comp,
boolean needMergeValueInCloseInterval) {
if (!needMergeValueInCloseInterval) {
return enumeratorMap.get(DEFAULT_ENUMERATOR);
}
if (comp == null) {
throw new IllegalArgumentException("��֪����ǰֵ��ʲô���͵ģ����ҵ���Ӧ��ö����" + comp);
}
Comparable value = comp.getValue();
if (value instanceof ComparativeBaseList) {
ComparativeBaseList comparativeBaseList = (ComparativeBaseList) value;
for (Comparative comparative : comparativeBaseList.getList()) {
return getCloseIntervalEnumeratorHandlerByComparative(comparative,
needMergeValueInCloseInterval);
}
throw new IllegalStateException("should not be here");
} else if (value instanceof Comparative) {
return getCloseIntervalEnumeratorHandlerByComparative(comp,
needMergeValueInCloseInterval);
} else {
//������һ��comparative����
CloseIntervalFieldsEnumeratorHandler enumeratorHandler = enumeratorMap.get(value
.getClass().getName());
if (enumeratorHandler != null) {
return enumeratorHandler;
} else {
return enumeratorMap.get(DEFAULT_ENUMERATOR);
}
}
}
@SuppressWarnings("unchecked")
public Set<Object> getEnumeratedValue(Comparable condition, Integer cumulativeTimes,
Comparable<?> atomIncrValue,
boolean needMergeValueInCloseInterval) {
Set<Object> retValue = null;
if (!isDebug) {
retValue = new HashSet<Object>();
} else {
retValue = new TreeSet<Object>();
}
try {
process(condition, retValue, cumulativeTimes, atomIncrValue,
needMergeValueInCloseInterval);
} catch (EnumerationInterruptException e) {
processAllPassableFields(e.getComparative(), retValue, cumulativeTimes, atomIncrValue,
needMergeValueInCloseInterval);
}
return retValue;
}
protected void process(Comparable<?> condition, Set<Object> retValue, Integer cumulativeTimes,
Comparable<?> atomIncrValue, boolean needMergeValueInCloseInterval) {
if (condition == null) {
retValue.add(null);
} else if (condition instanceof ComparativeOR) {
processComparativeOR(condition, retValue, cumulativeTimes, atomIncrValue,
needMergeValueInCloseInterval);
} else if (condition instanceof ComparativeAND) {
processComparativeAnd(condition, retValue, cumulativeTimes, atomIncrValue,
needMergeValueInCloseInterval);
} else if (condition instanceof Comparative) {
processComparativeOne(condition, retValue, cumulativeTimes, atomIncrValue,
needMergeValueInCloseInterval);
} else {
retValue.add(condition);
}
}
private boolean containsEquvilentRelation(Comparative comp) {
int comparasion = comp.getComparison();
if (comparasion == Comparative.Equivalent || comparasion == Comparative.GreaterThanOrEqual
|| comparasion == Comparative.LessThanOrEqual) {
return true;
}
return false;
}
@SuppressWarnings("unchecked")
private void processComparativeAnd(Comparable<?> condition, Set<Object> retValue,
Integer cumulativeTimes, Comparable<?> atomIncrValue,
boolean needMergeValueInCloseInterval) {
List<Comparative> andList = ((ComparativeAND) condition).getList();
// ���������о�ûʲôʵ�ʵ����壬�������ٴ���
if (andList.size() == 2) {
Comparable<?> arg1 = andList.get(0);
Comparable<?> arg2 = andList.get(1);
Comparative compArg1 = valid2varableInAndIsNotComparativeBaseList(arg1);
Comparative compArg2 = valid2varableInAndIsNotComparativeBaseList(arg2);
//
// if(compArg1 == null){
// throw new IllegalArgumentException("and ��������һ��Ϊnull");
// }
// if(compArg2 == null){
// throw new IllegalArgumentException("and ��������һ��Ϊnull");
// }
int compResult = 0;
try {
compResult = compArg1.getValue().compareTo(compArg2.getValue());
} catch (NullPointerException e) {
throw new RuntimeException("and��������һ��ֵΪnull", e);
}
if (compResult == 0) {
// ֵ��ȣ����������=��ϵ����ô���и������㣬����һ�������㶼û��
if (containsEquvilentRelation(compArg1) && containsEquvilentRelation(compArg2)) {
retValue.add(compArg1.getValue());
}
// else{
// һ�������㶼û�е�������ӵ�
// }
} else if (compResult < 0) {
// arg1 < arg2
processTwoDifferentArgsInComparativeAnd(retValue, compArg1, compArg2,
cumulativeTimes, atomIncrValue, needMergeValueInCloseInterval);
} else {
// compResult>0
// arg1 > arg2
processTwoDifferentArgsInComparativeAnd(retValue, compArg2, compArg1,
cumulativeTimes, atomIncrValue, needMergeValueInCloseInterval);
}
} else {
throw new IllegalArgumentException("Ŀǰֻ֧��һ��and�ڵ����������ӽڵ�");
}
}
/**
* ������һ��and�����е�������ͬ��argument
*
* @param samplingField
* @param from
* @param to
*/
@SuppressWarnings("unchecked")
private void processTwoDifferentArgsInComparativeAnd(Set<Object> retValue, Comparative from,
Comparative to, Integer cumulativeTimes,
Comparable<?> atomIncrValue,
boolean needMergeValueInCloseInterval) {
if (isCloseInterval(from, to)) {
mergeFeildOfDefinitionInCloseInterval(from, to, retValue, cumulativeTimes,
atomIncrValue, needMergeValueInCloseInterval);
} else {
Comparable temp = compareAndGetIntersactionOneValue(from, to);
if (temp != null) {
retValue.add(temp);
} else {
//�������Ѿ��������x >= ? and x = ? ���� x <= ? and x = ?�н���Ҳ������������> �� <�Ѿ���ת��Ϊ >= �Լ�<=
//������Ҫ����������� x <= 3 and x>=5 ���࣬
if (from.getComparison() == Comparative.LessThanOrEqual
|| from.getComparison() == Comparative.LessThan) {
if (to.getComparison() == Comparative.LessThanOrEqual
|| to.getComparison() == Comparative.LessThan) {
processAllPassableFields(from, retValue, cumulativeTimes, atomIncrValue,
needMergeValueInCloseInterval);
} else {
//toΪGreaterThanOrEqual,����ΪEquals ��ô�Ǹ������䡣do nothing.
}
} else if (to.getComparison() == Comparative.GreaterThanOrEqual
|| to.getComparison() == Comparative.GreaterThan) {
if (from.getComparison() == Comparative.GreaterThanOrEqual
|| from.getComparison() == Comparative.GreaterThan) {
processAllPassableFields(to, retValue, cumulativeTimes, atomIncrValue,
needMergeValueInCloseInterval);
} else {
//fromΪLessThanOrEqual������ΪEquals,Ϊ������
}
} else {
throw new IllegalArgumentException("should not be here");
}
}
// else{
// ����0<x and x=3�������
// }
}
}
/**
* ����һ��and������ x > 1 and x = 3 �����������������Ϊǰ���Ѿ���from �� to ��ȵ�������˴���
* �������ֻ��Ҫ�����ȵ�����е��������⡣
* ͬʱҲ������x = 1 and x = 2����������Լ�x = 1 and x>2 ��x < 1 and x =2�������
*
* @param from
* @param to
* @return
*/
@SuppressWarnings("unchecked")
protected static Comparable compareAndGetIntersactionOneValue(Comparative from, Comparative to) {
// x = from and x <= to
if (from.getComparison() == Comparative.Equivalent) {
if (to.getComparison() == Comparative.LessThan
|| to.getComparison() == Comparative.LessThanOrEqual) {
return from.getValue();
}
}
// x <= from and x = to
if (to.getComparison() == Comparative.Equivalent) {
if (from.getComparison() == Comparative.GreaterThan
|| from.getComparison() == Comparative.GreaterThanOrEqual) {
return to.getValue();
}
}
return null;
}
protected static boolean isCloseInterval(Comparative from, Comparative to) {
int fromComparasion = from.getComparison();
int toComparasion = to.getComparison();
// �������ͨ����ֵ�ȴ�С�����������滹��not in,like����ı�ǣ����DZ��ص�д���
if ((fromComparasion == Comparative.GreaterThan || fromComparasion == Comparative.GreaterThanOrEqual)
&& (toComparasion == Comparative.LessThan || toComparasion == Comparative.LessThanOrEqual)) {
return true;
} else {
return false;
}
}
private Comparative valid2varableInAndIsNotComparativeBaseList(Comparable<?> arg) {
if (arg instanceof ComparativeBaseList) {
throw new IllegalArgumentException("��һ��and������ֻ֧��������Χ��ֵ��ͬ�����ֱ���֧��3��");
}
if (arg instanceof Comparative) {
Comparative comp = ((Comparative) arg);
int comparison = comp.getComparison();
if (comparison == 0) {
// 0��ʱ����ζ�������COmparativeBaseList��Comparative�Ǹ�����İ�װ����
return valid2varableInAndIsNotComparativeBaseList(comp.getValue());
} else {
// ���������������ֵ������
return comp;
}
} else {
// ������ǻ�������Ӧ���õ��ڰ�װ
throw new IllegalArgumentException("input value is not a comparative: " + arg);
// return new Comparative(Comparative.Equivalent,arg);
}
}
private void processComparativeOne(Comparable<?> condition, Set<Object> retValue,
Integer cumulativeTimes, Comparable<?> atomIncrValue,
boolean needMergeValueInCloseInterval) {
Comparative comp = (Comparative) condition;
int comparison = comp.getComparison();
switch (comparison) {
case 0:
// Ϊ0 ��ʱ���ʾ����İ�װ����
process(comp.getValue(), retValue, cumulativeTimes, atomIncrValue,
needMergeValueInCloseInterval);
break;
case Comparative.Equivalent:
// ���ڹ�ϵ��ֱ�ӷ���collection
retValue.add(comp.getValue());
break;
case Comparative.GreaterThan:
case Comparative.GreaterThanOrEqual:
case Comparative.LessThan:
case Comparative.LessThanOrEqual:
//������Ҫȫȡ�����
throw new EnumerationInterruptException(comp);
default:
throw new NotSupportException("not support yet");
}
}
private void processComparativeOR(Comparable<?> condition, Set<Object> retValue,
Integer cumulativeTimes, Comparable<?> atomIncrValue,
boolean needMergeValueInCloseInterval) {
List<Comparative> orList = ((ComparativeOR) condition).getList();
for (Comparative comp : orList) {
process(comp, retValue, cumulativeTimes, atomIncrValue, needMergeValueInCloseInterval);
}
}
/**
* ��ٳ���from��to�е�����ֵ����������value
*
* @param from
* @param to
*/
protected void mergeFeildOfDefinitionInCloseInterval(Comparative from, Comparative to,
Set<Object> retValue,
Integer cumulativeTimes,
Comparable<?> atomIncrValue,
boolean needMergeValueInCloseInterval) {
if (!needMergeValueInCloseInterval) {
throw new IllegalArgumentException(
"������needMergeValueInCloseIntervalѡ���֧�ַֿ�ֱ�������ʹ��> < >= <=");
}
//�ع� �������ּܹ��£�id =? id in (?,?,?)���������·����������ж�� id > ? and id < ? or id> ? and id<? ��Ҫ��map�в��Ρ�������Ϊ��������Ƚ��٣���˿��Ժ���
CloseIntervalFieldsEnumeratorHandler closeIntervalFieldsEnumeratorHandler = getCloseIntervalEnumeratorHandlerByComparative(
from, needMergeValueInCloseInterval);
closeIntervalFieldsEnumeratorHandler.mergeFeildOfDefinitionInCloseInterval(from, to,
retValue, cumulativeTimes, atomIncrValue);
}
/**
* ������Ŀ���Ƿ���ȫ�����ܵ�ֵ����Ҫ�������Ķ�����Ĵ���һ���˵�����ڲ����������ֲ������ĺ������ߡ�
* ���ֵӦ���Ǵ�����һ��ֵ��ʼ������ԭ������ֵ�뱶����ٳ��ú�����y��һ���仯������x��Ӧ�ı仯���ڵ����е㼴�ɡ�
* @param retValue
* @param cumulativeTimes
* @param atomIncrValue
*/
protected void processAllPassableFields(Comparative source, Set<Object> retValue,
Integer cumulativeTimes, Comparable<?> atomIncrValue,
boolean needMergeValueInCloseInterval) {
if (!needMergeValueInCloseInterval) {
throw new IllegalArgumentException(
"������needMergeValueInCloseIntervalѡ���֧�ַֿ�ֱ�������ʹ��> < >= <=");
}
//�ع� �������ּܹ��£�id =? id in (?,?,?)���������·����������ж�� id > ? and id < ? or id> ? and id<? ��Ҫ��map�в��Ρ�������Ϊ��������Ƚ��٣���˿��Ժ���
CloseIntervalFieldsEnumeratorHandler closeIntervalFieldsEnumeratorHandler = getCloseIntervalEnumeratorHandlerByComparative(
source, needMergeValueInCloseInterval);
closeIntervalFieldsEnumeratorHandler.processAllPassableFields(source, retValue,
cumulativeTimes, atomIncrValue);
}
// public boolean isNeedMergeValueInCloseInterval() {
// return needMergeValueInCloseInterval;
// }
//
// public void setNeedMergeValueInCloseInterval(
// boolean needMergeValueInCloseInterval) {
// this.needMergeValueInCloseInterval = needMergeValueInCloseInterval;
// }
public boolean isDebug() {
return isDebug;
}
public void setDebug(boolean isDebug) {
this.isDebug = isDebug;
}
}