This commit is contained in:
kamhung
2015-12-04 18:49:54 +08:00
parent 3966da6b7a
commit bf75aaad96
7 changed files with 492 additions and 593 deletions

View File

@@ -142,8 +142,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public Number getNumberResult(Class entityClass, Reckon reckon, String column, FilterBean bean) {
return source.getNumberResult(entityClass, reckon, column, bean);
public final Number getNumberResult(Class entityClass, Reckon reckon, String column, FilterBean bean) {
return getNumberResult(entityClass, reckon, column, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -157,8 +157,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <K extends Serializable, V extends Number> Map<K, V> getMapResult(Class entityClass, String keyColumn, Reckon reckon, String reckonColumn, FilterBean bean) {
return source.getMapResult(entityClass, keyColumn, reckon, reckonColumn, bean);
public final <K extends Serializable, V extends Number> Map<K, V> getMapResult(Class entityClass, String keyColumn, Reckon reckon, String reckonColumn, FilterBean bean) {
return getMapResult(entityClass, keyColumn, reckon, reckonColumn, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -187,8 +187,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T> T find(Class<T> clazz, FilterBean bean) {
return source.find(clazz, bean);
public final <T> T find(Class<T> clazz, FilterBean bean) {
return find(clazz, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -202,8 +202,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T> boolean exists(Class<T> clazz, FilterBean bean) {
return source.exists(clazz, bean);
public final <T> boolean exists(Class<T> clazz, FilterBean bean) {
return exists(clazz, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -217,8 +217,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T, V> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterBean bean) {
return source.queryColumnSet(selectedColumn, clazz, bean);
public final <T, V> HashSet<V> queryColumnSet(String selectedColumn, Class<T> clazz, FilterBean bean) {
return queryColumnSet(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -232,8 +232,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T, V> List<V> queryColumnList(String selectedColumn, Class<T> clazz, FilterBean bean) {
return source.queryColumnList(selectedColumn, clazz, bean);
public final <T, V> List<V> queryColumnList(String selectedColumn, Class<T> clazz, FilterBean bean) {
return queryColumnList(selectedColumn, clazz, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -242,8 +242,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <K extends Serializable, T> Map<K, T> queryMap(Class<T> clazz, FilterBean bean) {
return source.queryMap(clazz, bean);
public final <K extends Serializable, T> Map<K, T> queryMap(Class<T> clazz, FilterBean bean) {
return queryMap(clazz, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -252,8 +252,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <K extends Serializable, T> Map<K, T> queryMap(Class<T> clazz, SelectColumn selects, FilterBean bean) {
return source.queryMap(clazz, selects, bean);
public final <K extends Serializable, T> Map<K, T> queryMap(Class<T> clazz, SelectColumn selects, FilterBean bean) {
return queryMap(clazz, selects, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -267,8 +267,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T> List<T> queryList(Class<T> clazz, FilterBean bean) {
return source.queryList(clazz, bean);
public final <T> List<T> queryList(Class<T> clazz, FilterBean bean) {
return queryList(clazz, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -277,8 +277,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T> List<T> queryList(Class<T> clazz, SelectColumn selects, FilterBean bean) {
return source.queryList(clazz, bean);
public final <T> List<T> queryList(Class<T> clazz, SelectColumn selects, FilterBean bean) {
return queryList(clazz, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -292,8 +292,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T> List<T> queryList(Class<T> clazz, Flipper flipper, FilterBean bean) {
return source.queryList(clazz, flipper, bean);
public final <T> List<T> queryList(Class<T> clazz, Flipper flipper, FilterBean bean) {
return queryList(clazz, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -302,13 +302,13 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T> List<T> queryList(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterBean bean) {
return source.queryList(clazz, selects, flipper, bean);
public final <T> List<T> queryList(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterBean bean) {
return queryList(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override
public <T, V> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterBean bean) {
return source.queryColumnSheet(selectedColumn, clazz, flipper, bean);
public final <T, V> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterBean bean) {
return queryColumnSheet(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -317,8 +317,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T> Sheet<T> querySheet(Class<T> clazz, Flipper flipper, FilterBean bean) {
return source.querySheet(clazz, flipper, bean);
public final <T> Sheet<T> querySheet(Class<T> clazz, Flipper flipper, FilterBean bean) {
return querySheet(clazz, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override
@@ -327,8 +327,8 @@ public class DataSourceService implements DataSource, Service {
}
@Override
public <T> Sheet<T> querySheet(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterBean bean) {
return source.querySheet(clazz, selects, flipper, bean);
public final <T> Sheet<T> querySheet(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterBean bean) {
return querySheet(clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override

View File

@@ -110,7 +110,7 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
}
}
private final Function<Class, List> fullloader = (t) -> querySheet(false, false, t, null, null, (FilterNode) null, null).list(true);
private final Function<Class, List> fullloader = (t) -> querySheet(false, false, t, null, null, (FilterNode) null).list(true);
public DataDefaultSource() throws IOException {
this("");
@@ -339,10 +339,6 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
return EntityInfo.load(clazz, this.nodeid, this.cacheForbidden, fullloader);
}
private <T extends FilterBean> FilterBeanNode loadFilterBeanNode(Class<T> clazz) {
return FilterBeanNode.load(clazz, this.nodeid, this.cacheForbidden, fullloader);
}
/**
* 将entity的对象全部加载到Cache中去如果clazz没有被@javax.persistence.Cacheable注解则不做任何事
* <p>
@@ -651,7 +647,7 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
if (!info.isVirtualEntity()) {
Map<Class, String> joinTabalis = node.getJoinTabalis();
CharSequence join = node.createSQLJoin(this, joinTabalis, info);
CharSequence where = node.createSQLExpress(info, joinTabalis, null);
CharSequence where = node.createSQLExpress(info, joinTabalis);
String sql = "DELETE " + (mysql ? "a" : "") + " FROM " + info.getTable() + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
if (debug.get()) logger.finest(info.getType().getSimpleName() + " delete sql=" + sql);
final Statement stmt = conn.createStatement();
@@ -1062,7 +1058,7 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
if (cache == null) return;
String column = info.getPrimary().field();
for (Serializable id : ids) {
Sheet<T> sheet = querySheet(false, true, clazz, null, FLIPPER_ONE, FilterNode.create(column, id), null);
Sheet<T> sheet = querySheet(false, true, clazz, null, FLIPPER_ONE, FilterNode.create(column, id));
T value = sheet.isEmpty() ? null : sheet.list().get(0);
if (value != null) cache.update(value);
}
@@ -1071,33 +1067,28 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
//-----------------------getNumberResult-----------------------------
@Override
public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column) {
return getNumberResult(entityClass, reckon, column, null, null);
return getNumberResult(entityClass, reckon, column, (FilterNode) null);
}
@Override
public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column, FilterBean bean) {
return getNumberResult(entityClass, reckon, column, null, bean);
return getNumberResult(entityClass, reckon, column, FilterNodeBean.createFilterNode(bean));
}
@Override
public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column, FilterNode node) {
return getNumberResult(entityClass, reckon, column, node, null);
}
private <T> Number getNumberResult(final Class<T> entityClass, final Reckon reckon, final String column, FilterNode node, FilterBean bean) {
public Number getNumberResult(final Class entityClass, final Reckon reckon, final String column, final FilterNode node) {
final Connection conn = createReadSQLConnection();
try {
final EntityInfo<T> info = loadEntityInfo(entityClass);
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
final EntityCache<T> cache = info.getCache();
final EntityInfo info = loadEntityInfo(entityClass);
final EntityCache cache = info.getCache();
if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) {
if (node == null || node.isCacheUseable(this)) {
return cache.getNumberResult(reckon, column, node, bean);
return cache.getNumberResult(reckon, column, node);
}
}
final Map<Class, String> joinTabalis = node == null ? null : node.getJoinTabalis();
final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis, bean);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis);
final String sql = "SELECT " + reckon.getColumn((column == null || column.isEmpty() ? "*" : ("a." + column))) + " FROM " + info.getTable() + " a"
+ (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(entityClass.getSimpleName() + " single sql=" + sql);
@@ -1120,34 +1111,29 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
//-----------------------getMapResult-----------------------------
@Override
public <K extends Serializable, V extends Number> Map<K, V> getMapResult(Class entityClass, final String keyColumn, Reckon reckon, final String reckonColumn) {
return getMapResult(entityClass, keyColumn, reckon, reckonColumn, null, null);
return getMapResult(entityClass, keyColumn, reckon, reckonColumn, (FilterNode) null);
}
@Override
public <K extends Serializable, V extends Number> Map<K, V> getMapResult(Class entityClass, final String keyColumn, Reckon reckon, final String reckonColumn, FilterBean bean) {
return getMapResult(entityClass, keyColumn, reckon, reckonColumn, null, bean);
return getMapResult(entityClass, keyColumn, reckon, reckonColumn, FilterNodeBean.createFilterNode(bean));
}
@Override
public <K extends Serializable, V extends Number> Map<K, V> getMapResult(Class entityClass, final String keyColumn, Reckon reckon, final String reckonColumn, FilterNode node) {
return getMapResult(entityClass, keyColumn, reckon, reckonColumn, node, null);
}
private <K extends Serializable, V extends Number> Map<K, V> getMapResult(final Class entityClass, final String keyColumn, final Reckon reckon, final String reckonColumn, FilterNode node, FilterBean bean) {
public <K extends Serializable, V extends Number> Map<K, V> getMapResult(final Class entityClass, final String keyColumn, final Reckon reckon, final String reckonColumn, FilterNode node) {
final Connection conn = createReadSQLConnection();
try {
final EntityInfo info = loadEntityInfo(entityClass);
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
final EntityCache cache = info.getCache();
if (cache != null && (info.isVirtualEntity() || cache.isFullLoaded())) {
if (node == null || node.isCacheUseable(this)) {
return cache.getMapResult(keyColumn, reckon, reckonColumn, node, bean);
return cache.getMapResult(keyColumn, reckon, reckonColumn, node);
}
}
final String sqlkey = info.getSQLColumn(null, keyColumn);
final Map<Class, String> joinTabalis = node == null ? null : node.getJoinTabalis();
final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis, bean);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis);
final String sql = "SELECT a." + sqlkey + ", " + reckon.getColumn((reckonColumn == null || reckonColumn.isEmpty() ? "*" : ("a." + reckonColumn)))
+ " 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);
@@ -1209,31 +1195,30 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
@Override
public <T> T findByColumn(final Class<T> clazz, final String column, final Serializable key) {
return find(clazz, null, FilterNode.create(column, key), null);
return find(clazz, null, FilterNode.create(column, key));
}
@Override
public <T> T find(final Class<T> clazz, final FilterBean bean) {
return find(clazz, null, null, bean);
return find(clazz, null, FilterNodeBean.createFilterNode(bean));
}
@Override
public <T> T find(final Class<T> clazz, final FilterNode node) {
return find(clazz, null, node, null);
return find(clazz, null, node);
}
private <T> T find(final Class<T> clazz, final SelectColumn selects, FilterNode node, final FilterBean bean) {
public <T> T find(final Class<T> clazz, final SelectColumn selects, final FilterNode node) {
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
if (cache != null && cache.isFullLoaded() && (node == null || node.isCacheUseable(this))) return cache.find(selects, node, bean);
if (cache != null && cache.isFullLoaded() && (node == null || node.isCacheUseable(this))) return cache.find(selects, node);
final Connection conn = createReadSQLConnection();
try {
final SelectColumn sels = selects;
final Map<Class, String> joinTabalis = node == null ? null : node.getJoinTabalis();
final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis, bean);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis);
final String sql = "SELECT a.* FROM " + info.getTable() + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " find sql=" + sql);
final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
@@ -1273,26 +1258,21 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
}
@Override
public <T> boolean exists(final Class<T> clazz, final FilterNode node) {
return exists(clazz, node, null);
public <T> boolean exists(final Class<T> clazz, final FilterBean bean) {
return exists(clazz, FilterNodeBean.createFilterNode(bean));
}
@Override
public <T> boolean exists(final Class<T> clazz, final FilterBean bean) {
return exists(clazz, null, bean);
}
private <T> boolean exists(final Class<T> clazz, FilterNode node, final FilterBean bean) {
public <T> boolean exists(final Class<T> clazz, final FilterNode node) {
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
if (cache != null && cache.isFullLoaded() && (node == null || node.isCacheUseable(this))) return cache.exists(node, bean);
if (cache != null && cache.isFullLoaded() && (node == null || node.isCacheUseable(this))) return cache.exists(node);
final Connection conn = createReadSQLConnection();
try {
final Map<Class, String> joinTabalis = node == null ? null : node.getJoinTabalis();
final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis, bean);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis);
final String sql = "SELECT COUNT(" + info.getPrimarySQLColumn("a") + ") FROM " + info.getTable() + " a" + (join == null ? "" : join) + ((where == null || where.length() == 0) ? "" : (" WHERE " + where));
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " exists sql=" + sql);
final PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
@@ -1446,12 +1426,12 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
@Override
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
return querySheet(true, false, clazz, selects, flipper, node, null).list(true);
return querySheet(true, false, clazz, selects, flipper, node).list(true);
}
@Override
public <T> List<T> queryList(final Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
return querySheet(true, false, clazz, selects, flipper, null, bean).list(true);
return querySheet(true, false, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean)).list(true);
}
//-----------------------sheet----------------------------
@@ -1468,16 +1448,12 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
*/
@Override
public <T, V> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, final Flipper flipper, final FilterBean bean) {
return queryColumnSheet(selectedColumn, clazz, flipper, null, bean);
return queryColumnSheet(selectedColumn, clazz, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override
public <T, V> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, final Flipper flipper, final FilterNode node) {
return queryColumnSheet(selectedColumn, clazz, flipper, node, null);
}
private <T, V> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, final Flipper flipper, final FilterNode node, final FilterBean bean) {
Sheet<T> sheet = querySheet(true, true, clazz, SelectColumn.createIncludes(selectedColumn), flipper, node, bean);
Sheet<T> sheet = querySheet(true, true, clazz, SelectColumn.createIncludes(selectedColumn), flipper, node);
final Sheet<V> rs = new Sheet<>();
if (sheet.isEmpty()) return rs;
rs.setTotal(sheet.getTotal());
@@ -1522,22 +1498,21 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
*/
@Override
public <T> Sheet<T> querySheet(Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterBean bean) {
return querySheet(true, true, clazz, selects, flipper, null, bean);
return querySheet(true, true, clazz, selects, flipper, FilterNodeBean.createFilterNode(bean));
}
@Override
public <T> Sheet<T> querySheet(Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
return querySheet(true, true, clazz, selects, flipper, node, null);
return querySheet(true, true, clazz, selects, flipper, node);
}
private <T> Sheet<T> querySheet(boolean readcache, boolean needtotal, Class<T> clazz, final SelectColumn selects, final Flipper flipper, FilterNode node, final FilterBean bean) {
private <T> Sheet<T> querySheet(boolean readcache, boolean needtotal, Class<T> clazz, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
final EntityInfo<T> info = loadEntityInfo(clazz);
final EntityCache<T> cache = info.getCache();
if (node == null && bean != null) node = loadFilterBeanNode(bean.getClass());
if (readcache && cache != null) {
if (node == null || node.isCacheUseable(this)) {
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);
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " cache query predicate = " + (node == null ? null : node.createPredicate(cache)));
Sheet<T> sheet = cache.querySheet(needtotal, selects, flipper, node);
if (!sheet.isEmpty() || info.isVirtualEntity() || cache.isFullLoaded()) return sheet;
}
}
@@ -1547,7 +1522,7 @@ public final class DataDefaultSource implements DataSource, Nameable, Function<C
final List<T> list = new ArrayList();
final Map<Class, String> joinTabalis = node == null ? null : node.getJoinTabalis();
final CharSequence join = node == null ? null : node.createSQLJoin(this, joinTabalis, info);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis, bean);
final CharSequence where = node == null ? null : node.createSQLExpress(info, joinTabalis);
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))

View File

@@ -104,12 +104,7 @@ public final class EntityCache<T> {
}
public T find(final SelectColumn selects, FilterNode node) {
return find(selects, node, null);
}
public T find(final SelectColumn selects, 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 Predicate<T> filter = node == null ? null : node.createPredicate(this);
Stream<T> stream = this.list.stream();
if (filter != null) stream = stream.filter(filter);
Optional<T> opt = stream.findFirst();
@@ -144,9 +139,8 @@ public final class EntityCache<T> {
return this.map.containsKey(id);
}
public boolean exists(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);
public boolean exists(FilterNode node) {
final Predicate<T> filter = node == null ? null : node.createPredicate(this);
Stream<T> stream = this.list.stream();
if (filter != null) stream = stream.filter(filter);
return stream.findFirst().isPresent();
@@ -156,14 +150,9 @@ public final class EntityCache<T> {
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) {
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());
public <K, V> Map<Serializable, Number> getMapResult(final String keyColumn, final Reckon reckon, final String reckonColumn, FilterNode node) {
final Attribute<T, Serializable> keyAttr = info.getAttribute(keyColumn);
final Predicate filter = node == null ? null : node.createPredicate(this, bean);
final Predicate filter = node == null ? null : node.createPredicate(this);
final Attribute reckonAttr = reckonColumn == null ? null : info.getAttribute(reckonColumn);
Stream<T> stream = this.list.stream();
if (filter != null) stream = stream.filter(filter);
@@ -210,14 +199,9 @@ public final class EntityCache<T> {
return rs;
}
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());
public <V> Number getNumberResult(final Reckon reckon, final String column, FilterNode node) {
final Attribute<T, Serializable> attr = column == null ? null : info.getAttribute(column);
final Predicate<T> filter = node == null ? null : node.createPredicate(this, bean);
final Predicate<T> filter = node == null ? null : node.createPredicate(this);
Stream<T> stream = this.list.stream();
if (filter != null) stream = stream.filter(filter);
switch (reckon) {
@@ -283,20 +267,11 @@ public final class EntityCache<T> {
}
public Sheet<T> querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node) {
return querySheet(selects, flipper, node, null);
return querySheet(true, selects, flipper, node);
}
public Sheet<T> querySheet(final SelectColumn selects, final Flipper flipper, final FilterNode node, final FilterBean bean) {
return querySheet(true, selects, flipper, node, bean);
}
public Sheet<T> querySheet(final boolean needtotal, final SelectColumn selects, final Flipper flipper, final FilterNode node) {
return querySheet(needtotal, selects, flipper, node, null);
}
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);
public Sheet<T> querySheet(final boolean needtotal, final SelectColumn selects, final Flipper flipper, FilterNode node) {
final Predicate<T> filter = node == null ? null : node.createPredicate(this);
final Comparator<T> comparator = createComparator(flipper);
long total = 0;
if (needtotal) {
@@ -358,7 +333,7 @@ public final class EntityCache<T> {
public Serializable[] delete(final FilterNode node) {
if (node == null || this.list.isEmpty()) return new Serializable[0];
Object[] rms = this.list.stream().filter(node.createPredicate(this, null)).toArray();
Object[] rms = this.list.stream().filter(node.createPredicate(this)).toArray();
Serializable[] ids = new Serializable[rms.length];
int i = -1;
for (Object o : rms) {

View File

@@ -1,387 +0,0 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.source;
import static com.wentch.redkale.source.FilterExpress.*;
import com.wentch.redkale.util.*;
import java.io.Serializable;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.*;
import java.util.logging.Logger;
import javax.persistence.Transient;
/**
*
* @author zhangjx
*/
@SuppressWarnings("unchecked")
final class FilterBeanNode extends FilterNode {
private static final Logger logger = Logger.getLogger(FilterBeanNode.class.getSimpleName());
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,
Function<Class, List> fullloader) {
FilterBeanNode rs = beanodes.get(clazz);
if (rs != null) return rs;
synchronized (beanodes) {
rs = beanodes.get(clazz);
if (rs == null) {
rs = createNode(clazz, nodeid, cacheForbidden, fullloader);
beanodes.put(clazz, rs);
}
return rs;
}
}
private static <T extends FilterBean> FilterBeanNode createNode(Class<T> clazz, final int nodeid, final boolean cacheForbidden,
Function<Class, List> fullloader) {
Class cltmp = clazz;
Set<String> fields = new HashSet<>();
final Map<Class, String> joinTables = new HashMap<>();
Map<String, FilterBeanNode> nodemap = new HashMap<>();
boolean joinallcached = true;
final StringBuilder joinsb = new StringBuilder();
do {
for (Field field : cltmp.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
if (fields.contains(field.getName())) continue;
if (field.getAnnotation(Ignore.class) != null) continue;
if (field.getAnnotation(Transient.class) != null) continue;
final boolean pubmod = Modifier.isPublic(field.getModifiers());
char[] chars = field.getName().toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
final Class t = field.getType();
Method getter = null;
try {
getter = cltmp.getMethod(((t == boolean.class || t == Boolean.class) ? "is" : "get") + new String(chars));
} catch (Exception ex) {
if (!pubmod) continue;
}
fields.add(field.getName());
FilterBeanNode newnode = new FilterBeanNode(field.getName(), true, pubmod ? Attribute.create(field) : Attribute.create(getter, null));
newnode.setField(field);
//------------------------------------
{
FilterJoinColumn joinCol = field.getAnnotation(FilterJoinColumn.class);
if (joinCol != null) {
boolean first = false;
final Class joinClass = joinCol.table();
if (!joinTables.containsKey(joinClass)) {
first = true;
joinTables.put(joinClass, String.valueOf((char) ('b' + joinTables.size())));
}
final String alias = joinTables.get(joinClass);
final EntityInfo secinfo = EntityInfo.load(joinClass, nodeid, cacheForbidden, fullloader);
if (secinfo.getCache() == null || !secinfo.getCache().isFullLoaded()) {
joinallcached = false;
}
final String jc = joinCol.column().isEmpty() ? secinfo.getPrimary().field() : joinCol.column();
if (first) {
joinsb.append(" INNER JOIN ").append(secinfo.getTable())
.append(" ").append(alias).append(" ON ").append(secinfo.getSQLColumn("a", jc)).append(" = ").append(secinfo.getSQLColumn(alias, jc));
}
newnode.foreignCache = secinfo.getCache();
newnode.tabalis = alias;
newnode.columnAttribute = secinfo.getAttribute(newnode.column);
newnode.byjoinColumn = jc;
newnode.foreignAttribute = secinfo.getAttribute(jc);
if (newnode.foreignCache != null && newnode.foreignAttribute == null) throw new RuntimeException(clazz.getName() + "." + field.getName() + " have illegal FilterJoinColumn " + joinCol);
}
}
//------------------------------------
{
FilterGroup[] refs = field.getAnnotationsByType(FilterGroup.class);
String[] groups = new String[refs.length];
for (int i = 0; i < refs.length; i++) {
groups[i] = refs[i].value();
}
if (groups.length == 0) groups = new String[]{"[AND]"};
for (String key : groups) {
if (!key.startsWith("[AND]") && !key.startsWith("[OR]")) {
throw new RuntimeException(field + "'s FilterGroup.value(" + key + ") illegal, must be [AND] or [OR] startsWith");
}
FilterBeanNode node = nodemap.get(key);
if (node == null) {
nodemap.put(key, newnode);
} else {
node.any(newnode, key.contains("[OR]"));
}
}
}
}
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
FilterBeanNode rs = null;
for (FilterBeanNode f : nodemap.values()) {
if (rs == null) {
rs = f;
} else {
rs.and(f);
}
}
if (rs != null) {
rs.joinallcached = joinallcached;
if (joinsb.length() > 0) rs.joinSQL = joinsb.toString();
}
return rs;
}
//--------------------------- only header -----------------------------------------------------
private boolean joinallcached = true;
private String joinSQL;
//---------------------------------------------------------------------------------------------
private Attribute beanAttribute;
private EntityCache foreignCache; // join 表
private String byjoinColumn; //被join表的join字段
private Attribute foreignAttribute; //join表的join字段
private Attribute columnAttribute;
private String tabalis;
private long least;
private boolean string;
private boolean number;
protected FilterBeanNode(String col, boolean sign, Attribute beanAttr) {
this.column = col;
this.or = sign;
this.beanAttribute = beanAttr;
}
private void setField(Field field) {
final FilterColumn fc = field.getAnnotation(FilterColumn.class);
if (fc != null && !fc.name().isEmpty()) this.column = fc.name();
final Class type = field.getType();
this.least = fc == null ? 1L : fc.least();
this.number = (type.isPrimitive() && type != boolean.class) || Number.class.isAssignableFrom(type);
this.string = CharSequence.class.isAssignableFrom(type);
FilterExpress exp = fc == null ? null : fc.express();
if (type.isArray() || Collection.class.isAssignableFrom(type)) {
if (Range.class.isAssignableFrom(type.getComponentType())) {
if (AND != exp) exp = OR;
} else if (NOTIN != exp) exp = IN;
} else if (Range.class.isAssignableFrom(type)) {
if (NOTBETWEEN != exp) exp = BETWEEN;
}
if (exp == null) exp = EQUAL;
this.express = exp;
this.tabalis = "a";
}
protected String getTabalis() {
return tabalis;
}
@Override
protected void append(FilterNode node, boolean sign) {
FilterBeanNode newnode = new FilterBeanNode(this.column, this.or, this.beanAttribute);
newnode.express = this.express;
newnode.nodes = this.nodes;
newnode.foreignCache = this.foreignCache;
newnode.byjoinColumn = this.byjoinColumn;
newnode.foreignAttribute = this.foreignAttribute;
newnode.columnAttribute = this.columnAttribute;
newnode.least = this.least;
newnode.number = this.number;
newnode.string = this.string;
this.nodes = new FilterNode[]{newnode};
this.column = node.column;
this.express = node.express;
this.or = sign;
this.setValue(node.getValue());
if (node instanceof FilterBeanNode) {
FilterBeanNode beanNode = ((FilterBeanNode) node);
this.beanAttribute = beanNode.beanAttribute;
this.foreignCache = beanNode.foreignCache;
this.byjoinColumn = beanNode.byjoinColumn;
this.foreignAttribute = beanNode.foreignAttribute;
this.columnAttribute = beanNode.columnAttribute;
this.least = beanNode.least;
this.number = beanNode.number;
this.string = beanNode.string;
}
}
@Override
protected <T> CharSequence createSQLJoin(final Function<Class, EntityInfo> func, final Map<Class, String> joinTabalis, final EntityInfo<T> info) {
if (joinSQL == null) return null;
return joinSQL;
}
@Override
protected <T, E> Predicate<T> createPredicate(final EntityCache<T> cache, FilterBean bean) {
if (this.foreignCache == null) return super.createPredicate(cache, bean);
final Map<EntityCache, Predicate> foreign = new HashMap<>();
Predicate<T> result = null;
putForeignPredicate(cache, foreign, bean);
if (this.nodes != null) {
for (FilterNode n : this.nodes) {
FilterBeanNode node = (FilterBeanNode) n;
if (node.foreignCache == null) {
Predicate<T> f = node.createPredicate(cache, bean);
if (f == null) continue;
final Predicate<T> one = result;
final Predicate<T> two = f;
result = (result == null) ? f : (or ? new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) || two.test(t);
}
@Override
public String toString() {
return "(" + one + " OR " + two + ")";
}
} : new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) && two.test(t);
}
@Override
public String toString() {
return "(" + one + " AND " + two + ")";
}
});
} else {
putForeignPredicate(cache, foreign, bean);
}
}
}
if (foreign.isEmpty()) return result;
final String byjoinCol = this.byjoinColumn;
final Attribute foreignAttr = this.foreignAttribute;
for (final Map.Entry<EntityCache, Predicate> en : foreign.entrySet()) {
Attribute<T, Serializable> byjoinAttr = cache.getAttribute(byjoinCol);
final Predicate p = en.getValue();
final EntityCache joinCache = en.getKey();
Predicate<T> f = new Predicate<T>() {
@Override
public boolean test(T t) {
Serializable key = byjoinAttr.get(t);
Predicate k = (e) -> key.equals(foreignAttr.get(e));
return joinCache.exists(k.and(p));
}
@Override
public String toString() {
return "(" + byjoinAttr.field() + " = " + en.getKey().getType().getSimpleName() + "." + foreignAttr.field() + " AND " + p + ")";
}
};
final Predicate<T> one = result;
final Predicate<T> two = f;
result = (result == null) ? f : (or ? new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) || two.test(t);
}
@Override
public String toString() {
return "(" + one + " OR " + two + ")";
}
} : new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) && two.test(t);
}
@Override
public String toString() {
return "(" + one + " AND " + two + ")";
}
});
}
return result;
}
private <T> void putForeignPredicate(final EntityCache<T> cache, final Map<EntityCache, Predicate> foreign, FilterBean bean) {
if (this.foreignCache == null) return;
final Serializable val = getElementValue(bean);
Predicate filter = (val == null && express != ISNULL && express != ISNOTNULL) ? new Predicate<T>() {
@Override
public boolean test(T t) {
return or;
}
@Override
public String toString() {
return "" + or;
}
} : super.createElementPredicate(cache, false, this.columnAttribute, bean);
if (filter == null) return;
Predicate p = foreign.get(this.foreignCache);
if (p == null) {
foreign.put(foreignCache, filter);
} else {
final Predicate<T> one = p;
final Predicate<T> two = filter;
p = or ? new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) || two.test(t);
}
@Override
public String toString() {
return "(" + one + " OR " + two + ")";
}
} : new Predicate<T>() {
@Override
public boolean test(T t) {
return one.test(t) && two.test(t);
}
@Override
public String toString() {
return "(" + one + " AND " + two + ")";
}
};
foreign.put(foreignCache, p);
}
}
@Override
protected boolean isCacheUseable(final Function<Class, EntityInfo> entityApplyer) {
return joinallcached;
}
@Override
protected Serializable getElementValue(FilterBean bean) {
if (bean == null || beanAttribute == null) return null;
Serializable rs = (Serializable) beanAttribute.get(bean);
if (rs == null) return null;
if (string && ((CharSequence) rs).length() == 0) return null;
if (number && ((Number) rs).longValue() < this.least) return null;
return rs;
}
}

View File

@@ -56,15 +56,21 @@ public class FilterJoinNode extends FilterNode {
}
@Override
protected <T> CharSequence createSQLExpress(final EntityInfo<T> info, final Map<Class, String> joinTabalis, final FilterBean bean) {
return super.createSQLExpress(this.joinEntity, joinTabalis, bean);
protected void check(FilterNode node) {
Objects.requireNonNull(node);
if (!(node instanceof FilterJoinNode)) throw new IllegalArgumentException(this + " check " + String.valueOf(node) + "is not a " + FilterJoinNode.class.getSimpleName());
}
@Override
protected <T, E> Predicate<T> createPredicate(final EntityCache<T> cache, final FilterBean bean) {
protected <T> CharSequence createSQLExpress(final EntityInfo<T> info, final Map<Class, String> joinTabalis) {
return super.createSQLExpress(this.joinEntity, joinTabalis);
}
@Override
protected <T, E> Predicate<T> createPredicate(final EntityCache<T> cache) {
if (column == null && this.nodes == null) return null;
final EntityCache<E> joinCache = this.joinEntity.getCache();
Predicate<E> filter = createChildPredicate(bean);
Predicate<E> filter = createChildPredicate();
if (filter == null) return null;
final Predicate<E> inner = filter;
@@ -95,13 +101,13 @@ public class FilterJoinNode extends FilterNode {
};
}
private <E> Predicate<E> createChildPredicate(final FilterBean bean) {
private <E> Predicate<E> createChildPredicate() {
if (column == null && this.nodes == null) return null;
final EntityCache<E> joinCache = this.joinEntity.getCache();
Predicate<E> filter = createElementPredicate(joinCache, true, bean);
Predicate<E> filter = createElementPredicate(joinCache, true);
if (this.nodes != null) {
for (FilterNode node : this.nodes) {
Predicate<E> f = ((FilterJoinNode) node).createChildPredicate(bean);
Predicate<E> f = ((FilterJoinNode) node).createChildPredicate();
if (f == null) continue;
final Predicate<E> one = filter;
final Predicate<E> two = f;
@@ -181,13 +187,7 @@ public class FilterJoinNode extends FilterNode {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("#-- ON ").append(joinColumns[0]).append(" = ").append(joinClass == null ? "null" : joinClass.getSimpleName()).append('.').append(joinColumns[0]);
for (int i = 1; i < joinColumns.length; i++) {
sb.append(" AND ").append(joinColumns[i]).append(" = ").append(joinClass == null ? "null" : joinClass.getSimpleName()).append('.').append(joinColumns[i]);
}
sb.append(" --# ").append(toString(joinClass == null ? null : joinClass.getSimpleName(), null));
return sb.toString();
return toString(joinClass == null ? null : joinClass.getSimpleName()).toString();
}
public Class getJoinClass() {

View File

@@ -77,7 +77,7 @@ public class FilterNode {
return or(new FilterNode(column, express, value));
}
protected final FilterNode any(FilterNode node, boolean sign) {
protected final FilterNode any(FilterNode node, boolean signor) {
Objects.requireNonNull(node);
if (this.column == null) {
this.column = node.column;
@@ -87,17 +87,24 @@ public class FilterNode {
}
if (this.nodes == null) {
this.nodes = new FilterNode[]{node};
this.or = sign;
this.or = signor;
return this;
}
if (or == sign) {
if (or == signor) {
FilterNode[] newsiblings = new FilterNode[nodes.length + 1];
System.arraycopy(nodes, 0, newsiblings, 0, nodes.length);
newsiblings[nodes.length] = node;
this.nodes = newsiblings;
return this;
}
this.append(node, sign);
FilterNode newnode = new FilterNode(this.column, this.express, this.value);
newnode.or = this.or;
newnode.nodes = this.nodes;
this.nodes = new FilterNode[]{newnode, node};
this.column = null;
this.express = null;
this.or = signor;
this.value = null;
return this;
}
@@ -105,27 +112,9 @@ public class FilterNode {
* 该方法需要重载
*
* @param node
* @param sign
*/
protected void append(FilterNode node, boolean sign) {
FilterNode newnode = new FilterNode(this.column, this.express, this.value);
newnode.or = this.or;
newnode.nodes = this.nodes;
this.nodes = new FilterNode[]{newnode, node};
this.column = null;
this.express = null;
this.or = sign;
this.value = null;
}
/**
* 该方法需要重载
*
* @param bean
* @return
*/
protected Serializable getElementValue(final FilterBean bean) {
return value;
protected void check(FilterNode node) {
Objects.requireNonNull(node);
}
/**
@@ -199,8 +188,8 @@ public class FilterNode {
* @param bean
* @return
*/
protected <T> CharSequence createSQLExpress(final EntityInfo<T> info, final Map<Class, String> joinTabalis, final FilterBean bean) {
CharSequence sb0 = createElementSQLExpress(info, joinTabalis == null ? null : joinTabalis.get(info.getType()), bean);
protected <T> CharSequence createSQLExpress(final EntityInfo<T> info, final Map<Class, String> joinTabalis) {
CharSequence sb0 = createElementSQLExpress(info, joinTabalis == null ? null : joinTabalis.get(info.getType()));
if (this.nodes == null) return sb0;
final StringBuilder rs = new StringBuilder();
rs.append('(');
@@ -210,7 +199,7 @@ public class FilterNode {
rs.append(sb0);
}
for (FilterNode node : this.nodes) {
CharSequence f = node.createSQLExpress(info, joinTabalis, bean);
CharSequence f = node.createSQLExpress(info, joinTabalis);
if (f == null || f.length() < 3) continue;
if (more) rs.append(or ? " OR " : " AND ");
rs.append(f);
@@ -229,13 +218,13 @@ public class FilterNode {
return new FilterNode(column, express, value);
}
protected final <T> CharSequence createElementSQLExpress(final EntityInfo<T> info, String talis, final FilterBean bean) {
protected final <T> CharSequence createElementSQLExpress(final EntityInfo<T> info, String talis) {
if (column == null) return null;
if (talis == null) talis = "a";
if (express == ISNULL || express == ISNOTNULL) {
return new StringBuilder().append(info.getSQLColumn(talis, column)).append(' ').append(express.value());
}
final CharSequence val = formatToString(express, getElementValue(bean));
final CharSequence val = formatToString(express, getValue());
if (val == null) return null;
StringBuilder sb = new StringBuilder(32);
if (express == IGNORECASELIKE || express == IGNORECASENOTLIKE) {
@@ -259,12 +248,12 @@ public class FilterNode {
return sb;
}
protected <T, E> Predicate<T> createPredicate(final EntityCache<T> cache, final FilterBean bean) {
protected <T, E> Predicate<T> createPredicate(final EntityCache<T> cache) {
if (cache == null || (column == null && this.nodes == null)) return null;
Predicate<T> filter = createElementPredicate(cache, false, bean);
Predicate<T> filter = createElementPredicate(cache, false);
if (this.nodes == null) return filter;
for (FilterNode node : this.nodes) {
Predicate<T> f = node.createPredicate(cache, bean);
Predicate<T> f = node.createPredicate(cache);
if (f == null) continue;
final Predicate<T> one = filter;
final Predicate<T> two = f;
@@ -295,12 +284,12 @@ public class FilterNode {
return filter;
}
protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final boolean join, final FilterBean bean) {
protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final boolean join) {
if (column == null) return null;
return createElementPredicate(cache, join, cache.getAttribute(column), bean);
return createElementPredicate(cache, join, cache.getAttribute(column));
}
protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final boolean join, final Attribute<T, Serializable> attr, final FilterBean bean) {
protected final <T> Predicate<T> createElementPredicate(final EntityCache<T> cache, final boolean join, final Attribute<T, Serializable> attr) {
if (attr == null) return null;
final String field = join ? (cache.getType().getSimpleName() + "." + attr.field()) : attr.field();
if (express == ISNULL) return new Predicate<T>() {
@@ -328,7 +317,7 @@ public class FilterNode {
}
};
if (attr == null) return null;
Serializable val0 = getElementValue(bean);
Serializable val0 = getValue();
if (val0 == null) return null;
final Class atype = attr.type();
@@ -833,43 +822,39 @@ public class FilterNode {
@Override
public String toString() {
return toString(null, null);
return toString(null).toString();
}
protected String toString(final String prefix, final FilterBean bean) {
protected StringBuilder toString(final String prefix) {
StringBuilder sb = new StringBuilder();
if (nodes == null) {
if (column != null) {
String col = prefix == null ? column : (prefix + "." + column);
Serializable ev = getElementValue(bean);
if (express == ISNULL || express == ISNOTNULL) {
sb.append(col).append(' ').append(express.value());
} else if (ev != null) {
sb.append((express == IGNORECASELIKE || express == IGNORECASENOTLIKE) ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(' ').append(formatToString(express, ev));
}
}
} else {
boolean more = false;
if (column != null) {
String col = prefix == null ? column : (prefix + "." + column);
Serializable ev = getElementValue(bean);
if (express == ISNULL || express == ISNOTNULL) {
sb.append('(').append(col).append(' ').append(express.value());
more = true;
} else if (ev != null) {
sb.append('(').append((express == IGNORECASELIKE || express == IGNORECASENOTLIKE) ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(' ').append(formatToString(express, ev));
more = true;
}
}
StringBuilder element = toElementString(prefix);
boolean more = element.length() > 0 && this.nodes != null;
if (more) sb.append('(');
sb.append(element);
if (this.nodes != null) {
for (FilterNode node : this.nodes) {
String s = node.toString();
if (s.isEmpty()) continue;
if (sb.length() > 0) sb.append(or ? " OR " : " AND ");
if (s.length() < 1) continue;
if (sb.length() > 1) sb.append(or ? " OR " : " AND ");
sb.append(s);
}
if (more) sb.append(')');
}
return sb.toString();
if (more) sb.append(')');
return sb;
}
protected final StringBuilder toElementString(final String prefix) {
StringBuilder sb = new StringBuilder();
if (column != null) {
String col = prefix == null ? column : (prefix + "." + column);
Serializable ev = getValue();
if (express == ISNULL || express == ISNOTNULL) {
sb.append(col).append(' ').append(express.value());
} else if (ev != null) {
sb.append((express == IGNORECASELIKE || express == IGNORECASENOTLIKE) ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(' ').append(formatToString(express, ev));
}
}
return sb;
}
protected static CharSequence formatToString(Object value) {

View File

@@ -0,0 +1,351 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.wentch.redkale.source;
import static com.wentch.redkale.source.FilterExpress.*;
import com.wentch.redkale.util.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import javax.persistence.*;
/**
*
* @author zhangjx
*/
public final class FilterNodeBean<T> implements Comparable<FilterNodeBean<T>> {
private static final ConcurrentHashMap<Class, FilterNodeBean> beanodes = new ConcurrentHashMap<>();
private Attribute<T, Serializable> beanAttr;
private String column;
private FilterExpress express;
private boolean or;
private FilterNodeBean[] nodeBeans;
//-----------------join table--------------------------
private Class joinClass;
private String[] joinColumns;
//----------------------------------------------------
private long least;
private boolean string;
private boolean number;
public FilterNodeBean(FilterNodeBean bean) {
this.beanAttr = bean.beanAttr;
this.column = bean.column;
this.express = bean.express;
this.joinClass = bean.joinClass;
this.joinColumns = bean.joinColumns;
this.least = bean.least;
this.string = bean.string;
this.number = bean.number;
this.or = bean.or;
this.nodeBeans = bean.nodeBeans;
}
private FilterNodeBean(final FilterJoinColumn joinCol, final FilterColumn filterCol, final Attribute<T, Serializable> attr) {
this.beanAttr = attr;
this.joinClass = joinCol == null ? null : joinCol.table();
this.joinColumns = joinCol == null ? null : (joinCol.columns().length == 0 ? new String[]{joinCol.column()} : joinCol.columns());
final Class type = attr.type();
this.column = (filterCol != null && !filterCol.name().isEmpty()) ? filterCol.name() : attr.field();
FilterExpress exp = filterCol == null ? null : filterCol.express();
if (type.isArray() || Collection.class.isAssignableFrom(type)) {
if (Range.class.isAssignableFrom(type.getComponentType())) {
if (AND != exp) exp = OR;
} else if (NOTIN != exp) exp = IN;
} else if (Range.class.isAssignableFrom(type)) {
if (NOTBETWEEN != exp) exp = BETWEEN;
}
if (exp == null) exp = EQUAL;
this.express = exp;
this.least = filterCol == null ? 1 : filterCol.least();
this.number = (type.isPrimitive() && type != boolean.class) || Number.class.isAssignableFrom(type);
this.string = CharSequence.class.isAssignableFrom(type);
}
private FilterNodeBean or(FilterNodeBean node) {
return any(node, true);
}
private FilterNodeBean and(FilterNodeBean node) {
return any(node, false);
}
private FilterNodeBean any(FilterNodeBean node, boolean signor) {
Objects.requireNonNull(node);
if (this.column == null) {
this.beanAttr = node.beanAttr;
this.column = node.column;
this.express = node.express;
this.joinClass = node.joinClass;
this.joinColumns = node.joinColumns;
this.least = node.least;
this.string = node.string;
this.number = node.number;
return this;
}
if (this.nodeBeans == null) {
this.nodeBeans = new FilterNodeBean[]{node};
this.or = signor;
return this;
}
if (or == signor) {
FilterNodeBean[] newsiblings = new FilterNodeBean[nodeBeans.length + 1];
System.arraycopy(nodeBeans, 0, newsiblings, 0, nodeBeans.length);
newsiblings[nodeBeans.length] = node;
this.nodeBeans = newsiblings;
return this;
}
this.nodeBeans = new FilterNodeBean[]{new FilterNodeBean(this), node};
this.column = null;
this.or = signor;
return this;
}
public static FilterNode createFilterNode(final FilterBean bean) {
if (bean == null) return null;
return load(bean.getClass()).create(bean);
}
private FilterNode create(final T bean) {
if (bean == null) return null;
FilterNode node = null;
final Serializable val = beanAttr.get(bean);
if (column != null && val != null) {
boolean skip = false;
if (string && ((CharSequence) val).length() == 0) {
skip = true;
} else if (number && ((Number) val).longValue() < least) {
skip = true;
}
if (!skip) {
if (this.joinClass == null) {
node = FilterNode.create(column, express, val);
} else {
node = FilterJoinNode.create(joinClass, joinColumns, column, express, val);
}
}
}
if (this.nodeBeans == null) return node;
for (final FilterNodeBean fnb : this.nodeBeans) {
FilterNode n = fnb.create(bean);
if (n == null) continue;
node = node == null ? n : ((!(n instanceof FilterJoinNode)) ? n.any(node, or) : node.any(n, or));
}
return node;
}
private static <T extends FilterBean> FilterNodeBean createFilterNodeBean(final Class<T> clazz) {
final Set<String> fields = new HashSet<>();
final Map<String, FilterNodeBean> nodemap = new LinkedHashMap();
Class cltmp = clazz;
do {
for (final Field field : cltmp.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())) continue;
if (fields.contains(field.getName())) continue;
if (field.getAnnotation(Ignore.class) != null) continue;
if (field.getAnnotation(Transient.class) != null) continue;
final boolean pubmod = Modifier.isPublic(field.getModifiers());
char[] chars = field.getName().toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
final Class t = field.getType();
Method getter = null;
try {
getter = cltmp.getMethod(((t == boolean.class || t == Boolean.class) ? "is" : "get") + new String(chars));
} catch (Exception ex) {
if (!pubmod) continue;
}
fields.add(field.getName());
final Attribute<T, Serializable> beanAttr = pubmod ? Attribute.create(field) : Attribute.create(getter, null);
FilterNodeBean<T> nodeBean = new FilterNodeBean(field.getAnnotation(FilterJoinColumn.class), field.getAnnotation(FilterColumn.class), beanAttr);
//------------------------------------
{
FilterGroup[] refs = field.getAnnotationsByType(FilterGroup.class);
String[] groups = new String[refs.length];
for (int i = 0; i < refs.length; i++) {
groups[i] = refs[i].value();
}
if (groups.length == 0) groups = new String[]{"[AND]"};
for (String key : groups) {
if (!key.startsWith("[AND]") && !key.startsWith("[OR]")) {
throw new RuntimeException(field + "'s FilterGroup.value(" + key + ") illegal, must be [AND] or [OR] startsWith");
}
FilterNodeBean node = nodemap.get(key);
if (node == null) {
nodemap.put(key, nodeBean);
} else {
node.any(nodeBean, key.substring(key.lastIndexOf('.') + 1).contains("[OR]"));
}
}
}
}
} while ((cltmp = cltmp.getSuperclass()) != Object.class);
final Map<String, LinkNode> linkes = new LinkedHashMap<>();
nodemap.forEach((k, v) -> {
String[] keys = k.split("\\.");
LinkNode link = linkes.get(keys[0]);
if (link == null) {
linkes.put(keys[0], new LinkNode(k, v));
} else {
link.put(keys, 0, v);
}
});
FilterNodeBean rs = null;
for (LinkNode link : linkes.values()) {
FilterNodeBean f = link.createFilterNodeBean();
if (f == null) continue;
rs = rs == null ? f : rs.and(f);
}
if (rs.nodeBeans != null) Arrays.sort(rs.nodeBeans);
return rs;
}
@Override
public int compareTo(FilterNodeBean<T> o) {
if (this.joinClass == null && o.joinClass == null) return 0;
if (this.joinClass != null && o.joinClass != null) return 0;
return this.joinClass == null ? -1 : 1;
}
private static class LinkNode {
public final boolean or;
public final String key;
public final List<FilterNodeBean> beans = new ArrayList<>();
public final Map<String, LinkNode> nexts = new LinkedHashMap<>();
public LinkNode(String keyString, FilterNodeBean node) {
String[] keys = keyString.split("\\.");
this.key = keys[0];
this.or = this.key.contains("[OR]");
put(keys, 0, node);
}
public LinkNode(String[] keyStrings, int pos, FilterNodeBean node) {
this.key = keyStrings[pos];
this.or = this.key.contains("[OR]");
put(keyStrings, pos, node);
}
public FilterNodeBean createFilterNodeBean() {
FilterNodeBean node = null;
for (FilterNodeBean bean : beans) {
node = node == null ? bean : node.any(bean, or);
}
for (LinkNode link : nexts.values()) {
FilterNodeBean f = link.createFilterNodeBean();
if (f == null) continue;
node = node == null ? f : node.any(f, or);
}
return node;
}
public final void put(final String[] keys, int pos, final FilterNodeBean node) {
if (keys.length == pos + 1 && this.key.equals(keys[pos])) {
this.beans.add(node);
return;
}
LinkNode link = nexts.get(keys[pos + 1]);
if (link == null) {
nexts.put(keys[pos + 1], new LinkNode(keys, pos + 1, node));
} else {
link.put(keys, pos + 1, node);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{key = '").append(key).append("', or = ").append(or);
if (!beans.isEmpty()) {
sb.append(", beans = [\r\n");
for (FilterNodeBean bean : this.beans) {
sb.append(" ").append(bean).append("\r\n");
}
sb.append("]");
}
if (!nexts.isEmpty()) {
sb.append(", nexts = [\r\n");
for (LinkNode link : this.nexts.values()) {
sb.append(" ").append(link).append("\r\n");
}
sb.append("]");
}
sb.append("}");
return sb.toString();
}
}
private static FilterNodeBean load(Class<? extends FilterBean> clazz) {
FilterNodeBean rs = beanodes.get(clazz);
if (rs != null) return rs;
synchronized (beanodes) {
rs = beanodes.get(clazz);
if (rs == null) {
rs = createFilterNodeBean(clazz);
beanodes.put(clazz, rs);
}
return rs;
}
}
@Override
public String toString() {
return toString(joinClass == null ? null : joinClass.getSimpleName()).toString();
}
protected StringBuilder toString(final String prefix) {
StringBuilder sb = new StringBuilder();
StringBuilder element = toElementString(prefix);
boolean more = element.length() > 0 && this.nodeBeans != null;
if (more) sb.append('(');
sb.append(element);
if (this.nodeBeans != null) {
for (FilterNodeBean node : this.nodeBeans) {
String s = node.toString();
if (s.length() < 1) continue;
if (sb.length() > 1) sb.append(or ? " OR " : " AND ");
sb.append(s);
}
}
if (more) sb.append(')');
return sb;
}
protected final StringBuilder toElementString(final String prefix) {
StringBuilder sb = new StringBuilder();
if (column != null) {
String col = prefix == null ? column : (prefix + "." + column);
if (express == ISNULL || express == ISNOTNULL) {
sb.append(col).append(' ').append(express.value());
} else {
sb.append((express == IGNORECASELIKE || express == IGNORECASENOTLIKE) ? ("LOWER(" + col + ')') : col).append(' ').append(express.value()).append(" ?");
}
}
return sb;
}
}