Skip to content

Commit 1b7c6f1

Browse files
committed
Operation.ON 改为 IF 并新增支持执行自定义代码
1 parent 39bdc58 commit 1b7c6f1

File tree

4 files changed

+157
-27
lines changed

4 files changed

+157
-27
lines changed

APIJSONORM/src/main/java/apijson/JSON.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ public static JSONObject parseObject(String json) {
9898
* @return
9999
*/
100100
public static <T> T parseObject(String json, Class<T> clazz) {
101-
if (clazz == null) {
102-
Log.e(TAG, "parseObject clazz == null >> return null;");
101+
if (clazz == null || StringUtil.isEmpty(json, true)) {
102+
Log.e(TAG, "parseObject clazz == null || StringUtil.isEmpty(json, true) >> return null;");
103103
} else {
104104
try {
105105
return com.alibaba.fastjson.JSON.parseObject(getCorrectJson(json), clazz, DEFAULT_FASTJSON_FEATURES);
@@ -132,10 +132,14 @@ public static JSONArray parseArray(Object obj) {
132132
* @return
133133
*/
134134
public static JSONArray parseArray(String json) {
135-
try {
136-
return com.alibaba.fastjson.JSON.parseArray(getCorrectJson(json, true));
137-
} catch (Exception e) {
138-
Log.i(TAG, "parseArray catch \n" + e.getMessage());
135+
if (StringUtil.isEmpty(json, true)) {
136+
Log.e(TAG, "parseArray StringUtil.isEmpty(json, true) >> return null;");
137+
} else {
138+
try {
139+
return com.alibaba.fastjson.JSON.parseArray(getCorrectJson(json, true));
140+
} catch (Exception e) {
141+
Log.i(TAG, "parseArray catch \n" + e.getMessage());
142+
}
139143
}
140144
return null;
141145
}
@@ -153,8 +157,8 @@ public static <T> List<T> parseArray(JSONArray array, Class<T> clazz) {
153157
* @return
154158
*/
155159
public static <T> List<T> parseArray(String json, Class<T> clazz) {
156-
if (clazz == null) {
157-
Log.e(TAG, "parseArray clazz == null >> return null;");
160+
if (clazz == null || StringUtil.isEmpty(json, true)) {
161+
Log.e(TAG, "parseArray clazz == null || StringUtil.isEmpty(json, true) >> return null;");
158162
} else {
159163
try {
160164
return com.alibaba.fastjson.JSON.parseArray(getCorrectJson(json, true), clazz);
@@ -170,6 +174,9 @@ public static <T> List<T> parseArray(String json, Class<T> clazz) {
170174
* @return
171175
*/
172176
public static String toJSONString(Object obj) {
177+
if (obj == null) {
178+
return null;
179+
}
173180
if (obj instanceof String) {
174181
return (String) obj;
175182
}
@@ -187,6 +194,9 @@ public static String toJSONString(Object obj) {
187194
* @return
188195
*/
189196
public static String toJSONString(Object obj, SerializerFeature... features) {
197+
if (obj == null) {
198+
return null;
199+
}
190200
if (obj instanceof String) {
191201
return (String) obj;
192202
}

APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java

Lines changed: 116 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
import static apijson.orm.Operation.UNIQUE;
2424
import static apijson.orm.Operation.UPDATE;
2525
import static apijson.orm.Operation.VERIFY;
26-
import static apijson.orm.Operation.ON;
26+
import static apijson.orm.Operation.IF;
27+
//import static apijson.orm.Operation.CODE;
2728

2829
import java.net.URL;
2930
import java.time.LocalDate;
@@ -33,6 +34,8 @@
3334
import java.util.regex.Matcher;
3435
import java.util.regex.Pattern;
3536

37+
import apijson.orm.script.JavaScriptExecutor;
38+
import apijson.orm.script.ScriptExecutor;
3639
import com.alibaba.fastjson.JSONArray;
3740
import com.alibaba.fastjson.JSONObject;
3841

@@ -65,6 +68,10 @@
6568
import apijson.orm.model.AllColumnComment;
6669
import apijson.orm.model.TestRecord;
6770

71+
import javax.script.ScriptEngine;
72+
import javax.script.ScriptEngineFactory;
73+
import javax.script.ScriptEngineManager;
74+
6875
/**校验器(权限、请求参数、返回结果等)
6976
* TODO 合并 Structure 的代码
7077
* @author Lemon
@@ -107,6 +114,10 @@ public abstract class AbstractVerifier<T extends Object> implements Verifier<T>,
107114
*/
108115
public static final String ADMIN = "ADMIN";
109116

117+
public static ParserCreator PARSER_CREATOR;
118+
119+
public static ScriptEngineManager SCRIPT_ENGINE_MANAGER;
120+
public static ScriptEngine SCRIPT_ENGINE;
110121

111122
// 共享 STRUCTURE_MAP 则不能 remove 等做任何变更,否则在并发情况下可能会出错,加锁效率又低,所以这里改为忽略对应的 key
112123
public static Map<String, Entry<String, Object>> ROLE_MAP;
@@ -133,6 +144,9 @@ public abstract class AbstractVerifier<T extends Object> implements Verifier<T>,
133144
@NotNull
134145
public static final Map<String, Pattern> COMPILE_MAP;
135146
static {
147+
SCRIPT_ENGINE_MANAGER = new ScriptEngineManager();
148+
SCRIPT_ENGINE = SCRIPT_ENGINE_MANAGER.getEngineByName("js");
149+
136150
ROLE_MAP = new LinkedHashMap<>();
137151
ROLE_MAP.put(UNKNOWN, new Entry<String, Object>());
138152
ROLE_MAP.put(LOGIN, new Entry<String, Object>("userId>", 0));
@@ -152,7 +166,8 @@ public abstract class AbstractVerifier<T extends Object> implements Verifier<T>,
152166
OPERATION_KEY_LIST.add(REMOVE.name());
153167
OPERATION_KEY_LIST.add(MUST.name());
154168
OPERATION_KEY_LIST.add(REFUSE.name());
155-
OPERATION_KEY_LIST.add(ON.name());
169+
OPERATION_KEY_LIST.add(IF.name());
170+
// OPERATION_KEY_LIST.add(CODE.name());
156171
OPERATION_KEY_LIST.add(ALLOW_PARTIAL_UPDATE_FAIL.name());
157172

158173

@@ -914,7 +929,19 @@ public static <T extends Object> JSONObject parse(@NotNull final RequestMethod m
914929
String remove = StringUtil.getString(target.getString(REMOVE.name()));
915930
String must = StringUtil.getString(target.getString(MUST.name()));
916931
String refuse = StringUtil.getString(target.getString(REFUSE.name()));
917-
JSONObject on = target.getJSONObject(ON.name());
932+
933+
Object _if = target.get(IF.name());
934+
boolean ifIsStr = _if instanceof String && StringUtil.isNotEmpty(_if, true);
935+
JSONObject ifObj = ifIsStr == false && _if instanceof JSONObject ? (JSONObject) _if : null;
936+
// : (_if instanceof String ? new apijson.JSONRequest((String) _if, "" /* "throw new Error('')" */ ) : null);
937+
if (ifObj == null && _if != null && ifIsStr == false) {
938+
// if (_if instanceof JSONArray) {
939+
// }
940+
throw new IllegalArgumentException(name + ": { " + IF.name() + ": value } 中 value 类型错误!只允许 String, JSONObject!");
941+
}
942+
943+
// Object code = target.get(CODE.name());
944+
918945
String allowPartialUpdateFail = StringUtil.getString(target.getString(ALLOW_PARTIAL_UPDATE_FAIL.name()));
919946

920947

@@ -1143,7 +1170,7 @@ public static <T extends Object> JSONObject parse(@NotNull final RequestMethod m
11431170
long exceptId = real.getLongValue(finalIdKey);
11441171
Map<String,Object> map = new HashMap<>();
11451172
for (String u : uniques) {
1146-
map.put(u,real.get(u));
1173+
map.put(u, real.get(u));
11471174
}
11481175
verifyRepeat(name, map, exceptId, finalIdKey, creator);
11491176
}
@@ -1176,38 +1203,111 @@ public static <T extends Object> JSONObject parse(@NotNull final RequestMethod m
11761203
// 校验并配置允许部分批量增删改失败>>>>>>>>>>>>>>>>>>>
11771204

11781205

1179-
String[] nks = on == null ? null : StringUtil.split(real.getString(JSONRequest.KEY_NULL));
1206+
String[] nks = ifObj == null ? null : StringUtil.split(real.getString(JSONRequest.KEY_NULL));
11801207
Collection<?> nkl = nks == null || nks.length <= 0 ? new HashSet<>() : Arrays.asList(nks);
11811208

1182-
Set<Map.Entry<String, Object>> onSet = on == null ? null : on.entrySet();
1183-
if (onSet != null) {
1209+
Set<Map.Entry<String, Object>> ifSet = ifObj == null ? null : ifObj.entrySet();
1210+
if (ifIsStr || (ifSet != null && ifSet.isEmpty() == false)) {
11841211
// 没必要限制,都是后端配置的,安全可控,而且可能确实有特殊需求,需要 id, @column 等
11851212
// List<String> condKeys = new ArrayList<>(Arrays.asList(apijson.JSONRequest.KEY_ID, apijson.JSONRequest.KEY_ID_IN
11861213
// , apijson.JSONRequest.KEY_USER_ID, apijson.JSONRequest.KEY_USER_ID_IN));
11871214
// condKeys.addAll(JSONRequest.TABLE_KEY_LIST);
11881215

1189-
for (Map.Entry<String, Object> entry : onSet) {
1190-
String k = entry == null ? null : entry.getKey();
1216+
String preCode = "var curObj = " + JSON.format(real) + ";";
1217+
1218+
// 未传的 key 在后面 eval 时总是报错 undefined,而且可能有冲突,例如对象里有 "curObj": val 键值对,就会覆盖当前对象定义,还不如都是 curObj.sex 这样取值
1219+
// Set<Map.Entry<String, Object>> rset = real.entrySet();
1220+
// for (Map.Entry<String, Object> entry : rset) {
1221+
// String k = entry == null ? null : entry.getKey();
1222+
// if (StringUtil.isEmpty(k)) {
1223+
// continue;
1224+
// }
1225+
// String vn = JSONResponse.formatOtherKey(k);
1226+
// if (StringUtil.isName(vn) == false) { // 通过 curObj['id@'] 这样取值,写在 IF 配置里
1227+
// continue;
1228+
// }
1229+
//
1230+
// Object v = entry.getValue();
1231+
// String vs = v instanceof String ? "\"" + ((String) v).replaceAll("\"", "\\\"") + "\""
1232+
// : (JSON.isBooleanOrNumberOrString(v) ? v.toString() : JSON.format(v));
1233+
// preCode += "\nvar " + vn + " = " + vs + ";";
1234+
// }
1235+
1236+
if (ifIsStr) {
1237+
String ifStr = (String) _if;
1238+
int ind = ifStr.indexOf(":");
1239+
String lang = ind < 0 ? null : ifStr.substring(0, ind);
1240+
ScriptEngine engine = getScriptEngine(lang);
1241+
engine.eval(preCode + "\n" + _if);
1242+
}
1243+
else {
1244+
for (Map.Entry<String, Object> entry : ifSet) {
1245+
String k = entry == null ? null : entry.getKey();
11911246
// if (condKeys.contains(k)) {
11921247
// throw new IllegalArgumentException("Request 表 structure 配置的 " + ON.name()
11931248
// + ":{ " + k + ":value } 中 key 不合法,不允许传 [" + StringUtil.join(condKeys.toArray(new String[]{})) + "] 中的任何一个 !");
11941249
// }
11951250

1196-
Object v = k == null ? null : entry.getValue();
1197-
if (v instanceof JSONObject == false) {
1198-
throw new IllegalArgumentException("Request 表 structure 配置的 " + ON.name()
1199-
+ ":{ " + k + ":value } 中 value 不合法,必须是 JSONObject {} !");
1200-
}
1251+
Object v = k == null ? null : entry.getValue();
1252+
if (v instanceof String) {
1253+
int ind = k.indexOf(":");
1254+
String lang = ind < 0 ? null : k.substring(0, ind);
1255+
ScriptEngine engine = getScriptEngine(lang);
1256+
k = ind < 0 ? k : k.substring(ind + 1);
1257+
1258+
boolean isElse = StringUtil.isEmpty(k, false); // 其它直接报错,不允许传 StringUtil.isEmpty(k, true) || "ELSE".equals(k);
1259+
// String code = preCode + "\n\n" + (StringUtil.isEmpty(v, false) ? k : (isElse ? v : "if (" + k + ") {\n " + v + "\n}"));
1260+
String code = preCode + "\n\n" + (isElse ? v : "if (" + k + ") {\n " + v + "\n}");
1261+
1262+
// ScriptExecutor executor = new JavaScriptExecutor();
1263+
// executor.execute(null, real, )
12011264

1202-
if (nkl.contains(k) || real.get(k) != null) {
1203-
real = parse(method, name, (JSONObject) v, real, database, schema, datasource, idCallback, creator, callback);
1265+
engine.eval(code);
1266+
1267+
// PARSER_CREATOR.createFunctionParser()
1268+
// .setCurrentObject(real)
1269+
// .setKey(k)
1270+
// .setMethod(method)
1271+
// .invoke()
1272+
continue;
1273+
}
1274+
1275+
if (v instanceof JSONObject == false) {
1276+
throw new IllegalArgumentException("Request 表 structure 配置的 " + IF.name()
1277+
+ ":{ " + k + ":value } 中 value 不合法,必须是 JSONObject {} !");
1278+
}
1279+
1280+
if (nkl.contains(k) || real.get(k) != null) {
1281+
real = parse(method, name, (JSONObject) v, real, database, schema, datasource, idCallback, creator, callback);
1282+
}
12041283
}
12051284
}
12061285
}
12071286
Log.i(TAG, "parse return real = " + JSON.toJSONString(real));
12081287
return real;
12091288
}
12101289

1290+
public static ScriptEngine getScriptEngine(String lang) {
1291+
List<ScriptEngineFactory> list = StringUtil.isEmpty(lang, true) ? null : SCRIPT_ENGINE_MANAGER.getEngineFactories();
1292+
1293+
ScriptEngine engine = null;
1294+
if (list == null || list.isEmpty()) {
1295+
engine = SCRIPT_ENGINE; // StringUtil.isEmpty(lang) ? SCRIPT_ENGINE : null;
1296+
}
1297+
else {
1298+
for (ScriptEngineFactory sef : list) {
1299+
if (sef != null && lang.equals(sef.getEngineName())) {
1300+
engine = sef.getScriptEngine();
1301+
}
1302+
}
1303+
}
1304+
1305+
if (engine == null) {
1306+
throw new NullPointerException("找不到可执行 " + (StringUtil.isEmpty(lang, true) ? "js" : lang) + " 脚本的引擎!engine == null!");
1307+
}
1308+
1309+
return engine;
1310+
}
12111311

12121312

12131313
/**执行操作

APIJSONORM/src/main/java/apijson/orm/Operation.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,28 @@ public enum Operation {
119119
* "key0": {}
120120
* 例如 "name": { "UPDATE": { "Comment": { "userName@": "/name" } } }
121121
* 当 User.name 被修改时,同步修改 Comment.userName
122+
*
123+
* 例如 "sex != 0 && sex != 1": "throw new Error('sex 必须在 [0, 1] 内!')"
124+
* 自定义代码,当满足条件是执行后面的代码
125+
*
126+
* 还有
127+
* "ELSE": ""
128+
* 自定义代码,不处理,和不传一样
122129
*/
123-
ON,
130+
IF,
131+
132+
// /** 直接用 IF 替代
133+
// * 自定义代码,结构是 "code",例如
134+
// * "var a = 1;
135+
// * var b = a + 2;
136+
// * if (b % 2 == 0) {
137+
// * throw new Error('b % 2 == 0 !');
138+
// * }
139+
// * "
140+
// *
141+
// * 或 { "code": "JS", "code2": "LUA" }
142+
// */
143+
// CODE,
124144

125145
/**
126146
* 允许批量增删改部分失败,结构是

APIJSONORM/src/main/java/apijson/orm/script/JSR223ScriptExecutor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ public Object execute(AbstractFunctionParser parser, JSONObject currentObject, S
6666
}
6767

6868
Map<String, Object> metaMap = new HashMap<>();
69-
metaMap.put("version", parser.getVersion());
70-
metaMap.put("tag", parser.getTag());
69+
metaMap.put("version", parser == null ? 0 : parser.getVersion());
70+
metaMap.put("tag", parser == null ? null : parser.getTag());
7171
metaMap.put("args", args);
7272
bindings.put("_meta", metaMap);
7373
return compiledScript.eval(bindings);

0 commit comments

Comments
 (0)