This commit is contained in:
@@ -1407,6 +1407,7 @@ public final class DataDefaultSource implements DataSource, Nameable {
|
|||||||
if (readcache && cache != null) {
|
if (readcache && cache != null) {
|
||||||
Predicate<T> filter = node == null ? null : node.createFilterPredicate(info, bean);
|
Predicate<T> filter = node == null ? null : node.createFilterPredicate(info, bean);
|
||||||
if (node == null || node.isJoinAllCached()) {
|
if (node == null || node.isJoinAllCached()) {
|
||||||
|
if (debug.get() && info.isLoggable(Level.FINEST)) logger.finest(clazz.getSimpleName() + " cache query predicate = " + filter);
|
||||||
Sheet<T> sheet = cache.querySheet(selects, filter, flipper, FilterNode.createFilterComparator(info, flipper));
|
Sheet<T> sheet = cache.querySheet(selects, filter, flipper, FilterNode.createFilterComparator(info, flipper));
|
||||||
if (!sheet.isEmpty() || info.isVirtualEntity() || cache.isFullLoaded()) return sheet;
|
if (!sheet.isEmpty() || info.isVirtualEntity() || cache.isFullLoaded()) return sheet;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -238,7 +238,8 @@ final class FilterBeanNode extends FilterNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private <T> Predicate<T> createFilterPredicate(final boolean first, final EntityInfo<T> info, FilterBean bean) {
|
private <T> Predicate<T> createFilterPredicate(final boolean first, final EntityInfo<T> info, FilterBean bean) {
|
||||||
if ((this.joinSQL == null && first) || this.foreignEntity == null) return super.createFilterPredicate(info, bean);
|
//if ((this.joinSQL == null && first) || this.foreignEntity == null) return super.createFilterPredicate(info, 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(foreign, bean);
|
||||||
@@ -248,7 +249,31 @@ final class FilterBeanNode extends FilterNode {
|
|||||||
if (node.foreignEntity == null) {
|
if (node.foreignEntity == null) {
|
||||||
Predicate<T> f = node.createFilterPredicate(false, info, bean);
|
Predicate<T> f = node.createFilterPredicate(false, info, bean);
|
||||||
if (f == null) continue;
|
if (f == null) continue;
|
||||||
result = (result == null) ? f : (signand ? result.and(f) : result.or(f));
|
final Predicate<T> one = result;
|
||||||
|
final Predicate<T> two = f;
|
||||||
|
result = (result == null) ? f : (signand ? new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return one.test(t) && two.test(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + one + " AND " + two + ")";
|
||||||
|
}
|
||||||
|
} : new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return one.test(t) || two.test(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + one + " OR " + two + ")";
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
putForeignPredicate(foreign, bean);
|
putForeignPredicate(foreign, bean);
|
||||||
}
|
}
|
||||||
@@ -256,16 +281,49 @@ final class FilterBeanNode extends FilterNode {
|
|||||||
}
|
}
|
||||||
if (foreign.isEmpty()) return result;
|
if (foreign.isEmpty()) return result;
|
||||||
final Attribute foreignAttr = this.foreignAttribute;
|
final Attribute foreignAttr = this.foreignAttribute;
|
||||||
for (Map.Entry<EntityInfo, Predicate> en : foreign.entrySet()) {
|
for (final Map.Entry<EntityInfo, Predicate> en : foreign.entrySet()) {
|
||||||
Attribute<T, Serializable> mainIdAttr = info.getPrimary();
|
Attribute<T, Serializable> mainIdAttr = info.getPrimary();
|
||||||
final EntityCache cache = en.getKey().getCache();
|
final EntityCache cache = en.getKey().getCache();
|
||||||
final Predicate p = en.getValue();
|
final Predicate p = en.getValue();
|
||||||
Predicate<T> f = (T t) -> {
|
Predicate<T> f = new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Serializable key = mainIdAttr.get(t);
|
Serializable key = mainIdAttr.get(t);
|
||||||
Predicate k = (e) -> key.equals(foreignAttr.get(e));
|
Predicate k = (e) -> key.equals(foreignAttr.get(e));
|
||||||
return cache.exists(k.and(p));
|
return cache.exists(k.and(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + mainIdAttr.field() + " = " + en.getKey().getType().getSimpleName() + "." + foreignAttr.field() + " AND " + p + ")";
|
||||||
|
}
|
||||||
};
|
};
|
||||||
result = (result == null) ? f : (signand ? result.and(f) : result.or(f));
|
final Predicate<T> one = result;
|
||||||
|
final Predicate<T> two = f;
|
||||||
|
result = (result == null) ? f : (signand ? new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return one.test(t) && two.test(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + one + " AND " + two + ")";
|
||||||
|
}
|
||||||
|
} : new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return one.test(t) || two.test(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + one + " OR " + two + ")";
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,7 +227,31 @@ public class FilterNode {
|
|||||||
for (FilterNode node : this.nodes) {
|
for (FilterNode node : this.nodes) {
|
||||||
Predicate<T> f = node.createFilterPredicate(info, bean);
|
Predicate<T> f = node.createFilterPredicate(info, bean);
|
||||||
if (f == null) continue;
|
if (f == null) continue;
|
||||||
filter = (filter == null) ? f : (signand ? filter.and(f) : filter.or(f));
|
final Predicate<T> one = filter;
|
||||||
|
final Predicate<T> two = f;
|
||||||
|
filter = (filter == null) ? f : (signand ? new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return one.test(t) && two.test(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + one + " AND " + two + ")";
|
||||||
|
}
|
||||||
|
} : new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return one.test(t) || two.test(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + one + " OR " + two + ")";
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
@@ -252,88 +276,327 @@ public class FilterNode {
|
|||||||
}
|
}
|
||||||
final Serializable val = val0;
|
final Serializable val = val0;
|
||||||
switch (express) {
|
switch (express) {
|
||||||
case EQUAL: return (T t) -> val.equals(attr.get(t));
|
case EQUAL: return new Predicate<T>() {
|
||||||
case NOTEQUAL: return (T t) -> !val.equals(attr.get(t));
|
|
||||||
case GREATERTHAN: return (T t) -> ((Number) attr.get(t)).longValue() > ((Number) val).longValue();
|
@Override
|
||||||
case LESSTHAN: return (T t) -> ((Number) attr.get(t)).longValue() < ((Number) val).longValue();
|
public boolean test(T t) {
|
||||||
case GREATERTHANOREQUALTO: return (T t) -> ((Number) attr.get(t)).longValue() >= ((Number) val).longValue();
|
return val.equals(attr.get(t));
|
||||||
case LESSTHANOREQUALTO: return (T t) -> ((Number) attr.get(t)).longValue() <= ((Number) val).longValue();
|
}
|
||||||
case ISNULL: return (T t) -> attr.get(t) == null;
|
|
||||||
case ISNOTNULL: return (T t) -> attr.get(t) != null;
|
@Override
|
||||||
case OPAND: return (T t) -> (((Number) attr.get(t)).longValue() & ((Number) val).longValue()) > 0;
|
public String toString() {
|
||||||
case OPOR: return (T t) -> (((Number) attr.get(t)).longValue() | ((Number) val).longValue()) > 0;
|
return attr.field() + ' ' + express.value() + ' ' + val;
|
||||||
case OPANDNO: return (T t) -> (((Number) attr.get(t)).longValue() & ((Number) val).longValue()) == 0;
|
}
|
||||||
|
};
|
||||||
|
case NOTEQUAL: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return !val.equals(attr.get(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
case GREATERTHAN: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return ((Number) attr.get(t)).longValue() > ((Number) val).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
case LESSTHAN: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return ((Number) attr.get(t)).longValue() < ((Number) val).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
case GREATERTHANOREQUALTO: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return ((Number) attr.get(t)).longValue() >= ((Number) val).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
case LESSTHANOREQUALTO: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return ((Number) attr.get(t)).longValue() <= ((Number) val).longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + val;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
case ISNULL: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return attr.get(t) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + " = null";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
case ISNOTNULL: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return attr.get(t) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + " != null";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
case OPAND: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return (((Number) attr.get(t)).longValue() & ((Number) val).longValue()) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + " & " + val + " > 0";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
case OPOR: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return (((Number) attr.get(t)).longValue() | ((Number) val).longValue()) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + " | " + val + " > 0";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
case OPANDNO: return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return (((Number) attr.get(t)).longValue() & ((Number) val).longValue()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + " & " + val + " = 0";
|
||||||
|
}
|
||||||
|
};
|
||||||
case LIKE:
|
case LIKE:
|
||||||
return (T t) -> {
|
return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Object rs = attr.get(t);
|
Object rs = attr.get(t);
|
||||||
return rs != null && rs.toString().contains(val.toString());
|
return rs != null && rs.toString().contains(val.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + val;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
case NOTLIKE:
|
case NOTLIKE:
|
||||||
return (T t) -> {
|
return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Object rs = attr.get(t);
|
Object rs = attr.get(t);
|
||||||
return rs == null || !rs.toString().contains(val.toString());
|
return rs == null || !rs.toString().contains(val.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + val;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
case BETWEEN:
|
case BETWEEN:
|
||||||
case NOTBETWEEN:
|
case NOTBETWEEN:
|
||||||
Range range = (Range) val;
|
Range range = (Range) val;
|
||||||
final Comparable min = range.getMin();
|
final Comparable min = range.getMin();
|
||||||
final Comparable max = range.getMax();
|
final Comparable max = range.getMax();
|
||||||
Predicate<T> p = (T t) -> {
|
if (express == BETWEEN) return new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Comparable rs = (Comparable) attr.get(t);
|
Comparable rs = (Comparable) attr.get(t);
|
||||||
if (rs == null) return false;
|
if (rs == null) return false;
|
||||||
if (min != null && min.compareTo(rs) >= 0) return false;
|
if (min != null && min.compareTo(rs) >= 0) return false;
|
||||||
return !(max != null && max.compareTo(rs) <= 0);
|
return !(max != null && max.compareTo(rs) <= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + " BETWEEN " + min + " AND " + max;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if (express == NOTBETWEEN) p = p.negate();
|
if (express == NOTBETWEEN) return new Predicate<T>() {
|
||||||
return p;
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
Comparable rs = (Comparable) attr.get(t);
|
||||||
|
if (rs == null) return true;
|
||||||
|
if (min != null && min.compareTo(rs) >= 0) return true;
|
||||||
|
return (max != null && max.compareTo(rs) <= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + " NOT BETWEEN " + min + " AND " + max;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return null;
|
||||||
case IN:
|
case IN:
|
||||||
case NOTIN:
|
case NOTIN:
|
||||||
Predicate<T> filter;
|
Predicate<T> filter;
|
||||||
if (val instanceof Collection) {
|
if (val instanceof Collection) {
|
||||||
filter = (T t) -> {
|
filter = new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Object rs = attr.get(t);
|
Object rs = attr.get(t);
|
||||||
return rs != null && ((Collection) val).contains(rs);
|
return rs != null && ((Collection) val).contains(rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + val;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
Class type = val.getClass();
|
Class type = val.getClass();
|
||||||
if (type == int[].class) {
|
if (type == int[].class) {
|
||||||
filter = (T t) -> {
|
filter = new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Object rs = attr.get(t);
|
Object rs = attr.get(t);
|
||||||
if (rs == null) return false;
|
if (rs == null) return false;
|
||||||
return Arrays.binarySearch((int[]) val, (int) rs) >= 0;
|
return Arrays.binarySearch((int[]) val, (int) rs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + Arrays.toString((int[]) val);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else if (type == short[].class) {
|
} else if (type == short[].class) {
|
||||||
filter = (T t) -> {
|
filter = new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Object rs = attr.get(t);
|
Object rs = attr.get(t);
|
||||||
if (rs == null) return false;
|
if (rs == null) return false;
|
||||||
return Arrays.binarySearch((short[]) val, (short) rs) >= 0;
|
return Arrays.binarySearch((short[]) val, (short) rs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + Arrays.toString((short[]) val);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else if (type == long[].class) {
|
} else if (type == long[].class) {
|
||||||
filter = (T t) -> {
|
filter = new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Object rs = attr.get(t);
|
Object rs = attr.get(t);
|
||||||
if (rs == null) return false;
|
if (rs == null) return false;
|
||||||
return Arrays.binarySearch((long[]) val, (long) rs) >= 0;
|
return Arrays.binarySearch((long[]) val, (long) rs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + Arrays.toString((long[]) val);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else if (type == float[].class) {
|
} else if (type == float[].class) {
|
||||||
filter = (T t) -> {
|
filter = new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Object rs = attr.get(t);
|
Object rs = attr.get(t);
|
||||||
if (rs == null) return false;
|
if (rs == null) return false;
|
||||||
return Arrays.binarySearch((float[]) val, (float) rs) >= 0;
|
return Arrays.binarySearch((float[]) val, (float) rs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + Arrays.toString((float[]) val);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else if (type == double[].class) {
|
} else if (type == double[].class) {
|
||||||
filter = (T t) -> {
|
filter = new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Object rs = attr.get(t);
|
Object rs = attr.get(t);
|
||||||
if (rs == null) return false;
|
if (rs == null) return false;
|
||||||
return Arrays.binarySearch((double[]) val, (double) rs) >= 0;
|
return Arrays.binarySearch((double[]) val, (double) rs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + Arrays.toString((double[]) val);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
filter = (T t) -> {
|
filter = new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
Object rs = attr.get(t);
|
Object rs = attr.get(t);
|
||||||
return rs != null && Arrays.binarySearch((Object[]) val, rs) > -1;
|
return rs != null && Arrays.binarySearch((Object[]) val, rs) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return attr.field() + ' ' + express.value() + ' ' + Arrays.toString((Object[]) val);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (express == NOTIN) filter = filter.negate();
|
if (express == NOTIN) {
|
||||||
|
final Predicate<T> filter2 = filter;
|
||||||
|
filter = new Predicate<T>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean test(T t) {
|
||||||
|
return !filter2.test(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return filter2.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user