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.
gu.sql2java.wherehelper.BeanShellWhereBuilder Maven / Gradle / Ivy
package gu.sql2java.wherehelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.base.Strings.nullToEmpty;
import static com.google.common.base.MoreObjects.firstNonNull;
import static gu.sql2java.bean.BeanPropertyUtils.isEmpty;
import static gu.sql2java.bean.BeanPropertyUtils.allEmpty;
import static gu.sql2java.SimpleLog.log;
import static gu.sql2java.wherehelper.VarTestType.checkVarTestType;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.Resources;
import gu.sql2java.BaseBean;
import gu.sql2java.BaseRow;
import gu.sql2java.wherehelper.annotations.BitTest;
import gu.sql2java.wherehelper.annotations.Compare;
import gu.sql2java.wherehelper.annotations.EnableWhereHelper;
import gu.sql2java.wherehelper.annotations.Equal;
import gu.sql2java.wherehelper.annotations.EqualIf;
import gu.sql2java.wherehelper.annotations.Expression;
import gu.sql2java.wherehelper.annotations.GroupBy;
import gu.sql2java.wherehelper.annotations.IfElse;
import gu.sql2java.wherehelper.annotations.Like;
import gu.sql2java.wherehelper.annotations.OrderBy;
import gu.sql2java.wherehelper.annotations.Range;
/**
* 基于调用者提供的表达式生成动态执行脚本(BeanShell)
* @author guyadong
*
*/
public class BeanShellWhereBuilder{
/*****************************************/
/** 脚本模板名称定义 **/
/*****************************************/
private static final String TMPL_EQUAL = "equal.tmpl";
private static final String TMPL_BIT_TEST = "bit_test.tmpl";
private static final String TMPL_EQUAL_IF = "equal_if.tmpl";
private static final String TMPL_IF_ELSE = "if_else.tmpl";
private static final String TMPL_LIKE = "like.tmpl";
private static final String TMPL_COMPARE = "compare.tmpl";
private static final String TMPL_GROUP_BY = "group_by.tmpl";
private static final String TMPL_ORDER_BY = "order_by.tmpl";
private static final String TMPL_EXP = "exp.tmpl";
private static final String TMPL_LIMIT = "limit.tmpl";
private static final String TMPL_BEFORE_COND = "before_cond.tmpl";
private static final String TMPL_AFTER_COND = "after_cond.tmpl";
public static final String NOT_EQUAL = "$";
public static final String OR_NULL = "$";
public static final String BIT_OR = "$";
public static final String IGNORE_EMPTY = "$";
private static final String AND_OR = "$";
private static final String TEST = "$";
private static final String AGG_FUN = "$";
private static final String DEFAULT_ORDER_BY_VAR = "order_by_column";
private static final String DEFAULT_GROUP_BY_VAR = "group_by_column";
public static final String KEYWORD_COND_COUNT = "cond_count";
public static final String KEYWORD_WHERE_BUFFER = "where_buffer";
public static final String KEYWORD_EXP_BUFFER = "cond_buffer";
public static final String DT_MYSQL="MySQL";
private static class Tmpls{
/**
* 模板名-动态脚本模板内容映射
*/
private final static ImmutableMap tmpls = loadAllTemplates();
}
private String selectFrom = "";
private String andor = "AND";
/**
* 所有imoprt导入语句
*/
private List importLines = Lists.newLinkedList();
/**
* 所有表达式的bsh脚本
*/
private List conditionCodes = Lists.newLinkedList();
private List orderByColumns = Lists.newLinkedList();
private List groupByColumns = Lists.newLinkedList();
/**
* SQL 类型,目前只支持MySQL
*/
private String sqltype = DT_MYSQL;
/**
* 是否输出调试日志
*/
private boolean debuglog = false;
/**
* 是否生成分页查询语句
*/
private boolean pagequery = true;
/**
* 输入参数的目标表对象,默认为 {@link BaseBean}
*/
private Class extends BaseRow> targetClass = BaseRow.class;
/**
* 引用变量名列表
*/
private Set referenceVariables;
/**
* 变量字段名对应的类型映射
*/
private Map> varTypes = Collections.emptyMap();
private String orderByVarname = DEFAULT_ORDER_BY_VAR;
private String groupByVarname = DEFAULT_GROUP_BY_VAR;
BeanShellWhereBuilder(){
}
public boolean debuglog() {
return debuglog;
}
/**
* 设置是否输出调试信息
* @param debuglog
* @return 当前对象
*/
public BeanShellWhereBuilder debuglog(boolean debuglog) {
this.debuglog = debuglog;
return this;
}
/**
* 设置是否支持生成分页查询语句(如MySQL LIMIT ${row_count} OFFSET ${offset})
* @param pagequery
* @return 当前对象
*/
public BeanShellWhereBuilder pagequery(boolean pagequery){
this.pagequery = pagequery;
return this;
}
public Set getReferenceVariables() {
return referenceVariables;
}
public Class extends BaseRow> getTargetClass() {
return targetClass;
}
public Map> getVarTypes() {
return varTypes;
}
/**
* @return orderByVarname
*/
public String getOrderByVarname() {
return orderByVarname;
}
/**
* @return groupByVarname
*/
public String getGroupByVarname() {
return groupByVarname;
}
/**
* @return orderByColumns
*/
public String getOrderByColumns() {
return Joiner.on(',').join(orderByColumns);
}
/**
* @return groupByColumns
*/
public String getGroupByColumns() {
return Joiner.on(',').join(groupByColumns);
}
/**
* 生成一般表达式
* @param exp
* @return 当前对象
*/
public BeanShellWhereBuilder exp(String exp){
exp = nullToEmpty(exp).trim();
if(!isNullOrEmpty(exp)) {
conditionCodes.add(Tmpls.tmpls.get(TMPL_EXP)
.replace(AND_OR, andor)
.replace("$", exp) );
}
return this;
}
/**
* 指定与前一个表达式的连接方式为OR
* @return 当前对象
*/
public BeanShellWhereBuilder or(){
andor = "OR";
return this;
}
/**
* 指定与前一个表达式的连接方式为AND
* @return 当前对象
*/
public BeanShellWhereBuilder and(){
andor = "AND";
return this;
}
/**
* 参见{@link #equal(String)},不之处在于如果column_name为{@code null}或空则忽略,不生成表达式
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field
* @param not 为{@code true}执行不等价比较
* @param notCheckEmpty 为{@code true} 不检查字段是否为{@code null}或空
* @param orNull 为{@code true}输出等价或为NULL表达式,例如 (left=value OR left IS NULL)
* @return 当前对象
*/
private BeanShellWhereBuilder equal(String left,String field, boolean not, boolean notCheckEmpty, boolean orNull){
if(!isNullOrEmpty(field)) {
conditionCodes.add(Tmpls.tmpls.get(TMPL_EQUAL)
.replace(NOT_EQUAL, "" + not)
.replace(IGNORE_EMPTY, "" + notCheckEmpty)
.replace(OR_NULL, "" + orNull)
.replace(AND_OR, andor)
.replace("$", field)
.replace("$", column(left,field)));
}
return this;
}
/**
* 创建等价表达式,如{@code column_name = $},
* 如果column_name为{@code null}或空,则表达式为 {@code column_name IS NULL}
* 如果column_name为集合,则为IN表达式 {@code column_name IN (...)}
* @param field
* @return 当前对象
*/
public BeanShellWhereBuilder equal(String field){
return equal(null,field,false, true, false);
}
/**
* @param left
* @param field
* @since 3.17.5
*/
public BeanShellWhereBuilder equal(String left, String field){
return equal(left,field,false, true, false);
}
/**
* 创建一个不等价表达式,如{@code column_name != $},
* 如果column_name为{@code null}或空,则表达式为 {@code column_name IS NOT NULL}
* 如果column_name为集合,则为IN表达式 {@code column_name NOT IN (...)}
* @param field
* @return 当前对象
*/
public BeanShellWhereBuilder equalNot(String field){
return equal(null,field,true, true, false);
}
public BeanShellWhereBuilder equalNot(String left,String field){
return equal(left,field,true, true, false);
}
/**
* 创建等价或为NULL表达式,
* 如{@code column_name = $ OR column_name IS NULL},
* @param field
* @return 当前对象
* @since 3.26.0
*/
public BeanShellWhereBuilder equalOrNull(String field){
return equal(null,field,false, false, true);
}
/**
* @param left
* @param field
* @since 3.26.0
*/
public BeanShellWhereBuilder equalOrNull(String left,String field){
return equal(left,field,false, false, true);
}
/**
* 参见{@link #equal(String)},不之处在于如果column_name为{@code null}或空则忽略,不生成表达式
* @param field
* @param not 为{@code true}执行不等价比较
* @return 当前对象
*/
public BeanShellWhereBuilder equalIfNonEmpty(String field, boolean not){
return equal(null,field,not, false, false);
}
/**
* @param left
* @param field
* @param not
* @return 当前对象
* @since 3.17.5
*/
public BeanShellWhereBuilder equalIfNonEmpty(String left, String field, boolean not){
return equal(left,field,not, false, false);
}
/**
* 参见{@link #equal(String)},不之处在于如果column_name为{@code null}或空则忽略,不生成表达式
* @param field
* @return 当前对象
*/
public BeanShellWhereBuilder equalIfNonEmpty(String field){
return equal(null,field,false, false, false);
}
/**
* @param left
* @param field
* @return 当前对象
* @since 3.17.5
*/
public BeanShellWhereBuilder equalIfNonEmpty(String left,String field){
return equal(left,field,false, false, false);
}
/**
* 当满足{@code test}指定的条件时,创建等价表达式
* 输入参数为{@code null}或空则忽略,不生成表达式
* @param test 判断条件
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 字段名
* @param not 为{@code true}执行不等价比较
* @param notCheckEmpty 为{@code true} 不检查字段是否为{@code null}或空
* @return 当前对象
* @see #equal(String)
* @since 3.17.5
*/
public BeanShellWhereBuilder equalIf(String test,String left,String field,boolean not, boolean notCheckEmpty){
if(!isNullOrEmpty(test) && !isNullOrEmpty(field)) {
conditionCodes.add(Tmpls.tmpls.get(TMPL_EQUAL_IF)
.replace(NOT_EQUAL, "" + not)
.replace(IGNORE_EMPTY, "" + notCheckEmpty)
.replace(AND_OR, andor)
.replace("$", test)
.replace("$", field)
.replace("$", column(left,field)));
}
return this;
}
/**
* 当满足{@code test}指定的条件以及{@code testNullVars,testNonullVars,testEmptyVars,testNoEmptyVars,testTrueVars,testFalseVars}指定变量满足条件时,创建等价表达式
* 输入参数为{@code null}或空则忽略,不生成表达式
* @param test 判断条件
* @param testNullVars 要求为{@code null}的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testNonullVars 要求不为{@code null}的变量名列表,['var1','var2'],等价于'null!=${var1} && null!=${var2}',为{@code null}或空则默认为'true'
* @param testEmptyVars 要求为{@code null}或空的变量名列表,['var1','var2'],等价于'isEmpty(${var1}) && isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testNoEmptyVars 要求不为{@code null}或空的变量名列表,['var1','var2'],等价于'!isEmpty(${var1}) && !isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testTrueVars 要求为{@code true}的变量名列表,['var1','var2'],等价于'isTrue(${var1)} && isTrue(${var2})',为空则默认为'true'
* @param testFalseVars 要求为{@code false}的变量名列表,['var1','var2'],等价于'isFalse(${var1}) && isFalse(${var2})',为空则默认为'true'
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field
* @param not 为{@code true}执行不等价比较
* @param notCheckEmpty 为{@code true} 不检查字段是否为{@code null}或空
* @return 当前对象
* @see #equalIf(String, String, String, boolean, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder equalIf(String test,
String[] testNullVars,String[] testNonullVars,String[] testEmptyVars, String[] testNoEmptyVars,
String[] testTrueVars, String[] testFalseVars, String left, String field, boolean not, boolean notCheckEmpty){
return equalIf(buildTestExps(test, testNullVars, testNonullVars, testEmptyVars, testNoEmptyVars, testTrueVars, testFalseVars),
left, field, not, notCheckEmpty);
}
/**
* 当满足{@code test}指定的条件时,创建等价表达式
* 输入参数为{@code null}或空则忽略,不生成表达式
* @param test 判断条件
* @param field
* @param not 为{@code true}执行不等价比较
* @param notCheckEmpty 为{@code true} 不检查字段是否为{@code null}或空
* @return 当前对象
* @see #equalIf(String, String, String, boolean, boolean)
*/
public BeanShellWhereBuilder equalIf(String test,String field,boolean not, boolean notCheckEmpty){
return equalIf(test,field,field,not, notCheckEmpty);
}
/**
* 当满足{@code test}指定的条件时,创建等价表达式
* 输入参数为{@code null}或空则忽略,不生成表达式
* @param test 判断条件
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field
* @param not 为{@code true}执行不等价比较
* @return 当前对象
* @see #equalIf(String, String, String, boolean, boolean)
* @since 3.17.5
*/
public BeanShellWhereBuilder equalIf(String test,String left,String field,boolean not){
return equalIf(test,left,field,not, false);
}
/**
* 当满足{@code test}指定的条件时,创建等价表达式
* 输入参数为{@code null}或空则忽略,不生成表达式
* @param test 判断条件
* @param field
* @param not 为{@code true}执行不等价比较
* @return 当前对象
* @see #equalIf(String, String, String, boolean, boolean)
*/
public BeanShellWhereBuilder equalIf(String test,String field,boolean not){
return equalIf(test,field,field,not, false);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,则创建等价表达式
* {@code testVars,testType}为{@code null}或空视为{@code true},
* 输入参数为{@code null}或空则忽略,不生成表达式
* @param testVars 要求为null的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testType
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field
* @param not 为{@code true}执行不等价比较
* @param notCheckEmpty 为{@code true} 不检查字段是否为{@code null}或空
* @return 当前对象
* @see #equalIf(String, String, String, boolean, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder equalIf(String[] testVars,VarTestType testType, String left, String field, boolean not, boolean notCheckEmpty){
return equalIf(renderVars(testVars, testType),left,field,not, notCheckEmpty);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,则创建等价表达式
* {@code testVars,testType}为{@code null}或空视为{@code true},
* 输入参数为{@code null}或空则忽略,不生成表达式
* @param testVars 要求为null的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testType
* @param field
* @param not 为{@code true}执行不等价比较
* @param notCheckEmpty 为{@code true} 不检查字段是否为{@code null}或空
* @return 当前对象
* @see #equalIf(String, String, String, boolean, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder equalIf(String[] testVars,VarTestType testType,String field, boolean not, boolean notCheckEmpty){
return equalIf(renderVars(testVars, testType),null,field,not, notCheckEmpty);
}
/**
* 根据{@code testType}指定的类型测试{@code testVar} 指定的变量满足条件,则创建等价表达式
* {@code field,testType}为{@code null}或空视则忽略,不生成表达式
* @param testVar 条件测试表达式变量名,为{@code null}或空则默认为{@code field}
* @param testType 变量测试类型
* @param testOp 条件测试操作符
* @param testValue 变量条件测试的目标值
* @param testQuote 为{@code true}生成表达式对{@code testValue} 以字符串对头尾增加单引号,{@code refValue}为{@code true}时忽略
* @param testRefValue 为{@code true}生成表达式对{@code testValue} 视为变量名
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 创建等价表达式的字段名
* @param not 为{@code true}执行不等价比较
* @param notCheckEmpty 为{@code true} 不检查字段是否为{@code null}或空
* @return 当前对象
* @since 3.25.0
*/
public BeanShellWhereBuilder equalIf(String testVar,VarTestType testType,CompareOp testOp, Object testValue,boolean testQuote,boolean testRefValue,
String left,String field,boolean not, boolean notCheckEmpty){
String test = buildTestVarExp(testVar, testType, testOp, testValue, testQuote, testRefValue, field);
if(!test.isEmpty()) {
return equalIf(test,left,left,not,notCheckEmpty);
}
return this;
}
/**
* 创建位运算比较表达式,如{@code (column_name & 100) = $},
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field
* @param bitOr 为{@code true}执行OR运算
* @param notCheckEmpty 为{@code true} 不检查字段是否为{@code null}或空
* @param aggFun 自定义参数聚合实现类
* @return 当前对象
* @since 3.27.0
*/
@SuppressWarnings("rawtypes")
BeanShellWhereBuilder bitTest(String left,String field, boolean bitOr, boolean notCheckEmpty,Class extends BitAggFun> aggFun){
if(!isNullOrEmpty(field)) {
conditionCodes.add(Tmpls.tmpls.get(TMPL_BIT_TEST)
.replace(BIT_OR, "" + bitOr)
.replace(IGNORE_EMPTY, "" + notCheckEmpty)
.replace(AND_OR, andor)
.replace(AGG_FUN, null == aggFun || BitAggFun.class.equals(aggFun) ? "null" :aggFun.getName()+".class")
.replace("$", field)
.replace("$", column(left,field)));
}
return this;
}
/**
* 创建位运算比较表达式,如{@code (column_name & 100) = $},
* @param field
* @return 当前对象
* @since 3.27.0
* @see #bitTest(String, String, boolean, boolean, Class)
*/
public BeanShellWhereBuilder bitTest(String field){
return bitTest(null,field,false, false, null);
}
/**
* 创建位运算比较表达式,如{@code (column_name & 100) = $},
* @param field
* @param aggFun
* @return 当前对象
* @see #bitTest(String, String, boolean, boolean, Class)
* @since 3.27.0
*/
@SuppressWarnings("rawtypes")
public BeanShellWhereBuilder bitTest(String field,Class extends BitAggFun> aggFun){
return bitTest(null,field,false, false, aggFun);
}
/**
* 创建位运算比较表达式,如{@code (column_name & 100) = $},
* @param left
* @param field
* @return 当前对象
* @see #bitTest(String, String, boolean, boolean, Class)
* @since 3.27.0
*/
public BeanShellWhereBuilder bitTest(String left, String field){
return bitTest(left,field,false, false, null);
}
/**
* 创建位运算比较表达式,如{@code (column_name & 100) = $},
* @param left
* @param field
* @param aggFun
* @return 当前对象
* @see #bitTest(String, String, boolean, boolean, Class)
* @since 3.27.0
*/
@SuppressWarnings("rawtypes")
public BeanShellWhereBuilder bitTest(String left, String field,Class extends BitAggFun> aggFun){
return bitTest(left,field,false, false, aggFun);
}
/**
* 输入条件{@code test}为{@code true}则生成{@code doStatement}指定的表达式,
* 否则生成{@code elseStatement}指定的表达式,{@code elseStatement}为{@code null}时不生成表达式
* @param test 判断条件
* @param doStatement 判断条件为真时的执行语句
* @param elseStatement 判断条件为假时的执行语句,为{@code null}忽略
* @return 当前对象
*/
public BeanShellWhereBuilder ifelse(String test,String doStatement,String elseStatement){
if(!isNullOrEmpty(test) && !isNullOrEmpty(doStatement)) {
elseStatement = nullToEmpty(elseStatement);
conditionCodes.add(Tmpls.tmpls.get(TMPL_IF_ELSE)
.replace(AND_OR, andor)
.replace("$", test)
.replace("$", doStatement)
.replace("$", elseStatement));
}
return this;
}
/**
* 当满足{@code test}指定的条件以及{@code testNullVars,testNonullVars,testEmptyVars,testNoEmptyVars,testTrueVars,testFalseVars}指定变量满足条件时
* 则生成{@code doStatement}指定的表达式,
* 否则生成{@code elseStatement}指定的表达式,{@code elseStatement}为{@code null}时不生成表达式,
* {@code test,testNullVars,testNonullVars,testEmptyVars,testNoEmptyVars,testTrueVars,testFalseVars}都为空时忽略
* @param test 判断条件
* @param testNullVars 要求为{@code null}的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testNonullVars 要求不为{@code null}的变量名列表,['var1','var2'],等价于'null!=${var1} && null!=${var2}',为{@code null}或空则默认为'true'
* @param testEmptyVars 要求为{@code null}或空的变量名列表,['var1','var2'],等价于'isEmpty(${var1}) && isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testNoEmptyVars 要求不为{@code null}或空的变量名列表,['var1','var2'],等价于'!isEmpty(${var1}) && !isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testTrueVars 要求为{@code true}的变量名列表,['var1','var2'],等价于'isTrue(${var1)} && isTrue(${var2})',为空则默认为'true'
* @param testFalseVars 要求为{@code false}的变量名列表,['var1','var2'],等价于'isFalse(${var1}) && isFalse(${var2})',为空则默认为'true'
* @param doStatement 判断条件为真时的执行语句
* @param elseStatement 判断条件为假时的执行语句,为{@code null}忽略
* @return 当前对象
* @see #ifelse(String, String, String)
* @since 3.25.0
*/
public BeanShellWhereBuilder ifelse(String test,
String[] testNullVars,String[] testNonullVars,String[] testEmptyVars, String[] testNoEmptyVars,
String[] testTrueVars,String[] testFalseVars, String doStatement, String elseStatement){
if(allEmpty(test,testNullVars,testNonullVars,testEmptyVars,testNoEmptyVars,testTrueVars,testFalseVars)) {
return this;
}
return ifelse(buildTestExps(test, testNullVars, testNonullVars, testEmptyVars, testNoEmptyVars, testTrueVars, testFalseVars),
doStatement,elseStatement);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,
* 则生成{@code doStatement}指定的表达式,
* 否则生成{@code elseStatement}指定的表达式,{@code elseStatement}为{@code null}时不生成表达式,
* {@code testVars,testType}为{@code null}或空视为{@code true},
* @param testVars 要求为null的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testType 操作数为1的测试类型
* @param doStatement 判断条件为真时的执行语句
* @param elseStatement 判断条件为假时的执行语句,为{@code null}忽略
* @return 当前对象
* @see #ifelse(String, String, String)
* @since 3.25.0
*/
public BeanShellWhereBuilder ifelse(String[] testVars,VarTestType testType, String doStatement,String elseStatement){
return ifelse(renderVars(testVars, checkVarTestType(testType,1)),doStatement,elseStatement);
}
/**
* 生成对变量{@code testVar}的测试表达式if... else语句,表达式为{@code true}则生成{@code doStatement}指定的表达式,
* 否则生成{@code elseStatement}指定的表达式,{@code elseStatement}为{@code null}时不生成表达式
* @param testVar 条件测试表达式变量名
* @param testType 变量测试类型
* @param testOp 条件测试操作符
* @param testValue 变量条件测试的目标值
* @param testQuote 为{@code true}生成表达式对{@code testValue} 以字符串对头尾增加单引号,{@code refValue}为{@code true}时忽略
* @param testRefValue 为{@code true}生成表达式对{@code testValue} 视为变量名
* @param doStatement 判断条件为真时的执行语句
* @param elseStatement 判断条件为假时的执行语句,为{@code null}忽略
* @return 当前对象
* @since 3.25.0
*/
public BeanShellWhereBuilder testVar(String testVar,VarTestType testType,CompareOp testOp, Object testValue,boolean testQuote,boolean testRefValue, String doStatement,String elseStatement){
if(!isNullOrEmpty(testVar) && null != testType && !isNullOrEmpty(doStatement)) {
String test = testType.render(testVar, testOp, testValue, testQuote,testRefValue);
return ifelse(test,doStatement,elseStatement);
}
return this;
}
/**
* 生成对变量{@code testVar}的测试表达式if语句,表达式为{@code true}则生成{@code doStatement}指定的表达式,
* @param testVar
* @param testType 操作数为3的测试类型
* @param testOp
* @param testValue
* @param testQuote
* @param testRefValue
* @param doStatement
* @see #testVar(String, VarTestType, CompareOp, Object, boolean, boolean, String, String)
* @since 3.25.0
*/
public BeanShellWhereBuilder testVar(String testVar,VarTestType testType,CompareOp testOp, Object testValue,boolean testQuote,boolean testRefValue, String doStatement){
return testVar(testVar,checkVarTestType(testType,3),testOp,testValue,testQuote,testRefValue,doStatement,null);
}
/**
* 生成对变量{@code testVar}的测试表达式if语句,表达式为{@code true}则生成{@code doStatement}指定的表达式,
* @param testVar
* @param testType 操作数为3的测试类型
* @param testOp
* @param testValue
* @param doStatement
* @see #testVar(String, VarTestType, CompareOp, Object, boolean, boolean, String, String)
* @since 3.25.0
*/
public BeanShellWhereBuilder testVar(String testVar,VarTestType testType,CompareOp testOp, Object testValue,String doStatement){
return testVar(testVar,checkVarTestType(testType,3),testOp,testValue,false,false,doStatement,null);
}
/**
* 生成对变量{@code testVar}的测试表达式if语句,表达式为{@code true}则生成{@code doStatement}指定的表达式,
* @param testVar
* @param testType 操作数为2的测试类型
* @param testValue
* @param testQuote
* @param testRefValue
* @param doStatement
* @see #testVar(String, VarTestType, CompareOp, Object, boolean, boolean, String, String)
* @since 3.25.0
*/
public BeanShellWhereBuilder testVar(String testVar,VarTestType testType,Object testValue,boolean testQuote,boolean testRefValue,String doStatement){
return testVar(testVar,checkVarTestType(testType,2),null,testValue,testQuote,testRefValue,doStatement,null);
}
/**
* 生成对变量{@code testVar}的测试表达式if语句,表达式为{@code true}则生成{@code doStatement}指定的表达式,
* @param testVar
* @param testType 操作数为2的测试类型
* @param testValue
* @param doStatement
* @see #testVar(String, VarTestType, CompareOp, Object, boolean, boolean, String, String)
* @since 3.25.0
*/
public BeanShellWhereBuilder testVar(String testVar,VarTestType testType,Object testValue,String doStatement){
return testVar(testVar,checkVarTestType(testType,2),null,testValue,false,false,doStatement,null);
}
/**
* 生成对变量{@code testVar}的测试表达式if语句,表达式为{@code true}则生成{@code doStatement}指定的表达式,
* @param testVar
* @param testType 操作数为1的测试类型
* @param doStatement
* @see #testVar(String, VarTestType, CompareOp, Object, boolean, boolean, String, String)
* @since 3.25.0
*/
public BeanShellWhereBuilder testVar(String testVar,VarTestType testType,String doStatement){
return testVar(testVar,checkVarTestType(testType,1),null,null,false,false,doStatement,null);
}
/**
* 同{@link #ifelse(String, String, String)},只是没有{@code elseStatement}
* @param test 判断条件
* @param doStatement 判断条件为真时的执行语句
* @return 当前对象
* @since 3.25.0
*/
public BeanShellWhereBuilder onlyif(String test,String doStatement){
return ifelse(test, doStatement, null);
}
/**
* 同{@link #ifelse(String, String[], String[], String[], String[], String[], String[], String, String)},只是没有{@code elseStatement}
* @since 3.25.0
*/
public BeanShellWhereBuilder onlyif(String test,
String[] testNullVars,String[] testNonullVars,
String[] testEmptyVars, String[] testNoEmptyVars,
String[] testTrueVars,String[] testFalseVars,
String doStatement){
if(allEmpty(test,testNullVars,testNonullVars,testEmptyVars,testNoEmptyVars,testTrueVars,testFalseVars)) {
return this;
}
return ifelse(buildTestExps(test, testNullVars, testNonullVars, testEmptyVars, testNoEmptyVars, testTrueVars, testFalseVars), doStatement, null);
}
/**
* 同{@link #ifelse(String[], VarTestType, String, String)},只是没有{@code elseStatement}
* @param testVars
* @param testType 操作数为1的测试类型
* @param doStatement
* @since 3.25.0
*/
public BeanShellWhereBuilder onlyif(String[] testVars,VarTestType testType,
String doStatement){
return ifelse(renderVars(testVars, checkVarTestType(testType,1)), doStatement, null);
}
/**
* 创建模糊匹配表达式,如{@code column_name LIKE '%$%'}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则默认为'true'
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param likeOp 模糊匹配方式
* @param refValue 为{@code true}或{@code left}为{@code null}或空生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @since 3.25.0
*/
public BeanShellWhereBuilder like(String test,
String left,String field,LikeOp likeOp, boolean refValue){
if(!isNullOrEmpty(field)) {
checkValidLeft(refValue,left);
conditionCodes.add(Tmpls.tmpls.get(TMPL_LIKE)
.replace(AND_OR, andor)
.replace("${$}", (isNullOrEmpty(left) || refValue)?"${$}":JSON.toJSONString(field))
.replace("$", column(left,field))
.replace("$", field)
.replace(TEST, isNullOrEmpty(test)?"true":test)
.replace("$", firstNonNull(likeOp,LikeOp.DEFAULT).name()));
}
return this;
}
/**
* 创建模糊匹配表达式,如{@code column_name LIKE '%$%'}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则默认为'true'
* @param testNullVars 要求为{@code null}的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testNonullVars 要求不为{@code null}的变量名列表,['var1','var2'],等价于'null!=${var1} && null!=${var2}',为{@code null}或空则默认为'true'
* @param testEmptyVars 要求为{@code null}或空的变量名列表,['var1','var2'],等价于'isEmpty(${var1}) && isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testNoEmptyVars 要求不为{@code null}或空的变量名列表,['var1','var2'],等价于'!isEmpty(${var1}) && !isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testTrueVars 要求为{@code true}的变量名列表,['var1','var2'],等价于'isTrue(${var1)} && isTrue(${var2})',为空则默认为'true'
* @param testFalseVars 要求为{@code false}的变量名列表,['var1','var2'],等价于'isFalse(${var1}) && isFalse(${var2})',为空则默认为'true'
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param likeOp 模糊匹配方式
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @see #like(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder like(String test,
String[] testNullVars,String[] testNonullVars,String[] testEmptyVars, String[] testNoEmptyVars,
String[] testTrueVars, String[] testFalseVars, String left, String field, LikeOp likeOp, boolean refValue){
return like(buildTestExps(test, testNullVars, testNonullVars, testEmptyVars, testNoEmptyVars, testTrueVars, testFalseVars),left,field,likeOp, refValue);
}
/**
* 创建模糊匹配表达式,如{@code column_name LIKE '%$%'}
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param likeOp 模糊匹配方式
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @see #like(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder like(String left,String field,LikeOp likeOp,boolean refValue){
return like(null,left,field,likeOp, refValue);
}
/**
* 创建两侧模糊匹配表达式,如{@code column_name LIKE '%$%'}
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param refValue 为{@code true}或{@code left}为{@code null}或空生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @see #like(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder like(String left,String field, boolean refValue){
return like(null,left,field,LikeOp.DEFAULT,refValue);
}
/**
* 创建两侧模糊匹配表达式,如{@code column_name LIKE '%$%'}
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @return 当前对象
* @see #like(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder like(String left,String field){
return like(null,left,field,LikeOp.DEFAULT,true);
}
/**
* 创建两侧模糊匹配表达式,如{@code column_name LIKE '%$%'}
* @param field 变量名,不为null或空,否则忽略
* @return 当前对象
* @see #like(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder like(String field){
return like(null,null,field,LikeOp.DEFAULT,true);
}
/**
* 如果{@code test} 定义的表达式为{@code true}} ,则创建条件执行的两侧模糊匹配表达式,如{@code column_name LIKE '%$%'}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则不创建表达式
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param likeOp 模糊匹配方式
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @see #like(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder likeIf(String test,String left,String field, LikeOp likeOp, boolean refValue){
if(!isNullOrEmpty(test)) {
return like(test,left,field,likeOp, refValue);
}
return this;
}
/**
* 如果{@code test} 定义的表达式为{@code true}} ,则创建条件执行的两侧模糊匹配表达式,如{@code column_name LIKE '%$%'}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则不创建表达式
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @see #like(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder likeIf(String test,String left,String field, boolean refValue){
return likeIf(test,left,field,LikeOp.DEFAULT, refValue);
}
/**
* 创建条件执行的两侧模糊匹配表达式,如{@code column_name LIKE '%$%'}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则不创建表达式
* @param field 变量名,不为null或空,否则忽略
* @return 当前对象
* @see #like(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder likeIf(String test,String field){
return likeIf(test,null,field,LikeOp.DEFAULT, true);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,则创建模糊匹配表达式,如{@code column_name LIKE '%$%'}
* {@code testVars,testType}为{@code null}或空则不创建表达式
* @param testVars 要求为null的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testType 变量测试类型
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param likeOp 模糊匹配方式
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @see #likeIf(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder likeIf(String[] testVars,VarTestType testType, String left,String field,LikeOp likeOp, boolean refValue){
return likeIf(renderVars(testVars, testType),left,field,likeOp, refValue);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,则创建模糊匹配表达式,如{@code column_name LIKE '%$%'}
* {@code testVars,testType}为{@code null}或空则不创建表达式
* @param testVars 要求为null的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testType 变量测试类型
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param likeOp 模糊匹配方式
* @return 当前对象
* @see #likeIf(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder likeIf(String[] testVars,VarTestType testType, String left,String field,LikeOp likeOp){
return likeIf(renderVars(testVars, testType),left,field,likeOp, true);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,则创建模糊匹配表达式,如{@code column_name LIKE '%$%'}
* {@code testVars,testType}为{@code null}或空则不创建表达式
* @param testVars 要求为null的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param field 变量名,不为null或空,否则忽略
* @param likeOp 模糊匹配方式
* @return 当前对象
* @see #likeIf(String, String, String, LikeOp, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder likeIf(String[] testVars,VarTestType testType, String field,LikeOp likeOp){
return likeIf(renderVars(testVars, testType),null,field,likeOp, true);
}
/**
* 根据{@code testType}指定的类型测试{@code testVar} 指定的变量满足条件,则创建LIKE表达式
* {@code field,testType}为{@code null}或空视则忽略,不生成表达式
* @param testVar 条件测试表达式变量名,为{@code null}或空则默认为{@code field}
* @param testType 变量测试类型
* @param testOp 条件测试操作符
* @param testValue 变量条件测试的目标值
* @param testQuote 为{@code true}生成表达式对{@code testValue} 以字符串对头尾增加单引号,{@code refValue}为{@code true}时忽略
* @param testRefValue 为{@code true}生成表达式对{@code testValue} 视为变量名
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 创建等价表达式的字段名
* @param likeOp 模糊匹配方式
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @since 3.25.0
*/
public BeanShellWhereBuilder likeIf(String testVar,VarTestType testType,CompareOp testOp, Object testValue,boolean testQuote,boolean testRefValue,
String left,String field, LikeOp likeOp, boolean refValue){
String test = buildTestVarExp(testVar, testType, testOp, testValue, testQuote, testRefValue, field);
return likeIf(test,left,field,likeOp, refValue);
}
/**
* 创建算述比较表达式,如{@code column_name > $}
* 当 {@code checkFieldEmpty} 为{@code true}对{@code field}指定的变量执行判断空检查,如果不为{@code null}或空则创建表达式,
* 当 {@code checkFieldEmpty} 为{@code false}对{@code field}指定的变量执行判断null检查,如果不为{@code null}则创建表达式,
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则默认为'true'
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param op 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @param checkFieldEmpty 是否对{@code field}指定的变量执行判断空检查,此参数对于类型为String的参数有影响
*
* {@code true} -- {@code field}指定的变量执行判断空检查
* {@code false} -- 只需要判断是否为{@code null}
* 空 -- 使用{@code quote}
*
* @return 当前对象
* @since 3.25.0
*/
public BeanShellWhereBuilder compare(String test,
String left,String field,CompareOp op, boolean quote,
boolean refValue, Boolean checkFieldEmpty){
if(!isNullOrEmpty(field) && null != op) {
checkValidLeft(refValue,left);
/**
* 非引用模式下,如果不要求加引号,则要求field不能为全空格([ \t\n\r\f\v])字符串否则抛出异常
* 因为这样生成的脚本肯定会因为有语法错误而报错
* */
if(!refValue && !quote && field.replaceAll("\\s*","").isEmpty()) {
throw new WhereHelperException("NOT EMPTY string required for field if refValue is false");
}
String checkEmpty;
if(refValue) {
checkEmpty = firstNonNull(checkFieldEmpty, quote)?"!isEmpty(${$})":"isNonull(${$})";
}else {
checkEmpty = "true";
}
conditionCodes.add(Tmpls.tmpls.get(TMPL_COMPARE)
.replace(AND_OR, andor)
.replace("$", checkEmpty)
.replace("${$}", (isNullOrEmpty(left) || refValue)?"${$}":field)
.replace("$", column(left,field))
.replace("$", field)
.replace(TEST, isNullOrEmpty(test)?"true":test)
.replace("$", String.valueOf(quote))
.replace("$", op.op));
}
return this;
}
/**
* 创建算述比较表达式,如{@code column_name > $}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则默认为'true'
* @param testNullVars 要求为{@code null}的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testNonullVars 要求不为{@code null}的变量名列表,['var1','var2'],等价于'null!=${var1} && null!=${var2}',为{@code null}或空则默认为'true'
* @param testEmptyVars 要求为{@code null}或空的变量名列表,['var1','var2'],等价于'isEmpty(${var1}) && isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testNoEmptyVars 要求不为{@code null}或空的变量名列表,['var1','var2'],等价于'!isEmpty(${var1}) && !isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testTrueVars 要求为{@code true}的变量名列表,['var1','var2'],等价于'isTrue(${var1)} && isTrue(${var2})',为空则默认为'true'
* @param testFalseVars 要求为{@code false}的变量名列表,['var1','var2'],等价于'isFalse(${var1}) && isFalse(${var2})',为空则默认为'true'
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param compareOp 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @param checkFieldEmpty 是否对{@code field}指定的变量执行判断空检查,此参数对于类型为String的参数有影响
* @return 当前对象
* @see #compare(String, String, String, CompareOp, boolean, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder compare(String test,
String[] testNullVars,String[] testNonullVars,String[] testEmptyVars, String[] testNoEmptyVars,
String[] testTrueVars, String[] testFalseVars, String left, String field, CompareOp compareOp, boolean quote, Boolean checkFieldEmpty){
return compare(buildTestExps(test, testNullVars, testNonullVars, testEmptyVars, testNoEmptyVars, testTrueVars, testFalseVars),
left, field, compareOp, quote, true, checkFieldEmpty);
}
/**
* 创建算述比较表达式,如{@code column_name > $}
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param op 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @see #compare(String, String, String, CompareOp, boolean, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder compare(String left, String field, CompareOp op, boolean quote, boolean refValue){
return compare(null,left,field,op,quote,refValue, null);
}
/**
* 创建算述比较表达式,如{@code column_name > $}
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param op 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #compare(String, String, String, CompareOp, boolean, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder compare(String left, String field, CompareOp op, boolean quote){
return compare(null,left,field,op,quote,true, null);
}
/**
* 创建算述比较表达式,如{@code column_name > $}
* @param field 变量名,不为null或空,否则忽略
* @param op 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #compare(String, String, String, CompareOp, boolean, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder compare(String field, CompareOp op, boolean quote){
return compare(null,null,field,op,quote,true, null);
}
/**
* 如果{@code test} 定义的表达式为{@code true}} ,则创建算述比较表达式,如{@code column_name > $}
* @param test 判断条件,条件为'true'则生成比较表达式,为{@code null}或空则不创建表达式
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param op 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @see #compare(String, String, String, CompareOp, boolean, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder compareIf(String test,String left, String field, CompareOp op, boolean quote, boolean refValue){
if(!isNullOrEmpty(test)) {
return compare(test,left,field,op,quote,refValue, null);
}
return this;
}
/**
* 如果{@code test} 定义的表达式为{@code true}} ,则如果{@code test} 定义的表达式为{@code true}} ,则创建算述比较表达式,如{@code column_name > $}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则默认为'true'
* @param field 变量名,不为null或空,否则忽略
* @param op 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #compareIf(String, String, String, CompareOp, boolean, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder compareIf(String test,String field, CompareOp op, boolean quote){
return compareIf(test,null,field,op,quote, true);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,则创建算述比较表达式,如{@code column_name > $}
* {@code testVars,testType}为{@code null}或空视为{@code true},
* @param testVars 要求为null的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 变量名,不为null或空,否则忽略
* @param op 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #compareIf(String, String, String, CompareOp, boolean, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder compareIf(String[] testVars,VarTestType testType, String left, String field, CompareOp op, boolean quote){
return compareIf(renderVars(testVars, testType),left,field,op,quote, true);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,则创建算述比较表达式,如{@code column_name > $}
* {@code testVars,testType}为{@code null}或空视为{@code true},
* @param testVars 要求为null的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param field 变量名,不为null或空,否则忽略
* @param op 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #compareIf(String, String, String, CompareOp, boolean, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder compareIf(String[] testVars,VarTestType testType, String field, CompareOp op, boolean quote){
return compareIf(renderVars(testVars, testType),null,field,op,quote, true);
}
/**
* 根据{@code testType}指定的类型测试{@code testVar} 指定的变量满足条件,则创建算述比较表达式,
* 如{@code column_name > $(column_name)}
* {@code field,testType}为{@code null}或空视则忽略,不生成表达式
* @param testVar 条件测试表达式变量名,为{@code null}或空则默认为{@code field}
* @param testType 变量测试类型
* @param testOp 条件测试操作符
* @param testValue 变量条件测试的目标值
* @param testQuote 为{@code true}生成表达式对{@code testValue} 以字符串对头尾增加单引号,{@code refValue}为{@code true}时忽略
* @param testRefValue 为{@code true}生成表达式对{@code testValue} 视为变量名
* @param left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例left为'dcc.',field为'name',则左侧表达式为'dcc.name'
* @param field 创建等价表达式的字段名
* @param op 算述比较运算符
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @param refValue 为{@code true}生成表达式对{@code field} 视为变量名,否则视为常量
* @return 当前对象
* @since 3.25.0
*/
public BeanShellWhereBuilder compareIf(String testVar,VarTestType testType,CompareOp testOp, Object testValue,boolean testQuote,boolean testRefValue,
String left, String field, CompareOp op, boolean quote,boolean refValue){
String test = buildTestVarExp(testVar, testType, testOp, testValue, testQuote, testRefValue, field);
return compareIf(test,left,field,op, quote, refValue);
}
/**
* 创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* 当 {@code checkFieldEmpty} 为{@code true}对{@code field}指定的变量执行判断空检查,如果不为{@code null}或空则创建表达式,
* 当 {@code checkFieldEmpty} 为{@code false}对{@code field}指定的变量执行判断null检查,如果不为{@code null}则创建表达式,
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则默认为'true'
* @param field 字段名,不为null或空,否则忽略
* @param lowerVar 左侧范围(较小值)变量名,不为null或空,否则忽略
* @param lowerSuffix 左侧范围(较小值)变量名后缀
* @param lowerRefValue 为{@code true}生成SQL表达式对{@code lowerVar}视为变量名,否则视为常量
* @param upperVar 右侧范围(较大值) 变量名,不为null或空,否则忽略
* @param upperSuffix 右侧范围(较大值) 变量名后缀
* @param upperRefValue 为{@code true}生成SQL表达式对{@code upperVar} 视为变量名,否则视为常量
* @param rangeType 范围类型
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @param checkFieldEmpty 是否对{@code field}指定的变量执行判断空检查,此参数对于类型为String的参数有影响
*
* {@code true} -- {@code field}指定的变量执行判断空检查
* {@code false} -- 只需要判断是否为{@code null}
* 空 -- 使用{@code quote}
*
* @return 当前对象
* @since 3.25.0
*/
public BeanShellWhereBuilder range(String test,
String field,String lowerVar,String lowerSuffix, boolean lowerRefValue,
String upperVar, String upperSuffix, boolean upperRefValue, RangeType rangeType, boolean quote, Boolean checkFieldEmpty){
if(!isNullOrEmpty(field)) {
rangeType = firstNonNull(rangeType, RangeType.CLOSEOPEN);
compare(test, field,rangeVar(field,lowerVar,lowerSuffix),rangeType.lower,quote, lowerRefValue, checkFieldEmpty);
compare(test, field,rangeVar(field,upperVar,upperSuffix),rangeType.upper,quote, upperRefValue, checkFieldEmpty);
}
return this;
}
/**
* 创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则默认为'true'
* @param testNullVars 要求为{@code null}的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param testNonullVars 要求不为{@code null}的变量名列表,['var1','var2'],等价于'null!=${var1} && null!=${var2}',为{@code null}或空则默认为'true'
* @param testEmptyVars 要求为{@code null}或空的变量名列表,['var1','var2'],等价于'isEmpty(${var1}) && isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testNoEmptyVars 要求不为{@code null}或空的变量名列表,['var1','var2'],等价于'!isEmpty(${var1}) && !isEmpty(${var2})',为{@code null}或空则默认为'true'
* @param testTrueVars 要求为{@code true}的变量名列表,['var1','var2'],等价于'isTrue(${var1)} && isTrue(${var2})',为空则默认为'true'
* @param testFalseVars 要求为{@code false}的变量名列表,['var1','var2'],等价于'isFalse(${var1}) && isFalse(${var2})',为空则默认为'true'
* @param field 字段名,不为null或空,否则忽略
* @param lowerVar 左侧范围(较小值)变量名,不为null或空,否则忽略
* @param lowerSuffix 左侧范围(较小值)变量名后缀
* @param lowerRefValue 为{@code true}生成SQL表达式对{@code lowerVar}视为变量名,否则视为常量
* @param upperVar 右侧范围(较大值) 变量名,不为null或空,否则忽略
* @param upperSuffix 右侧范围(较大值) 变量名后缀
* @param upperRefValue 为{@code true}生成SQL表达式对{@code upperVar} 视为变量名,否则视为常量
* @param rangeType 范围类型
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @param checkFieldEmpty 是否对{@code field}指定的变量执行判断空检查,此参数对于类型为String的参数有影响
* @return 当前对象
* @see #range(String, String, String, String, boolean, String, String, boolean, RangeType, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder range(String test,
String[] testNullVars,String[] testNonullVars,String[] testEmptyVars, String[] testNoEmptyVars,
String[] testTrueVars, String[] testFalseVars, String field,
String lowerVar, String lowerSuffix, boolean lowerRefValue,
String upperVar, String upperSuffix, boolean upperRefValue,
RangeType rangeType, boolean quote, Boolean checkFieldEmpty){
return range(buildTestExps(test, testNullVars, testNonullVars, testEmptyVars, testNoEmptyVars, testTrueVars, testFalseVars),
field, lowerVar, lowerSuffix, lowerRefValue, upperVar, upperSuffix, upperRefValue, rangeType, quote, checkFieldEmpty);
}
/**
* 创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* @param field 字段名,不为null或空,否则忽略
* @param lowerVar 左侧范围(较小值)变量名,不为null或空,否则忽略
* @param lowerSuffix 左侧范围(较小值)变量名后缀
* @param lowerRefValue 为{@code true}生成SQL表达式对{@code lowerVar}视为变量名,否则视为常量
* @param upperVar 右侧范围(较大值) 变量名,不为null或空,否则忽略
* @param upperSuffix 右侧范围(较大值) 变量名后缀
* @param upperRefValue 为{@code true}生成SQL表达式对{@code upperVar} 视为变量名,否则视为常量
* @param rangeType 范围类型,为{@code null}则视为默认值: {@link RangeType#OPENCLOSE}
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #range(String, String, String, String, boolean, String, String, boolean, RangeType, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder range(String field, String lowerVar,String lowerSuffix, boolean lowerRefValue,String upperVar, String upperSuffix,
boolean upperRefValue, RangeType rangeType, boolean quote){
return range(null,field,lowerVar,lowerSuffix,lowerRefValue,upperVar,upperSuffix,upperRefValue,rangeType, quote, null);
}
/**
* 创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* @param field 字段名,不为null或空,否则忽略
* @param lowerVar 左侧范围(较小值)变量名,不为null或空,否则忽略
* @param upperVar 右侧范围(较大值) 变量名,不为null或空,否则忽略
* @param rangeType 范围类型,为{@code null}则视为默认值: {@link RangeType#OPENCLOSE}
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #range(String, String, String, String, boolean, String, String, boolean, RangeType, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder range(String field, String lowerVar, String upperVar, RangeType rangeType,
boolean quote){
return range(null,field,lowerVar,"_min",true,upperVar,"_max",true,rangeType, quote, null);
}
/**
* 创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* @param field 字段名,不为null或空,否则忽略
* @param rangeType 范围类型,为{@code null}则视为默认值: {@link RangeType#OPENCLOSE}
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #range(String, String, String, String, boolean, String, String, boolean, RangeType, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder range(String field, RangeType rangeType,
boolean quote){
return range(null,field,null,"_min",true,null,"_max",true,rangeType, quote, null);
}
/**
* 创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* 范围类型为{@link RangeType#OPENCLOSE}
* @param field 字段名,不为null或空,否则忽略
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #range(String, String, String, String, boolean, String, String, boolean, RangeType, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder range(String field, boolean quote){
return range(null,field,null,"_min",true,null,"_max",true,RangeType.OPENCLOSE, quote, null);
}
/**
* 如果{@code test} 定义的表达式为{@code true}} ,则创建数值范围算述比较表达式,如{@code column_name > $(lower_value)> && column_name <= $(upper_value)}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则不创建表达式
* @param field 字段名,不为null或空,否则忽略
* @param lowerVar 左侧范围(较小值)变量名,不为null或空,否则忽略
* @param lowerSuffix 左侧范围(较小值)变量名后缀
* @param lowerRefValue 为{@code true}生成SQL表达式对{@code lowerVar}视为变量名,否则视为常量
* @param upperVar 右侧范围(较大值) 变量名,不为null或空,否则忽略
* @param upperSuffix 右侧范围(较大值) 变量名后缀
* @param upperRefValue 为{@code true}生成SQL表达式对{@code upperVar} 视为变量名,否则视为常量
* @param rangeType 范围类型,为{@code null}则视为默认值: {@link RangeType#OPENCLOSE}
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #range(String, String, String, String, boolean, String, String, boolean, RangeType, boolean, Boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder rangeIf(String test,
String field,String lowerVar,String lowerSuffix, boolean lowerRefValue,String upperVar, String upperSuffix,
boolean upperRefValue, RangeType rangeType, boolean quote){
if(!isNullOrEmpty(test)) {
return range(test,field,lowerVar,lowerSuffix,lowerRefValue,upperVar,upperSuffix,upperRefValue,rangeType, quote, null);
}
return this;
}
/**
* 如果{@code test} 定义的表达式为{@code true}} ,则创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则不创建表达式
* @param field 字段名,不为null或空,否则忽略
* @param lowerVar 左侧范围(较小值)变量名,不为null或空,否则忽略
* @param upperVar 右侧范围(较大值) 变量名,不为null或空,否则忽略
* @param rangeType 范围类型,为{@code null}则视为默认值: {@link RangeType#OPENCLOSE}
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #rangeIf(String, String, String, String, boolean, String, String, boolean, RangeType, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder rangeIf(String test, String field,String lowerVar,String upperVar, RangeType rangeType, boolean quote){
return rangeIf(test,field,lowerVar,"_min",true,upperVar,"_max",true,rangeType, quote);
}
/**
* 如果{@code test} 定义的表达式为{@code true}} ,则创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* @param test 判断条件,条件为'true'则生成LIKE表达式,为{@code null}或空则不创建表达式
* @param field 字段名,不为null或空,否则忽略
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #rangeIf(String, String, String, String, boolean, String, String, boolean, RangeType, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder rangeIf(String test, String field, boolean quote){
return rangeIf(test,field,null,"_min",true,null,"_max",true,RangeType.OPENCLOSE, quote);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,则创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* {@code testVars,testType}为{@code null}或空视为{@code true},
* @param testVars 要求为{@code null}的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param field 字段名,不为null或空,否则忽略
* @param lowerVar 左侧范围(较小值)变量名,不为null或空,否则忽略
* @param lowerSuffix 左侧范围(较小值)变量名后缀
* @param lowerRefValue 为{@code true}生成SQL表达式对{@code lowerVar}视为变量名,否则视为常量
* @param upperVar 右侧范围(较大值) 变量名,不为null或空,否则忽略
* @param upperSuffix 右侧范围(较大值) 变量名后缀
* @param upperRefValue 为{@code true}生成SQL表达式对{@code upperVar} 视为变量名,否则视为常量
* @param rangeType 范围类型,为{@code null}则视为默认值: {@link RangeType#OPENCLOSE}
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #rangeIf(String, String, String, String, boolean, String, String, boolean, RangeType, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder rangeIf(String[] testVars,VarTestType testType,String field,
String lowerVar,String lowerSuffix, boolean lowerRefValue,
String upperVar, String upperSuffix, boolean upperRefValue,
RangeType rangeType, boolean quote){
return rangeIf(renderVars(testVars, testType),field,lowerVar,lowerSuffix,lowerRefValue,upperVar,upperSuffix,upperRefValue,rangeType, quote);
}
/**
* 根据{@code testType}指定的类型测试{@code testVars} 指定的变量所有变量都满足条件,则创建数值范围算述比较表达式,如{@code column_name > $(column_name_min) && column_name <= $(column_name_max)}
* {@code testVars,testType}为{@code null}或空视为{@code true},
* @param testNullVars 要求为{@code null}的变量名列表,['var1','var2'],等价于'null==${var1} && null==${var2}',为{@code null}或空则默认为'true'
* @param field 字段名,不为null或空,否则忽略
* @param lowerVar 左侧范围(较小值)变量名,不为null或空,否则忽略
* @param upperVar 右侧范围(较大值) 变量名,不为null或空,否则忽略
* @param rangeType 范围类型,为{@code null}则视为默认值: {@link RangeType#OPENCLOSE}
* @param quote 为{@code true}生成表达式对数值以字符串对头尾增加单引号
* @return 当前对象
* @see #rangeIf(String, String, String, String, boolean, String, String, boolean, RangeType, boolean)
* @since 3.25.0
*/
public BeanShellWhereBuilder rangeIf(String[] testNullVars,VarTestType testType, String field,
String lowerVar, String upperVar, RangeType rangeType, boolean quote){
return range(renderVars(testNullVars, testType),field,lowerVar,"_min",true,upperVar,"_max",true,rangeType, quote, null);
}
/**
* 指定SELECT .... FROM 语句,如果不指定,则只生成 WHERE ....部分语句
* @param selectFrom select 语句(不含 WHERE部分),为{@code null}忽略
* @return 当前对象
*/
public BeanShellWhereBuilder selectFrom(String selectFrom) {
if(!isNullOrEmpty(selectFrom)) {
this.selectFrom = selectFrom;
}
return this;
}
/**
* 指定ORDER BY 的字段名
* @param columnName order by 字段名
* @param desc 排序方式,为{@code true}降序
* @return 当前对象
*/
public BeanShellWhereBuilder orderBy(String columnName,boolean desc) {
columnName = nullToEmpty(columnName).trim();
if(!isNullOrEmpty(columnName)) {
checkArgument(columnName.matches("('\\w+'|\\w+)"));
orderByColumns.add(columnName +(desc?" DESC ": ""));
}
return this;
}
/**
* 指定ORDER BY 的字段名,格式要求 ${字段名}[ DESC|ASC]
* @param columnName order by 字段名,为{@code null}或空忽略
* @return 当前对象
*/
public BeanShellWhereBuilder orderBy(String columnName) {
if(!isNullOrEmpty(columnName)){
orderByColumns.add(validOrderBy(columnName));
}
return this;
}
/**
* 指定ORDER BY 的字段变量名
* @param varName order by 字段字段名,为{@code null}或空忽略
* @return 当前对象
*/
public BeanShellWhereBuilder orderByVar(String varName) {
if(!isNullOrEmpty(varName)){
varName = varName.trim();
// 必须是以字母开头的只包含数字字母下划线的字符串
checkArgument(varName.matches("^[_a-zA-Z]\\w*(\\.\\w+)?$"),"INVALID variable name [%s]",varName);
this.orderByVarname = varName;
}
return this;
}
/**
* 指定GROUP BY 的字段名
* @param columnNames group by 字段名列表,为{@code null}忽略
* @return 当前对象
*/
public BeanShellWhereBuilder groupBy(String ...columnNames) {
if(null != columnNames){
Iterable normalized = Iterables.transform(Arrays.asList(columnNames), getFormatJsonFieldFunction());
Iterables.addAll(groupByColumns,
Iterables.filter(normalized, s->!isNullOrEmpty(s)));
}
return this;
}
/**
* 指定GROUP BY 的字段变量名
* @param varName group by 字段变量名,为{@code null}或空忽略
* @return 当前对象
*/
public BeanShellWhereBuilder groupByVar(String varName) {
if(!isNullOrEmpty(varName)){
varName = varName.trim();
// 必须是以字母开头的只包含数字字母下划线的字符串
checkArgument(varName.matches("$[[:alpha:]]\\w?"));
this.groupByVarname = varName;
}
return this;
}
/**
* 增加import类型语句,每一个元素为一行导入语句,为{@code null}或空忽略。
* 如: {@code import xxx..xxx.ClassA;} 或只提供导入类全名 {@code xxx..xxx.ClassA}
* @param imports
* @return 当前对象
*/
public BeanShellWhereBuilder imports(String ...imports){
if(null != imports){
return withImports(Arrays.asList(imports));
}
return this;
}
/**
* 增加import类型语句,每一个元素为一行导入语句,为{@code null}或空忽略。
* 如: {@code import xxx..xxx.ClassA;}或只提供导入类全名 {@code xxx..xxx.ClassA}
* @param imports
* @return 当前对象
*/
public BeanShellWhereBuilder withImports(Iterable imports){
if(null != imports){
Iterable trans = Iterables.transform(imports, imp->{
imp = nullToEmpty(imp).trim();
if(!imp.isEmpty()){
if(!imp.startsWith("import")){
imp = "import " + imp;
}
if(!imp.endsWith(";")){
imp = imp + ";";
}
imp = imp.replace('$', '.');
}
return imp;
});
Iterables.addAll(importLines,trans);
}
return this;
}
/**
* 从注解中创建表达式
* @param annots
* @return 当前对象
*/
public BeanShellWhereBuilder from(Annotation[] annots){
if(null != annots){
for(Annotation a:annots){
if(a.annotationType() == EnableWhereHelper.class){
EnableWhereHelper enableWhereHelper = (EnableWhereHelper)a;
selectFrom = enableWhereHelper.value();
debuglog = enableWhereHelper.debuglog();
andor = validLogicOperator(enableWhereHelper.logicOperator());
targetClass = enableWhereHelper.targetClass();
buildVarTypes(enableWhereHelper);
}else if(a.annotationType() == Equal.class ){
Equal eq = (Equal)a;
equal(eq.left(),eq.value(),eq.not(), eq.orNull()?false:eq.notCheckEmpty(), eq.orNull());
}else if(a.annotationType() == BitTest.class ){
BitTest eq = (BitTest)a;
bitTest(eq.left(),eq.value(),eq.bitOr(), eq.orNull()?false:eq.notCheckEmpty(), eq.aggFun());
}else if(a.annotationType() == EqualIf.class ){
EqualIf eq = (EqualIf)a;
String testVarExp = buildTestVarExp(eq.testVar(), eq.testType(), eq.testOp(),
eq.testValue(), eq.testQuote(),eq.testRefValue(),eq.field());
String testexps = buildTestExps(eq.test(),
eq.testNullVars(),eq.testNonullVars(),
eq.testEmptyVars(),eq.testNoEmptyVars(),
eq.testTrueVars(), eq.testFalseVars());
equalIf(reduceExps(testexps,testVarExp),eq.left(),eq.field(), eq.not(), eq.notCheckEmpty());
}else if(a.annotationType() == Expression.class ){
Expression exp = (Expression)a;
exp(exp.value());
}else if(a.annotationType() == Like.class ){
Like like = (Like)a;
String testVarExp = buildTestVarExp(like.testVar(), like.testType(), like.testOp(),
like.testValue(), like.testQuote(),like.testRefValue(),like.value());
String testexps = buildTestExps(like.test(),
like.testNullVars(),like.testNonullVars(),
like.testEmptyVars(),like.testNoEmptyVars(),
like.testTrueVars(), like.testFalseVars());
like(reduceExps(testexps,testVarExp),like.left(),like.value(),like.op(), like.refValue());
}else if(a.annotationType() == Compare.class ){
Compare cmp = (Compare)a;
String testVarExp = buildTestVarExp(cmp.testVar(), cmp.testType(), cmp.testOp(),
cmp.testValue(), cmp.testQuote(),cmp.testRefValue(),cmp.value());
String testexps = buildTestExps(cmp.test(),
cmp.testNullVars(),cmp.testNonullVars(),
cmp.testEmptyVars(),cmp.testNoEmptyVars(),
cmp.testTrueVars(), cmp.testFalseVars());
compare(reduceExps(testexps,testVarExp),
cmp.left(),cmp.value(),cmp.op(),cmp.quote(),
cmp.refValue(),
/** 为空使用 quote */
cmp.checkFieldEmpty().length==0 ? cmp.quote() : cmp.checkFieldEmpty()[0]);
}else if(a.annotationType() == Range.class ){
Range range = (Range)a;
String testVarExp = buildTestVarExp(range.testVar(), range.testType(), range.testOp(),
range.testValue(), range.quote(),range.testRefValue(),range.testVar());
String testexps = buildTestExps(range.test(),
range.testNullVars(),range.testNonullVars(),
range.testEmptyVars(),range.testNoEmptyVars(),
range.testTrueVars(), range.testFalseVars());
range(reduceExps(testexps,testVarExp),
range.field(),
range.lowerVar(), range.lowerSuffix(),range.lowerRefValue(),
range.upperVar(), range.upperSuffix(),range.upperRefValue(),
range.rangeType(), range.quote(), /** 为空使用 quote */
range.checkFieldEmpty().length==0 ? range.quote() : range.checkFieldEmpty()[0]);
}else if(a.annotationType() == IfElse.class){
IfElse ifelse = (IfElse)a;
String testVarExp = buildTestVarExp(ifelse.testVar(), ifelse.testType(), ifelse.testOp(),
ifelse.testValue(), ifelse.testQuote(),ifelse.testRefValue(),ifelse.testVar());
String testexps = buildTestExps(ifelse.test(),
ifelse.testNullVars(),ifelse.testNonullVars(),
ifelse.testEmptyVars(),ifelse.testNoEmptyVars(),
ifelse.testTrueVars(), ifelse.testFalseVars());
ifelse(reduceExps(testexps,testVarExp), ifelse.doStatement(), ifelse.elseStatement());
}else if (a.annotationType() == OrderBy.class) {
OrderBy orderBy = (OrderBy)a;
String[] orderBys = orderBy.value();
for(String o: orderBys){
orderBy(o);
}
orderByVar(orderBy.orderByVarname());
} else if (a.annotationType() == GroupBy.class) {
groupBy(((GroupBy)a).value());
} else {
try {
Method method = a.annotationType().getMethod("value");
Class> returnType = method.getReturnType();
if(returnType.isArray() && Annotation.class.isAssignableFrom(returnType.getComponentType()) ){
// 递归
from((Annotation[])method.invoke(a));
}
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
}
}
}
}
return this;
}
/**
* 根据指定的条件生成BeanShell脚本
* @return BeanShell脚本字符串
*/
String buildScript() {
//checkState(!conditionCodes.isEmpty(),"must define condition statement");
conditionCodes.add(Tmpls.tmpls.get(TMPL_GROUP_BY)
.replace("${"+DEFAULT_GROUP_BY_VAR+"}", "${"+groupByVarname+"}"));
conditionCodes.add(Tmpls.tmpls.get(TMPL_ORDER_BY)
.replace("${"+DEFAULT_ORDER_BY_VAR+"}", "${"+orderByVarname+"}"));
if(pagequery){
if(DT_MYSQL.equals(sqltype)){
conditionCodes.add(Tmpls.tmpls.get(TMPL_LIMIT));
}
}
StringBuffer buffer = new StringBuffer();
if(!importLines.isEmpty()){
buffer.append(Joiner.on("\n").join(importLines));
}
if(!selectFrom.isEmpty()) {
buffer.append(String.format("where_buffer.append(\"%s \");\n",selectFrom));
}
String script=buffer.append(Tmpls.tmpls.get(TMPL_BEFORE_COND))
.append(extractReferenceVariables(Joiner.on("\n").join(conditionCodes)))
.append(Tmpls.tmpls.get(TMPL_AFTER_COND)).toString();
log(debuglog,"\n"+renderLine(script));
log(debuglog,"referenceVariables: {}",Iterables.toString(referenceVariables));
return script;
}
/**
* 将字符串中的${varname}格式的变量引用名从字符串中摘出参与运算,
* 并生成引用变量名集合保存到{@link #referenceVariables}
* @param input
* @return 引用变量名集合
*/
private String extractReferenceVariables(String input){
this.referenceVariables = Sets.newHashSet();
if(!isNullOrEmpty(input)){
Pattern pattern = Pattern.compile("\\$\\{(\\w+)\\}");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
referenceVariables.add(matcher.group(1));
}
return replaceVar(input);
}
return input;
}
/**
* 通过正则表达式匹配将字符串中的${varname}格式的变量引用名从字符串中摘出参与运算,
* @param input
* @return 替换后的字符串
*/
private String replaceVar(String input){
/**
* 支持 (?[] vartypes = annot.varTypeValues();
/** 数组长度必须一样 */
checkArgument(varnames.length == vartypes.length,
"INVALID variable type defined by EnableWhereHelper,array length of varTypeKeys must equal with varTypeValues");
this.varTypes = Maps.newHashMap();
for(int i=0;i 1 && isEmpty(testValue)) {
return "";
}
/** 3个操作数时要求 testOp不能为null */
if(testType.opcount > 2 && (null == testOp)) {
return "";
}
if(isNullOrEmpty(testVar)) {
testVar = field;
}
return testType.render(testVar, testOp, testValue, testQuote,testRefValue);
}
return "";
}
/**
* 为输入的字符串每一行前端加行号
* @param input
*/
static String renderLine(String input) {
if(!isNullOrEmpty(input)) {
Pattern p1= Pattern.compile("^(.*)",Pattern.MULTILINE);
Matcher m1 = p1.matcher(input);
StringBuffer sb = new StringBuffer();
int line = 0;
while(m1.find()){
m1.appendReplacement(sb, String.format("%03d:$1",++line));
}
m1.appendTail(sb);
return sb.toString();
}
return input;
}
/**
* 计算范围表达式的左右侧范围变量名
*
* var值 suffix值 field值 返回值
* 非空 var
* 空 非空 非空 field+suffix
* 空 空 null
*
* @param field 字段名
* @param var 范围变量名
* @param suffix 范围变量名后缀
*/
private static String rangeVar(String field, String var,String suffix) {
if(!isEmpty(var)) {
return var;
}
if(!isNullOrEmpty(suffix) && !isNullOrEmpty(field)) {
return field + suffix;
}
return null;
}
private static String renderVars(String[] testVars,VarTestType testType) {
String truestr = String.valueOf(true);
if(!isEmpty(testVars) && null != testType) {
String defOp = " && ";
String first = firstNonNull(testVars[0], defOp).trim() ;
String rx = "^(&&|\\|\\|)$";
String combinOp = first.matches(rx)? " "+ first +" ": defOp;
return Arrays.asList(testVars)
.stream().filter(s->!isNullOrEmpty(s)&& !s.trim().matches(rx)).map(testType::render).reduce((l,r)->l + combinOp + r).orElse(truestr);
}
return truestr;
}
static String buildTestExps(String test,
String[] testNullVars,String[] testNonullVars,
String[] testEmptyVars, String[] testNoEmptyVars,
String[] testTrueVars, String[] testFalseVars){
String truestr = String.valueOf(true);
String nullexp = renderVars(testNullVars,VarTestType.NULL);
String nonullexp = renderVars(testNonullVars,VarTestType.NONULL);
String emptyexp = renderVars(testEmptyVars,VarTestType.EMPTY);
String noemptyexp = renderVars(testNoEmptyVars,VarTestType.NOEMPTY);
String trueexp = renderVars(testTrueVars,VarTestType.TRUE);
String falseexp = renderVars(testFalseVars,VarTestType.FALSE);
return Arrays.asList(isNullOrEmpty(test)? truestr:test,nullexp,nonullexp,emptyexp,noemptyexp,trueexp,falseexp)
.stream()
.filter(s->!truestr.equals(s))
.reduce((l,r)->"("+l+") && ("+r+")").orElse(truestr);
}
private static String reduceExps(String... exps){
return isEmpty(exps)? "":Arrays.asList(exps)
.stream()
.filter(s->!isNullOrEmpty(s))
.reduce((l,r)->"("+l+") && ("+r+")").orElse("");
}
/**
* 根据输入的值计算表达式左边的字段名
* left 为'.'结尾的字符串,则left被视为表名前缀,其左侧表达式值拼接会field,示例:left为'dcc.',field为'name',则返回的左侧表达式为'dcc.name'
* @param left 输入的表达式左侧字段名
* @param field 字段/变量名
*/
private static String column(String left,String field) {
String _left = left;
if(isNullOrEmpty(_left)) {
_left = field;
}else {
if(_left.endsWith(".")) {
_left += field;
}else {
if (_left.matches(".+->>?$")) {
_left += field;
}
_left = getFormatJsonFieldFunction().apply(_left);
}
}
return _left;
}
/**
* 检查 输入的{@code left}是否有效无效则抛出异常
* {@code refValue}为{@code true}时 left 为{@code null}或空或 为'.'结尾的字符串,则抛出异常
* @param refValue 字段/变量名是否为引用
* @param left 输入的表达式左侧字段名
* @return always left
*/
private static String checkValidLeft(boolean refValue,String left) {
if(!refValue && (isNullOrEmpty(left) ||left.endsWith("."))) {
throw new WhereHelperException("INVALID left: " + String.valueOf(left)+" ,not null,not empty,not end with . required");
}
return left;
}
/**
* 适用于MYSQL的JSON字符表达格式化方法
*/
static final Function FMT_JSON_FIELD_MYSQL = new Function(){
@Override
public String apply(String input) {
input = nullToEmpty(input).trim();
Matcher matcher = Pattern.compile("(\\w+)->>?(\\$\\.)?(\\w+)|'(\\w+)->>?(\\$\\.)?(\\w+)'").matcher(input);
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
if(!isNullOrEmpty(matcher.group(1))) {
matcher.appendReplacement(buffer, "$1->>'\\$.$3'");
}else {
matcher.appendReplacement(buffer, "$4->>'\\$.$6'");
}
}
matcher.appendTail(buffer);
return buffer.toString();
}};
/**
* @return JSON字符表达格式化方法
* @since 3.28.0
*/
static Function getFormatJsonFieldFunction(){
return FMT_JSON_FIELD_MYSQL;
}
/**
* 检查ORDER BY 字段的合法性,不合法则抛出异常
* @param input
* @return input always
*/
private static String validOrderBy(String input){
input = getFormatJsonFieldFunction().apply(input);
Matcher matcher = Pattern.compile("((^|,)\\s*(\\w+\\.)?\\w+(->>?'(\\$\\.)?\\w+')?(?: +(ASC|DESC))?)*",
Pattern.CASE_INSENSITIVE).matcher(input);
checkArgument(!isNullOrEmpty(input) && matcher.matches() ,"INVALID ORDER BY COLUMN %s",input);
return input;
}
/**
* 检查逻辑操作符的合法性
* @param input
* @return input always
*/
private static String validLogicOperator(String input){
input = nullToEmpty(input).trim();
checkArgument(!isNullOrEmpty(input) && Pattern.compile("AND|OR",Pattern.CASE_INSENSITIVE).matcher(input).matches()
," INVALID logic operator [%s],'AND' or 'OR' required",input);
return input;
}
/**
* 加载指定的bsh脚本模板资源
* @param tmpl
* @return bsh脚本模板
*/
private static String loadTemplate(String tmpl){
URL url = checkNotNull(WhereHelper.class.getResource(tmpl),"not found template %s", tmpl);
try {
return Resources.toString(url, Charsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 加载所有需要的bsh脚本模板数据
* @return ${模板名}--${脚本模板数据}的映射
*/
private static ImmutableMap loadAllTemplates(){
// 加载所有模板
return Maps.toMap(Sets.newHashSet(TMPL_EXP,TMPL_EQUAL,TMPL_BIT_TEST,TMPL_EQUAL_IF,TMPL_IF_ELSE,TMPL_LIKE,TMPL_COMPARE,TMPL_GROUP_BY,TMPL_ORDER_BY,TMPL_LIMIT,TMPL_BEFORE_COND,TMPL_AFTER_COND),
new Function() {
@Override
public String apply(String input) {
return loadTemplate("bsh_" + input);
}
});
}
}