diff --git a/src/com/wentch/redkale/source/FilterBeanNode.java b/src/com/wentch/redkale/source/FilterBeanNode.java new file mode 100644 index 000000000..7588cde14 --- /dev/null +++ b/src/com/wentch/redkale/source/FilterBeanNode.java @@ -0,0 +1,110 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.wentch.redkale.source; + +import static com.wentch.redkale.source.FilterExpress.*; +import com.wentch.redkale.util.Attribute; +import java.io.Serializable; +import java.lang.reflect.*; +import java.util.Collection; + +/** + * + * @author zhangjx + */ +public class FilterBeanNode extends FilterNode { + + private Attribute beanAttribute; + + private boolean array; + + private boolean collection; + + private boolean string; + + private boolean number; + + private boolean likefit; + + private boolean ignoreCase; + + private long least; + + FilterBeanNode(String col, boolean sign, Attribute beanAttr) { + this.column = col; + this.signand = sign; + this.beanAttribute = beanAttr; + } + + void setField(Field field) { + final FilterColumn fc = field.getAnnotation(FilterColumn.class); + if (fc != null && !fc.name().isEmpty()) this.column = fc.name(); + final Class type = field.getType(); + this.array = type.isArray(); + this.collection = Collection.class.isAssignableFrom(type); + this.least = fc == null ? 1L : fc.least(); + this.likefit = fc == null ? true : fc.likefit(); + this.ignoreCase = fc == null ? true : fc.ignoreCase(); + this.number = type.isPrimitive() || Number.class.isAssignableFrom(type); + this.string = CharSequence.class.isAssignableFrom(type); + + FilterExpress exp = fc == null ? null : fc.express(); + if (this.array || this.collection) { + if (Range.class.isAssignableFrom(type.getComponentType())) { + if (exp == null) exp = AND; + if (AND != exp) exp = OR; + } else { + if (NOTIN != exp) exp = IN; + } + } else if (Range.class.isAssignableFrom(type)) { + if (NOTBETWEEN != exp) exp = BETWEEN; + } + if (exp == null) exp = EQUAL; + this.express = exp; + } + + @Override + protected void append(FilterNode node, boolean sign) { + FilterBeanNode newnode = new FilterBeanNode(this.column, this.signand, this.beanAttribute); + newnode.express = this.express; + newnode.nodes = this.nodes; + newnode.array = this.array; + newnode.collection = this.collection; + newnode.ignoreCase = this.ignoreCase; + newnode.least = this.least; + newnode.likefit = this.likefit; + newnode.number = this.number; + newnode.string = this.string; + this.nodes = new FilterNode[]{newnode}; + this.column = node.column; + this.express = node.express; + this.signand = sign; + this.setValue(node.getValue()); + if (node instanceof FilterBeanNode) { + FilterBeanNode beanNode = ((FilterBeanNode) node); + this.beanAttribute = beanNode.beanAttribute; + this.array = beanNode.array; + this.collection = beanNode.collection; + this.ignoreCase = beanNode.ignoreCase; + this.least = beanNode.least; + this.likefit = beanNode.likefit; + this.number = beanNode.number; + this.string = beanNode.string; + } + } + + @Override + protected Serializable getValue(FilterBean bean) { + if (bean == null || beanAttribute == null) return null; + Serializable rs = (Serializable) beanAttribute.get(bean); + if (rs == null) return null; + if (string && ((CharSequence) rs).length() == 0) return null; + if (number && ((Number) rs).longValue() < this.least) return null; + if (array && Array.getLength(rs) == 0) return null; + if (collection && ((Collection) rs).isEmpty()) return null; + return rs; + } +} diff --git a/src/com/wentch/redkale/source/FilterNode.java b/src/com/wentch/redkale/source/FilterNode.java index 14f5163bf..9c1a669d2 100644 --- a/src/com/wentch/redkale/source/FilterNode.java +++ b/src/com/wentch/redkale/source/FilterNode.java @@ -16,7 +16,7 @@ import java.util.function.*; * * @author zhangjx */ -public abstract class FilterNode { +public class FilterNode { protected boolean signand = true; @@ -26,16 +26,39 @@ public abstract class FilterNode { protected FilterNode[] nodes; + private Serializable value; + + public FilterNode() { + } + + FilterNode(String col, FilterExpress exp, Serializable val) { + Objects.requireNonNull(col); + if (exp == null) { + if (val instanceof Range) { + exp = FilterExpress.BETWEEN; + } else if (val instanceof Collection) { + exp = FilterExpress.IN; + } else if (val != null && val.getClass().isArray()) { + exp = FilterExpress.IN; + } else { + exp = FilterExpress.EQUAL; + } + } + this.column = col; + this.express = exp; + this.value = val; + } + public final FilterNode and(FilterNode node) { return any(node, true); } public final FilterNode and(String column, Serializable value) { - return and(new FilterSimpleNode(column, null, value)); + return and(new FilterNode(column, null, value)); } public final FilterNode and(String column, FilterExpress express, Serializable value) { - return and(new FilterSimpleNode(column, express, value)); + return and(new FilterNode(column, express, value)); } public final FilterNode or(FilterNode node) { @@ -43,11 +66,11 @@ public abstract class FilterNode { } public final FilterNode or(String column, Serializable value) { - return or(new FilterSimpleNode(column, null, value)); + return or(new FilterNode(column, null, value)); } public final FilterNode or(String column, FilterExpress express, Serializable value) { - return or(new FilterSimpleNode(column, express, value)); + return or(new FilterNode(column, express, value)); } protected final FilterNode any(FilterNode node, boolean sign) { @@ -64,23 +87,34 @@ public abstract class FilterNode { this.nodes = newsiblings; return this; } - this.copyFrom(node, sign); + this.append(node, sign); return this; } - protected abstract void copyFrom(FilterNode node, boolean sign); + protected void append(FilterNode node, boolean sign) { + FilterNode newnode = new FilterNode(this.column, this.express, this.value); + newnode.signand = this.signand; + newnode.nodes = this.nodes; + this.nodes = new FilterNode[]{newnode}; + this.column = node.column; + this.express = node.express; + this.signand = sign; + this.value = node.value; + } - protected abstract Serializable getValue(Object bean); + protected Serializable getValue(FilterBean bean) { + return value; + } public static FilterNode create(String column, Serializable value) { return create(column, FilterExpress.EQUAL, value); } public static FilterNode create(String column, FilterExpress express, Serializable value) { - return new FilterSimpleNode(column, express, value); + return new FilterNode(column, express, value); } - protected final Predicate createFilterPredicate(final EntityInfo info, Object bean) { + protected final Predicate createFilterPredicate(final EntityInfo info, FilterBean bean) { if (info == null) return null; final Serializable val = getValue(bean); if (val == null && express != ISNULL && express != ISNOTNULL) return null; @@ -224,6 +258,29 @@ public abstract class FilterNode { return String.valueOf(value); } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + if (nodes == null) { + sb.append(column).append(' ').append(express.value()).append(' ').append(formatValue(value)); + } else { + sb.append('(').append(column).append(' ').append(express.value()).append(' ').append(formatValue(value)); + for (FilterNode node : this.nodes) { + sb.append(signand ? " AND " : " OR ").append(node.toString()); + } + sb.append(')'); + } + return sb.toString(); + } + + public Serializable getValue() { + return value; + } + + public void setValue(Serializable value) { + this.value = value; + } + public boolean isSignand() { return signand; } diff --git a/src/com/wentch/redkale/source/FilterSimpleNode.java b/src/com/wentch/redkale/source/FilterSimpleNode.java deleted file mode 100644 index 189f7cc83..000000000 --- a/src/com/wentch/redkale/source/FilterSimpleNode.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package com.wentch.redkale.source; - -import java.io.*; -import java.util.*; - -/** - * - * @author zhangjx - */ -public final class FilterSimpleNode extends FilterNode { - - private Serializable value; - - public FilterSimpleNode() { - } - - FilterSimpleNode(String col, FilterExpress exp, Serializable val) { - Objects.requireNonNull(col); - if (exp == null) { - if (val instanceof Range) { - exp = FilterExpress.BETWEEN; - } else if (val instanceof Collection) { - exp = FilterExpress.IN; - } else if (val != null && val.getClass().isArray()) { - exp = FilterExpress.IN; - } else { - exp = FilterExpress.EQUAL; - } - } - this.column = col; - this.express = exp; - this.value = val; - } - - @Override - protected void copyFrom(FilterNode node, boolean sign) { - FilterSimpleNode newnode = new FilterSimpleNode(this.column, this.express, this.value); - newnode.signand = this.signand; - newnode.nodes = this.nodes; - this.nodes = new FilterNode[]{newnode}; - this.column = node.column; - this.express = node.express; - this.signand = sign; - if (node instanceof FilterSimpleNode) this.value = ((FilterSimpleNode) node).value; - } - - @Override - protected Serializable getValue(Object bean) { - return value; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - if (nodes == null) { - sb.append(column).append(' ').append(express.value()).append(' ').append(formatValue(value)); - } else { - sb.append('(').append(column).append(' ').append(express.value()).append(' ').append(formatValue(value)); - for (FilterNode node : this.nodes) { - sb.append(signand ? " AND " : " OR ").append(node.toString()); - } - sb.append(')'); - } - return sb.toString(); - } - - public Serializable getValue() { - return value; - } - - public void setValue(Serializable value) { - this.value = value; - } - -}