package com.github.yulichang.wrapper;
import com.baomidou.mybatisplus.core.conditions.SharedString;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.metadata.*;
import com.baomidou.mybatisplus.core.toolkit.*;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.github.yulichang.toolkit.Constant;
import com.github.yulichang.toolkit.LambdaUtils;
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
import com.github.yulichang.wrapper.interfaces.LambdaJoin;
import com.github.yulichang.wrapper.interfaces.Query;
import com.github.yulichang.wrapper.interfaces.on.OnFunction;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* 参考 {@link com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper}
* Lambda 语法使用 Wrapper
*
* 推荐使用 Wrappers.lambdaJoin();构造
*
* @author yulichang
* @see com.github.yulichang.toolkit.Wrappers
*/
@SuppressWarnings("unused")
public class MPJLambdaWrapper extends MPJAbstractLambdaWrapper>
implements Query>, LambdaJoin> {
/**
* 查询字段 sql
*/
private final SharedString sqlSelect = new SharedString();
/**
* 查询表
*/
private final SharedString from = new SharedString();
/**
* 查询的字段
*/
private final List selectColumns = new ArrayList<>();
/**
* 忽略查询的字段
*/
private final List ignoreColumns = new ArrayList<>();
/**
* ON sql wrapper集合
*/
private final List joinSql = new ArrayList<>();
/**
* 不建议直接 new 该实例,使用 Wrappers.lambdaQuery()
*/
public MPJLambdaWrapper() {
this.hasAlias = true;
super.initNeed();
}
/**
* 不建议直接 new 该实例,使用 Wrappers.lambdaQuery(...)
*/
MPJLambdaWrapper(Class> entityClass, AtomicInteger paramNameSeq,
Map paramNameValuePairs, MergeSegments mergeSegments,
SharedString lastSql, SharedString sqlComment, SharedString sqlFirst, boolean hasAlias) {
this.entityClass =entityClass;
this.paramNameSeq = paramNameSeq;
this.paramNameValuePairs = paramNameValuePairs;
this.expression = mergeSegments;
this.lastSql = lastSql;
this.sqlComment = sqlComment;
this.sqlFirst = sqlFirst;
this.hasAlias = hasAlias;
}
@Override
protected MPJLambdaWrapper instance() {
return instance(true, null);
}
protected MPJLambdaWrapper instance(boolean hasAlias, Class> entityClass) {
return new MPJLambdaWrapper<>(entityClass, paramNameSeq, paramNameValuePairs, new MergeSegments(),
SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(), hasAlias);
}
@Override
@SafeVarargs
public final MPJLambdaWrapper select(SFunction... columns) {
if (ArrayUtils.isNotEmpty(columns)) {
for (SFunction s : columns) {
selectColumns.add(getThisAlias(s) + getCache(s).getColumn());
}
}
return typedThis;
}
@Override
public MPJLambdaWrapper select(Class entityClass, Predicate predicate) {
TableInfo info = TableInfoHelper.getTableInfo(entityClass);
Assert.notNull(info, "table can not be find");
MPJTableInfo tableInfo = MPJTableInfoHelper.getTableInfo(entityClass);
info.getFieldList().stream().filter(predicate).collect(Collectors.toList()).forEach(i ->
selectColumns.add((hasAlias ? tableInfo.getAliasDOT() : StringPool.EMPTY) + i.getColumn()));
return typedThis;
}
@Override
public MPJLambdaWrapper selectAs(SFunction column, String alias) {
selectColumns.add(getThisAlias(column) + getCache(column).getColumn() + Constants.AS + alias);
return typedThis;
}
public MPJLambdaWrapper selectFunc(boolean condition, BaseFuncEnum funcEnum, SFunction column,
String alias) {
if (condition) {
selectColumns.add(String.format(funcEnum.getSql(), getThisAlias(column) + getCache(column).getColumn())
+ Constants.AS + alias);
}
return typedThis;
}
@Override
public MPJLambdaWrapper selectFunc(boolean condition, BaseFuncEnum funcEnum, Object column, String alias) {
if (condition) {
selectColumns.add(String.format(funcEnum.getSql(), column.toString()) + Constants.AS + alias);
}
return typedThis;
}
public final MPJLambdaWrapper selectAll(Class> clazz) {
TableInfo info = TableInfoHelper.getTableInfo(clazz);
Assert.notNull(info, "table can not be find -> %s", clazz);
String dot = hasAlias ? MPJTableInfoHelper.getTableInfo(clazz).getAliasDOT() : StringPool.EMPTY;
if (info.havePK()) {
selectColumns.add(dot + info.getKeyColumn());
}
info.getFieldList().stream().filter(TableFieldInfo::isSelect).forEach(c ->
selectColumns.add(dot + c.getColumn()));
return typedThis;
}
@Override
@SafeVarargs
public final MPJLambdaWrapper selectIgnore(SFunction... columns) {
if (ArrayUtils.isNotEmpty(columns)) {
for (SFunction s : columns) {
ignoreColumns.add(getThisAlias(s) + getCache(s).getColumn());
}
}
return typedThis;
}
@Override
public MPJLambdaWrapper selectQuery(Class> clazz, OnFunction function, String alias) {
MPJLambdaWrapper> apply = function.apply(instance(false, clazz));
selectColumns.add(String.format("(SELECT %s FROM %s %s)", apply.getSqlSelect(),
TableInfoHelper.getTableInfo(clazz).getTableName(), apply.getCustomSqlSegment()) + Constants.AS + alias);
return this;
}
/**
* 查询条件 SQL 片段
*/
@Override
public String getSqlSelect() {
if (StringUtils.isBlank(sqlSelect.getStringValue())) {
if (CollectionUtils.isNotEmpty(ignoreColumns)) {
selectColumns.removeIf(ignoreColumns::contains);
}
sqlSelect.setStringValue(String.join(StringPool.COMMA, selectColumns));
}
return sqlSelect.getStringValue();
}
/**
* 获取连表部分语句
*/
public String getFrom() {
if (StringUtils.isBlank(from.getStringValue())) {
from.setStringValue(String.join(StringPool.SPACE, joinSql));
}
return from.getStringValue();
}
public boolean getAutoAlias() {
return true;
}
@Override
public void clear() {
super.clear();
sqlSelect.toNull();
from.toNull();
selectColumns.clear();
ignoreColumns.clear();
joinSql.clear();
}
@Override
public MPJLambdaWrapper join(String keyWord, boolean condition, Class clazz, OnFunction function) {
if (condition) {
joinSql.add(keyWord + TableInfoHelper.getTableInfo(clazz).getTableName() +
Constants.SPACE + MPJTableInfoHelper.getTableInfo(clazz).getAlias() +
Constant.ON + function.apply(instance()).getExpression().getNormal().getSqlSegment());
}
return typedThis;
}
private String getThisAlias(SFunction, ?> function) {
return hasAlias ? MPJTableInfoHelper.getTableInfo(LambdaUtils.getEntityClass(function)).getAliasDOT() :
StringPool.EMPTY;
}
}