All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 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 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 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 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 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); } }); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy