com.jquicker.persistent.rdb.sqlfile.SQLParser Maven / Gradle / Ivy
package com.jquicker.persistent.rdb.sqlfile;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import com.jquicker.args.MethodInfo;
import com.jquicker.commons.util.ObjectUtils;
import com.jquicker.commons.util.RandomUtils;
import com.jquicker.commons.util.RegexUtils;
import com.jquicker.commons.util.StringUtils;
import com.jquicker.model.BaseEntity;
import com.jquicker.persistent.rdb.model.FinalSQL;
import com.jquicker.persistent.rdb.model.DynamicSQL;
import com.jquicker.persistent.rdb.model.SQLExpression;
import com.jquicker.persistent.rdb.model.SQLParam;
public class SQLParser {
public static final String COMMENT = "/\\*[\\S\\s]*?\\*/";
public static final String PARAMS = "(#|$)\\(([A-Za-z0-9_]+?)\\)"; // #(paramName)
public static final String EXPRESSION = "#(if|else\\s*if|else|for)\\s*(?:\\(([\\S\\s]+?)\\))?\\s*\\{([\\S\\s]*?)\\}";
public static final String IF = "if";
public static final String ELSE_IF = "elseif";
public static final String ELSE = "else";
public static final String FOR = "for";
static ScriptEngineManager engineManager = new ScriptEngineManager();
private static Map methodMap = new HashMap();
public static MethodInfo getMethodInfo(String className, String methodName) {
return methodMap.get(StringUtils.concat(".", className, methodName));
}
public static void addMethodInfo(String className, String methodName, MethodInfo methodInfo) {
methodMap.put(StringUtils.concat(".", className, methodName), methodInfo);
}
/**
* 取得原始sql中的所有表达式
* @param sqlStatement
* @return
* @author OL
*/
public static List findExpressions(String sqlStatement){
List list = new ArrayList();
Pattern pattern = Pattern.compile(EXPRESSION);
Matcher matcher = pattern.matcher(sqlStatement);
while (matcher.find()) {
SQLExpression expression = new SQLExpression();
expression.setContent(matcher.group(0));
expression.setKey(matcher.group(1).trim().replace(" ", ""));
expression.setCondition(matcher.group(2) == null ? null : matcher.group(2).trim());
expression.setSqlPart(matcher.group(3) == null ? null : matcher.group(3).trim());
list.add(expression);
}
return list;
}
/**
* 取得sql语句中的参数列表
* @param sqlStatement
* @return
* @author OL
*/
public static List findParams(String sqlStatement){
List list = new ArrayList();
Pattern pattern = Pattern.compile(PARAMS);
Matcher matcher = pattern.matcher(sqlStatement);
while (matcher.find()) {
SQLParam param = new SQLParam();
param.setContent(matcher.group(0));
param.setKey(matcher.group(1));
param.setName(matcher.group(2));
list.add(param);
}
return list;
}
/**
* 根据传入参数动态解析表达式
* @param sql
* @param params
* @return
* @author OL
*/
public static FinalSQL parse(DynamicSQL sql, Map params){
boolean mark = false;
List expressions = sql.getExpressions();
String sqlStatement = sql.getSqlStatement();
for (int i = 0; i < expressions.size(); i++) {
SQLExpression expression = expressions.get(i);
String key = expression.getKey();
String sqlPart = expression.getSqlPart();
String condition = expression.getCondition();
boolean isTrue = false;
if(IF.equals(key)) {
mark = false; // 碰上IF则把mark置为false
mark = isTrue = eval(condition, params);
}
if(ELSE_IF.equals(key)) {
if(mark) { // 当mark为true时,表示在一个IF()...ELSE IF()...里面已经有满足条件的分支了
isTrue = false;
} else {
mark = isTrue = eval(condition, params);
}
}
if(ELSE.equals(key)) {
if(mark == false) {
isTrue = true;
}
}
if(FOR.equals(key)){
isTrue = true;
sqlPart = parseFor(expression, params);
}
if(isTrue){
sqlStatement = sqlStatement.replace("expression_" + i, sqlPart);
} else {
sqlStatement = sqlStatement.replaceAll("expression_" + i + "\\s*", "");
}
}
List sqlParams = findParams(sqlStatement); // 取得sql中的参数列表
Object[] finalArgs = new Object[sqlParams.size()];
for (int i = 0; i < finalArgs.length; i++) {
SQLParam param = sqlParams.get(i);
String name = param.getName();
finalArgs[i] = params.get(name);
}
FinalSQL finalSQL = new FinalSQL();
finalSQL.setSql(SQLParser.makeFinalSql(sqlStatement));
finalSQL.setParams(finalArgs);
return finalSQL;
}
/**
* 根据传入参数动态解析表达式
* @param sql
* @param methodInfo
* @param args
* @return
* @author OL
*/
public static FinalSQL parse(DynamicSQL sql, MethodInfo methodInfo, Object... args){
Map params = convertArgs(methodInfo, args);
return parse(sql, params);
}
/**
* 去掉注释
*
* @return
* @author OL
*/
public static void removeComment(DynamicSQL sql) {
String sqlStatement = sql.getSqlStatement().replaceAll(COMMENT, " ");
sql.setSqlStatement(sqlStatement);
}
public static boolean eval(String script, Map params) {
boolean result = false;
if(script.matches("[a-zA-Z0-9_]+")) {
Object obj = params.get(script);
if(obj == null || obj == "" || obj.equals("")) {
return false;
} else {
Class> clazz = obj.getClass();
if(clazz.isArray()){
if(Array.getLength(obj) == 0){
return false;
}
} else if(Collection.class.isAssignableFrom(clazz)){
Collection> c = (Collection>) obj;
if(c.isEmpty()){
return false;
}
} else if(Map.class.isAssignableFrom(clazz)){
Map, ?> m = (Map, ?>) obj;
if(m.isEmpty()){
return false;
}
}
return true;
}
}
ScriptEngine engine = engineManager.getEngineByName("JavaScript");
try {
if(params != null) {
Set> set = params.entrySet();
for (Entry entry : set) {
engine.put(entry.getKey(), entry.getValue());
}
}
result = (boolean) engine.eval(script);
} catch (ScriptException e) {
e.printStackTrace();
} finally {
engine = null;
}
return result;
}
/**
* 生成最终Sql
* 即将命名参数占位符替换成“?”
* @param sql
* @return
* @author OL
*/
public static String makeFinalSql(String sqlStatement){
return sqlStatement.replaceAll(PARAMS, "?");
}
/**
* 将方法入参按类型转换成Map形式,以便解析动态SQL
* @param methodInfo
* @param args
* @return
* @author OL
*/
@SuppressWarnings("unchecked")
private static Map convertArgs(MethodInfo methodInfo, Object[] args) {
Class>[] types = methodInfo.getParamTypes();
String[] argNames = methodInfo.getNames();
int count = methodInfo.getParamCount();
Map params = new HashMap();
for (int i = 0; i < count; i++) {
Class> type = types[i];
if(ObjectUtils.isPrimitivePlus(type)) {
// 如果是String、Integer...
params.put(argNames[i], args[i]);
} else if(BaseEntity.class.isAssignableFrom(type)) {
// 如果是BaseEntity
params.putAll(((BaseEntity) args[i]).getFields());
} else if(Map.class.isAssignableFrom(type)) {
// 如果是Map
params.putAll((Map) args[i]);
} else if(type.isArray() || Collection.class.isAssignableFrom(type)) {
// 如果是数组 OR Collection
params.put(argNames[i], args[i]);
} else {
// 普通对象
params.putAll(ObjectUtils.toMap(args[i]));
}
}
return params;
}
/**
* 解析FOR语句
* @param expression
* @param params
* @author OL
*/
private static String parseFor(SQLExpression expression, Map params){
StringBuilder sqlPartBuilder = new StringBuilder();
String sqlPart = expression.getSqlPart();
String condition = expression.getCondition();
String[] array = condition.split("\\s*,\\s*(?!\\s*'|\\s*\")"); // 不匹配包在单引号或者双引号之间的逗号
String before = "";
String after = "";
if(array.length > 1){
for (int i = 1; i < array.length; i++) {
String[] tmps = array[i].split("\\s*=\\s*");
if(tmps[0].equals("before")){
before = tmps[1].replaceAll("'|\"", "");
} else if(tmps[0].equals("after")){
after = tmps[1].replaceAll("'|\"", "");
}
}
}
String[] forSentence = array[0].split("\\s*:\\s*");
Object obj = params.get(forSentence[1]);
if(obj == null){
return sqlPartBuilder.toString();
}
String itemName = forSentence[0];
List sqlPartScripts = RegexUtils.find(sqlPart, itemName + "([.][a-zA-Z0-9_]+)?");
String random = RandomUtils.number(4);
String prefix = forSentence[1] + "_";
Class> clazz = obj.getClass();
if(clazz.isArray()){
Object[] objs = (Object[]) obj;
for (int i = 0; i < objs.length; i++) {
String tmpPart = sqlPart;
sqlPartBuilder.append(before);
for (String script : sqlPartScripts) {
String name = prefix + script.replace(".", "_") + "_" + random + "_" + i;
// sqlPartBuilder.append(eval(sqlPart, itemName, objs[i]));
// sqlPart = sqlPart.replace("for.index", i + "");
tmpPart = tmpPart.replace(script, "#(" + name + ")");
params.put(name, getValue(script, itemName, objs[i]));
}
sqlPartBuilder.append(tmpPart);
sqlPartBuilder.append(after);
}
if(sqlPartBuilder.length() > 0){
sqlPartBuilder.delete(0, before.length());
sqlPartBuilder.delete(sqlPartBuilder.lastIndexOf(after), sqlPartBuilder.length());
}
} else if(Collection.class.isAssignableFrom(clazz)){
@SuppressWarnings("unchecked")
Collection
© 2015 - 2024 Weber Informatics LLC | Privacy Policy