|
@@ -4,6 +4,7 @@ import java.lang.reflect.Field;
|
|
|
import java.math.BigInteger;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Collection;
|
|
|
import java.util.Collections;
|
|
|
import java.util.Date;
|
|
|
import java.util.Map;
|
|
@@ -14,16 +15,16 @@ import com.chelvc.framework.base.context.SessionContextHolder;
|
|
|
import com.chelvc.framework.common.util.DateUtils;
|
|
|
import com.chelvc.framework.common.util.ObjectUtils;
|
|
|
import com.chelvc.framework.common.util.StringUtils;
|
|
|
-import com.chelvc.framework.database.support.MyBatisUtils;
|
|
|
-import com.chelvc.framework.database.support.TableField;
|
|
|
import com.google.common.collect.Lists;
|
|
|
import com.google.common.collect.Maps;
|
|
|
import com.google.common.collect.Sets;
|
|
|
+import lombok.NonNull;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import net.sf.jsqlparser.expression.Expression;
|
|
|
import net.sf.jsqlparser.expression.LongValue;
|
|
|
import net.sf.jsqlparser.expression.StringValue;
|
|
|
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
|
|
|
+import net.sf.jsqlparser.expression.operators.relational.ItemsList;
|
|
|
import net.sf.jsqlparser.schema.Column;
|
|
|
import org.apache.commons.lang3.tuple.Pair;
|
|
|
|
|
@@ -36,9 +37,9 @@ import org.apache.commons.lang3.tuple.Pair;
|
|
|
@Slf4j
|
|
|
final class Expressions {
|
|
|
/**
|
|
|
- * 枚举选项限定配置属性名
|
|
|
+ * 枚举选项限定配置
|
|
|
*/
|
|
|
- private static final String ENUM_OPTION_LIMIT_PROPERTY = "enum.option.limit";
|
|
|
+ private static final String ENUM_OPTION_LIMIT = "enum.option.limit";
|
|
|
|
|
|
private Expressions() {
|
|
|
}
|
|
@@ -69,24 +70,24 @@ final class Expressions {
|
|
|
public static final Column CREATOR_COLUMN = new Column("creator");
|
|
|
|
|
|
/**
|
|
|
- * 创建时间字段
|
|
|
+ * 更新人字段
|
|
|
*/
|
|
|
- public static final Column CREATE_TIME_COLUMN = new Column("create_time");
|
|
|
+ public static final Column UPDATER_COLUMN = new Column("updater");
|
|
|
|
|
|
/**
|
|
|
- * 更新人字段
|
|
|
+ * 逻辑删除字段
|
|
|
*/
|
|
|
- public static final Column UPDATER_COLUMN = new Column("updater");
|
|
|
+ public static final Column DELETED_COLUMN = new Column("deleted");
|
|
|
|
|
|
/**
|
|
|
- * 更新时间字段
|
|
|
+ * 创建时间字段
|
|
|
*/
|
|
|
- public static final Column UPDATE_TIME_COLUMN = new Column("update_time");
|
|
|
+ public static final Column CREATE_TIME_COLUMN = new Column("create_time");
|
|
|
|
|
|
/**
|
|
|
- * 逻辑删除字段
|
|
|
+ * 更新时间字段
|
|
|
*/
|
|
|
- public static final Column DELETED_COLUMN = new Column("deleted");
|
|
|
+ public static final Column UPDATE_TIME_COLUMN = new Column("update_time");
|
|
|
|
|
|
/**
|
|
|
* 零值/表达式映射
|
|
@@ -104,70 +105,88 @@ final class Expressions {
|
|
|
private static volatile Pair<String, Expression> ENV;
|
|
|
|
|
|
/**
|
|
|
- * 解析数据查询附加条件配置
|
|
|
- *
|
|
|
- * @param config 配置信息
|
|
|
- * @return 表名/枚举字段名/选项值映射表
|
|
|
+ * 表达式提供器接口
|
|
|
*/
|
|
|
- private static Map<String, Map<String, ExpressionList>> analyseSelectAdditionalCondition(String config) {
|
|
|
- if (StringUtils.isEmpty(config)) {
|
|
|
- return Collections.emptyMap();
|
|
|
- }
|
|
|
+ interface Provider {
|
|
|
+ /**
|
|
|
+ * 获取表达式
|
|
|
+ *
|
|
|
+ * @param table 表信息
|
|
|
+ * @return 字段名/表达式值映射表
|
|
|
+ */
|
|
|
+ Map<String, ItemsList> get(Tables.Table table);
|
|
|
+ }
|
|
|
|
|
|
- // 构建表名/枚举字段上下文映射表
|
|
|
- String[] expressions = config.split(",");
|
|
|
- if (ObjectUtils.isEmpty(expressions)) {
|
|
|
- return Collections.emptyMap();
|
|
|
- }
|
|
|
- Map<String, Set<TableField>> tables = Maps.newHashMapWithExpectedSize(expressions.length);
|
|
|
- for (String expression : expressions) {
|
|
|
- if (StringUtils.isEmpty(expression = expression.trim())) {
|
|
|
- continue;
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 表达式提供器抽象实现
|
|
|
+ */
|
|
|
+ static abstract class AbstractProvider implements Provider {
|
|
|
+ protected final Set<String> columns;
|
|
|
+ private volatile Map<String, ItemsList> expressions;
|
|
|
|
|
|
- // 解析表字段配置表达式
|
|
|
- String table, column;
|
|
|
- int index = expression.indexOf('.');
|
|
|
- if (index < 1 || StringUtils.isEmpty(table = expression.substring(0, index))
|
|
|
- || StringUtils.isEmpty(column = expression.substring(index + 1))) {
|
|
|
- log.warn("Invalid column expression: {}", expression);
|
|
|
- continue;
|
|
|
+ public AbstractProvider(@NonNull Collection<String> columns) {
|
|
|
+ this.columns = Collections.unmodifiableSet(Sets.newHashSet(columns));
|
|
|
+ if (this.columns.isEmpty()) {
|
|
|
+ this.expressions = Collections.emptyMap();
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取字段值表达式
|
|
|
+ *
|
|
|
+ * @param table 表对象
|
|
|
+ * @param column 字段名
|
|
|
+ * @return 表达式实例
|
|
|
+ */
|
|
|
+ protected abstract ItemsList expression(Tables.Table table, String column);
|
|
|
|
|
|
- // 获取表字段上下文信息
|
|
|
- TableField field = MyBatisUtils.getTableField(table, column);
|
|
|
- if (field != null && Enum.class.isAssignableFrom(field.getType())) {
|
|
|
- tables.computeIfAbsent(MyBatisUtils.unquote(table), k -> Sets.newHashSet()).add(field);
|
|
|
+ @Override
|
|
|
+ public Map<String, ItemsList> get(@NonNull Tables.Table table) {
|
|
|
+ if (this.expressions == null) {
|
|
|
+ synchronized (this) {
|
|
|
+ if (this.expressions == null) {
|
|
|
+ this.expressions = Maps.newHashMapWithExpectedSize(this.columns.size());
|
|
|
+ this.columns.forEach(column -> {
|
|
|
+ ItemsList expression = this.expression(table, column);
|
|
|
+ if (expression != null) {
|
|
|
+ this.expressions.put(column, expression);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
+ return this.expressions;
|
|
|
}
|
|
|
- if (ObjectUtils.isEmpty(tables)) {
|
|
|
- return Collections.emptyMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 枚举字段值表达式提供器实现
|
|
|
+ */
|
|
|
+ static class EnumerateProvider extends AbstractProvider {
|
|
|
+ public EnumerateProvider(@NonNull Set<String> columns) {
|
|
|
+ super(columns);
|
|
|
}
|
|
|
|
|
|
- // 构建表明/枚举字段名/选项值映射表
|
|
|
- Map<String, Map<String, ExpressionList>> conditions = Maps.newHashMapWithExpectedSize(tables.size());
|
|
|
- tables.forEach((table, contexts) -> {
|
|
|
- Map<String, ExpressionList> additional = Maps.newLinkedHashMapWithExpectedSize(contexts.size());
|
|
|
- for (TableField context : contexts) {
|
|
|
- Field[] fields = context.getType().getDeclaredFields();
|
|
|
- if (ObjectUtils.notEmpty(fields)) {
|
|
|
- ArrayList<Expression> values = Lists.newArrayListWithCapacity(fields.length);
|
|
|
- for (Field field : fields) {
|
|
|
- if (!field.isSynthetic() && field.isEnumConstant()) {
|
|
|
- values.add(new StringValue(field.getName()));
|
|
|
+ @Override
|
|
|
+ protected ItemsList expression(@NonNull Tables.Table table, @NonNull String column) {
|
|
|
+ Tables.Field field = table.getField(column);
|
|
|
+ if (field != null && field.getType().isEnum()) {
|
|
|
+ Field[] options = field.getType().getDeclaredFields();
|
|
|
+ if (ObjectUtils.notEmpty(options)) {
|
|
|
+ ArrayList<Expression> values = Lists.newArrayListWithCapacity(options.length);
|
|
|
+ for (Field option : options) {
|
|
|
+ if (!option.isSynthetic() && option.isEnumConstant()) {
|
|
|
+ values.add(new StringValue(option.getName()));
|
|
|
}
|
|
|
}
|
|
|
if (!values.isEmpty()) {
|
|
|
values.trimToSize();
|
|
|
- additional.put(context.getColumn(), new ExpressionList(values));
|
|
|
+ return new ExpressionList(values);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- if (!additional.isEmpty()) {
|
|
|
- conditions.put(table, Collections.unmodifiableMap(additional));
|
|
|
- }
|
|
|
- });
|
|
|
- return conditions.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(conditions);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -210,13 +229,39 @@ final class Expressions {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取数据查询附加条件
|
|
|
+ * 获取字段值表达式提供器
|
|
|
*
|
|
|
- * @return 表名称/字段名/值映射表
|
|
|
+ * @return 表名称/字段值表达式提供器映射表
|
|
|
*/
|
|
|
- public static Map<String, Map<String, ExpressionList>> getSelectAdditionalConditions() {
|
|
|
- return ApplicationContextHolder.getProperty(
|
|
|
- ENUM_OPTION_LIMIT_PROPERTY, Expressions::analyseSelectAdditionalCondition
|
|
|
- );
|
|
|
+ public static Map<String, Provider> getExpressionProviders() {
|
|
|
+ return ApplicationContextHolder.getProperty(ENUM_OPTION_LIMIT, property -> {
|
|
|
+ if (StringUtils.isEmpty(property) || (property = property.trim()).isEmpty()) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Set<String>> tables = Maps.newHashMap();
|
|
|
+ for (String expression : property.split(",")) {
|
|
|
+ if ((expression = expression.trim()).isEmpty()) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ String table, column;
|
|
|
+ int delimiter = expression.lastIndexOf('.');
|
|
|
+ if (delimiter < 1 || StringUtils.isEmpty(table = expression.substring(0, delimiter).trim())
|
|
|
+ || StringUtils.isEmpty(column = expression.substring(delimiter + 1).trim())) {
|
|
|
+ log.warn("Invalid column expression: {}", expression);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ tables.computeIfAbsent(table, k -> Sets.newHashSet()).add(column);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ObjectUtils.isEmpty(tables)) {
|
|
|
+ return Collections.emptyMap();
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<String, Provider> providers = Maps.newHashMapWithExpectedSize(tables.size());
|
|
|
+ tables.forEach((table, columns) -> providers.put(table, new EnumerateProvider(columns)));
|
|
|
+ return providers;
|
|
|
+ });
|
|
|
}
|
|
|
}
|