filter 改版中……

This commit is contained in:
kamhung
2015-11-19 17:50:38 +08:00
parent 61050e7d00
commit ef17090446
6 changed files with 561 additions and 425 deletions

View File

@@ -641,7 +641,9 @@ public final class DataDefaultSource implements DataSource, Nameable {
private <T> void delete(final Connection conn, final EntityInfo<T> info, final FilterNode node) { private <T> void delete(final Connection conn, final EntityInfo<T> info, final FilterNode node) {
try { try {
if (!info.isVirtualEntity()) { if (!info.isVirtualEntity()) {
String sql = "DELETE FROM " + info.getTable() + node.createFilterSQLExpress(info, null); CharSequence join = node.createSQLJoin(info);
CharSequence where = node.createSQLExpress(info, null);
String sql = "DELETE FROM " + info.getTable() + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
if (debug.get()) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql); if (debug.get()) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql);
final Statement stmt = conn.createStatement(); final Statement stmt = conn.createStatement();
stmt.execute(sql); stmt.execute(sql);
@@ -1081,12 +1083,14 @@ public final class DataDefaultSource implements DataSource, Nameable {
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass()); if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) { if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) {
if (node == null || node.isJoinAllCached()) { if (node == null || node.isCacheUseable()) {
return cache.getNumberResult(reckon, column, node, bean); return cache.getNumberResult(reckon, column, node, bean);
} }
} }
final CharSequence join = node == null ? null : node.createSQLJoin(info);
final CharSequence where = node == null ? null : node.createSQLExpress(info, bean);
final String sql = "SELECT " + reckon.getColumn((column == null || column.isEmpty() ? "*" : ("a." + column))) + " FROM " + info.getTable() + " a" final String sql = "SELECT " + reckon.getColumn((column == null || column.isEmpty() ? "*" : ("a." + column))) + " FROM " + info.getTable() + " a"
+ (node == null ? "" : node.createFilterSQLExpress(info, bean)); + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql); if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql);
final PreparedStatement prestmt = conn.prepareStatement(sql); final PreparedStatement prestmt = conn.prepareStatement(sql);
Number rs = null; Number rs = null;
@@ -1127,13 +1131,15 @@ public final class DataDefaultSource implements DataSource, Nameable {
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass()); if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
final EntityCache cache = info.getCache(); final EntityCache cache = info.getCache();
if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) { if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) {
if (node == null || node.isJoinAllCached()) { if (node == null || node.isCacheUseable()) {
return cache.getMapResult(keyColumn, reckon, reckonColumn, node, bean); return cache.getMapResult(keyColumn, reckon, reckonColumn, node, bean);
} }
} }
final String sqlkey = info.getSQLColumn(keyColumn); final String sqlkey = info.getSQLColumn(keyColumn);
final CharSequence join = node == null ? null : node.createSQLJoin(info);
final CharSequence where = node == null ? null : node.createSQLExpress(info, bean);
final String sql = "SELECT a." + sqlkey + ", " + reckon.getColumn((reckonColumn == null || reckonColumn.isEmpty() ? "*" : ("a." + reckonColumn))) final String sql = "SELECT a." + sqlkey + ", " + reckon.getColumn((reckonColumn == null || reckonColumn.isEmpty() ? "*" : ("a." + reckonColumn)))
+ " FROM " + info.getTable() + " a" + (node == null ? "" : node.createFilterSQLExpress(info, bean)) + " GROUP BY a." + sqlkey; + " FROM " + info.getTable() + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where)) + " GROUP BY a." + sqlkey;
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql); if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql);
final PreparedStatement prestmt = conn.prepareStatement(sql); final PreparedStatement prestmt = conn.prepareStatement(sql);
Map<K, V> rs = new LinkedHashMap<>(); Map<K, V> rs = new LinkedHashMap<>();
@@ -1433,8 +1439,8 @@ public final class DataDefaultSource implements DataSource, Nameable {
final EntityCache<T> cache = info.getCache(); final EntityCache<T> cache = info.getCache();
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass()); if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
if (readcache && cache != null) { if (readcache && cache != null) {
if (node == null || node.isJoinAllCached()) { if (node == null || node.isCacheUseable()) {
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " cache query predicate = " + (node == null ? null : node.createFilterPredicate(info, bean))); if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " cache query predicate = " + (node == null ? null : node.createPredicate(cache, bean)));
Sheet<T> sheet = cache.querySheet(needtotal, selects, flipper, node, bean); Sheet<T> sheet = cache.querySheet(needtotal, selects, flipper, node, bean);
if (!sheet.isEmpty() || info.isVirtualEntity() || cache.isFullLoaded()) return sheet; if (!sheet.isEmpty() || info.isVirtualEntity() || cache.isFullLoaded()) return sheet;
} }
@@ -1443,8 +1449,10 @@ public final class DataDefaultSource implements DataSource, Nameable {
try { try {
final SelectColumn sels = selects; final SelectColumn sels = selects;
final List<T> list = new ArrayList(); final List<T> list = new ArrayList();
final String sql = "SELECT a.* FROM " + info.getTable() + " a" final CharSequence join = node == null ? null : node.createSQLJoin(info);
+ (node == null ? "" : node.createFilterSQLExpress(info, bean)) + createFilterSQLOrderBy(info, flipper); final CharSequence where = node == null ? null : node.createSQLExpress(info, bean);
final String sql = "SELECT a.* FROM " + info.getTable() + " a" + (join == null ? "" : join)
+ ((where == null || where.length() == 0) ? "" : (" WHERE " + where)) + info.createSQLOrderby(flipper);
if (debug.get() && info.isLoggable(Level.FINEST)) if (debug.get() && info.isLoggable(Level.FINEST))
logger.finest(clazz.getSimpleName() + " query sql=" + sql + (flipper == null ? "" : (" LIMIT " + flipper.index() + "," + flipper.getSize()))); logger.finest(clazz.getSimpleName() + " query sql=" + sql + (flipper == null ? "" : (" LIMIT " + flipper.index() + "," + flipper.getSize())));
final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

View File

@@ -25,81 +25,11 @@ import java.util.stream.*;
*/ */
public final class EntityCache<T> { public final class EntityCache<T> {
private static class UniqueSequence implements Serializable {
private final Serializable[] value;
public UniqueSequence(Serializable[] val) {
this.value = val;
}
@Override
public int hashCode() {
return Arrays.deepHashCode(this.value);
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final UniqueSequence other = (UniqueSequence) obj;
if (value.length != other.value.length) return false;
for (int i = 0; i < value.length; i++) {
if (!value[i].equals(other.value[i])) return false;
}
return true;
}
}
private static interface UniqueAttribute<T> extends Predicate<FilterNode> {
public Serializable getValue(T bean);
@Override
public boolean test(FilterNode node);
public static <T> UniqueAttribute<T> create(final Attribute<T, Serializable>[] attributes) {
if (attributes.length == 1) {
final Attribute<T, Serializable> attribute = attributes[0];
return new UniqueAttribute<T>() {
@Override
public Serializable getValue(T bean) {
return attribute.get(bean);
}
@Override
public boolean test(FilterNode node) {
return true;
}
};
} else {
return new UniqueAttribute<T>() {
@Override
public Serializable getValue(T bean) {
final Serializable[] rs = new Serializable[attributes.length];
for (int i = 0; i < rs.length; i++) {
rs[i] = attributes[i].get(bean);
}
return new UniqueSequence(rs);
}
@Override
public boolean test(FilterNode node) {
return true;
}
};
}
}
}
private static final Logger logger = Logger.getLogger(EntityCache.class.getName()); private static final Logger logger = Logger.getLogger(EntityCache.class.getName());
private final ConcurrentHashMap<Serializable, T> map = new ConcurrentHashMap(); private final ConcurrentHashMap<Serializable, T> map = new ConcurrentHashMap();
private final CopyOnWriteArrayList<T> list = new CopyOnWriteArrayList(); // CopyOnWriteArrayList 插入慢、查询快; 10w数据插入需要3.2秒; ConcurrentLinkedQueue 插入快、查询慢10w数据查询需要 0.062秒, 查询慢40%; private final Collection<T> list = new CopyOnWriteArrayList(); // CopyOnWriteArrayList 插入慢、查询快; 10w数据插入需要3.2秒; ConcurrentLinkedQueue 插入快、查询慢10w数据查询需要 0.062秒, 查询慢40%;
private final HashMap<UniqueAttribute<T>, ConcurrentHashMap<Serializable, Collection<T>>> uniques = new HashMap<>(); private final HashMap<UniqueAttribute<T>, ConcurrentHashMap<Serializable, Collection<T>>> uniques = new HashMap<>();
@@ -180,14 +110,19 @@ public final class EntityCache<T> {
} }
public boolean exists(final Predicate<T> filter) { public boolean exists(final Predicate<T> filter) {
return (filter != null) && listStream().filter(filter).findFirst().isPresent(); return (filter != null) && this.list.stream().filter(filter).findFirst().isPresent();
} }
public <K, V> Map<Serializable, Number> getMapResult(final String keyColumn, final Reckon reckon, final String reckonColumn, final FilterNode node, final FilterBean bean) { public <K, V> Map<Serializable, Number> getMapResult(final String keyColumn, final Reckon reckon, final String reckonColumn, final FilterNode node) {
return getMapResult(keyColumn, reckon, reckonColumn, node, null);
}
public <K, V> Map<Serializable, Number> getMapResult(final String keyColumn, final Reckon reckon, final String reckonColumn, FilterNode node, final FilterBean bean) {
if (node == null && bean != null) node = FilterBeanNode.load(bean.getClass());
final Attribute<T, Serializable> keyAttr = info.getAttribute(keyColumn); final Attribute<T, Serializable> keyAttr = info.getAttribute(keyColumn);
final Predicate filter = node == null ? null : node.createFilterPredicate(this.info, bean); final Predicate filter = node == null ? null : node.createPredicate(this, bean);
final Attribute reckonAttr = reckonColumn == null ? null : info.getAttribute(reckonColumn); final Attribute reckonAttr = reckonColumn == null ? null : info.getAttribute(reckonColumn);
Stream<T> stream = listStream(); Stream<T> stream = this.list.stream();
if (filter != null) stream = stream.filter(filter); if (filter != null) stream = stream.filter(filter);
Collector<T, Map, ?> collector = null; Collector<T, Map, ?> collector = null;
final Class valtype = reckonAttr == null ? null : reckonAttr.type(); final Class valtype = reckonAttr == null ? null : reckonAttr.type();
@@ -232,10 +167,15 @@ public final class EntityCache<T> {
return rs; return rs;
} }
public <V> Number getNumberResult(final Reckon reckon, final String column, final FilterNode node, final FilterBean bean) { public <V> Number getNumberResult(final Reckon reckon, final String column, final FilterNode node) {
return getNumberResult(reckon, column, node, null);
}
public <V> Number getNumberResult(final Reckon reckon, final String column, FilterNode node, final FilterBean bean) {
if (node == null && bean != null) node = FilterBeanNode.load(bean.getClass());
final Attribute<T, Serializable> attr = column == null ? null : info.getAttribute(column); final Attribute<T, Serializable> attr = column == null ? null : info.getAttribute(column);
final Predicate<T> filter = node == null ? null : node.createFilterPredicate(this.info, bean); final Predicate<T> filter = node == null ? null : node.createPredicate(this, bean);
Stream<T> stream = listStream(); Stream<T> stream = this.list.stream();
if (filter != null) stream = stream.filter(filter); if (filter != null) stream = stream.filter(filter);
switch (reckon) { switch (reckon) {
case AVG: case AVG:
@@ -299,21 +239,30 @@ public final class EntityCache<T> {
return -1; return -1;
} }
public Sheet<T> querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node) {
return querySheet(selects, flipper, node, null);
}
public Sheet<T> querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node, final FilterBean bean) { public Sheet<T> querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node, final FilterBean bean) {
return querySheet(true, selects, flipper, node, bean); return querySheet(true, selects, flipper, node, bean);
} }
public Sheet<T> querySheet(final boolean needtotal, final SelectColumn selects, final Flipper flipper, final FilterNode node, final FilterBean bean) { public Sheet<T> querySheet(final boolean needtotal, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
final Predicate<T> filter = node == null ? null : node.createFilterPredicate(this.info, bean); return querySheet(needtotal, selects, flipper, node, null);
final Comparator<T> comparator = FilterNode.createFilterComparator(this, flipper); }
public Sheet<T> querySheet(final boolean needtotal, final SelectColumn selects, final Flipper flipper, FilterNode node, final FilterBean bean) {
if (node == null && bean != null) node = FilterBeanNode.load(bean.getClass());
final Predicate<T> filter = node == null ? null : node.createPredicate(this, bean);
final Comparator<T> comparator = createComparator(flipper);
long total = 0; long total = 0;
if (needtotal) { if (needtotal) {
Stream<T> stream = listStream(); Stream<T> stream = this.list.stream();
if (filter != null) stream = stream.filter(filter); if (filter != null) stream = stream.filter(filter);
total = stream.count(); total = stream.count();
} }
if (needtotal && total == 0) return new Sheet<>(); if (needtotal && total == 0) return new Sheet<>();
Stream<T> stream = listStream(); Stream<T> stream = this.list.stream();
if (filter != null) stream = stream.filter(filter); if (filter != null) stream = stream.filter(filter);
if (comparator != null) stream = stream.sorted(comparator); if (comparator != null) stream = stream.sorted(comparator);
if (flipper != null) stream = stream.skip(flipper.index()).limit(flipper.getSize()); if (flipper != null) stream = stream.skip(flipper.index()).limit(flipper.getSize());
@@ -327,9 +276,9 @@ public final class EntityCache<T> {
} }
} else { } else {
final List<Attribute<T, Serializable>> attrs = new ArrayList<>(); final List<Attribute<T, Serializable>> attrs = new ArrayList<>();
for (Map.Entry<String, Attribute<T, Serializable>> en : info.attributes.entrySet()) { info.forEachAttribute((k, v) -> {
if (selects.validate(en.getKey())) attrs.add(en.getValue()); if (selects.validate(k)) attrs.add(v);
} });
Consumer<? super T> action = x -> { Consumer<? super T> action = x -> {
final T item = creator.create(); final T item = creator.create();
for (Attribute attr : attrs) { for (Attribute attr : attrs) {
@@ -371,7 +320,7 @@ public final class EntityCache<T> {
public Serializable[] delete(final FilterNode node) { public Serializable[] delete(final FilterNode node) {
if (node == null || this.list.isEmpty()) return new Serializable[0]; if (node == null || this.list.isEmpty()) return new Serializable[0];
Object[] rms = listStream().filter(node.createFilterPredicate(this.info, null)).toArray(); Object[] rms = this.list.stream().filter(node.createPredicate(this, null)).toArray();
Serializable[] ids = new Serializable[rms.length]; Serializable[] ids = new Serializable[rms.length];
int i = -1; int i = -1;
for (Object o : rms) { for (Object o : rms) {
@@ -453,15 +402,237 @@ public final class EntityCache<T> {
return rs; return rs;
} }
private Stream<T> listStream() { public Attribute<T, Serializable> getAttribute(String fieldname) {
return this.list.stream(); return info.getAttribute(fieldname);
} }
protected Comparator<T> getSortComparator(String sort) { //-------------------------------------------------------------------------------------------------------------------------------
return this.sortComparators.get(sort); protected Comparator<T> createComparator(Flipper flipper) {
} if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null;
final String sort = flipper.getSort();
Comparator<T> comparator = this.sortComparators.get(sort);
if (comparator != null) return comparator;
for (String item : sort.split(",")) {
if (item.trim().isEmpty()) continue;
String[] sub = item.trim().split("\\s+");
int pos = sub[0].indexOf('(');
Attribute<T, Serializable> attr;
if (pos <= 0) {
attr = getAttribute(sub[0]);
} else { //含SQL函数
int pos2 = sub[0].lastIndexOf(')');
final Attribute<T, Serializable> pattr = getAttribute(sub[0].substring(pos + 1, pos2));
final String func = sub[0].substring(0, pos);
if ("ABS".equalsIgnoreCase(func)) {
if (pattr.type() == int.class || pattr.type() == Integer.class) {
attr = new Attribute<T, Serializable>() {
protected void putSortComparator(String sort, Comparator<T> comparator) { @Override
public Class type() {
return pattr.type();
}
@Override
public Class declaringClass() {
return pattr.declaringClass();
}
@Override
public String field() {
return pattr.field();
}
@Override
public Serializable get(T obj) {
return Math.abs(((Number) pattr.get(obj)).intValue());
}
@Override
public void set(T obj, Serializable value) {
pattr.set(obj, value);
}
};
} else if (pattr.type() == long.class || pattr.type() == Long.class) {
attr = new Attribute<T, Serializable>() {
@Override
public Class type() {
return pattr.type();
}
@Override
public Class declaringClass() {
return pattr.declaringClass();
}
@Override
public String field() {
return pattr.field();
}
@Override
public Serializable get(T obj) {
return Math.abs(((Number) pattr.get(obj)).longValue());
}
@Override
public void set(T obj, Serializable value) {
pattr.set(obj, value);
}
};
} else if (pattr.type() == float.class || pattr.type() == Float.class) {
attr = new Attribute<T, Serializable>() {
@Override
public Class type() {
return pattr.type();
}
@Override
public Class declaringClass() {
return pattr.declaringClass();
}
@Override
public String field() {
return pattr.field();
}
@Override
public Serializable get(T obj) {
return Math.abs(((Number) pattr.get(obj)).floatValue());
}
@Override
public void set(T obj, Serializable value) {
pattr.set(obj, value);
}
};
} else if (pattr.type() == double.class || pattr.type() == Double.class) {
attr = new Attribute<T, Serializable>() {
@Override
public Class type() {
return pattr.type();
}
@Override
public Class declaringClass() {
return pattr.declaringClass();
}
@Override
public String field() {
return pattr.field();
}
@Override
public Serializable get(T obj) {
return Math.abs(((Number) pattr.get(obj)).doubleValue());
}
@Override
public void set(T obj, Serializable value) {
pattr.set(obj, value);
}
};
} else {
throw new RuntimeException("Flipper not supported sort illegal type by ABS (" + flipper.getSort() + ")");
}
} else if (func.isEmpty()) {
attr = pattr;
} else {
throw new RuntimeException("Flipper not supported sort illegal function (" + flipper.getSort() + ")");
}
}
Comparator<T> c = (sub.length > 1 && sub[1].equalsIgnoreCase("DESC")) ? (T o1, T o2) -> {
Comparable c1 = (Comparable) attr.get(o1);
Comparable c2 = (Comparable) attr.get(o2);
return c2 == null ? -1 : c2.compareTo(c1);
} : (T o1, T o2) -> {
Comparable c1 = (Comparable) attr.get(o1);
Comparable c2 = (Comparable) attr.get(o2);
return c1 == null ? -1 : c1.compareTo(c2);
};
if (comparator == null) {
comparator = c;
} else {
comparator = comparator.thenComparing(c);
}
}
this.sortComparators.put(sort, comparator); this.sortComparators.put(sort, comparator);
return comparator;
} }
private static class UniqueSequence implements Serializable {
private final Serializable[] value;
public UniqueSequence(Serializable[] val) {
this.value = val;
}
@Override
public int hashCode() {
return Arrays.deepHashCode(this.value);
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
final UniqueSequence other = (UniqueSequence) obj;
if (value.length != other.value.length) return false;
for (int i = 0; i < value.length; i++) {
if (!value[i].equals(other.value[i])) return false;
}
return true;
}
}
private static interface UniqueAttribute<T> extends Predicate<FilterNode> {
public Serializable getValue(T bean);
@Override
public boolean test(FilterNode node);
public static <T> UniqueAttribute<T> create(final Attribute<T, Serializable>[] attributes) {
if (attributes.length == 1) {
final Attribute<T, Serializable> attribute = attributes[0];
return new UniqueAttribute<T>() {
@Override
public Serializable getValue(T bean) {
return attribute.get(bean);
}
@Override
public boolean test(FilterNode node) {
return true;
}
};
} else {
return new UniqueAttribute<T>() {
@Override
public Serializable getValue(T bean) {
final Serializable[] rs = new Serializable[attributes.length];
for (int i = 0; i < rs.length; i++) {
rs[i] = attributes[i].get(bean);
}
return new UniqueSequence(rs);
}
@Override
public boolean test(FilterNode node) {
return true;
}
};
}
}
}
} }

View File

@@ -44,7 +44,7 @@ public final class EntityInfo<T> {
//key是field的name 不是sql字段。 //key是field的name 不是sql字段。
//存放所有与数据库对应的字段, 包括主键 //存放所有与数据库对应的字段, 包括主键
final Map<String, Attribute<T, Serializable>> attributes = new HashMap<>(); private final HashMap<String, Attribute<T, Serializable>> attributes = new HashMap<>();
//key是field的name value是Column的别名即数据库表的字段名 //key是field的name value是Column的别名即数据库表的字段名
//只有field.name 与 Column.name不同才存放在aliasmap里. //只有field.name 与 Column.name不同才存放在aliasmap里.
@@ -93,10 +93,12 @@ public final class EntityInfo<T> {
synchronized (entityInfos) { synchronized (entityInfos) {
rs = entityInfos.get(clazz); rs = entityInfos.get(clazz);
if (rs == null) { if (rs == null) {
if (nodeid < 0) throw new IllegalArgumentException("nodeid(" + nodeid + ") is illegal");
rs = new EntityInfo(clazz, nodeid, cacheForbidden); rs = new EntityInfo(clazz, nodeid, cacheForbidden);
entityInfos.put(clazz, rs); entityInfos.put(clazz, rs);
AutoLoad auto = clazz.getAnnotation(AutoLoad.class); AutoLoad auto = clazz.getAnnotation(AutoLoad.class);
if (rs.cache != null && auto != null && auto.value() && fullloader != null) { if (rs.cache != null && auto != null && auto.value()) {
if (fullloader == null) throw new IllegalArgumentException(clazz.getName() + " auto loader is illegal");
rs.cache.fullLoad(fullloader.apply(clazz)); rs.cache.fullLoad(fullloader.apply(clazz));
} }
} }
@@ -107,7 +109,7 @@ public final class EntityInfo<T> {
private EntityInfo(Class<T> type, int nodeid, final boolean cacheForbidden) { private EntityInfo(Class<T> type, int nodeid, final boolean cacheForbidden) {
this.type = type; this.type = type;
//--------------------------------------------- //---------------------------------------------
this.nodeid = nodeid; this.nodeid = nodeid >= 0 ? nodeid : 0;
DistributeGenerator.DistributeTables dt = type.getAnnotation(DistributeGenerator.DistributeTables.class); DistributeGenerator.DistributeTables dt = type.getAnnotation(DistributeGenerator.DistributeTables.class);
this.distributeTables = dt == null ? null : dt.value(); this.distributeTables = dt == null ? null : dt.value();
@@ -267,7 +269,12 @@ public final class EntityInfo<T> {
return this.primary; return this.primary;
} }
public void forEachAttribute(BiConsumer<String, Attribute<T, Serializable>> action) {
this.attributes.forEach(action);
}
public Attribute<T, Serializable> getAttribute(String fieldname) { public Attribute<T, Serializable> getAttribute(String fieldname) {
if (fieldname == null) return null;
return this.attributes.get(fieldname); return this.attributes.get(fieldname);
} }
@@ -279,12 +286,32 @@ public final class EntityInfo<T> {
return this.aliasmap == null; return this.aliasmap == null;
} }
public String getSortOrderbySql(String sort) { protected String createSQLOrderby(Flipper flipper) {
return this.sortOrderbySqls.get(sort); if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return "";
} final String sort = flipper.getSort();
String sql = this.sortOrderbySqls.get(sort);
protected void putSortOrderbySql(String sort, String sql) { if (sql != null) return sql;
final StringBuilder sb = new StringBuilder();
sb.append(" ORDER BY ");
if (isNoAlias()) {
sb.append(sort);
} else {
boolean flag = false;
for (String item : sort.split(",")) {
if (item.isEmpty()) continue;
String[] sub = item.split("\\s+");
if (flag) sb.append(',');
if (sub.length < 2 || sub[1].equalsIgnoreCase("ASC")) {
sb.append("a.").append(getSQLColumn(sub[0])).append(" ASC");
} else {
sb.append("a.").append(getSQLColumn(sub[0])).append(" DESC");
}
flag = true;
}
}
sql = sb.toString();
this.sortOrderbySqls.put(sort, sql); this.sortOrderbySqls.put(sort, sql);
return sql;
} }
//根据field字段名获取数据库对应的字段名 //根据field字段名获取数据库对应的字段名

View File

@@ -26,6 +26,10 @@ final class FilterBeanNode extends FilterNode {
private static final ConcurrentHashMap<Class, FilterBeanNode> beanodes = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<Class, FilterBeanNode> beanodes = new ConcurrentHashMap<>();
public static <T extends FilterBean> FilterBeanNode load(Class<T> clazz) {
return load(clazz, -1, true, null);
}
public static <T extends FilterBean> FilterBeanNode load(Class<T> clazz, final int nodeid, final boolean cacheForbidden, public static <T extends FilterBean> FilterBeanNode load(Class<T> clazz, final int nodeid, final boolean cacheForbidden,
Function<Class, List> fullloader) { Function<Class, List> fullloader) {
FilterBeanNode rs = beanodes.get(clazz); FilterBeanNode rs = beanodes.get(clazz);
@@ -55,17 +59,19 @@ final class FilterBeanNode extends FilterNode {
if (field.getAnnotation(Ignore.class) != null) continue; if (field.getAnnotation(Ignore.class) != null) continue;
if (field.getAnnotation(Transient.class) != null) continue; if (field.getAnnotation(Transient.class) != null) continue;
final boolean pubmod = Modifier.isPublic(field.getModifiers());
char[] chars = field.getName().toCharArray(); char[] chars = field.getName().toCharArray();
chars[0] = Character.toUpperCase(chars[0]); chars[0] = Character.toUpperCase(chars[0]);
final Class t = field.getType(); final Class t = field.getType();
Method getter; Method getter = null;
try { try {
getter = cltmp.getMethod(((t == boolean.class || t == Boolean.class) ? "is" : "get") + new String(chars)); getter = cltmp.getMethod(((t == boolean.class || t == Boolean.class) ? "is" : "get") + new String(chars));
} catch (Exception ex) { } catch (Exception ex) {
continue; if (!pubmod) continue;
} }
fields.add(field.getName()); fields.add(field.getName());
FilterBeanNode newnode = new FilterBeanNode(field.getName(), true, Attribute.create(getter, null)); FilterBeanNode newnode = new FilterBeanNode(field.getName(), true, pubmod ? Attribute.create(field) : Attribute.create(getter, null));
newnode.setField(field); newnode.setField(field);
//------------------------------------ //------------------------------------
{ {
@@ -163,7 +169,7 @@ final class FilterBeanNode extends FilterNode {
protected FilterBeanNode(String col, boolean sign, Attribute beanAttr) { protected FilterBeanNode(String col, boolean sign, Attribute beanAttr) {
this.column = col; this.column = col;
this.signand = sign; this.and = sign;
this.beanAttribute = beanAttr; this.beanAttribute = beanAttr;
} }
@@ -195,7 +201,7 @@ final class FilterBeanNode extends FilterNode {
@Override @Override
protected void append(FilterNode node, boolean sign) { protected void append(FilterNode node, boolean sign) {
FilterBeanNode newnode = new FilterBeanNode(this.column, this.signand, this.beanAttribute); FilterBeanNode newnode = new FilterBeanNode(this.column, this.and, this.beanAttribute);
newnode.express = this.express; newnode.express = this.express;
newnode.nodes = this.nodes; newnode.nodes = this.nodes;
newnode.foreignEntity = this.foreignEntity; newnode.foreignEntity = this.foreignEntity;
@@ -211,7 +217,7 @@ final class FilterBeanNode extends FilterNode {
this.nodes = new FilterNode[]{newnode}; this.nodes = new FilterNode[]{newnode};
this.column = node.column; this.column = node.column;
this.express = node.express; this.express = node.express;
this.signand = sign; this.and = sign;
this.setValue(node.getValue()); this.setValue(node.getValue());
if (node instanceof FilterBeanNode) { if (node instanceof FilterBeanNode) {
FilterBeanNode beanNode = ((FilterBeanNode) node); FilterBeanNode beanNode = ((FilterBeanNode) node);
@@ -230,29 +236,27 @@ final class FilterBeanNode extends FilterNode {
} }
@Override @Override
protected <T> StringBuilder createFilterSQLExpress(final boolean first, final EntityInfo<T> info, FilterBean bean) { protected <T> CharSequence createSQLJoin(final EntityInfo<T> info) {
if (joinSQL == null || !first) return super.createFilterSQLExpress(first, info, bean); if (joinSQL == null) return null;
StringBuilder sb = super.createFilterSQLExpress(first, info, bean); return new StringBuilder(joinSQL);
if (joinSQL == null) return sb;
return new StringBuilder(sb.length() + joinSQL.length()).append(joinSQL).append(sb);
} }
@Override @Override
protected <T> Predicate<T> createFilterPredicate(final EntityInfo<T> info, FilterBean bean) { protected <T> Predicate<T> createPredicate(final EntityCache<T> cache, FilterBean bean) {
//if ((this.joinSQL == null && first) || this.foreignEntity == null) return super.createFilterPredicate(info, bean); if (this.foreignEntity == null) return super.createPredicate(cache, bean);
if (this.foreignEntity == null) return super.createFilterPredicate(info, bean);
final Map<EntityInfo, Predicate> foreign = new HashMap<>(); final Map<EntityInfo, Predicate> foreign = new HashMap<>();
Predicate<T> result = null; Predicate<T> result = null;
putForeignPredicate(foreign, bean); putForeignPredicate(cache, foreign, bean);
if (this.nodes != null) { if (this.nodes != null) {
for (FilterNode n : this.nodes) { for (FilterNode n : this.nodes) {
FilterBeanNode node = (FilterBeanNode) n; FilterBeanNode node = (FilterBeanNode) n;
if (node.foreignEntity == null) { if (node.foreignEntity == null) {
Predicate<T> f = node.createFilterPredicate(info, bean); Predicate<T> f = node.createPredicate(cache, bean);
if (f == null) continue; if (f == null) continue;
final Predicate<T> one = result; final Predicate<T> one = result;
final Predicate<T> two = f; final Predicate<T> two = f;
result = (result == null) ? f : (signand ? new Predicate<T>() { result = (result == null) ? f : (and ? new Predicate<T>() {
@Override @Override
public boolean test(T t) { public boolean test(T t) {
@@ -276,7 +280,7 @@ final class FilterBeanNode extends FilterNode {
} }
}); });
} else { } else {
putForeignPredicate(foreign, bean); putForeignPredicate(cache, foreign, bean);
} }
} }
} }
@@ -284,8 +288,7 @@ final class FilterBeanNode extends FilterNode {
final String byjoinCol = this.byjoinColumn; final String byjoinCol = this.byjoinColumn;
final Attribute foreignAttr = this.foreignAttribute; final Attribute foreignAttr = this.foreignAttribute;
for (final Map.Entry<EntityInfo, Predicate> en : foreign.entrySet()) { for (final Map.Entry<EntityInfo, Predicate> en : foreign.entrySet()) {
Attribute<T, Serializable> byjoinAttr = info.getAttribute(byjoinCol); Attribute<T, Serializable> byjoinAttr = cache.getAttribute(byjoinCol);
final EntityCache cache = en.getKey().getCache();
final Predicate p = en.getValue(); final Predicate p = en.getValue();
Predicate<T> f = new Predicate<T>() { Predicate<T> f = new Predicate<T>() {
@@ -303,7 +306,7 @@ final class FilterBeanNode extends FilterNode {
}; };
final Predicate<T> one = result; final Predicate<T> one = result;
final Predicate<T> two = f; final Predicate<T> two = f;
result = (result == null) ? f : (signand ? new Predicate<T>() { result = (result == null) ? f : (and ? new Predicate<T>() {
@Override @Override
public boolean test(T t) { public boolean test(T t) {
@@ -330,21 +333,21 @@ final class FilterBeanNode extends FilterNode {
return result; return result;
} }
private <T> void putForeignPredicate(final Map<EntityInfo, Predicate> foreign, FilterBean bean) { private <T> void putForeignPredicate(final EntityCache<T> cache, final Map<EntityInfo, Predicate> foreign, FilterBean bean) {
if (this.foreignEntity == null) return; if (this.foreignEntity == null) return;
final Serializable val = getValue(bean); final Serializable val = getElementValue(bean);
Predicate filter = (val == null && express != ISNULL && express != ISNOTNULL) ? new Predicate<T>() { Predicate filter = (val == null && express != ISNULL && express != ISNOTNULL) ? new Predicate<T>() {
@Override @Override
public boolean test(T t) { public boolean test(T t) {
return signand; return and;
} }
@Override @Override
public String toString() { public String toString() {
return "" + signand; return "" + and;
} }
} : super.createFilterPredicate(this.columnAttribute, val); } : super.createElementPredicate(cache, this.columnAttribute, bean);
if (filter == null) return; if (filter == null) return;
Predicate p = foreign.get(this.foreignEntity); Predicate p = foreign.get(this.foreignEntity);
if (p == null) { if (p == null) {
@@ -352,7 +355,7 @@ final class FilterBeanNode extends FilterNode {
} else { } else {
final Predicate<T> one = p; final Predicate<T> one = p;
final Predicate<T> two = filter; final Predicate<T> two = filter;
p = signand ? new Predicate<T>() { p = and ? new Predicate<T>() {
@Override @Override
public boolean test(T t) { public boolean test(T t) {
@@ -380,12 +383,12 @@ final class FilterBeanNode extends FilterNode {
} }
@Override @Override
protected boolean isJoinAllCached() { protected boolean isCacheUseable() {
return joinallcached; return joinallcached;
} }
@Override @Override
protected Serializable getValue(FilterBean bean) { protected Serializable getElementValue(FilterBean bean) {
if (bean == null || beanAttribute == null) return null; if (bean == null || beanAttribute == null) return null;
Serializable rs = (Serializable) beanAttribute.get(bean); Serializable rs = (Serializable) beanAttribute.get(bean);
if (rs == null) return null; if (rs == null) return null;

View File

@@ -0,0 +1,66 @@
/*
* 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.util.*;
/**
*
* @author zhangjx
*/
public final class FilterJoinNode extends FilterNode {
private Class joinClass;
private String joinColumn;
private String foreignColumn;
public FilterJoinNode() {
}
protected FilterJoinNode(Class joinClass, String joinColumn, String foreignColumn) {
this.joinClass = joinClass;
this.joinColumn = joinColumn;
this.foreignColumn = foreignColumn;
}
public static FilterJoinNode create(Class joinClass, String joinColumn) {
return create(joinClass, joinColumn, joinColumn);
}
public static FilterJoinNode create(Class joinClass, String joinColumn, String foreignColumn) {
Objects.requireNonNull(joinClass);
Objects.requireNonNull(joinColumn);
Objects.requireNonNull(foreignColumn);
return new FilterJoinNode(joinClass, joinColumn, foreignColumn);
}
public Class getJoinClass() {
return joinClass;
}
public void setJoinClass(Class joinClass) {
this.joinClass = joinClass;
}
public String getJoinColumn() {
return joinColumn;
}
public void setJoinColumn(String joinColumn) {
this.joinColumn = joinColumn;
}
public String getForeignColumn() {
return foreignColumn;
}
public void setForeignColumn(String foreignColumn) {
this.foreignColumn = foreignColumn;
}
}

View File

@@ -38,12 +38,11 @@ public class FilterNode {
protected Serializable value; protected Serializable value;
//---------------------------------------------- //----------------------------------------------
protected boolean and = true;
protected boolean signand = true;
protected FilterNode[] nodes; protected FilterNode[] nodes;
protected FilterNode() { public FilterNode() {
} }
protected FilterNode(String col, FilterExpress exp, Serializable val) { protected FilterNode(String col, FilterExpress exp, Serializable val) {
@@ -69,7 +68,7 @@ public class FilterNode {
} }
public final FilterNode and(String column, Serializable value) { public final FilterNode and(String column, Serializable value) {
return and(new FilterNode(column, null, value)); return and(column, null, value);
} }
public final FilterNode and(String column, FilterExpress express, Serializable value) { public final FilterNode and(String column, FilterExpress express, Serializable value) {
@@ -81,7 +80,7 @@ public class FilterNode {
} }
public final FilterNode or(String column, Serializable value) { public final FilterNode or(String column, Serializable value) {
return or(new FilterNode(column, null, value)); return or(column, null, value);
} }
public final FilterNode or(String column, FilterExpress express, Serializable value) { public final FilterNode or(String column, FilterExpress express, Serializable value) {
@@ -90,12 +89,18 @@ public class FilterNode {
protected final FilterNode any(FilterNode node, boolean sign) { protected final FilterNode any(FilterNode node, boolean sign) {
Objects.requireNonNull(node); Objects.requireNonNull(node);
if (nodes == null) { if (this.column == null) {
nodes = new FilterNode[]{node}; this.column = node.column;
this.signand = sign; this.express = node.express;
this.value = node.value;
return this; return this;
} }
if (signand == sign) { if (nodes == null) {
nodes = new FilterNode[]{node};
this.and = sign;
return this;
}
if (and == sign) {
FilterNode[] newsiblings = new FilterNode[nodes.length + 1]; FilterNode[] newsiblings = new FilterNode[nodes.length + 1];
System.arraycopy(nodes, 0, newsiblings, 0, nodes.length); System.arraycopy(nodes, 0, newsiblings, 0, nodes.length);
newsiblings[nodes.length] = node; newsiblings[nodes.length] = node;
@@ -106,23 +111,51 @@ public class FilterNode {
return this; return this;
} }
/**
* 该方法需要重载
*
* @param node
* @param sign
*/
protected void append(FilterNode node, boolean sign) { protected void append(FilterNode node, boolean sign) {
FilterNode newnode = new FilterNode(this.column, this.express, this.value); FilterNode newnode = new FilterNode(this.column, this.express, this.value);
newnode.signand = this.signand; newnode.and = this.and;
newnode.nodes = this.nodes; newnode.nodes = this.nodes;
this.nodes = new FilterNode[]{newnode, node}; this.nodes = new FilterNode[]{newnode, node};
this.tabalis = null; this.tabalis = null;
this.column = null; this.column = null;
this.express = null; this.express = null;
this.signand = sign; this.and = sign;
this.value = null; this.value = null;
} }
protected Serializable getValue(FilterBean bean) { /**
* 该方法需要重载
*
* @param bean
* @return
*/
protected Serializable getElementValue(final FilterBean bean) {
return value; return value;
} }
protected boolean isJoinAllCached() { /**
* 该方法需要重载
*
* @param <T>
* @param info
* @return
*/
protected <T> CharSequence createSQLJoin(final EntityInfo<T> info) {
return null;
}
/**
* 该方法需要重载
*
* @return
*/
protected boolean isCacheUseable() {
return true; return true;
} }
@@ -134,50 +167,42 @@ public class FilterNode {
return new FilterNode(column, express, value); return new FilterNode(column, express, value);
} }
protected final <T> StringBuilder createFilterSQLExpress(final EntityInfo<T> info, FilterBean bean) { protected final <T> CharSequence createSQLExpress(final EntityInfo<T> info, final FilterBean bean) {
return createFilterSQLExpress(true, info, bean); CharSequence sb0 = createElementSQLExpress(info, bean);
} if (this.nodes == null) return sb0;
protected <T> StringBuilder createFilterSQLExpress(final boolean first, final EntityInfo<T> info, FilterBean bean) {
final Serializable val = getValue(bean);
if (val == null && (express == ISNULL || express == ISNOTNULL)) return new StringBuilder(0);
StringBuilder sb0 = createFilterSQLExpress(info, val);
if (this.nodes == null) {
if (sb0 == null) return new StringBuilder(0);
if (!first) return sb0;
return new StringBuilder(sb0.length() + 8).append(" WHERE ").append(sb0);
}
final StringBuilder rs = new StringBuilder(); final StringBuilder rs = new StringBuilder();
rs.append(first ? " WHERE (" : " ("); rs.append('(');
boolean more = false; boolean more = false;
if (sb0 != null && sb0.length() > 2) { if (sb0 != null && sb0.length() > 2) {
more = true; more = true;
rs.append(sb0); rs.append(sb0);
} }
for (FilterNode node : this.nodes) { for (FilterNode node : this.nodes) {
StringBuilder f = node.createFilterSQLExpress(false, info, bean); CharSequence f = node.createSQLExpress(info, bean);
if (f == null || f.length() < 3) continue; if (f == null || f.length() < 3) continue;
if (more) rs.append(signand ? " AND " : " OR "); if (more) rs.append(and ? " AND " : " OR ");
rs.append(f); rs.append(f);
more = true; more = true;
} }
rs.append(')'); rs.append(')');
if (rs.length() < (first ? 10 : 5)) return new StringBuilder(0); if (rs.length() < 5) return null;
return rs; return rs;
} }
private <T> StringBuilder createFilterSQLExpress(final EntityInfo<T> info, Serializable val0) { protected final <T> CharSequence createElementSQLExpress(final EntityInfo<T> info, final FilterBean bean) {
if (column == null) return null; if (column == null) return null;
final StringBuilder val = formatValue(val0); if (express == ISNULL || express == ISNOTNULL) {
StringBuilder sb = new StringBuilder();
if (tabalis != null) sb.append(tabalis).append('.');
sb.append(info.getSQLColumn(column)).append(' ').append(express.value());
return sb;
}
final StringBuilder val = formatToString(express, getElementValue(bean));
if (val == null) return null; if (val == null) return null;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder(32);
if (tabalis != null) sb.append(tabalis).append('.'); if (tabalis != null) sb.append(tabalis).append('.');
sb.append(info.getSQLColumn(column)).append(' '); sb.append(info.getSQLColumn(column)).append(' ');
switch (express) { switch (express) {
case ISNULL:
case ISNOTNULL:
sb.append(express.value());
break;
case OPAND: case OPAND:
case OPOR: case OPOR:
sb.append(express.value()).append(' ').append(val).append(" > 0"); sb.append(express.value()).append(' ').append(val).append(" > 0");
@@ -192,45 +217,16 @@ public class FilterNode {
return sb; return sb;
} }
protected static <E> String createFilterSQLOrderBy(EntityInfo<E> info, Flipper flipper) { protected <T> Predicate<T> createPredicate(final EntityCache<T> cache, final FilterBean bean) {
if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return ""; if (cache == null || (column == null && this.nodes == null)) return null;
final String sort = flipper.getSort(); Predicate<T> filter = createElementPredicate(cache, bean);
String sql = info.getSortOrderbySql(sort);
if (sql != null) return sql;
final StringBuilder sb = new StringBuilder();
sb.append(" ORDER BY ");
if (info.isNoAlias()) {
sb.append(sort);
} else {
boolean flag = false;
for (String item : sort.split(",")) {
if (item.isEmpty()) continue;
String[] sub = item.split("\\s+");
if (flag) sb.append(',');
if (sub.length < 2 || sub[1].equalsIgnoreCase("ASC")) {
sb.append("a.").append(info.getSQLColumn(sub[0])).append(" ASC");
} else {
sb.append("a.").append(info.getSQLColumn(sub[0])).append(" DESC");
}
flag = true;
}
}
sql = sb.toString();
info.putSortOrderbySql(sort, sql);
return sql;
}
protected <T> Predicate<T> createFilterPredicate(final EntityInfo<T> info, FilterBean bean) {
if (info == null || (column == null && this.nodes == null)) return null;
final Serializable val = getValue(bean);
Predicate<T> filter = createFilterPredicate(column == null ? null : info.getAttribute(column), val);
if (this.nodes == null) return filter; if (this.nodes == null) return filter;
for (FilterNode node : this.nodes) { for (FilterNode node : this.nodes) {
Predicate<T> f = node.createFilterPredicate(info, bean); Predicate<T> f = node.createPredicate(cache, bean);
if (f == null) continue; if (f == null) continue;
final Predicate<T> one = filter; final Predicate<T> one = filter;
final Predicate<T> two = f; final Predicate<T> two = f;
filter = (filter == null) ? f : (signand ? new Predicate<T>() { filter = (filter == null) ? f : (and ? new Predicate<T>() {
@Override @Override
public boolean test(T t) { public boolean test(T t) {
@@ -257,35 +253,39 @@ public class FilterNode {
return filter; return filter;
} }
protected final <T> Predicate<T> createFilterPredicate(final Attribute<T, Serializable> attr, Serializable val0) { protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final FilterBean bean) {
if (val0 == null) { return createElementPredicate(cache, cache.getAttribute(column), bean);
if (express == ISNULL) return new Predicate<T>() { }
@Override protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final Attribute<T, Serializable> attr, final FilterBean bean) {
public boolean test(T t) {
return attr.get(t) == null;
}
@Override if (express == ISNULL) return new Predicate<T>() {
public String toString() {
return attr.field() + " = null";
}
};
if (express == ISNOTNULL) return new Predicate<T>() {
@Override @Override
public boolean test(T t) { public boolean test(T t) {
return attr.get(t) != null; return attr.get(t) == null;
} }
@Override @Override
public String toString() { public String toString() {
return attr.field() + " != null"; return attr.field() + " = null";
} }
}; };
return null; if (express == ISNOTNULL) return new Predicate<T>() {
}
@Override
public boolean test(T t) {
return attr.get(t) != null;
}
@Override
public String toString() {
return attr.field() + " != null";
}
};
if (attr == null) return null; if (attr == null) return null;
Serializable val0 = getElementValue(bean);
if (val0 == null) return null;
final Class atype = attr.type(); final Class atype = attr.type();
final Class valtype = val0.getClass(); final Class valtype = val0.getClass();
@@ -743,174 +743,51 @@ public class FilterNode {
return null; return null;
} }
protected static <E> Comparator<E> createFilterComparator(EntityCache<E> cache, Flipper flipper) { @Override
if (flipper == null || flipper.getSort() == null || flipper.getSort().isEmpty()) return null; public String toString() {
final String sort = flipper.getSort(); return toString(null);
Comparator<E> comparator = cache.getSortComparator(sort);
if (comparator != null) return comparator;
for (String item : sort.split(",")) {
if (item.trim().isEmpty()) continue;
String[] sub = item.trim().split("\\s+");
int pos = sub[0].indexOf('(');
Attribute<E, Serializable> attr;
if (pos <= 0) {
attr = cache.info.getAttribute(sub[0]);
} else { //含SQL函数
int pos2 = sub[0].lastIndexOf(')');
final Attribute<E, Serializable> pattr = cache.info.getAttribute(sub[0].substring(pos + 1, pos2));
final String func = sub[0].substring(0, pos);
if ("ABS".equalsIgnoreCase(func)) {
if (pattr.type() == int.class || pattr.type() == Integer.class) {
attr = new Attribute<E, Serializable>() {
@Override
public Class type() {
return pattr.type();
}
@Override
public Class declaringClass() {
return pattr.declaringClass();
}
@Override
public String field() {
return pattr.field();
}
@Override
public Serializable get(E obj) {
return Math.abs(((Number) pattr.get(obj)).intValue());
}
@Override
public void set(E obj, Serializable value) {
pattr.set(obj, value);
}
};
} else if (pattr.type() == long.class || pattr.type() == Long.class) {
attr = new Attribute<E, Serializable>() {
@Override
public Class type() {
return pattr.type();
}
@Override
public Class declaringClass() {
return pattr.declaringClass();
}
@Override
public String field() {
return pattr.field();
}
@Override
public Serializable get(E obj) {
return Math.abs(((Number) pattr.get(obj)).longValue());
}
@Override
public void set(E obj, Serializable value) {
pattr.set(obj, value);
}
};
} else if (pattr.type() == float.class || pattr.type() == Float.class) {
attr = new Attribute<E, Serializable>() {
@Override
public Class type() {
return pattr.type();
}
@Override
public Class declaringClass() {
return pattr.declaringClass();
}
@Override
public String field() {
return pattr.field();
}
@Override
public Serializable get(E obj) {
return Math.abs(((Number) pattr.get(obj)).floatValue());
}
@Override
public void set(E obj, Serializable value) {
pattr.set(obj, value);
}
};
} else if (pattr.type() == double.class || pattr.type() == Double.class) {
attr = new Attribute<E, Serializable>() {
@Override
public Class type() {
return pattr.type();
}
@Override
public Class declaringClass() {
return pattr.declaringClass();
}
@Override
public String field() {
return pattr.field();
}
@Override
public Serializable get(E obj) {
return Math.abs(((Number) pattr.get(obj)).doubleValue());
}
@Override
public void set(E obj, Serializable value) {
pattr.set(obj, value);
}
};
} else {
throw new RuntimeException("Flipper not supported sort illegal type by ABS (" + flipper.getSort() + ")");
}
} else if (func.isEmpty()) {
attr = pattr;
} else {
throw new RuntimeException("Flipper not supported sort illegal function (" + flipper.getSort() + ")");
}
}
Comparator<E> c = (sub.length > 1 && sub[1].equalsIgnoreCase("DESC")) ? (E o1, E o2) -> {
Comparable c1 = (Comparable) attr.get(o1);
Comparable c2 = (Comparable) attr.get(o2);
return c2 == null ? -1 : c2.compareTo(c1);
} : (E o1, E o2) -> {
Comparable c1 = (Comparable) attr.get(o1);
Comparable c2 = (Comparable) attr.get(o2);
return c1 == null ? -1 : c1.compareTo(c2);
};
if (comparator == null) {
comparator = c;
} else {
comparator = comparator.thenComparing(c);
}
}
cache.putSortComparator(sort, comparator);
return comparator;
} }
protected StringBuilder formatValue(Object value) { public String toString(final FilterBean bean) {
return formatValue(express, value); StringBuilder sb = new StringBuilder();
if (nodes == null) {
if (column != null) {
Serializable ev = getElementValue(bean);
if (express == ISNULL || express == ISNOTNULL) {
sb.append(column).append(' ').append(express.value());
} else if (ev != null) {
sb.append(column).append(' ').append(express.value()).append(' ').append(formatToString(express, ev));
}
}
} else {
boolean more = false;
if (column != null) {
Serializable ev = getElementValue(bean);
if (express == ISNULL || express == ISNOTNULL) {
sb.append('(').append(column).append(' ').append(express.value());
more = true;
} else if (ev != null) {
sb.append('(').append(column).append(' ').append(express.value()).append(' ').append(formatToString(express, ev));
more = true;
}
}
for (FilterNode node : this.nodes) {
String s = node.toString();
if (s.isEmpty()) continue;
if (sb.length() > 0) sb.append(and ? " AND " : " OR ");
sb.append(s);
}
if (more) sb.append(')');
}
return sb.toString();
} }
protected static String formatToString(Object value) { protected static String formatToString(Object value) {
StringBuilder sb = formatValue(null, value); StringBuilder sb = formatToString(null, value);
return sb == null ? null : sb.toString(); return sb == null ? null : sb.toString();
} }
private static StringBuilder formatValue(FilterExpress express, Object value) { private static StringBuilder formatToString(FilterExpress express, Object value) {
if (value == null) return null; if (value == null) return null;
if (value instanceof Number) return new StringBuilder().append(value); if (value instanceof Number) return new StringBuilder().append(value);
if (value instanceof CharSequence) { if (value instanceof CharSequence) {
@@ -937,7 +814,7 @@ public class FilterNode {
if (len == 0) return express == NOTIN ? null : new StringBuilder("(NULL)"); if (len == 0) return express == NOTIN ? null : new StringBuilder("(NULL)");
if (len == 1) { if (len == 1) {
Object firstval = Array.get(value, 0); Object firstval = Array.get(value, 0);
if (firstval != null && firstval.getClass().isArray()) return formatValue(express, firstval); if (firstval != null && firstval.getClass().isArray()) return formatToString(express, firstval);
} }
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append('('); sb.append('(');
@@ -969,67 +846,51 @@ public class FilterNode {
return new StringBuilder().append(value); return new StringBuilder().append(value);
} }
@Override public final Serializable getValue() {
public String toString() {
StringBuilder sb = new StringBuilder();
if (nodes == null) {
sb.append(column).append(' ').append(express.value()).append(' ').append(formatValue(value));
} else {
if (column != null) sb.append('(').append(column).append(' ').append(express.value()).append(' ').append(formatValue(value));
for (FilterNode node : this.nodes) {
if (sb.length() > 0) sb.append(signand ? " AND " : " OR ");
sb.append(node.toString());
}
sb.append(')');
}
return sb.toString();
}
public Serializable getValue() {
return value; return value;
} }
public void setValue(Serializable value) { public final void setValue(Serializable value) {
this.value = value; this.value = value;
} }
public boolean isSignand() { public final boolean isAnd() {
return signand; return and;
} }
public void setSignand(boolean signand) { public final void setAnd(boolean and) {
this.signand = signand; this.and = and;
} }
public String getTabalis() { public final String getTabalis() {
return tabalis; return tabalis;
} }
public void setTabalis(String tabalis) { public final void setTabalis(String tabalis) {
this.tabalis = tabalis; this.tabalis = tabalis;
} }
public String getColumn() { public final String getColumn() {
return column; return column;
} }
public void setColumn(String column) { public final void setColumn(String column) {
this.column = column; this.column = column;
} }
public FilterExpress getExpress() { public final FilterExpress getExpress() {
return express; return express;
} }
public void setExpress(FilterExpress express) { public final void setExpress(FilterExpress express) {
this.express = express; this.express = express;
} }
public FilterNode[] getNodes() { public final FilterNode[] getNodes() {
return nodes; return nodes;
} }
public void setNodes(FilterNode[] nodes) { public final void setNodes(FilterNode[] nodes) {
this.nodes = nodes; this.nodes = nodes;
} }