filter 改版中……
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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字段名获取数据库对应的字段名
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
66
src/com/wentch/redkale/source/FilterJoinNode.java
Normal file
66
src/com/wentch/redkale/source/FilterJoinNode.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user