This commit is contained in:
RedKale
2016-04-09 17:59:20 +08:00
parent c4434f04c3
commit ef58827fad
4 changed files with 287 additions and 43 deletions

View File

@@ -5,9 +5,9 @@
*/
package org.redkale.source;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
/**
*
@@ -46,4 +46,11 @@ public @interface FilterColumn {
*/
FilterExpress express() default FilterExpress.EQUAL;
/**
* 当标记的字段类型是数组/Collection类型且express不是IN/NOTIN时则构建过滤条件时会遍历字段值的元素来循环构建表达式元素之间的关系是AND或OR由该值来确定
*
* @return 数组元素间的表达式是否AND关系
*/
boolean itemand() default true;
}

View File

@@ -5,15 +5,18 @@
*/
package org.redkale.source;
import java.io.*;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.*;
import org.redkale.util.*;
import static org.redkale.source.FilterExpress.EQUAL;
import org.redkale.util.Attribute;
/**
*
* <p> 详情见: http://www.redkale.org
* <p>
* 详情见: http://www.redkale.org
*
* @author zhangjx
*/
public class FilterJoinNode extends FilterNode {
@@ -27,41 +30,55 @@ public class FilterJoinNode extends FilterNode {
public FilterJoinNode() {
}
protected FilterJoinNode(Class joinClass, String[] joinColumns, String column, Serializable value) {
this(joinClass, joinColumns, column, null, value);
}
protected FilterJoinNode(Class joinClass, String[] joinColumns, String column, FilterExpress express, Serializable value) {
protected FilterJoinNode(Class joinClass, String[] joinColumns, String column, FilterExpress express, boolean itemand, Serializable value) {
Objects.requireNonNull(joinClass);
Objects.requireNonNull(joinColumns);
if (express == null && value != null) {
if (value instanceof Range) {
express = FilterExpress.BETWEEN;
} else if (value instanceof Collection) {
express = FilterExpress.IN;
} else if (value.getClass().isArray()) {
express = FilterExpress.IN;
}
}
this.joinClass = joinClass;
this.joinColumns = joinColumns;
this.column = column;
this.express = express;
this.express = express == null ? EQUAL : express;
this.itemand = itemand;
this.value = value;
}
protected FilterJoinNode(FilterJoinNode node) {
this(node.joinClass, node.joinColumns, node.column, node.express, node.value);
this(node.joinClass, node.joinColumns, node.column, node.express, node.itemand, node.value);
this.joinEntity = node.joinEntity;
this.or = node.or;
this.nodes = node.nodes;
}
public static FilterJoinNode create(Class joinClass, String joinColumn, String column, Serializable value) {
return new FilterJoinNode(joinClass, new String[]{joinColumn}, column, value);
return create(joinClass, new String[]{joinColumn}, column, value);
}
public static FilterJoinNode create(Class joinClass, String joinColumn, String column, FilterExpress express, Serializable value) {
return new FilterJoinNode(joinClass, new String[]{joinColumn}, column, express, value);
return create(joinClass, new String[]{joinColumn}, column, express, value);
}
public static FilterJoinNode create(Class joinClass, String joinColumn, String column, FilterExpress express, boolean itemand, Serializable value) {
return create(joinClass, new String[]{joinColumn}, column, express, itemand, value);
}
public static FilterJoinNode create(Class joinClass, String[] joinColumns, String column, Serializable value) {
return new FilterJoinNode(joinClass, joinColumns, column, value);
return create(joinClass, joinColumns, column, null, value);
}
public static FilterJoinNode create(Class joinClass, String[] joinColumns, String column, FilterExpress express, Serializable value) {
return new FilterJoinNode(joinClass, joinColumns, column, express, value);
return create(joinClass, joinColumns, column, express, true, value);
}
public static FilterJoinNode create(Class joinClass, String[] joinColumns, String column, FilterExpress express, boolean itemand, Serializable value) {
return new FilterJoinNode(joinClass, joinColumns, column, express, itemand, value);
}
@Override
@@ -87,6 +104,7 @@ public class FilterJoinNode extends FilterNode {
this.nodes = new FilterNode[]{new FilterJoinNode(node), node};
this.column = null;
this.express = null;
this.itemand = true;
this.value = null;
this.joinClass = null;
this.joinEntity = null;
@@ -260,7 +278,7 @@ public class FilterJoinNode extends FilterNode {
StringBuilder sb = new StringBuilder();
String[] joinColumns = node.joinColumns;
sb.append(" INNER JOIN ").append(node.joinEntity.getTable()).append(" ").append(joinTabalis.get(node.joinClass))
.append(" ON ").append(info.getSQLColumn("a", joinColumns[0])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), joinColumns[0]));
.append(" ON ").append(info.getSQLColumn("a", joinColumns[0])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), joinColumns[0]));
for (int i = 1; i < joinColumns.length; i++) {
sb.append(" AND ").append(info.getSQLColumn("a", joinColumns[i])).append(" = ").append(node.joinEntity.getSQLColumn(joinTabalis.get(node.joinClass), joinColumns[i]));
}

View File

@@ -28,6 +28,8 @@ public class FilterNode {
protected Serializable value;
protected boolean itemand;
//----------------------------------------------
protected boolean or;
@@ -36,21 +38,40 @@ public class FilterNode {
public FilterNode() {
}
protected FilterNode(String col, FilterExpress exp, Serializable val) {
protected FilterNode(String col, FilterExpress exp, boolean itemand, Serializable val) {
Objects.requireNonNull(col);
if (exp == null) {
if (val instanceof Range) {
exp = FilterExpress.BETWEEN;
} else if (val instanceof Collection) {
exp = FilterExpress.IN;
if (!((Collection) val).isEmpty()) {
Object subval = null;
for (Object obj : (Collection) val) { //取第一个值
subval = obj;
break;
}
if (subval instanceof Range) {
exp = FilterExpress.BETWEEN;
} else if (subval instanceof Collection) {
exp = FilterExpress.IN;
} else if (subval != null && val.getClass().isArray()) {
exp = FilterExpress.IN;
}
} else { //空集合
exp = FilterExpress.IN;
}
} else if (val != null && val.getClass().isArray()) {
exp = FilterExpress.IN;
} else {
exp = FilterExpress.EQUAL;
Class comp = val.getClass().getComponentType();
if (Range.class.isAssignableFrom(comp)) {
exp = FilterExpress.BETWEEN;
} else if (comp.isArray() || Collection.class.isAssignableFrom(comp)) {
exp = FilterExpress.IN;
}
}
}
this.column = col;
this.express = exp;
this.express = exp == null ? EQUAL : exp;
this.itemand = itemand;
this.value = val;
}
@@ -63,7 +84,11 @@ public class FilterNode {
}
public final FilterNode and(String column, FilterExpress express, Serializable value) {
return and(new FilterNode(column, express, value));
return and(column, express, true, value);
}
public final FilterNode and(String column, FilterExpress express, boolean itemand, Serializable value) {
return and(new FilterNode(column, express, itemand, value));
}
public final FilterNode or(FilterNode node) {
@@ -75,7 +100,11 @@ public class FilterNode {
}
public final FilterNode or(String column, FilterExpress express, Serializable value) {
return or(new FilterNode(column, express, value));
return or(column, express, true, value);
}
public final FilterNode or(String column, FilterExpress express, boolean itemand, Serializable value) {
return or(new FilterNode(column, express, itemand, value));
}
protected FilterNode any(FilterNode node, boolean signor) {
@@ -83,6 +112,7 @@ public class FilterNode {
if (this.column == null) {
this.column = node.column;
this.express = node.express;
this.itemand = node.itemand;
this.value = node.value;
return this;
}
@@ -98,12 +128,13 @@ public class FilterNode {
this.nodes = newsiblings;
return this;
}
FilterNode newnode = new FilterNode(this.column, this.express, this.value);
FilterNode newnode = new FilterNode(this.column, this.express, this.itemand, this.value);
newnode.or = this.or;
newnode.nodes = this.nodes;
this.nodes = new FilterNode[]{newnode, node};
this.column = null;
this.express = null;
this.itemand = true;
this.or = signor;
this.value = null;
return this;
@@ -206,16 +237,81 @@ public class FilterNode {
}
public static FilterNode create(String column, FilterExpress express, Serializable value) {
return new FilterNode(column, express, value);
return create(column, express, true, value);
}
public static FilterNode create(String column, FilterExpress express, boolean itemand, Serializable value) {
return new FilterNode(column, express, itemand, value);
}
private boolean needSplit(final Object val0) {
return needSplit(express, val0);
}
private static boolean needSplit(final FilterExpress express, final Object val0) {
boolean items = express != IN && express != NOTIN; //是否数组集合的表达式
if (!items) {
if (val0.getClass().isArray()) {
Class comp = val0.getClass().getComponentType();
if (!(comp.isPrimitive() || CharSequence.class.isAssignableFrom(comp) || Number.class.isAssignableFrom(comp))) {
items = true;
}
} else if (val0 instanceof Collection) {
for (Object fv : (Collection) val0) {
if (fv == null) continue;
Class comp = fv.getClass();
if (!(comp.isPrimitive() || CharSequence.class.isAssignableFrom(comp) || Number.class.isAssignableFrom(comp))) {
items = true;
}
break; //只需检测第一个值
}
}
}
return items;
}
protected final <T> CharSequence createElementSQLExpress(final EntityInfo<T> info, String talis) {
final Object val0 = getValue();
if (needSplit(val0)) {
if (val0 instanceof Collection) {
StringBuilder sb = new StringBuilder();
boolean more = ((Collection) val0).size() > 1;
if (more) sb.append('(');
for (Object fv : (Collection) val0) {
if (fv == null) continue;
CharSequence cs = createElementSQLExpress(info, talis, fv);
if (cs == null) continue;
if (sb.length() > 2) sb.append(itemand ? " AND " : " OR ");
sb.append(cs);
}
if (more) sb.append(')');
return sb.length() > 3 ? sb : null; //若sb的值只是(),则不过滤
} else if (val0.getClass().isArray()) {
StringBuilder sb = new StringBuilder();
Object[] fvs = (Object[]) val0;
boolean more = fvs.length > 1;
if (more) sb.append('(');
for (Object fv : fvs) {
if (fv == null) continue;
CharSequence cs = createElementSQLExpress(info, talis, fv);
if (cs == null) continue;
if (sb.length() > 2) sb.append(itemand ? " AND " : " OR ");
sb.append(cs);
}
if (more) sb.append(')');
return sb.length() > 3 ? sb : null; //若sb的值只是(),则不过滤
}
}
return createElementSQLExpress(info, talis, val0);
}
private <T> CharSequence createElementSQLExpress(final EntityInfo<T> info, String talis, Object val0) {
if (column == null) return null;
if (talis == null) talis = "a";
if (express == ISNULL || express == ISNOTNULL) {
return new StringBuilder().append(info.getSQLColumn(talis, column)).append(' ').append(express.value());
}
Object val0 = getValue();
if (val0 == null) return null;
if (express == FV_MOD || express == FV_DIV) {
FilterValue fv = (FilterValue) val0;
@@ -294,6 +390,81 @@ public class FilterNode {
@SuppressWarnings("unchecked")
protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final boolean join, final Attribute<T, Serializable> attr) {
final Object val0 = getValue();
if (needSplit(val0)) {
if (val0 instanceof Collection) {
Predicate<T> filter = null;
for (Object fv : (Collection) val0) {
if (fv == null) continue;
Predicate<T> f = createElementPredicate(cache, join, attr, fv);
if (f == null) continue;
final Predicate<T> one = filter;
final Predicate<T> two = f;
filter = (filter == null) ? f : (!itemand ? new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) || two.test(t);
}
@Override
public String toString() {
return "(" + one + " OR " + two + ")";
}
} : new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) && two.test(t);
}
@Override
public String toString() {
return "(" + one + " AND " + two + ")";
}
});
}
return filter;
} else if (val0.getClass().isArray()) {
Predicate<T> filter = null;
for (Object fv : (Object[]) val0) {
if (fv == null) continue;
Predicate<T> f = createElementPredicate(cache, join, attr, fv);
if (f == null) continue;
final Predicate<T> one = filter;
final Predicate<T> two = f;
filter = (filter == null) ? f : (!itemand ? new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) || two.test(t);
}
@Override
public String toString() {
return "(" + one + " OR " + two + ")";
}
} : new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) && two.test(t);
}
@Override
public String toString() {
return "(" + one + " AND " + two + ")";
}
});
}
return filter;
}
}
return createElementPredicate(cache, join, attr, val0);
}
@SuppressWarnings("unchecked")
protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final boolean join, final Attribute<T, Serializable> attr, Object val0) {
if (attr == null) return null;
final String field = join ? (cache.getType().getSimpleName() + "." + attr.field()) : attr.field();
if (express == ISNULL) return new Predicate<T>() {
@@ -321,7 +492,6 @@ public class FilterNode {
}
};
if (attr == null) return null;
Serializable val0 = getValue();
if (val0 == null) return null;
final Class atype = attr.type();
@@ -436,7 +606,7 @@ public class FilterNode {
}
}
}
final Serializable val = val0;
final Serializable val = (Serializable) val0;
switch (express) {
case EQUAL:
return new Predicate<T>() {
@@ -1125,10 +1295,44 @@ public class FilterNode {
}
protected final StringBuilder toElementString(final String prefix) {
Serializable val0 = getValue();
if (needSplit(val0)) {
if (val0 instanceof Collection) {
StringBuilder sb = new StringBuilder();
boolean more = ((Collection) val0).size() > 1;
if (more) sb.append('(');
for (Object fv : (Collection) val0) {
if (fv == null) continue;
CharSequence cs = toElementString(prefix, fv);
if (cs == null) continue;
if (sb.length() > 2) sb.append(itemand ? " AND " : " OR ");
sb.append(cs);
}
if (more) sb.append(')');
return sb.length() > 3 ? sb : null; //若sb的值只是(),则不过滤
} else if (val0.getClass().isArray()) {
StringBuilder sb = new StringBuilder();
Object[] fvs = (Object[]) val0;
boolean more = fvs.length > 1;
if (more) sb.append('(');
for (Object fv : fvs) {
if (fv == null) continue;
CharSequence cs = toElementString(prefix, fv);
if (cs == null) continue;
if (sb.length() > 2) sb.append(itemand ? " AND " : " OR ");
sb.append(cs);
}
if (more) sb.append(')');
return sb.length() > 3 ? sb : null; //若sb的值只是(),则不过滤
}
}
return toElementString(prefix, val0);
}
protected final StringBuilder toElementString(final String prefix, Object ev) {
StringBuilder sb = new StringBuilder();
if (column != null) {
String col = prefix == null ? column : (prefix + "." + column);
Serializable ev = getValue();
if (express == ISNULL || express == ISNOTNULL) {
sb.append(col).append(' ').append(express.value());
} else if (ev != null) {
@@ -1245,6 +1449,14 @@ public class FilterNode {
this.express = express;
}
public final boolean isItemand() {
return itemand;
}
public final void setItemand(boolean itemand) {
this.itemand = itemand;
}
public final FilterNode[] getNodes() {
return nodes;
}

View File

@@ -5,13 +5,13 @@
*/
package org.redkale.source;
import java.io.*;
import java.io.Serializable;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import javax.persistence.*;
import java.util.concurrent.ConcurrentHashMap;
import javax.persistence.Transient;
import static org.redkale.source.FilterExpress.*;
import org.redkale.util.*;
import org.redkale.util.Attribute;
/**
*
@@ -19,8 +19,9 @@ import org.redkale.util.*;
* 详情见: http://www.redkale.org
*
* @author zhangjx
* @param <T> FilterBean泛型
*/
public final class FilterNodeBean<T> implements Comparable<FilterNodeBean<T>> {
public final class FilterNodeBean<T extends FilterBean> implements Comparable<FilterNodeBean<T>> {
private static final ConcurrentHashMap<Class, FilterNodeBean> beanodes = new ConcurrentHashMap<>();
@@ -30,6 +31,8 @@ public final class FilterNodeBean<T> implements Comparable<FilterNodeBean<T>> {
private FilterExpress express;
private boolean itemand;
private boolean or;
private FilterNodeBean[] nodeBeans;
@@ -50,6 +53,7 @@ public final class FilterNodeBean<T> implements Comparable<FilterNodeBean<T>> {
this.beanAttr = bean == null ? null : bean.beanAttr;
this.column = bean == null ? null : bean.column;
this.express = bean == null ? null : bean.express;
this.itemand = bean == null ? true : bean.itemand;
this.joinClass = bean == null ? null : bean.joinClass;
this.joinColumns = bean == null ? null : bean.joinColumns;
this.least = bean == null ? 1 : bean.least;
@@ -68,10 +72,12 @@ public final class FilterNodeBean<T> implements Comparable<FilterNodeBean<T>> {
this.column = (filterCol != null && !filterCol.name().isEmpty()) ? filterCol.name() : attr.field();
FilterExpress exp = filterCol == null ? null : filterCol.express();
if (type.isArray() || Collection.class.isAssignableFrom(type)) {
if ((exp == null || exp == EQUAL) && (type.isArray() || Collection.class.isAssignableFrom(type))) {
if (Range.class.isAssignableFrom(type.getComponentType())) {
if (AND != exp) exp = OR;
} else if (NOTIN != exp) exp = IN;
} else if (NOTIN != exp) {
exp = IN;
}
} else if (Range.class.isAssignableFrom(type)) {
if (NOTBETWEEN != exp) exp = BETWEEN;
}
@@ -97,6 +103,7 @@ public final class FilterNodeBean<T> implements Comparable<FilterNodeBean<T>> {
this.beanAttr = node.beanAttr;
this.column = node.column;
this.express = node.express;
this.itemand = node.itemand;
this.joinClass = node.joinClass;
this.joinColumns = node.joinColumns;
this.least = node.least;
@@ -133,16 +140,16 @@ public final class FilterNodeBean<T> implements Comparable<FilterNodeBean<T>> {
final Serializable val = beanAttr.get(bean);
if (column != null && val != null) {
boolean skip = false;
if (string && ((CharSequence) val).length() == 0) {
if (string && ((CharSequence) val).length() == 0) { //空字符串不需要进行过滤
skip = true;
} else if (number && ((Number) val).longValue() < least) {
} else if (number && ((Number) val).longValue() < least) { //数值小于过滤下值限则不需要过滤
skip = true;
}
if (!skip) {
if (this.joinClass == null) {
node = FilterNode.create(column, express, val);
node = FilterNode.create(column, express, itemand, val);
} else {
node = FilterJoinNode.create(joinClass, joinColumns, column, express, val);
node = FilterJoinNode.create(joinClass, joinColumns, column, express, itemand, val);
}
}
}
@@ -221,7 +228,7 @@ public final class FilterNodeBean<T> implements Comparable<FilterNodeBean<T>> {
if (f == null) continue;
rs = rs == null ? f : rs.and(f);
}
if (rs !=null && rs.nodeBeans != null) Arrays.sort(rs.nodeBeans);
if (rs != null && rs.nodeBeans != null) Arrays.sort(rs.nodeBeans);
return rs == null ? new FilterNodeBean(null) : rs;
}