From baa6a946f787a87833d5cf0ddfee36fc8fcc039c Mon Sep 17 00:00:00 2001 From: canonical Date: Wed, 6 Sep 2023 08:46:49 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=86=B3=E7=AD=96=E7=9F=A9?= =?UTF-8?q?=E9=98=B5=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=E3=80=82?= =?UTF-8?q?Excel=E5=AF=BC=E5=85=A5=E8=A7=84=E5=88=99=E6=97=B6=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=8D=E6=9D=82=E5=AF=B9=E8=B1=A1=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/nop/commons/util/StringHelper.java | 26 +- .../io/nop/core/lang/utils/Underscore.java | 7 + .../nop-quarkus-demo/reflect-config.json | 97 ++++++++ .../src/main/resources/nop-vfs-index.txt | 2 + .../java/io/nop/rule/core/IRuleManager.java | 7 +- .../java/io/nop/rule/core/IRuleRuntime.java | 7 + .../rule/core/execute/ComputedInputRule.java | 30 --- .../core/execute/DecoratedExecutableRule.java | 21 +- .../execute/NormalizeInputExecutableRule.java | 58 +++++ ...ava => NormalizeOutputExecutableRule.java} | 5 +- .../io/nop/rule/core/execute/RuleManager.java | 57 +---- .../io/nop/rule/core/execute/RuleRuntime.java | 23 +- .../core/model/compile/RuleModelCompiler.java | 15 +- .../core/service/impl/RuleServiceImpl.java | 2 +- .../resources/_vfs/nop/rule/imp/rule.imp.xml | 20 +- .../model/NopRuleOutput/NopRuleOutput.xmeta | 2 +- .../testDecisionMatrix/autotest.yaml | 0 .../input/decision-matrix.rule.xlsx | Bin 0 -> 15067 bytes .../testDecisionMatrix/input/request.json5 | 12 + .../testDecisionMatrix/input/request2.json5 | 14 ++ .../input/tables/nop_file_record.csv | 1 + .../input/tables/nop_rule_definition.csv | 1 + .../input/tables/nop_rule_node.csv | 1 + .../input/tables/nop_sys_sequence.csv | 1 + .../testDecisionMatrix/output/response.json5 | 87 +++++++ .../testDecisionMatrix/output/response2.json5 | 61 +++++ .../output/tables/nop_file_record.csv | 2 + .../output/tables/nop_rule_definition.csv | 228 ++++++++++++++++++ .../output/tables/nop_sys_sequence.csv | 2 + .../output/upload-result.json5 | 8 + .../testImport/output/response.json5 | 2 +- .../output/tables/nop_rule_definition.csv | 6 +- .../entity/TestNopRuleDefinitionBizModel.java | 14 +- 33 files changed, 703 insertions(+), 116 deletions(-) delete mode 100644 nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/ComputedInputRule.java create mode 100644 nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/NormalizeInputExecutableRule.java rename nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/{AggregateExecutableRule.java => NormalizeOutputExecutableRule.java} (93%) create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/autotest.yaml create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/input/decision-matrix.rule.xlsx create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/input/request.json5 create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/input/request2.json5 create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/input/tables/nop_file_record.csv create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/input/tables/nop_rule_definition.csv create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/input/tables/nop_rule_node.csv create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/input/tables/nop_sys_sequence.csv create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/response.json5 create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/response2.json5 create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_file_record.csv create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_rule_definition.csv create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_sys_sequence.csv create mode 100644 nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/upload-result.json5 diff --git a/nop-commons/src/main/java/io/nop/commons/util/StringHelper.java b/nop-commons/src/main/java/io/nop/commons/util/StringHelper.java index 07d04782b..012460885 100644 --- a/nop-commons/src/main/java/io/nop/commons/util/StringHelper.java +++ b/nop-commons/src/main/java/io/nop/commons/util/StringHelper.java @@ -3223,7 +3223,7 @@ private static boolean matchWildcard(CharSequence string, CharSequence pattern, * @return */ @Deterministic - public static String trimSuffix(String str, String suffix) { + public static String removeEnd(String str, String suffix) { if (str.endsWith(suffix)) { return str.substring(0, str.length() - suffix.length()); } else { @@ -3231,6 +3231,30 @@ public static String trimSuffix(String str, String suffix) { } } + @Deterministic + public static String removeStart(String str, String prefix) { + if (str.startsWith(prefix)) { + return str.substring(prefix.length()); + } else { + return str; + } + } + + @Deterministic + public static String chompStartChars(String str, String chars) { + if (str == null || str.isEmpty()) + return str; + char c = str.charAt(0); + if (chars.indexOf(c) < 0) + return str; + int i = 0; + for (int n = str.length(); i < n; i++) { + if (chars.indexOf(str.charAt(i)) < 0) + break; + } + return str.substring(i); + } + /** * 将复合属性名a.b.c编码为 a$b$c, 便于前台数据绑定框架使用 */ diff --git a/nop-core/src/main/java/io/nop/core/lang/utils/Underscore.java b/nop-core/src/main/java/io/nop/core/lang/utils/Underscore.java index afd2315ec..40548554c 100644 --- a/nop-core/src/main/java/io/nop/core/lang/utils/Underscore.java +++ b/nop-core/src/main/java/io/nop/core/lang/utils/Underscore.java @@ -12,6 +12,8 @@ import io.nop.api.core.annotations.lang.Deterministic; import io.nop.api.core.convert.ConvertHelper; import io.nop.api.core.util.Guard; +import io.nop.commons.collections.IKeyedList; +import io.nop.commons.collections.KeyedList; import io.nop.commons.collections.SafeOrderedComparator; import io.nop.commons.util.CollectionHelper; import io.nop.commons.util.MathHelper; @@ -725,4 +727,9 @@ public static Map mergeMap(Map mapA, Map IKeyedList toKeyedList(Collection c, String keyProp){ + return KeyedList.fromList(CollectionHelper.toList(c),item-> getFieldValue(item,keyProp)); + } } \ No newline at end of file diff --git a/nop-demo/nop-quarkus-demo/src/main/resources/META-INF/native-image/io.nop.demo/nop-quarkus-demo/reflect-config.json b/nop-demo/nop-quarkus-demo/src/main/resources/META-INF/native-image/io.nop.demo/nop-quarkus-demo/reflect-config.json index b8e147e36..095aee9ef 100644 --- a/nop-demo/nop-quarkus-demo/src/main/resources/META-INF/native-image/io.nop.demo/nop-quarkus-demo/reflect-config.json +++ b/nop-demo/nop-quarkus-demo/src/main/resources/META-INF/native-image/io.nop.demo/nop-quarkus-demo/reflect-config.json @@ -36256,6 +36256,16 @@ "name": "io.nop.rule.api.beans.RuleKeyBean", "unsafeAllocated": false }, + { + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "fields": [], + "methods": [], + "name": "io.nop.rule.api.beans.RuleLogMessageBean", + "unsafeAllocated": false + }, { "allDeclaredConstructors": true, "allDeclaredMethods": true, @@ -36317,6 +36327,57 @@ "name": "io.nop.rule.api.beans._gen._RuleKeyBean", "unsafeAllocated": false }, + { + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "fields": [], + "methods": [ + { + "name": "getLogTime", + "parameterTypes": [] + }, + { + "name": "getMessage", + "parameterTypes": [] + }, + { + "name": "getRuleNodeId", + "parameterTypes": [] + }, + { + "name": "getRuleNodeLabel", + "parameterTypes": [] + }, + { + "name": "setLogTime", + "parameterTypes": [ + "java.sql.Timestamp" + ] + }, + { + "name": "setMessage", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setRuleNodeId", + "parameterTypes": [ + "java.lang.String" + ] + }, + { + "name": "setRuleNodeLabel", + "parameterTypes": [ + "java.lang.String" + ] + } + ], + "name": "io.nop.rule.api.beans._gen._RuleLogMessageBean", + "unsafeAllocated": false + }, { "allDeclaredConstructors": true, "allDeclaredMethods": true, @@ -36436,6 +36497,10 @@ "allPublicMethods": true, "fields": [], "methods": [ + { + "name": "getLogMessages", + "parameterTypes": [] + }, { "name": "getOutputs", "parameterTypes": [] @@ -36452,6 +36517,12 @@ "name": "getRuleVersion", "parameterTypes": [] }, + { + "name": "setLogMessages", + "parameterTypes": [ + "java.util.List" + ] + }, { "name": "setOutputs", "parameterTypes": [ @@ -37144,11 +37215,23 @@ "io.nop.core.context.IServiceContext" ] }, + { + "name": "setLogMessageSaver", + "parameterTypes": [ + "io.nop.rule.core.service.IRuleLogMessageSaver" + ] + }, { "name": "setRuleManager", "parameterTypes": [ "io.nop.rule.core.IRuleManager" ] + }, + { + "name": "setSaveLogMessage", + "parameterTypes": [ + "boolean" + ] } ], "name": "io.nop.rule.core.service.impl.RuleServiceImpl", @@ -49162,6 +49245,10 @@ "name": "getLayoutMode", "parameterTypes": [] }, + { + "name": "getMessages", + "parameterTypes": [] + }, { "name": "getObjMeta", "parameterTypes": [] @@ -49282,6 +49369,10 @@ "name": "hasInitAsyncApi", "parameterTypes": [] }, + { + "name": "hasMessages", + "parameterTypes": [] + }, { "name": "hasRule", "parameterTypes": [ @@ -49444,6 +49535,12 @@ "java.lang.String" ] }, + { + "name": "setMessages", + "parameterTypes": [ + "java.util.Map" + ] + }, { "name": "setObjMeta", "parameterTypes": [ diff --git a/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt b/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt index 9e1fa6441..b4ae62afd 100644 --- a/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt +++ b/nop-demo/nop-quarkus-demo/src/main/resources/nop-vfs-index.txt @@ -339,10 +339,12 @@ /nop/rule/model/NopRuleRole/_NopRuleRole.xbiz /nop/rule/model/NopRuleRole/_NopRuleRole.xmeta /nop/rule/model/RuleService/RuleKeyBean.xmeta +/nop/rule/model/RuleService/RuleLogMessageBean.xmeta /nop/rule/model/RuleService/RuleMetaBean.xmeta /nop/rule/model/RuleService/RuleRequestBean.xmeta /nop/rule/model/RuleService/RuleResultBean.xmeta /nop/rule/model/RuleService/_RuleKeyBean.xmeta +/nop/rule/model/RuleService/_RuleLogMessageBean.xmeta /nop/rule/model/RuleService/_RuleMetaBean.xmeta /nop/rule/model/RuleService/_RuleRequestBean.xmeta /nop/rule/model/RuleService/_RuleResultBean.xmeta diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/IRuleManager.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/IRuleManager.java index 0a905e51f..f08c1b341 100644 --- a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/IRuleManager.java +++ b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/IRuleManager.java @@ -1,5 +1,6 @@ package io.nop.rule.core; +import io.nop.commons.cache.ICache; import io.nop.core.lang.eval.IEvalScope; import io.nop.rule.core.model.RuleModel; @@ -7,11 +8,9 @@ public interface IRuleManager { - IRuleRuntime newRuntime(IEvalScope scope); + IRuleRuntime newRuntime(ICache cache, IEvalScope scope); - default IRuleRuntime newRuntime() { - return newRuntime(null); - } + IRuleRuntime newRuntime(); IExecutableRule getRule(String ruleName, Integer ruleVersion); diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/IRuleRuntime.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/IRuleRuntime.java index cb92ed183..9a95172c5 100644 --- a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/IRuleRuntime.java +++ b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/IRuleRuntime.java @@ -8,6 +8,7 @@ package io.nop.rule.core; import io.nop.api.core.util.Guard; +import io.nop.commons.cache.ICache; import io.nop.core.context.IEvalContext; import io.nop.core.lang.eval.IEvalScope; import io.nop.rule.api.beans.RuleLogMessageBean; @@ -66,6 +67,12 @@ default List getOutputList(String name) { void setCollectLogMessage(boolean collectLogMessage); + Throwable getException(); + + void setException(Throwable exception); + + ICache getCache(); + static IRuleRuntime fromEvalContext(IEvalContext context) { if (context instanceof IRuleRuntime) return (IRuleRuntime) context; diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/ComputedInputRule.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/ComputedInputRule.java deleted file mode 100644 index 254baba00..000000000 --- a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/ComputedInputRule.java +++ /dev/null @@ -1,30 +0,0 @@ -package io.nop.rule.core.execute; - -import io.nop.core.lang.eval.IEvalAction; -import io.nop.rule.core.IExecutableRule; -import io.nop.rule.core.IRuleRuntime; -import io.nop.rule.core.model.RuleInputDefineModel; - -import java.util.List; - -public class ComputedInputRule implements IExecutableRule { - private final List vars; - private final IExecutableRule rule; - - public ComputedInputRule(List vars, IExecutableRule rule) { - this.vars = vars; - this.rule = rule; - } - - @Override - public boolean execute(IRuleRuntime ruleRt) { - for (RuleInputDefineModel var : vars) { - String name = var.getName(); - IEvalAction expr = var.getDefaultExpr(); - Object value = expr == null ? null : expr.invoke(ruleRt); - ruleRt.getEvalScope().setLocalValue(var.getLocation(), name, value); - } - - return rule.execute(ruleRt); - } -} diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/DecoratedExecutableRule.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/DecoratedExecutableRule.java index dc47b16cf..d48789d82 100644 --- a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/DecoratedExecutableRule.java +++ b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/DecoratedExecutableRule.java @@ -1,9 +1,9 @@ package io.nop.rule.core.execute; +import io.nop.api.core.exceptions.NopException; import io.nop.core.lang.eval.IEvalAction; import io.nop.rule.core.IExecutableRule; import io.nop.rule.core.IRuleRuntime; -import io.nop.rule.core.RuleConstants; public class DecoratedExecutableRule implements IExecutableRule { private final IEvalAction beforeExecute; @@ -20,13 +20,18 @@ public DecoratedExecutableRule(IEvalAction beforeExecute, @Override public boolean execute(IRuleRuntime ruleRt) { - if (beforeExecute != null) - beforeExecute.invoke(ruleRt); - boolean b = rule.execute(ruleRt); - if (afterExecute != null) { - ruleRt.getEvalScope().setLocalValue(RuleConstants.VAR_RULE_MATCH, b); - afterExecute.invoke(ruleRt); + try { + if (beforeExecute != null) + beforeExecute.invoke(ruleRt); + boolean b = rule.execute(ruleRt); + ruleRt.setRuleMatch(b); + return b; + } catch (Exception e) { + ruleRt.setException(e); + if (afterExecute != null) { + afterExecute.invoke(ruleRt); + } + throw NopException.adapt(e); } - return b; } } diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/NormalizeInputExecutableRule.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/NormalizeInputExecutableRule.java new file mode 100644 index 000000000..ddda5ffa2 --- /dev/null +++ b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/NormalizeInputExecutableRule.java @@ -0,0 +1,58 @@ +package io.nop.rule.core.execute; + +import io.nop.api.core.exceptions.NopException; +import io.nop.api.core.util.Guard; +import io.nop.commons.util.StringHelper; +import io.nop.core.reflect.bean.BeanTool; +import io.nop.core.type.IGenericType; +import io.nop.rule.core.IExecutableRule; +import io.nop.rule.core.IRuleRuntime; +import io.nop.rule.core.model.RuleInputDefineModel; + +import java.util.List; + +import static io.nop.rule.core.RuleErrors.ARG_DISPLAY_NAME; +import static io.nop.rule.core.RuleErrors.ARG_VAR_NAME; +import static io.nop.rule.core.RuleErrors.ERR_RULE_INPUT_VAR_NOT_ALLOW_EMPTY; + +public class NormalizeInputExecutableRule implements IExecutableRule { + private final List inputDefines; + private final IExecutableRule rule; + + public NormalizeInputExecutableRule(List inputDefines, IExecutableRule rule) { + this.inputDefines = Guard.notEmpty(inputDefines, "inputDefines"); + this.rule = rule; + } + + @Override + public boolean execute(IRuleRuntime ruleRt) { + for (RuleInputDefineModel inputDefine : inputDefines) { + String name = inputDefine.getName(); + Object value = ruleRt.getInput(name); + + if (inputDefine.isComputed()) { + // 计算表达式 + value = inputDefine.getDefaultExpr() == null ? null : inputDefine.getDefaultExpr().invoke(ruleRt); + } else if (value == null) { + if (inputDefine.getDefaultExpr() != null) { + value = inputDefine.getDefaultExpr().invoke(ruleRt); + } + } + + if (inputDefine.isMandatory()) { + if (StringHelper.isEmptyObject(value)) + throw new NopException(ERR_RULE_INPUT_VAR_NOT_ALLOW_EMPTY) + .source(inputDefine) + .param(ARG_VAR_NAME, name) + .param(ARG_DISPLAY_NAME, inputDefine.getDisplayName()); + } + + IGenericType type = inputDefine.getType(); + if (type != null && value != null) { + value = BeanTool.castBeanToType(value, type); + } + ruleRt.getEvalScope().setLocalValue(name, value); + } + return rule.execute(ruleRt); + } +} diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/AggregateExecutableRule.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/NormalizeOutputExecutableRule.java similarity index 93% rename from nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/AggregateExecutableRule.java rename to nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/NormalizeOutputExecutableRule.java index ca1c194a2..d6a6a1c65 100644 --- a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/AggregateExecutableRule.java +++ b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/NormalizeOutputExecutableRule.java @@ -10,12 +10,11 @@ import java.util.List; -public class AggregateExecutableRule implements IExecutableRule { +public class NormalizeOutputExecutableRule implements IExecutableRule { private final IExecutableRule rule; private final List outputs; - public AggregateExecutableRule(IExecutableRule rule, - List outputs) { + public NormalizeOutputExecutableRule(List outputs, IExecutableRule rule) { this.rule = rule; this.outputs = outputs; } diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/RuleManager.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/RuleManager.java index 48e8fa370..c19bef4dc 100644 --- a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/RuleManager.java +++ b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/RuleManager.java @@ -8,32 +8,35 @@ package io.nop.rule.core.execute; import io.nop.api.core.exceptions.NopException; -import io.nop.commons.util.StringHelper; +import io.nop.commons.cache.ICache; +import io.nop.commons.cache.LocalCache; +import io.nop.commons.cache.MapCache; import io.nop.core.lang.eval.IEvalScope; -import io.nop.core.reflect.bean.BeanTool; import io.nop.core.resource.component.ResourceComponentManager; -import io.nop.core.type.IGenericType; import io.nop.rule.core.IExecutableRule; import io.nop.rule.core.IRuleManager; import io.nop.rule.core.IRuleRuntime; -import io.nop.rule.core.RuleConstants; import io.nop.rule.core.model.RuleInputDefineModel; import io.nop.rule.core.model.RuleModel; +import io.nop.xlang.api.XLang; -import java.util.List; import java.util.Map; import static io.nop.rule.core.RuleErrors.ARG_DISPLAY_NAME; import static io.nop.rule.core.RuleErrors.ARG_VAR_NAME; import static io.nop.rule.core.RuleErrors.ERR_RULE_INPUT_NOT_ALLOW_COMPUTED_VAR; -import static io.nop.rule.core.RuleErrors.ERR_RULE_INPUT_VAR_NOT_ALLOW_EMPTY; import static io.nop.rule.core.RuleErrors.ERR_RULE_UNKNOWN_INPUT_VAR; public class RuleManager implements IRuleManager { @Override - public IRuleRuntime newRuntime(IEvalScope scope) { - return new RuleRuntime(scope); + public IRuleRuntime newRuntime(ICache cache, IEvalScope scope) { + return new RuleRuntime(cache, scope); + } + + @Override + public IRuleRuntime newRuntime() { + return newRuntime(new MapCache<>("rule-rt-cache",false), XLang.newEvalScope()); } @Override @@ -62,11 +65,6 @@ public Map executeRule(String ruleName, Integer ruleVersion, IRu boolean ruleMatch = rule.execute(ruleRt); ruleRt.setRuleMatch(ruleMatch); - if (ruleModel.getAfterExecute() != null) { - ruleRt.getEvalScope().setLocalValue(RuleConstants.VAR_RULE_MATCH, ruleMatch); - ruleModel.getAfterExecute().invoke(ruleRt); - } - return ruleRt.getOutputs(); } catch (NopException e) { e.addXplStack("executeRule:ruleName=" + ruleName + ",ruleVersion=" + ruleVersion); @@ -75,10 +73,6 @@ public Map executeRule(String ruleName, Integer ruleVersion, IRu } private void prepareScope(IRuleRuntime ruleRt, RuleModel ruleModel) { - if (ruleModel.getBeforeExecute() != null) { - ruleModel.getBeforeExecute().invoke(ruleRt); - } - if (ruleRt.getInputs() != null) { // 输入变量必须在已知范围之内 for (String name : ruleRt.getInputs().keySet()) { @@ -99,34 +93,5 @@ private void prepareScope(IRuleRuntime ruleRt, RuleModel ruleModel) { .param(ARG_DISPLAY_NAME, var.getDisplayName()); } } - - List inputDefines = ruleModel.getInputs(); - for (RuleInputDefineModel inputDefine : inputDefines) { - String name = inputDefine.getName(); - Object value = ruleRt.getInput(name); - - if (inputDefine.isComputed()) { - // 计算表达式 - value = inputDefine.getDefaultExpr() == null ? null : inputDefine.getDefaultExpr().invoke(ruleRt); - } else if (value == null) { - if (inputDefine.getDefaultExpr() != null) { - value = inputDefine.getDefaultExpr().invoke(ruleRt); - } - } - - if (inputDefine.isMandatory()) { - if (StringHelper.isEmptyObject(value)) - throw new NopException(ERR_RULE_INPUT_VAR_NOT_ALLOW_EMPTY) - .source(inputDefine) - .param(ARG_VAR_NAME, name) - .param(ARG_DISPLAY_NAME, inputDefine.getDisplayName()); - } - - IGenericType type = inputDefine.getType(); - if (type != null && value != null) { - value = BeanTool.castBeanToType(value, type); - } - ruleRt.getEvalScope().setLocalValue(name, value); - } } } \ No newline at end of file diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/RuleRuntime.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/RuleRuntime.java index cd4ebd6be..ba31f8745 100644 --- a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/RuleRuntime.java +++ b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/execute/RuleRuntime.java @@ -1,6 +1,7 @@ package io.nop.rule.core.execute; import io.nop.api.core.time.CoreMetrics; +import io.nop.commons.cache.ICache; import io.nop.core.lang.eval.IEvalScope; import io.nop.core.unittest.VarCollector; import io.nop.rule.api.beans.RuleLogMessageBean; @@ -18,6 +19,8 @@ public class RuleRuntime implements IRuleRuntime { static final Logger LOG = LoggerFactory.getLogger(RuleRuntime.class); + + private final ICache cache; private final IEvalScope scope; private final List logMessages = new ArrayList<>(); @@ -35,13 +38,17 @@ public class RuleRuntime implements IRuleRuntime { private boolean collectLogMessage; - public RuleRuntime(IEvalScope scope) { + private Throwable exception; + + public RuleRuntime(ICache cache, IEvalScope scope) { + this.cache = cache; this.scope = scope == null ? XLang.newEvalScope() : scope.newChildScope(); this.scope.setLocalValue(RuleConstants.VAR_RULE_RT, this); } - public RuleRuntime() { - this(XLang.newEvalScope()); + @Override + public ICache getCache() { + return cache; } @Override @@ -94,6 +101,16 @@ public Map> getOutputLists() { return outputLists; } + @Override + public Throwable getException() { + return exception; + } + + @Override + public void setException(Throwable exception) { + this.exception = exception; + } + @Override public void addOutput(String name, Object value) { List list = outputLists.get(name); diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/model/compile/RuleModelCompiler.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/model/compile/RuleModelCompiler.java index 55d246b64..3afc315dd 100644 --- a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/model/compile/RuleModelCompiler.java +++ b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/model/compile/RuleModelCompiler.java @@ -9,8 +9,8 @@ import io.nop.core.lang.eval.SeqEvalAction; import io.nop.core.model.table.CellPosition; import io.nop.rule.core.IExecutableRule; -import io.nop.rule.core.execute.AggregateExecutableRule; -import io.nop.rule.core.execute.ComputedInputRule; +import io.nop.rule.core.execute.NormalizeOutputExecutableRule; +import io.nop.rule.core.execute.NormalizeInputExecutableRule; import io.nop.rule.core.execute.DecoratedExecutableRule; import io.nop.rule.core.execute.ExecutableMatrixRule; import io.nop.rule.core.execute.ExecutableRule; @@ -18,7 +18,6 @@ import io.nop.rule.core.execute.RuleOutputAction; import io.nop.rule.core.model.RuleDecisionMatrixModel; import io.nop.rule.core.model.RuleDecisionTreeModel; -import io.nop.rule.core.model.RuleInputDefineModel; import io.nop.rule.core.model.RuleModel; import io.nop.rule.core.model.RuleOutputValueModel; import io.nop.rule.core.model.RuleTableCellModel; @@ -27,7 +26,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; public class RuleModelCompiler { private final XLangCompileTool compileTool; @@ -48,14 +46,9 @@ public IExecutableRule compileRule(RuleModel ruleModel) { rule = compileMatrix(ruleModel.getDecisionMatrix()); } - List computedVars = ruleModel.getInputs().stream().filter(RuleInputDefineModel::isComputed) - .collect(Collectors.toList()); + rule = new NormalizeOutputExecutableRule(ruleModel.getOutputs(), rule); - rule = new AggregateExecutableRule(rule, ruleModel.getOutputs()); - - if (!computedVars.isEmpty()) { - rule = new ComputedInputRule(computedVars, rule); - } + rule = new NormalizeInputExecutableRule(ruleModel.getInputs(), rule); if (ruleModel.getBeforeExecute() != null || ruleModel.getAfterExecute() != null) { rule = new DecoratedExecutableRule(ruleModel.getBeforeExecute(), diff --git a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/service/impl/RuleServiceImpl.java b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/service/impl/RuleServiceImpl.java index 28ec1614a..d5e96bfab 100644 --- a/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/service/impl/RuleServiceImpl.java +++ b/nop-rule/nop-rule-core/src/main/java/io/nop/rule/core/service/impl/RuleServiceImpl.java @@ -52,7 +52,7 @@ public void setRuleManager(IRuleManager ruleManager) { @Override public RuleResultBean executeRule(@RequestBean RuleRequestBean request, FieldSelectionBean selection, IServiceContext ctx) { - IRuleRuntime ruleRt = ruleManager.newRuntime(ctx.getEvalScope()); + IRuleRuntime ruleRt = ruleManager.newRuntime(ctx.getCache(), ctx.getEvalScope()); ruleRt.setInputs(request.getInputs()); ruleRt.setRuleName(request.getRuleName()); ruleRt.setRuleVersion(request.getRuleVersion()); diff --git a/nop-rule/nop-rule-core/src/main/resources/_vfs/nop/rule/imp/rule.imp.xml b/nop-rule/nop-rule-core/src/main/resources/_vfs/nop/rule/imp/rule.imp.xml index ff83aa43e..33ae682de 100644 --- a/nop-rule/nop-rule-core/src/main/resources/_vfs/nop/rule/imp/rule.imp.xml +++ b/nop-rule/nop-rule-core/src/main/resources/_vfs/nop/rule/imp/rule.imp.xml @@ -40,7 +40,7 @@ - + @@ -58,13 +58,23 @@ + + + + + - + @@ -120,6 +130,12 @@ + + diff --git a/nop-rule/nop-rule-meta/src/main/resources/_vfs/nop/rule/model/NopRuleOutput/NopRuleOutput.xmeta b/nop-rule/nop-rule-meta/src/main/resources/_vfs/nop/rule/model/NopRuleOutput/NopRuleOutput.xmeta index 74a266126..8d1e499a2 100644 --- a/nop-rule/nop-rule-meta/src/main/resources/_vfs/nop/rule/model/NopRuleOutput/NopRuleOutput.xmeta +++ b/nop-rule/nop-rule-meta/src/main/resources/_vfs/nop/rule/model/NopRuleOutput/NopRuleOutput.xmeta @@ -14,7 +14,7 @@ - + diff --git a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/autotest.yaml b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/autotest.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/input/decision-matrix.rule.xlsx b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/input/decision-matrix.rule.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8c12750b66694163686fe32c01410574dde41f48 GIT binary patch literal 15067 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\n \n \n \n \n \n 1\n \n \n \n \n \n \n 2\n \n \n \n \n \n \n 3\n \n \n \n \n \n \n 4\n \n \n \n \n \n \n 5\n \n \n \n \n \n \n 6\n \n \n \n \n \n \n 7\n \n \n \n \n \n \n 8\n \n \n \n \n \n \n 9\n \n \n \n \n \n \n 10\n \n \n \n \n \n \n 11\n \n \n \n \n \n \n 12\n \n \n \n \n \n \n 13\n \n \n \n \n \n \n 14\n \n \n 'A'\n \n \n \n \n \n \n 15\n \n \n \n \n \n \n 16\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n baseInfo.gender\n \n \n \n \n \n \n \n \n \n \n \n", + "status": 1, + "status_label": "1-启用", + "version": 0, + "createdBy": "autotest-ref", + "createTime": "@var:NopRuleDefinition@createTime", + "updatedBy": "autotest-ref", + "updateTime": "@var:NopRuleDefinition@createTime", + "ruleInputs": [ + { + "name": "是否有房", + "displayName": "是否有房", + "type": "Boolean", + "mandatory": true, + "computed": false, + "defaultExpr": null, + "description": null, + "schema": {} + }, + { + "name": "是否已婚", + "displayName": "是否已婚", + "type": "String", + "mandatory": true, + "computed": false, + "defaultExpr": null, + "description": null, + "schema": {} + }, + { + "name": "baseInfo", + "displayName": "基础信息", + "type": "Object", + "mandatory": true, + "computed": false, + "defaultExpr": null, + "description": null, + "schema": {} + }, + { + "name": "gender", + "displayName": "性别", + "type": "Integer", + "mandatory": true, + "computed": true, + "defaultExpr": "<_>baseInfo.gender", + "description": null, + "schema": { + "dict": "auth/gender" + } + } + ], + "ruleOutputs": [ + { + "name": "result", + "displayName": "分数", + "type": "Double", + "aggregate": null, + "description": null, + "schema": {} + }, + { + "name": "type", + "displayName": "类型", + "type": "String", + "aggregate": null, + "description": null, + "schema": {} + } + ], + "beforeExecute": null, + "decisionMatrix": "<_>\n \n \n \n \n 1\n \n \n \n \n \n \n 2\n \n \n \n \n \n \n 3\n \n \n \n \n \n \n 4\n \n \n \n \n \n \n 5\n \n \n \n \n \n \n 6\n \n \n \n \n \n \n 7\n \n \n \n \n \n \n 8\n \n \n \n \n \n \n 9\n \n \n \n \n \n \n 10\n \n \n \n \n \n \n 11\n \n \n \n \n \n \n 12\n \n \n \n \n \n \n 13\n \n \n \n \n \n \n 14\n \n \n 'A'\n \n \n \n \n \n \n 15\n \n \n \n \n \n \n 16\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n", + "id": "@var:NopRuleDefinition@ruleId", + "description": null, + "remark": null + }, + "status": 0 +} \ No newline at end of file diff --git a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/response2.json5 b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/response2.json5 new file mode 100644 index 000000000..fa3c58749 --- /dev/null +++ b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/response2.json5 @@ -0,0 +1,61 @@ +{ + "data": { + "logMessages": [ + { + "logTime": "@var:rule-log-time", + "message": "MISMATCH", + "ruleNodeId": "A3", + "ruleNodeLabel": "<20" + }, + { + "logTime": "@var:rule-log-time_1", + "message": "MISMATCH", + "ruleNodeId": "A5", + "ruleNodeLabel": "<30" + }, + { + "logTime": "@var:rule-log-time_2", + "message": "MATCH", + "ruleNodeId": "A6", + "ruleNodeLabel": ">=30" + }, + { + "logTime": "@var:rule-log-time_3", + "message": "MATCH", + "ruleNodeId": "B6", + "ruleNodeLabel": "-" + }, + { + "logTime": "@var:rule-log-time_4", + "message": "MISMATCH", + "ruleNodeId": "C1", + "ruleNodeLabel": "有房" + }, + { + "logTime": "@var:rule-log-time_5", + "message": "MATCH", + "ruleNodeId": "F1", + "ruleNodeLabel": "无房" + }, + { + "logTime": "@var:rule-log-time_6", + "message": "MISMATCH", + "ruleNodeId": "F2", + "ruleNodeLabel": "已婚" + }, + { + "logTime": "@var:rule-log-time_7", + "message": "MATCH", + "ruleNodeId": "G2", + "ruleNodeLabel": "未婚" + } + ], + "outputs": { + "result": 16 + }, + "ruleMatch": true, + "ruleName": "testMatrix", + "ruleVersion": 1 + }, + "status": 0 +} \ No newline at end of file diff --git a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_file_record.csv b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_file_record.csv new file mode 100644 index 000000000..aee5d228e --- /dev/null +++ b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_file_record.csv @@ -0,0 +1,2 @@ +_chgType,FILE_ID,FILE_NAME,FILE_PATH,FILE_EXT,MIME_TYPE,FILE_LENGTH,FILE_LAST_MODIFIED,BIZ_OBJ_NAME,BIZ_OBJ_ID,FIELD_NAME,FILE_HASH,DEL_FLAG,CREATED_BY,CREATE_TIME,REMARK +A,@var:NopFileRecord@fileId,decision-matrix.rule.xlsx,@var:NopFileRecord@filePath,xlsx,binary,1000,,NopRuleDefinition,__TEMP__,importFile,,1,autotest-ref,*, diff --git a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_rule_definition.csv b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_rule_definition.csv new file mode 100644 index 000000000..5b8c7f96f --- /dev/null +++ b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_rule_definition.csv @@ -0,0 +1,228 @@ +_chgType,RULE_ID,RULE_NAME,RULE_VERSION,DISPLAY_NAME,RULE_GROUP,RULE_TYPE,DESCRIPTION,MODEL_TEXT,STATUS,VERSION,CREATED_BY,CREATE_TIME,UPDATED_BY,UPDATE_TIME,REMARK +A,@var:NopRuleDefinition@ruleId,testMatrix,1,Test Matrix,default,MATX,," + + + + + + 1 + + + + + + + 2 + + + + + + + 3 + + + + + + + 4 + + + + + + + 5 + + + + + + + 6 + + + + + + + 7 + + + + + + + 8 + + + + + + + 9 + + + + + + + 10 + + + + + + + 11 + + + + + + + 12 + + + + + + + 13 + + + + + + + 14 + + + 'A' + + + + + + + 15 + + + + + + + 16 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + baseInfo.gender + + + + + + + + + + + +",1,0,autotest-ref,*,autotest-ref,*, diff --git a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_sys_sequence.csv b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_sys_sequence.csv new file mode 100644 index 000000000..9d72e730c --- /dev/null +++ b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/tables/nop_sys_sequence.csv @@ -0,0 +1,2 @@ +_chgType,SEQ_NAME,SEQ_TYPE,IS_UUID,NEXT_VALUE,STEP_SIZE,CACHE_SIZE,MAX_VALUE,RESET_TYPE,DEL_FLAG,VERSION,CREATED_BY,CREATE_TIME,UPDATED_BY,UPDATE_TIME,REMARK +A,default,seq,0,101,1,100,,,0,1,autotest-ref,*,autotest-ref,*, diff --git a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/upload-result.json5 b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/upload-result.json5 new file mode 100644 index 000000000..5c1e7e96e --- /dev/null +++ b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testDecisionMatrix/output/upload-result.json5 @@ -0,0 +1,8 @@ +{ + "data": { + "filename": "decision-matrix.rule.xlsx", + "url": null, + "value": "@var:downloadPath" + }, + "status": 0 +} \ No newline at end of file diff --git a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testImport/output/response.json5 b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testImport/output/response.json5 index ca00a7868..0d742516a 100644 --- a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testImport/output/response.json5 +++ b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testImport/output/response.json5 @@ -7,7 +7,7 @@ "ruleGroup": "default", "ruleType": "TREE", "ruleType_label": "TREE-决策树", - "modelText": "\n \n \n \n \n \n \n \n \n \n \n \n \n \n", + "modelText": "\n \n \n \n \n \n \n \n \n \n \n \n \n \n", "status": 1, "status_label": "1-启用", "version": 0, diff --git a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testImport/output/tables/nop_rule_definition.csv b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testImport/output/tables/nop_rule_definition.csv index b6f183b92..fd4b77bb7 100644 --- a/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testImport/output/tables/nop_rule_definition.csv +++ b/nop-rule/nop-rule-service/cases/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel/testImport/output/tables/nop_rule_definition.csv @@ -1,15 +1,15 @@ _chgType,RULE_ID,RULE_NAME,RULE_VERSION,DISPLAY_NAME,RULE_GROUP,RULE_TYPE,DESCRIPTION,MODEL_TEXT,STATUS,VERSION,CREATED_BY,CREATE_TIME,UPDATED_BY,UPDATE_TIME,REMARK A,@var:NopRuleDefinition@ruleId,test,1,Test Tree,default,TREE,," - + - + - + diff --git a/nop-rule/nop-rule-service/src/test/java/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel.java b/nop-rule/nop-rule-service/src/test/java/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel.java index a40154e2b..7f08f1b53 100644 --- a/nop-rule/nop-rule-service/src/test/java/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel.java +++ b/nop-rule/nop-rule-service/src/test/java/io/nop/rule/service/entity/TestNopRuleDefinitionBizModel.java @@ -28,12 +28,22 @@ public class TestNopRuleDefinitionBizModel extends JunitAutoTestCase { @EnableSnapshot @Test public void testImport() { - IResource resource = inputResource("decision-tree.rule.xlsx"); + runWithModelFile("decision-tree.rule.xlsx"); + } + + @EnableSnapshot + @Test + public void testDecisionMatrix() { + runWithModelFile("decision-matrix.rule.xlsx"); + } + + void runWithModelFile(String fileName) { + IResource resource = inputResource(fileName); InputStream is = resource.getInputStream(); try { UploadRequestBean request = new UploadRequestBean(); - request.setFileName("decision-tree.rule.xlsx"); + request.setFileName(fileName); request.setBizObjName(NopRuleDefinition.class.getSimpleName()); request.setFieldName("importFile"); request.setLength(1000);