package jef.database.query; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map.Entry; import java.util.Set; import java.util.TreeSet; import jef.database.annotation.PartitionFunction; import jef.tools.DateUtils; import jef.tools.support.LangUtils; import com.google.common.base.Objects; /* * 对应SQL条件 * 1. BETWEEN * 2. x > a and x < b * 3. x >=a and x<=b * ... * 注意,由于大于和小于也可能出现无限条件,比如 a > 1 * 这种情况,要特殊考虑 * 描述的区间始终一个 > min and <max的区间, 但Dimension本身不保证max一定>min * */ @SuppressWarnings("rawtypes") public class RangeDimension<T extends Comparable<T>> implements Dimension { /** * 区间的左边界 */ private T min; /** * 区间的右边界 */ private T max; // 是否左闭区间 private boolean isLeftCloseSpan = true; // 是否左开区间 private boolean isRightCloseSpan = true; /** * 默认构造,左右闭区间 * * @param min2 * @param max2 */ public RangeDimension(T min2, T max2) { this.min = min2; this.max = max2; } /** * 创建一个左闭右开区间 * * @param min * @param max */ @SuppressWarnings("unchecked") public static RangeDimension createLC(Object min, Object max) { return new RangeDimension((Comparable<?>)min, (Comparable<?>)max, true, false); } /** * 创建一个左开右闭区间 * @param min * @param max * @return */ @SuppressWarnings("unchecked") public static RangeDimension createCL(Object min, Object max) { return new RangeDimension((Comparable<?>)min, (Comparable<?>)max, false, true); } /** * 创建一个开区间 * @param min * @param max * @return */ @SuppressWarnings("unchecked") public static RangeDimension createCC(Object min, Object max) { return new RangeDimension((Comparable<?>)min, (Comparable<?>)max, false, false); } /** * 创建一个闭区间 * @param min * @param max * @return */ @SuppressWarnings("unchecked") public static RangeDimension create(Object min, Object max) { return new RangeDimension((Comparable<?>)min, (Comparable<?>)max); } /** * 构造,可以指定区间开启 * * @param min * @param max * @param leftClose * @param rightClose */ public RangeDimension(T min, T max, boolean leftClose, boolean rightClose) { this.min = min; this.max = max; this.isLeftCloseSpan = leftClose; this.isRightCloseSpan = rightClose; } public RangeDimension(T value) { this(value, value); } @SuppressWarnings("unchecked") public Dimension mergeAnd(Dimension d) { if (d instanceof ComplexDimension) { return d.mergeAnd(this); } // if (d instanceof Points) { // List<Object> list = ArrayUtils.asList(((Points) d).points); // for (Iterator<Object> iter = list.iterator(); iter.hasNext();) { // T obj = (T) iter.next(); // // 同时满足左右边界条件? // if (isInsideLeftBorder(obj) && isInsideRightBorder(obj)) { // } else { // iter.remove(); // } // } // return new Points(list.toArray()); // } else if (d instanceof RangeDimension) { // 算法,两个范围的合并 RangeDimension<T> other = (RangeDimension<T>) d; Entry<T, Boolean> eLeft = max(this.min, this.isLeftCloseSpan, other.min, other.isLeftCloseSpan, LangUtils.NULL_IS_MINIMUM, false);// 左取大; Entry<T, Boolean> eRight = min(this.max, this.isRightCloseSpan, other.max, other.isRightCloseSpan, LangUtils.NULL_IS_MAXIMUM, false);// 右取小; return new RangeDimension<T>(eLeft.getKey(), eRight.getKey(), eLeft.getValue(), eRight.getValue()); } else { throw new UnsupportedOperationException("Unknown dimenssion type:" + d.getClass().getName()); } } // 取两个点中较大的那个 private Entry<T, Boolean> max(T v1, Boolean c1, T v2, Boolean c2, int nullSupport, boolean closeFirst) { if (Objects.equal(v1, v2)) { if (closeFirst) {// 当值相等时,取闭区间 return new jef.common.Entry<T, Boolean>(v1, c1 || c2); } else { return new jef.common.Entry<T, Boolean>(v1, c1 && c2); } } else { Comparable max = LangUtils.max(v1, v2, nullSupport); if (max == v1) { return new jef.common.Entry<T, Boolean>(v1, c1); } else { return new jef.common.Entry<T, Boolean>(v2, c2); } } } // 取两个点中较小的那个 private Entry<T, Boolean> min(T v1, boolean c1, T v2, boolean c2, int nullSupport, boolean closeFirst) { if (Objects.equal(v1, v2)) { if (closeFirst) {// 当值相等时,取闭区间 return new jef.common.Entry<T, Boolean>(v1, c1 || c2); } else { // 当值相等时,取开区间 return new jef.common.Entry<T, Boolean>(v1, c1 && c2); } } else { Comparable max = LangUtils.min(v1, v2, nullSupport); if (max == v1) { return new jef.common.Entry<T, Boolean>(v1, c1); } else { return new jef.common.Entry<T, Boolean>(v2, c2); } } } /** * 判断给定的值是否 大于或大于等于(取决于左侧是否开区间) 左边界值。 * * @param obj * @return */ protected boolean isInsideLeftBorder(T obj, boolean include) { if (obj == null) return false; if (min == null) return true; int i = obj.compareTo(min); if (i == 0)// 相等的情况 return isLeftCloseSpan && include; if (i > 0) // 对方大于次方的最小值 return true; return false; } /** * 判断给定的值是否 小于或小于等于(取决于右侧是否开区间) 右边界值。 * * @param obj * @return */ protected boolean isInsideRightBorder(T obj, boolean include) { if (obj == null) return false; if (max == null) return true; int i = obj.compareTo(max); if (i == 0) return isRightCloseSpan && include; if (i < 0) return true; return false; } /** * 是否为全区间。 * 全区间就是从负无穷到正无穷的区间,是作为无效区间处理的。但是无效区间有两种,一种是空区间,一种是全区间 * @return */ public boolean isAll() { return min == null && max == null; } public boolean isValid() { if (min == null && max == null) return true; if (min == null || max == null) return true; int n = min.compareTo(max); if (n > 0) return false; if (n == 0) { return isLeftCloseSpan && isRightCloseSpan; } return true; } @SuppressWarnings("unchecked") public Dimension mergeOr(Dimension d) { if (d instanceof ComplexDimension) { return d.mergeOr(this); } if (d instanceof RangeDimension) { // 算法,两个范围的合并 // 首先检查两个区间必须有重叠 RangeDimension<T> other = (RangeDimension<T>) d; if (isInsideLeftBorder(other.max, other.isRightCloseSpan) && isInsideRightBorder(other.max, other.isRightCloseSpan) || isInsideLeftBorder(other.min, other.isLeftCloseSpan) && isInsideRightBorder(other.min, other.isLeftCloseSpan)) {//最大的点落在此处 // 在重叠的基础上,取较小的左边界和较大的右边界 Entry<T, Boolean> eLeft = min(this.min, this.isLeftCloseSpan, other.min, other.isLeftCloseSpan, LangUtils.NULL_IS_MINIMUM, true);// 左取小; Entry<T, Boolean> eRight = max(this.max, this.isRightCloseSpan, other.max, other.isRightCloseSpan, LangUtils.NULL_IS_MAXIMUM, true);// 右取大; return new RangeDimension<T>(eLeft.getKey(), eRight.getKey(), eLeft.getValue(), eRight.getValue()); } else { ComplexDimension result=new ComplexDimension(this); return result.mergeOr(d); } } else { throw new UnsupportedOperationException("Unknown dimenssion type:" + d.getClass().getName()); } } @Override public String toString() { T o = isPoint(); if (o != null) return format(o); if (min == null && max == null){ return "All!"; } if (isValid()) { StringBuilder sb = new StringBuilder(); sb.append(isLeftCloseSpan ? "[" : "("); sb.append(min == null ? "-∞" : format(min)).append(',').append(max == null ? "+∞" : format(max)); sb.append(isRightCloseSpan ? "]" : ")"); return sb.toString(); } else { return "Invalid!"; } } private String format(Object v) { if (v instanceof Date) { return DateUtils.formatDate((Date) v); } else { return String.valueOf(v); } } /** * 如果当前区间是收敛了一个点,那么返回这个点 * * @return */ public T isPoint() { if (max == null || min == null) return null; if (Objects.equal(max, min)) { if (this.isLeftCloseSpan && this.isRightCloseSpan) { return min; } } return null; } public T getMin() { return min; } public T getMax() { return max; } // 逻辑非运算 @SuppressWarnings("unchecked") public Dimension mergeNot() { ComplexDimension result = new ComplexDimension(new RangeDimension(null, min, true, !isLeftCloseSpan)); result.mergeOr(new RangeDimension(max, null, !isRightCloseSpan, true)); return result; } public static final List<Object> EMPTY_REGEXP=Arrays.<Object>asList(new RegexpDimension("")); @SuppressWarnings("unchecked") public static final RangeDimension<?> EMPTY_RANGE=new RangeDimension(null); /** * 将范围值转化为枚举值 */ @SuppressWarnings("unchecked") public Collection<?> toEnumationValue(Collection<PartitionFunction> funcs) { Object sObj = min; Object eObj = max; if(funcs.size()==1){ Collection<?> result=funcs.iterator().next().iterator(sObj, eObj, isLeftCloseSpan, isRightCloseSpan); if(result.isEmpty())return EMPTY_REGEXP; return result; } Set<?> set=new TreeSet(); for(PartitionFunction func:funcs){ Collection add=func.iterator(sObj,eObj,isLeftCloseSpan,isRightCloseSpan); //当有多个维度组合时且任何一个维护无法得出结论时,实际上实际上是无法判断哪个维护是最密枚举,而将稀疏枚举向上传递可能造成误报和漏报.此时当做无法枚举处理。 if(add.isEmpty())return add; set.addAll(add); } return set; } public void setMax(T max) { this.max = max; } }