Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
shz.orm.WhereInfo Maven / Gradle / Ivy
package shz.orm;
import shz.core.*;
import shz.core.model.PageInfo;
import shz.core.model.Range;
import shz.core.structure.limiter.Limiter;
import shz.core.type.TypeHelp;
import shz.orm.annotation.Where;
import shz.orm.enums.Condition;
import shz.orm.enums.ValueStrategy;
import shz.orm.exception.OrmClassNoFieldException;
import shz.orm.exception.OrmClassNoFieldWhereException;
import shz.orm.param.OrmParam;
import shz.orm.sql.ValueType;
import shz.orm.sql.WhereSql;
import shz.orm.sql.builder.SqlBuilder;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.IntFunction;
import java.util.function.Supplier;
final class WhereInfo {
private record WhereFieldInfo(Field field, String column, String fieldName, Condition condition,
ValueStrategy strategy) {
}
private static final class WhereValueInfo {
final String column;
Object val;
final Condition condition;
final ValueStrategy strategy;
WhereValueInfo(String column, Object val, Condition condition, ValueStrategy strategy) {
this.column = column;
this.val = val;
this.condition = condition;
this.strategy = strategy;
}
}
private static Map whereFields(ClassInfo classInfo, Class> cls) {
Map map = ToMap.get().build();
AccessibleHelp.fields(cls, f -> {
Where where = f.getAnnotation(Where.class);
if (where == null) return false;
String fieldName = NullHelp.isBlank(where.value()) ? f.getName() : where.value();
String columnName = classInfo.toColumnName(fieldName);
if (columnName == null) throw new OrmClassNoFieldException(classInfo.cls, fieldName);
map.put(columnName, new WhereFieldInfo(f, columnName, fieldName, where.condition(), where.strategy()));
return false;
});
return map;
}
static WhereSql where(ClassInfo classInfo, String fieldName, Object fieldValue, Condition condition, Supplier builderSupplier, Boolean logic) {
String column = classInfo.toColumnName(fieldName);
if (column == null) throw new OrmClassNoFieldException(classInfo.cls, fieldName);
SqlBuilder builder = builderSupplier.get().where().append("1=1");
List values = new LinkedList<>();
if (where(column, classInfo.getFieldByName(fieldName).getType(), fieldValue, condition, ValueStrategy.DEFAULT, builder, values))
return WhereSql.EMPTY;
return whereSql(classInfo, builder, values, logic, null);
}
private static boolean where(String column, Class> fieldType, Object val, Condition condition, ValueStrategy strategy, SqlBuilder builder, List values) {
condition = condition(condition, fieldType);
switch (strategy) {
case DEFAULT:
if (condition == Condition.EQ) {
if (val == null) {
builder.and().wrap(column).isNull();
return false;
}
} else if (condition == Condition.BETWEEN) {
Range> range = Range.asRange(val);
if (range == null || range.isEmpty()) return true;
val = range;
} else if (condition == Condition.IN || condition == Condition.NOT_IN) {
Set> set = ToSet.asSet(val);
if (set.isEmpty()) return true;
val = set;
}
break;
case NOT_NULL:
if (val == null) return false;
break;
case NOT_EMPTY:
if (NullHelp.isEmpty(val)) return false;
break;
case NOT_BLANK:
if (NullHelp.isBlank(val)) return false;
break;
default:
throw PRException.impossible();
}
switch (condition) {
case IS_NULL -> builder.and().wrap(column).isNull();
case IS_NOT_NULL -> builder.and().wrap(column).isNotNull();
case EQ -> {
builder.and().wrap(column).eq();
values.add(val);
}
case NEQ -> {
builder.and().wrap(column).neq();
values.add(val);
}
case GT -> {
builder.and().wrap(column).gt();
values.add(val);
}
case GE -> {
builder.and().wrap(column).ge();
values.add(val);
}
case LT -> {
builder.and().wrap(column).lt();
values.add(val);
}
case LE -> {
builder.and().wrap(column).le();
values.add(val);
}
case BETWEEN -> {
Range> range = Range.asRange(val);
if (range != null && !range.isEmpty()) {
builder.and().wrap(column).between(range, ValueType.PLACEHOLDER);
if (NullHelp.nonBlank(range.getMin())) values.add(range.getMin());
if (NullHelp.nonBlank(range.getMax())) values.add(range.getMax());
}
}
case IN -> {
Set> inSet = ToSet.asSet(val);
if (!inSet.isEmpty()) {
builder.and().wrap(column).in(inSet.size());
values.addAll(inSet);
}
}
case NOT_IN -> {
Set> notInSet = ToSet.asSet(val);
if (!notInSet.isEmpty()) {
builder.and().wrap(column).notIn(notInSet.size());
values.addAll(notInSet);
}
}
case LIKE -> {
builder.and().wrap(column).like();
values.add(val);
}
case LIKE_LEFT -> {
builder.and().wrap(column).likeLeft();
values.add(val);
}
case LIKE_RIGHT -> {
builder.and().wrap(column).likeRight();
values.add(val);
}
case REGEXP -> {
builder.and().wrap(column).regexp();
values.add(val);
}
default -> throw PRException.impossible();
}
return false;
}
private static Condition condition(Condition condition, Class> fieldType) {
if (condition != Condition.DEFAULT) return condition;
if (Collection.class.isAssignableFrom(fieldType) || fieldType.isArray()) return Condition.IN;
if (Range.class.isAssignableFrom(fieldType)) return Condition.BETWEEN;
return Condition.EQ;
}
private static WhereSql whereSql(ClassInfo classInfo, SqlBuilder builder, List values, Boolean logic, Consumer orderBys) {
if (classInfo.logicField != null && (logic == null || logic)) {
builder.and().wrap(classInfo.logicName).eq();
values.add(classInfo.logicVal);
}
if (orderBys != null) orderBys.accept(builder);
return WhereSql.of(builder.build(), values);
}
static WhereSql where(ClassInfo classInfo, List fieldNames, List fieldValues, List conditions, Supplier builderSupplier, Boolean logic) {
int size = NullHelp.size(fieldNames);
NullHelp.requireNon(size == 0 || NullHelp.size(fieldValues) != size || NullHelp.size(conditions) != size);
return where(classInfo, fieldNames, fieldValues, conditions::get, builderSupplier, logic);
}
private static WhereSql where(ClassInfo classInfo, List fieldNames, List fieldValues, IntFunction conditionFunc, Supplier builderSupplier, Boolean logic) {
int size = NullHelp.size(fieldNames);
SqlBuilder builder = builderSupplier.get().where().append("1=1");
List values = new LinkedList<>();
for (int i = 0; i < size; ++i) {
String column = classInfo.toColumnName(fieldNames.get(i));
if (column == null) throw new OrmClassNoFieldException(classInfo.cls, fieldNames.get(i));
if (where(column, classInfo.getFieldByName(fieldNames.get(i)).getType(), fieldValues.get(i), conditionFunc.apply(i), ValueStrategy.DEFAULT, builder, values))
return WhereSql.EMPTY;
}
return whereSql(classInfo, builder, values, logic, null);
}
static WhereSql where(ClassInfo classInfo, List fieldNames, List fieldValues, Condition condition, Supplier builderSupplier, Boolean logic) {
int size = NullHelp.size(fieldNames);
NullHelp.requireNon(size == 0 || NullHelp.size(fieldValues) != size);
return where(classInfo, fieldNames, fieldValues, i -> condition, builderSupplier, logic);
}
static WhereSql where(ClassInfo classInfo, Object obj, List conditions, Supplier builderSupplier, Boolean logic, boolean orderBy, String... fieldNames) {
Objects.requireNonNull(obj);
int len = NullHelp.length(fieldNames);
NullHelp.requireNon(len == 0 || NullHelp.size(conditions) != len);
return where(classInfo, obj, conditions::get, builderSupplier, logic, orderBy, fieldNames);
}
private static WhereSql where(ClassInfo classInfo, Object obj, IntFunction conditionFunc, Supplier builderSupplier, Boolean logic, boolean orderBy, String... fieldNames) {
int len = NullHelp.length(fieldNames);
if (obj instanceof Map, ?> map) {
List infoList = new ArrayList<>(len);
for (int i = 0; i < len; ++i) {
String columnName = classInfo.toColumnName(fieldNames[i]);
if (columnName == null) throw new OrmClassNoFieldException(classInfo.cls, fieldNames[i]);
infoList.add(new WhereValueInfo(columnName, map.get(fieldNames[i]), conditionFunc.apply(i), ValueStrategy.NOT_BLANK));
}
return where(classInfo, infoList, builderSupplier, logic, orderBy ? builder -> OrderByInfo.orderBy(classInfo, obj, builder) : null);
}
Class> cls;
NullHelp.requireNon(!TypeHelp.likeModel(cls = obj.getClass()));
Map whereFields = whereFields(classInfo, cls);
NullHelp.requireNonEmpty(whereFields);
List infoList = new ArrayList<>(len);
for (int i = 0; i < len; ++i) {
String columnName = classInfo.toColumnName(fieldNames[i]);
if (columnName == null) throw new OrmClassNoFieldException(classInfo.cls, fieldNames[i]);
WhereFieldInfo info = whereFields.get(columnName);
if (info == null) throw new OrmClassNoFieldWhereException(cls, fieldNames[i]);
infoList.add(new WhereValueInfo(columnName, AccessibleHelp.getField(info.field, obj), conditionFunc.apply(i), info.strategy));
}
return where(classInfo, infoList, builderSupplier, logic, orderBy ? builder -> OrderByInfo.orderBy(classInfo, obj, builder) : null);
}
private static WhereSql where(ClassInfo classInfo, List infoList, Supplier builderSupplier, Boolean logic, Consumer orderBys) {
SqlBuilder builder = builderSupplier.get().where().append("1=1");
List values = new LinkedList<>();
for (WhereValueInfo info : infoList)
if (where(info.column, classInfo.getFieldByColumn(info.column).getType(), info.val, info.condition, info.strategy, builder, values))
return WhereSql.EMPTY;
return whereSql(classInfo, builder, values, logic, orderBys);
}
static WhereSql where(ClassInfo classInfo, Object obj, Condition condition, Supplier builderSupplier, Boolean logic, boolean orderBy, String... fieldNames) {
Objects.requireNonNull(obj);
NullHelp.requireNonEmpty(fieldNames);
return where(classInfo, obj, i -> condition, builderSupplier, logic, orderBy, fieldNames);
}
static WhereSql where(ClassInfo classInfo, Object obj, Supplier builderSupplier, Boolean logic, boolean orderBy) {
if (obj == null) return null;
if (obj instanceof Map, ?> map) {
List infoList = new ArrayList<>(map.size());
map.forEach((k, v) -> {
String key = ToString.normal(k);
String columnName = classInfo.toColumnName(key);
if (columnName == null) throw new OrmClassNoFieldException(classInfo.cls, key);
infoList.add(new WhereValueInfo(columnName, map.get(k), Condition.DEFAULT, ValueStrategy.NOT_BLANK));
});
return where(classInfo, infoList, builderSupplier, logic, orderBy ? builder -> OrderByInfo.orderBy(classInfo, obj, builder) : null);
}
Class> cls;
NullHelp.requireNon(!TypeHelp.likeModel(cls = obj.getClass()));
Map whereFields = whereFields(classInfo, cls);
if (whereFields.isEmpty()) return WhereSql.EMPTY;
List infoList = new ArrayList<>(whereFields.size());
whereFields.forEach((k, v) -> infoList.add(new WhereValueInfo(k, AccessibleHelp.getField(v.field, obj), v.condition, v.strategy)));
return where(classInfo, infoList, builderSupplier, logic, orderBy ? builder -> OrderByInfo.orderBy(classInfo, obj, builder) : null);
}
static WhereSql where(ClassInfo classInfo, Parameter[] parameters, Object[] args, Supplier builderSupplier) {
if (parameters.length == 0) return null;
List infoList = new LinkedList<>();
for (int i = 0; i < parameters.length; ++i) {
Class> pt = parameters[i].getType();
if (args[i] != null && Map.class.isAssignableFrom(pt)) {
((Map, ?>) args[i]).forEach((k, v) -> {
String columnName = classInfo.toColumnName(ToString.normal(k));
if (columnName == null) throw new OrmClassNoFieldException(classInfo.cls, ToString.normal(k));
infoList.add(new WhereValueInfo(columnName, v, Condition.DEFAULT, ValueStrategy.NOT_BLANK));
});
continue;
}
if (Collection.class.isAssignableFrom(pt) || Range.class.isAssignableFrom(pt) || pt.isArray() || TypeHelp.likeCommon(pt)) {
Where where = parameters[i].getAnnotation(Where.class);
if (where != null) {
String columnName = classInfo.toColumnName(where.value());
if (columnName == null) throw new OrmClassNoFieldException(classInfo.cls, where.value());
infoList.add(new WhereValueInfo(columnName, args[i], where.condition(), where.strategy()));
}
continue;
}
if (PageInfo.class.isAssignableFrom(pt) || Limiter.class.isAssignableFrom(pt) || OrmParam.class.isAssignableFrom(pt))
continue;
Map whereFields = whereFields(classInfo, pt);
for (Map.Entry entry : whereFields.entrySet()) {
WhereFieldInfo v = entry.getValue();
infoList.add(new WhereValueInfo(entry.getKey(), AccessibleHelp.getField(v.field, args[i]), v.condition, v.strategy));
}
}
return where(classInfo, infoList, builderSupplier, null, builder -> OrderByInfo.orderBy(classInfo, parameters, args, builder));
}
static WhereSql uniqueWhere(ClassInfo classInfo, Object entity, Supplier builderSupplier, String... fieldNames) {
int len = NullHelp.length(fieldNames);
List infoList = new ArrayList<>(len);
for (int i = 0; i < len; ++i) {
String columnName = classInfo.toColumnName(fieldNames[i]);
if (columnName == null) throw new OrmClassNoFieldException(classInfo.cls, fieldNames[i]);
Object val = classInfo.getByName(fieldNames[i], entity);
if (NullHelp.nonBlank(val))
infoList.add(new WhereValueInfo(columnName, val, Condition.EQ, ValueStrategy.NOT_BLANK));
}
if (infoList.isEmpty()) return WhereSql.EMPTY;
return where(classInfo, infoList, builderSupplier, null, null);
}
}