├── .github └── workflows │ └── maven-publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── VERSIONS.md ├── pom.xml └── src ├── main └── java │ └── com │ └── ql │ └── util │ └── express │ ├── ArraySwap.java │ ├── CacheObject.java │ ├── CallResult.java │ ├── DefaultContext.java │ ├── DefaultExpressResourceLoader.java │ ├── DynamicParamsUtil.java │ ├── ExecuteTimeout.java │ ├── ExportItem.java │ ├── ExpressLoader.java │ ├── ExpressRemoteCacheRunner.java │ ├── ExpressRunner.java │ ├── ExpressUtil.java │ ├── IExpressContext.java │ ├── IExpressResourceLoader.java │ ├── InstructionSet.java │ ├── InstructionSetContext.java │ ├── InstructionSetRunner.java │ ├── LocalExpressCacheRunner.java │ ├── OperateData.java │ ├── Operator.java │ ├── OperatorOfNumber.java │ ├── QLambda.java │ ├── QLambdaInvocationHandler.java │ ├── RunEnvironment.java │ ├── annotation │ └── QLAlias.java │ ├── config │ ├── QLExpressRunStrategy.java │ ├── QLExpressTimer.java │ └── whitelist │ │ ├── AssignableChecker.java │ │ ├── CheckerFactory.java │ │ ├── MustChecker.java │ │ └── WhiteChecker.java │ ├── exception │ ├── QLBizException.java │ ├── QLCompileException.java │ ├── QLException.java │ ├── QLSecurityRiskException.java │ └── QLTimeoutException.java │ ├── instruction │ ├── BlockInstructionFactory.java │ ├── BreakInstructionFactory.java │ ├── CallFunctionInstructionFactory.java │ ├── CastInstructionFactory.java │ ├── ConstDataInstructionFactory.java │ ├── ContinueInstructionFactory.java │ ├── DefineInstructionFactory.java │ ├── FieldCallInstructionFactory.java │ ├── ForInstructionFactory.java │ ├── ForRelBreakContinue.java │ ├── FunctionInstructionFactory.java │ ├── FunctionInstructionSet.java │ ├── IOperateDataCache.java │ ├── IfInstructionFactory.java │ ├── InInstructionFactory.java │ ├── InstructionFactory.java │ ├── KeyValueInstructionFactory.java │ ├── LambdaInstructionFactory.java │ ├── LoadAttrInstructionFactory.java │ ├── MacroInstructionFactory.java │ ├── MethodCallInstructionFactory.java │ ├── NewInstructionFactory.java │ ├── NewVClassInstructionFactory.java │ ├── NullInstructionFactory.java │ ├── OperateDataCacheImpl.java │ ├── OperateDataCacheManager.java │ ├── OperatorInstructionFactory.java │ ├── detail │ │ ├── Instruction.java │ │ ├── InstructionCallMacro.java │ │ ├── InstructionCallSelfDefineFunction.java │ │ ├── InstructionClearDataStack.java │ │ ├── InstructionCloseNewArea.java │ │ ├── InstructionConstData.java │ │ ├── InstructionGoTo.java │ │ ├── InstructionGoToWithCondition.java │ │ ├── InstructionGoToWithNotNull.java │ │ ├── InstructionLoadAttr.java │ │ ├── InstructionLoadLambda.java │ │ ├── InstructionNewVirClass.java │ │ ├── InstructionOpenNewArea.java │ │ ├── InstructionOperator.java │ │ └── InstructionReturn.java │ ├── op │ │ ├── CanClone.java │ │ ├── OperatorAdd.java │ │ ├── OperatorAlias.java │ │ ├── OperatorAnd.java │ │ ├── OperatorAnonymousNewArray.java │ │ ├── OperatorAnonymousNewList.java │ │ ├── OperatorAnonymousNewMap.java │ │ ├── OperatorArray.java │ │ ├── OperatorBase.java │ │ ├── OperatorBit.java │ │ ├── OperatorCast.java │ │ ├── OperatorDef.java │ │ ├── OperatorDoubleAddReduce.java │ │ ├── OperatorEqualsLessMore.java │ │ ├── OperatorEvaluate.java │ │ ├── OperatorExportAlias.java │ │ ├── OperatorExportDef.java │ │ ├── OperatorFactory.java │ │ ├── OperatorField.java │ │ ├── OperatorIf.java │ │ ├── OperatorIn.java │ │ ├── OperatorInstanceOf.java │ │ ├── OperatorKeyValue.java │ │ ├── OperatorLike.java │ │ ├── OperatorMacro.java │ │ ├── OperatorMethod.java │ │ ├── OperatorMinMax.java │ │ ├── OperatorMultiplyDivide.java │ │ ├── OperatorNew.java │ │ ├── OperatorNor.java │ │ ├── OperatorNot.java │ │ ├── OperatorOr.java │ │ ├── OperatorPrint.java │ │ ├── OperatorPrintln.java │ │ ├── OperatorReduce.java │ │ ├── OperatorRound.java │ │ ├── OperatorSelfDefineClassFunction.java │ │ └── OperatorSelfDefineServiceFunction.java │ └── opdata │ │ ├── OperateClass.java │ │ ├── OperateDataAlias.java │ │ ├── OperateDataArrayItem.java │ │ ├── OperateDataAttr.java │ │ ├── OperateDataField.java │ │ ├── OperateDataKeyValue.java │ │ ├── OperateDataLocalVar.java │ │ └── OperateDataVirClass.java │ ├── match │ ├── IDataNode.java │ ├── INodeType.java │ ├── INodeTypeManager.java │ ├── QLMatchResult.java │ ├── QLMatchResultTree.java │ ├── QLPattern.java │ └── QLPatternNode.java │ ├── parse │ ├── AppendingClassFieldManager.java │ ├── AppendingClassMethodManager.java │ ├── ExpressNode.java │ ├── ExpressPackage.java │ ├── ExpressParse.java │ ├── KeyWordDefine4Java.java │ ├── NodeType.java │ ├── NodeTypeManager.java │ ├── Word.java │ └── WordSplit.java │ └── util │ └── QLAliasUtils.java └── test ├── java └── com │ └── ql │ └── util │ └── express │ ├── ExecuteTimeoutTest.java │ ├── annotation │ ├── Patient.java │ ├── Person.java │ ├── QLAliasContext.java │ └── QLAliasTest.java │ ├── bugfix │ ├── AdjustTypesTest.java │ ├── ArrCallBugFixTest.java │ ├── ArrayMapTest.java │ ├── AvoidNullPointMockTest.java │ ├── BreakContinueTest.java │ ├── CheckSyntaxTest.java │ ├── CommentTest.java │ ├── CompareObjectTest.java │ ├── CompileMemoryTest.java │ ├── ContextMessagePutTest.java │ ├── CrashTest.java │ ├── ErrorColumnTest.java │ ├── ExecuteReentrantTest.java │ ├── FunctionTest.java │ ├── IgnoreConstCharTest.java │ ├── ImportClassPathTest.java │ ├── InOperatorTest.java │ ├── InvokeSecurityRiskConstructorsBlackListTest.java │ ├── InvokeSecurityRiskConstructorsTest.java │ ├── InvokeSecurityRiskMethodsTest.java │ ├── Issue179LikeTest.java │ ├── LoopFunctionTest.java │ ├── LuofanTest.java │ ├── NullCompareTest.java │ ├── OverFlowTest.java │ ├── RecursivelyRunnerTest.java │ ├── RecursivelyTest.java │ ├── StackOverFlowTest.java │ ├── StringTest.java │ └── ThrowExceptionTest.java │ ├── cfuture │ ├── ArrayMisTypeTest.java │ ├── ArrayPropertyMixTest.java │ ├── DebugQlScriptTest.java │ └── LambdaTest.java │ ├── config │ └── QLExpressTimerTest.java │ ├── console │ ├── Console.java │ ├── ConsoleFrame.java │ ├── ConsoleFrame2.java │ ├── ExampleDefine.java │ ├── FileTree.java │ └── ReadExample.java │ ├── example │ ├── ArgumentTypeMismatchTest.java │ ├── BeanTest.java │ ├── CustBean.java │ ├── MultiLevelSecurityTest.java │ ├── OperatorTest.java │ ├── RiskBean.java │ ├── TypicalDemo.java │ ├── WorkflowTest.java │ └── operator │ │ ├── AddNOperator.java │ │ ├── AddTwiceOperator.java │ │ └── ApproveOperator.java │ ├── instruction │ └── op │ │ └── OperatorLikeTest.java │ ├── issue │ ├── Issue187InEqualitySignTest.java │ ├── Issue284LikeTest.java │ └── Issue337CommentInImportTest.java │ └── test │ ├── AClassDefineSingleTest.java │ ├── AClassDefineTest.java │ ├── ATempTest.java │ ├── AddMacroDefineTest.java │ ├── AddMethodInvokeTest.java │ ├── ArrayLenCheckTest.java │ ├── ArrayTest.java │ ├── BeanExample.java │ ├── BeanExampleChild.java │ ├── BitTest.java │ ├── CallWithNullParameterTest.java │ ├── DateFormatTest.java │ ├── DateTest.java │ ├── DefineTest.java │ ├── DemoShowTest.java │ ├── DynamicFieldTest.java │ ├── ExportDefineTest.java │ ├── ExpressCacheTest.java │ ├── ExpressContextExample.java │ ├── ExpressRemoteCacheTest.java │ ├── ExpressTest.java │ ├── ForFlowFunctionTest.java │ ├── FunctionDescTest.java │ ├── GetExpressAttrNamesTest.java │ ├── GetExpressFunctionNamesTest.java │ ├── GroupOperator.java │ ├── HTMLTest.java │ ├── IfTest.java │ ├── ImportTest.java │ ├── InTest.java │ ├── InstanceOfTest.java │ ├── IsAssignableTest.java │ ├── LoadExpressFromFileTest.java │ ├── LoveOperator.java │ ├── MapTest.java │ ├── MethodInvokeTest.java │ ├── MethodParamsTest.java │ ├── MinusOperatorTest.java │ ├── NewExpressTest.java │ ├── NullableOperatorEqualsLessMore.java │ ├── NumberComputerTest.java │ ├── NumberOperatorCalculatorTest.java │ ├── ObjectBean.java │ ├── ObjectTest.java │ ├── OpCallTest.java │ ├── PreloadExpressTest.java │ ├── PrintLineExceptionTest.java │ ├── ReplaceCompareOperatorTest.java │ ├── ReplaceOperatorTest.java │ ├── SerializableTest.java │ ├── SetTest.java │ ├── StaticMethodTest.java │ ├── SubtractTest.java │ ├── TimeoutExceptionTest.java │ ├── VarAreaTest.java │ ├── custom │ ├── CustomClassLoaderTest.java │ ├── SelfDefineObject1.java │ └── SelfDefineObject2.java │ ├── logic │ ├── ShortCircuitLogicTest.java │ └── SimpleShortCircuitLogicTest.java │ ├── rating │ ├── RatingTest.java │ ├── RatingWithPropertyTest.java │ ├── SubjectManager.java │ ├── SubjectOperator.java │ └── SubjectValue.java │ └── spring │ ├── BizLogicBean.java │ ├── QLExpressContext.java │ ├── QlExpressUtil.java │ ├── SpringDemoTest.java │ └── UserDO.java └── resources ├── bugfix └── error-column.ql ├── classes └── com │ └── ql │ └── util │ └── express │ └── test │ └── custom │ └── SelfDefineObject1.class ├── com └── ql │ └── util │ └── express │ └── console │ ├── closeFile.png │ ├── help.png │ ├── openFile.png │ └── run.png ├── example ├── approve.ql ├── approve1.ql └── approve2.ql ├── functionDef.ql ├── includeFunction.ql ├── includeMacro.ql ├── includeRoot.ql ├── lineTest.ql ├── log4j.properties ├── main.ql ├── rating.ql ├── ratingWithProperty.ql ├── spring-express-config.xml └── testFunctionParameterType.ql /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | name: Maven Central Repo Deployment 2 | on: 3 | release: 4 | types: [released, prereleased] 5 | jobs: 6 | publish: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout Git Repo 10 | uses: actions/checkout@v2 11 | - name: Set up Maven Central Repo 12 | uses: actions/setup-java@v4 13 | with: 14 | distribution: temurin 15 | java-version: 8 16 | server-id: ossrh 17 | server-username: 'OSSRH_USER' 18 | server-password: 'OSSRH_PASSWORD' 19 | gpg-passphrase: 'MAVEN_GPG_PASSPHRASE' 20 | gpg-private-key: ${{ secrets.GPG_SECRET }} 21 | - name: debug settings.xml 22 | run: cat /home/runner/.m2/settings.xml 23 | - name: Publish to Maven Central Repo 24 | run: mvn clean deploy --batch-mode --activate-profiles deploy 25 | env: 26 | OSSRH_USER: ${{ secrets.OSSRH_TOKEN_USER }} 27 | OSSRH_PASSWORD: ${{ secrets.OSSRH_TOKEN_PASSWORD }} 28 | MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSWORD }} 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | *.class 4 | !SelfDefineObject1.class 5 | 6 | target/* 7 | *.iml 8 | .idea/ 9 | gen/ 10 | 11 | 12 | # Mobile Tools for Java (J2ME) 13 | .mtj.tmp/ 14 | 15 | # Package Files # 16 | *.jar 17 | *.war 18 | *.ear 19 | 20 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 21 | hs_err_pid* 22 | 23 | test.log 24 | test-push.sh 25 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/ArraySwap.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | public final class ArraySwap { 4 | private OperateData[] operateDataArray; 5 | private int start; 6 | public int length; 7 | 8 | public void swap(OperateData[] operateDataArray, int start, int length) { 9 | this.operateDataArray = operateDataArray; 10 | this.start = start; 11 | this.length = length; 12 | } 13 | 14 | public OperateData get(int i) { 15 | return this.operateDataArray[i + start]; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/CacheObject.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | /** 4 | * 简单的缓存对象 5 | * 6 | * @author tianqiao 7 | */ 8 | public class CacheObject { 9 | private String expressName; 10 | 11 | private String text; 12 | 13 | private InstructionSet instructionSet; 14 | 15 | public String getExpressName() { 16 | return expressName; 17 | } 18 | 19 | public void setExpressName(String name) { 20 | this.expressName = name; 21 | } 22 | 23 | public String getText() { 24 | return text; 25 | } 26 | 27 | public void setText(String text) { 28 | this.text = text; 29 | } 30 | 31 | public InstructionSet getInstructionSet() { 32 | return instructionSet; 33 | } 34 | 35 | public void setInstructionSet(InstructionSet instructionSet) { 36 | this.instructionSet = instructionSet; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/CallResult.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | public class CallResult { 4 | private Object returnValue; 5 | private boolean isExit; 6 | 7 | public CallResult(Object returnValue, boolean isExit) { 8 | this.initial(returnValue, isExit); 9 | } 10 | 11 | public void initial(Object returnValue, boolean isExit) { 12 | this.returnValue = returnValue; 13 | this.isExit = isExit; 14 | } 15 | 16 | public void clear() { 17 | this.returnValue = null; 18 | this.isExit = false; 19 | } 20 | 21 | public Object getReturnValue() { 22 | return returnValue; 23 | } 24 | 25 | public boolean isExit() { 26 | return isExit; 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/DefaultContext.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | import java.util.HashMap; 4 | 5 | @SuppressWarnings("serial") 6 | public class DefaultContext extends HashMap implements IExpressContext { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/DefaultExpressResourceLoader.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.InputStream; 5 | import java.io.InputStreamReader; 6 | 7 | import com.ql.util.express.exception.QLException; 8 | 9 | public class DefaultExpressResourceLoader implements IExpressResourceLoader { 10 | @Override 11 | public String loadExpress(String expressName) throws Exception { 12 | expressName = expressName.replace('.', '/') + ".ql"; 13 | InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(expressName); 14 | if (inputStream == null) { 15 | throw new QLException("不能找到表达式文件:" + expressName); 16 | } 17 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 18 | StringBuilder stringBuilder = new StringBuilder(); 19 | String tmpStr; 20 | while ((tmpStr = bufferedReader.readLine()) != null) { 21 | stringBuilder.append(tmpStr).append("\n"); 22 | } 23 | bufferedReader.close(); 24 | inputStream.close(); 25 | return stringBuilder.toString(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/ExecuteTimeout.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | /** 4 | * Author: DQinYuan 5 | */ 6 | public class ExecuteTimeout { 7 | /** 8 | * 表示不限制时间的实例 9 | */ 10 | public static final ExecuteTimeout NO_TIMEOUT = new ExecuteTimeout(-1); 11 | 12 | private final long timeoutMillis; 13 | 14 | private final long endTime; 15 | 16 | public ExecuteTimeout(long timeoutMillis) { 17 | this.timeoutMillis = timeoutMillis; 18 | this.endTime = timeoutMillis != -1 ? System.currentTimeMillis() + timeoutMillis : -1; 19 | } 20 | 21 | public boolean isExpired() { 22 | return endTime != -1 && System.currentTimeMillis() > endTime; 23 | } 24 | 25 | public long getTimeoutMillis() { 26 | return timeoutMillis; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/ExportItem.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | /** 4 | * 输出给其它指令共享使用的对象 5 | * 6 | * @author xuannan 7 | */ 8 | public class ExportItem { 9 | public static final String TYPE_ALIAS = "alias"; 10 | public static final String TYPE_DEF = "def"; 11 | public static final String TYPE_FUNCTION = "function"; 12 | public static final String TYPE_MACRO = "macro"; 13 | private String globeName; 14 | String name; 15 | 16 | /** 17 | * def, alias 18 | */ 19 | private String type; 20 | 21 | /** 22 | * 类名或者别名 23 | */ 24 | private String desc; 25 | 26 | public ExportItem(String name, String type, String desc) { 27 | this.globeName = name; 28 | this.name = name; 29 | this.type = type; 30 | this.desc = desc; 31 | } 32 | 33 | public ExportItem(String globeName, String name, String type, String desc) { 34 | this.globeName = globeName; 35 | this.name = name; 36 | this.type = type; 37 | this.desc = desc; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return this.globeName + "[" + this.type + ":" + this.name + " " + this.desc + "]"; 43 | } 44 | 45 | public String getGlobeName() { 46 | return globeName; 47 | } 48 | 49 | public void setGlobeName(String globeName) { 50 | this.globeName = globeName; 51 | } 52 | 53 | public String getName() { 54 | return name; 55 | } 56 | 57 | public void setName(String name) { 58 | this.name = name; 59 | } 60 | 61 | public String getType() { 62 | return type; 63 | } 64 | 65 | public void setType(String type) { 66 | this.type = type; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/ExpressRemoteCacheRunner.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 远程缓存对象 7 | * 8 | * @author tianqiao 9 | */ 10 | public abstract class ExpressRemoteCacheRunner { 11 | public void loadCache(String expressName, String text) { 12 | InstructionSet instructionSet; 13 | try { 14 | instructionSet = getExpressRunner().parseInstructionSet(text); 15 | CacheObject cache = new CacheObject(); 16 | cache.setExpressName(expressName); 17 | cache.setText(text); 18 | cache.setInstructionSet(instructionSet); 19 | this.putCache(expressName, cache); 20 | } catch (Exception e) { 21 | throw new RuntimeException("解析指令并缓存过程出现错误.", e); 22 | } 23 | } 24 | 25 | public Object execute(String name, IExpressContext context, List errorList, boolean isTrace, 26 | boolean isCatchException) { 27 | try { 28 | CacheObject cache = (CacheObject)this.getCache(name); 29 | if (cache == null) { 30 | throw new RuntimeException("未获取到缓存对象."); 31 | } 32 | ExpressRunner expressRunner = getExpressRunner(); 33 | return expressRunner.execute(cache.getInstructionSet(), context, errorList, isTrace, isCatchException); 34 | } catch (Exception e) { 35 | throw new RuntimeException("获取缓存信息,并且执行指令集出现错误.", e); 36 | } 37 | } 38 | 39 | /** 40 | * 获取执行器ExpressRunner 41 | * 42 | * @return 43 | */ 44 | public abstract ExpressRunner getExpressRunner(); 45 | 46 | /** 47 | * 获取缓存对象 48 | * 49 | * @param key 50 | * @return 51 | */ 52 | public abstract Object getCache(String key); 53 | 54 | /** 55 | * 放置缓存的对象 56 | * 57 | * @param key 58 | * @param object 59 | */ 60 | public abstract void putCache(String key, Object object); 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/IExpressContext.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | /** 4 | * 表达式计算的数据注入接口 5 | * 6 | * @author qhlhl2010@gmail.com 7 | */ 8 | public interface IExpressContext { 9 | /** 10 | * 根据名称从属性列表中提取属性值。如果表达式中用到了Spring的对象,也是通过此方法获取 11 | * 12 | * @param key 属性名称 13 | * @return 14 | */ 15 | V get(Object key); 16 | 17 | /** 18 | * 表达式计算的结果可以设置回调用系统,例如 userId = 3 + 4 19 | * 20 | * @param name 属性名称 21 | * @param object 属性值 22 | */ 23 | V put(K name, V object); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/IExpressResourceLoader.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | /** 4 | * 加载表达式资源接口 5 | * 6 | * @author xuannan 7 | */ 8 | public interface IExpressResourceLoader { 9 | /** 10 | * 根据表达式名称获取表达式的内容 11 | * 12 | * @param expressName 13 | * @return 14 | * @throws Exception 15 | */ 16 | String loadExpress(String expressName) throws Exception; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/LocalExpressCacheRunner.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 作为表达式 8 | * 9 | * @author tianqiao 10 | */ 11 | public class LocalExpressCacheRunner extends ExpressRemoteCacheRunner { 12 | private static final Map EXPRESS_MAP = new HashMap<>(); 13 | 14 | private final ExpressRunner expressRunner; 15 | 16 | public LocalExpressCacheRunner(ExpressRunner expressRunner) { 17 | this.expressRunner = expressRunner; 18 | } 19 | 20 | @Override 21 | public final Object getCache(String key) { 22 | return EXPRESS_MAP.get(key); 23 | } 24 | 25 | @Override 26 | public final void putCache(String key, Object object) { 27 | EXPRESS_MAP.put(key, object); 28 | } 29 | 30 | @Override 31 | public final ExpressRunner getExpressRunner() { 32 | return this.expressRunner; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/QLambdaInvocationHandler.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | import java.lang.reflect.Modifier; 6 | 7 | public class QLambdaInvocationHandler implements InvocationHandler { 8 | private final QLambda qLambda; 9 | 10 | public QLambdaInvocationHandler(QLambda qLambda) { 11 | this.qLambda = qLambda; 12 | } 13 | 14 | @Override 15 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 16 | return Modifier.isAbstract(method.getModifiers()) ? qLambda.call(args) : 17 | // 为了应对 toString 方法 18 | method.getReturnType() == String.class ? "QLambdaProxy" : null; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/annotation/QLAlias.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.annotation; 2 | 3 | import java.lang.annotation.Inherited; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import static java.lang.annotation.ElementType.FIELD; 9 | import static java.lang.annotation.ElementType.METHOD; 10 | import static java.lang.annotation.ElementType.PARAMETER; 11 | import static java.lang.annotation.ElementType.TYPE; 12 | 13 | @Inherited 14 | @Target({TYPE, FIELD, METHOD, PARAMETER}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface QLAlias { 17 | /** 18 | * 注解内容 19 | */ 20 | String[] value(); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/config/QLExpressTimer.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.config; 2 | 3 | /** 4 | * @author tianqiao@taobao.com 5 | * @since 2019/6/17 4:12 PM 6 | */ 7 | public class QLExpressTimer { 8 | 9 | private static long globalTimeoutMillis = -1; 10 | 11 | /** 12 | * 设置全局脚本超时时间, 默认 -1, 表示不限制时间 13 | * 14 | * @param timeoutMillis 超时时间 15 | * @deprecated 原 api 命名不合理, 推荐替换为 {@link #setTimeout(long)} 16 | */ 17 | @Deprecated 18 | public static void setTimer(long timeoutMillis) { 19 | globalTimeoutMillis = timeoutMillis; 20 | } 21 | 22 | /** 23 | * 设置全局脚本超时时间, 默认 -1, 表示不限制时间 24 | * 25 | * @param timeoutMillis 超时时间 26 | * @since 3.3.3 27 | */ 28 | public static void setTimeout(long timeoutMillis) { 29 | globalTimeoutMillis = timeoutMillis; 30 | } 31 | 32 | public static long getTimeout() { 33 | return globalTimeoutMillis; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/config/whitelist/AssignableChecker.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.config.whitelist; 2 | 3 | public class AssignableChecker implements WhiteChecker { 4 | private final Class whiteClazz; 5 | 6 | public AssignableChecker(Class whiteClazz) { 7 | this.whiteClazz = whiteClazz; 8 | } 9 | 10 | @Override 11 | public boolean check(Class clazz) { 12 | return whiteClazz.isAssignableFrom(clazz); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/config/whitelist/CheckerFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.config.whitelist; 2 | 3 | public class CheckerFactory { 4 | 5 | public static WhiteChecker must(Class clazz) { 6 | return new MustChecker(clazz); 7 | } 8 | 9 | public static WhiteChecker assignable(Class clazz) { 10 | return new AssignableChecker(clazz); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/config/whitelist/MustChecker.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.config.whitelist; 2 | 3 | public class MustChecker implements WhiteChecker { 4 | private final Class whiteClazz; 5 | 6 | public MustChecker(Class whiteClazz) { 7 | this.whiteClazz = whiteClazz; 8 | } 9 | 10 | @Override 11 | public boolean check(Class clazz) { 12 | return clazz == whiteClazz; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/config/whitelist/WhiteChecker.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.config.whitelist; 2 | 3 | public interface WhiteChecker { 4 | 5 | /** 6 | * @param clazz 7 | * @return true 表示白名单校验通过 8 | */ 9 | boolean check(Class clazz); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/exception/QLBizException.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.exception; 2 | 3 | /** 4 | * 非QLExpress框架捕获的业务系统代码的异常 5 | * 6 | * @author tianqiao@taobao.com 7 | * @since 2019/6/18 2:13 PM 8 | */ 9 | public class QLBizException extends Exception { 10 | private static final long serialVersionUID = -5602081330453002691L; 11 | 12 | public QLBizException() { 13 | } 14 | 15 | public QLBizException(String message) { 16 | super(message); 17 | } 18 | 19 | public QLBizException(String message, Throwable cause) { 20 | super(message, cause); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/exception/QLCompileException.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.exception; 2 | 3 | /** 4 | * 编译器的异常信息 5 | * 6 | * @author tianqiao@taobao.com 7 | * @since 2019/6/18 2:13 PM 8 | */ 9 | public class QLCompileException extends Exception { 10 | private static final long serialVersionUID = -4743114416550746038L; 11 | 12 | public QLCompileException() { 13 | } 14 | 15 | public QLCompileException(String message) { 16 | super(message); 17 | } 18 | 19 | public QLCompileException(String message, Throwable cause) { 20 | super(message, cause); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/exception/QLException.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.exception; 2 | 3 | /** 4 | * QLExpress的框架执行过程中捕获的异常 5 | * 6 | * @author tianqiao@taobao.com 7 | * @since 2019/6/18 2:13 PM 8 | */ 9 | public class QLException extends Exception { 10 | private static final long serialVersionUID = -1861857045313408218L; 11 | 12 | public QLException() { 13 | } 14 | 15 | public QLException(String message) { 16 | super(message); 17 | } 18 | 19 | public QLException(String message, Throwable cause) { 20 | super(message, cause); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/exception/QLSecurityRiskException.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.exception; 2 | 3 | /** 4 | * 系统安全相关异常(比如调用操作系统命令等) 5 | * 6 | * @author tianqiao@taobao.com 7 | * @since 2019/6/18 10:36 AM 8 | */ 9 | public class QLSecurityRiskException extends QLException { 10 | private static final long serialVersionUID = 1832507141776889856L; 11 | 12 | public QLSecurityRiskException() { 13 | } 14 | 15 | public QLSecurityRiskException(String message) { 16 | super(message); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/exception/QLTimeoutException.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.exception; 2 | 3 | /** 4 | * 设置了timeoutMills造成的超时异常 5 | * 6 | * @author tianqiao@taobao.com 7 | * @since 2019/6/18 10:36 AM 8 | */ 9 | public class QLTimeoutException extends QLException { 10 | private static final long serialVersionUID = 8386258847642771321L; 11 | 12 | public QLTimeoutException() { 13 | } 14 | 15 | public QLTimeoutException(String message) { 16 | super(message); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/BlockInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.instruction.detail.InstructionClearDataStack; 8 | import com.ql.util.express.instruction.detail.InstructionCloseNewArea; 9 | import com.ql.util.express.instruction.detail.InstructionOpenNewArea; 10 | import com.ql.util.express.parse.ExpressNode; 11 | 12 | public class BlockInstructionFactory extends InstructionFactory { 13 | @Override 14 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 15 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception { 16 | if (node.isTypeEqualsOrChild("STAT_SEMICOLON") && result.getCurrentPoint() >= 0 && !(result.getInstruction( 17 | result.getCurrentPoint()) instanceof InstructionClearDataStack)) { 18 | result.addInstruction(new InstructionClearDataStack().setLine(node.getLine())); 19 | } 20 | 21 | boolean needOpenNewArea = !isRoot && "STAT_BLOCK".equals(node.getNodeType().getName()); 22 | if (needOpenNewArea) { 23 | result.addInstruction(new InstructionOpenNewArea().setLine(node.getLine())); 24 | } 25 | boolean returnVal; 26 | boolean hasDef = false; 27 | for (ExpressNode tmpNode : node.getChildrenArray()) { 28 | boolean tmpHas = expressRunner.createInstructionSetPrivate(result, forStack, tmpNode, false); 29 | hasDef = hasDef || tmpHas; 30 | } 31 | if (needOpenNewArea) { 32 | result.addInstruction(new InstructionCloseNewArea().setLine(node.getLine())); 33 | returnVal = false; 34 | } else { 35 | returnVal = hasDef; 36 | } 37 | return returnVal; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/BreakInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.instruction.detail.InstructionGoTo; 8 | import com.ql.util.express.parse.ExpressNode; 9 | 10 | public class BreakInstructionFactory extends InstructionFactory { 11 | @Override 12 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 13 | Stack forStack, ExpressNode node, boolean isRoot) { 14 | InstructionGoTo breakInstruction = new InstructionGoTo(result.getCurrentPoint() + 1); 15 | breakInstruction.setName("break"); 16 | forStack.peek().breakList.add(breakInstruction); 17 | result.addInstruction(breakInstruction.setLine(node.getLine())); 18 | return false; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/CallFunctionInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.instruction.detail.InstructionCallSelfDefineFunction; 8 | import com.ql.util.express.instruction.detail.InstructionOperator; 9 | import com.ql.util.express.instruction.op.OperatorBase; 10 | import com.ql.util.express.parse.ExpressNode; 11 | 12 | public class CallFunctionInstructionFactory extends InstructionFactory { 13 | @Override 14 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 15 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception { 16 | ExpressNode[] children = node.getChildrenArray(); 17 | String functionName = children[0].getValue(); 18 | boolean returnVal = false; 19 | children = node.getChildrenArray(); 20 | for (int i = 1; i < children.length; i++) { 21 | boolean tmpHas = expressRunner.createInstructionSetPrivate(result, forStack, children[i], false); 22 | returnVal = returnVal || tmpHas; 23 | } 24 | 25 | OperatorBase op = expressRunner.getOperatorFactory().getOperator(functionName); 26 | int opNum = children.length - 1; 27 | if (op != null) { 28 | result.addInstruction(new InstructionOperator(op, opNum).setLine(node.getLine())); 29 | } else { 30 | result.addInstruction( 31 | new InstructionCallSelfDefineFunction(functionName, opNum).setLine(children[0].getLine())); 32 | } 33 | return returnVal; 34 | } 35 | } 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/CastInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.exception.QLException; 8 | import com.ql.util.express.instruction.detail.InstructionOperator; 9 | import com.ql.util.express.instruction.op.OperatorBase; 10 | import com.ql.util.express.parse.ExpressNode; 11 | 12 | public class CastInstructionFactory extends InstructionFactory { 13 | @Override 14 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 15 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception { 16 | boolean returnVal = false; 17 | OperatorBase op = expressRunner.getOperatorFactory().newInstance(node); 18 | ExpressNode[] children = node.getChildrenArray(); 19 | if (children.length == 0) { 20 | throw new QLException("扩展类型不存在"); 21 | } else if (children.length > 2) { 22 | throw new QLException("扩展操作只能有一个类型为Class的操作数"); 23 | } else if (!children[0].getNodeType().isEqualsOrChild("CONST_CLASS")) { 24 | throw new QLException("扩展操作只能有一个类型为Class的操作数,当前的数据类型是:" + children[0].getNodeType().getName()); 25 | } 26 | 27 | for (ExpressNode child : children) { 28 | boolean tmpHas = expressRunner.createInstructionSetPrivate(result, forStack, child, false); 29 | returnVal = returnVal || tmpHas; 30 | } 31 | result.addInstruction(new InstructionOperator(op, children.length).setLine(node.getLine())); 32 | return returnVal; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/ConstDataInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.OperateData; 8 | import com.ql.util.express.instruction.detail.InstructionConstData; 9 | import com.ql.util.express.instruction.opdata.OperateClass; 10 | import com.ql.util.express.parse.ExpressNode; 11 | 12 | public class ConstDataInstructionFactory extends InstructionFactory { 13 | public OperateData genOperateData(ExpressNode node) { 14 | if (node.isTypeEqualsOrChild("CONST_CLASS")) { 15 | return new OperateClass(node.getValue(), (Class)node.getObjectValue()); 16 | } else { 17 | return new OperateData(node.getObjectValue(), node.getObjectValue().getClass()); 18 | } 19 | } 20 | 21 | @Override 22 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 23 | Stack forStack, ExpressNode node, boolean isRoot) { 24 | result.addInstruction(new InstructionConstData(genOperateData(node)).setLine(node.getLine())); 25 | return false; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/ContinueInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.instruction.detail.InstructionGoTo; 8 | import com.ql.util.express.parse.ExpressNode; 9 | 10 | public class ContinueInstructionFactory extends InstructionFactory { 11 | @Override 12 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 13 | Stack forStack, ExpressNode node, boolean isRoot) { 14 | InstructionGoTo continueInstruction = new InstructionGoTo(result.getCurrentPoint() + 1); 15 | continueInstruction.setName("continue"); 16 | forStack.peek().continueList.add(continueInstruction); 17 | result.addInstruction(continueInstruction.setLine(node.getLine())); 18 | return false; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/FieldCallInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.exception.QLCompileException; 8 | import com.ql.util.express.instruction.detail.InstructionOperator; 9 | import com.ql.util.express.instruction.op.OperatorBase; 10 | import com.ql.util.express.instruction.op.OperatorField; 11 | import com.ql.util.express.parse.ExpressNode; 12 | 13 | public class FieldCallInstructionFactory extends InstructionFactory { 14 | @Override 15 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 16 | Stack forStack, 17 | ExpressNode node, boolean isRoot) throws Exception { 18 | ExpressNode[] children = node.getChildrenArray(); 19 | 20 | //处理对象 21 | boolean returnValue = expressRunner.createInstructionSetPrivate(result, forStack, children[0], false); 22 | 23 | //处理属性名称 24 | if (!"CONST_STRING".equalsIgnoreCase(children[1].getNodeType().getName())) { 25 | throw new QLCompileException("对象属性名称不是字符串常量:" + children[1]); 26 | } 27 | 28 | String fieldName = (String)children[1].getObjectValue(); 29 | 30 | OperatorBase op = new OperatorField(fieldName); 31 | result.addInstruction(new InstructionOperator(op, 1).setLine(node.getLine())); 32 | return returnValue; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/ForRelBreakContinue.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.ql.util.express.instruction.detail.InstructionGoTo; 7 | 8 | public class ForRelBreakContinue { 9 | final List breakList = new ArrayList<>(); 10 | final List continueList = new ArrayList<>(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/FunctionInstructionSet.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import com.ql.util.express.InstructionSet; 4 | 5 | /** 6 | * TODO public field 7 | */ 8 | public class FunctionInstructionSet { 9 | public final String name; 10 | public final String type; 11 | public final InstructionSet instructionSet; 12 | 13 | public FunctionInstructionSet(String name, String type, InstructionSet instructionSet) { 14 | this.name = name; 15 | this.type = type; 16 | this.instructionSet = instructionSet; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/IOperateDataCache.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import com.ql.util.express.CallResult; 4 | import com.ql.util.express.ExecuteTimeout; 5 | import com.ql.util.express.ExpressLoader; 6 | import com.ql.util.express.ExpressRunner; 7 | import com.ql.util.express.IExpressContext; 8 | import com.ql.util.express.InstructionSet; 9 | import com.ql.util.express.InstructionSetContext; 10 | import com.ql.util.express.OperateData; 11 | import com.ql.util.express.RunEnvironment; 12 | import com.ql.util.express.instruction.opdata.OperateDataArrayItem; 13 | import com.ql.util.express.instruction.opdata.OperateDataAttr; 14 | import com.ql.util.express.instruction.opdata.OperateDataField; 15 | import com.ql.util.express.instruction.opdata.OperateDataKeyValue; 16 | import com.ql.util.express.instruction.opdata.OperateDataLocalVar; 17 | 18 | public interface IOperateDataCache { 19 | OperateData fetchOperateData(Object obj, Class type); 20 | 21 | OperateDataAttr fetchOperateDataAttr(String name, Class type); 22 | 23 | OperateDataLocalVar fetchOperateDataLocalVar(String name, Class type); 24 | 25 | OperateDataField fetchOperateDataField(Object fieldObject, String fieldName); 26 | 27 | OperateDataArrayItem fetchOperateDataArrayItem(OperateData operateData, int index); 28 | 29 | OperateDataKeyValue fetchOperateDataKeyValue(OperateData key, OperateData value); 30 | 31 | RunEnvironment fetRunEnvironment(InstructionSet instructionSet, InstructionSetContext instructionSetContext, 32 | boolean isTrace, ExecuteTimeout executeTimeOut); 33 | 34 | CallResult fetchCallResult(Object returnValue, boolean isExit); 35 | 36 | InstructionSetContext fetchInstructionSetContext(boolean isExpandToParent, ExpressRunner expressRunner, 37 | IExpressContext parent, ExpressLoader expressLoader, boolean isSupportDynamicFieldName); 38 | 39 | void resetCache(); 40 | 41 | long getFetchCount(); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/InInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.instruction.detail.InstructionOperator; 8 | import com.ql.util.express.instruction.op.OperatorBase; 9 | import com.ql.util.express.parse.ExpressNode; 10 | 11 | public class InInstructionFactory extends InstructionFactory { 12 | @Override 13 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 14 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception { 15 | ExpressNode[] children = node.getChildrenArray(); 16 | if (children[1].isTypeEqualsOrChild("CHILD_EXPRESS")) { 17 | node.getChildrenList().remove(1); 18 | ExpressNode[] parameterList = children[1].getChildrenArray(); 19 | for (ExpressNode expressNode : parameterList) { 20 | node.getChildrenList().add(expressNode); 21 | } 22 | } 23 | 24 | boolean returnVal = false; 25 | children = node.getChildrenArray(); 26 | for (ExpressNode child : children) { 27 | boolean tmpHas = expressRunner.createInstructionSetPrivate(result, forStack, child, false); 28 | returnVal = returnVal || tmpHas; 29 | } 30 | OperatorBase op = expressRunner.getOperatorFactory().newInstance(node); 31 | result.addInstruction(new InstructionOperator(op, children.length).setLine(node.getLine())); 32 | return returnVal; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/InstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Stack; 6 | 7 | import com.ql.util.express.ExpressRunner; 8 | import com.ql.util.express.InstructionSet; 9 | import com.ql.util.express.parse.ExpressNode; 10 | 11 | public abstract class InstructionFactory { 12 | private static final Map INSTRUCTION_FACTORY_MAP = new HashMap<>(); 13 | 14 | public static InstructionFactory getInstructionFactory(String factory) { 15 | try { 16 | InstructionFactory result = INSTRUCTION_FACTORY_MAP.get(factory); 17 | if (result == null) { 18 | result = (InstructionFactory)Class.forName(factory).newInstance(); 19 | INSTRUCTION_FACTORY_MAP.put(factory, result); 20 | } 21 | return result; 22 | } catch (Exception e) { 23 | throw new RuntimeException(e); 24 | } 25 | } 26 | 27 | public abstract boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 28 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception; 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/LoadAttrInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.exception.QLException; 8 | import com.ql.util.express.instruction.detail.InstructionCallMacro; 9 | import com.ql.util.express.instruction.detail.InstructionLoadAttr; 10 | import com.ql.util.express.parse.ExpressNode; 11 | 12 | public class LoadAttrInstructionFactory extends InstructionFactory { 13 | @Override 14 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 15 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception { 16 | FunctionInstructionSet functionSet = result.getMacroDefine(node.getValue()); 17 | if (functionSet != null) { 18 | //是宏定义 19 | result.insertInstruction(result.getCurrentPoint() + 1, new InstructionCallMacro(node.getValue()).setLine( 20 | node.getLine()).setLine(node.getLine())); 21 | } else { 22 | result.addInstruction(new InstructionLoadAttr(node.getValue()).setLine(node.getLine())); 23 | if (node.getChildrenArray().length > 0) { 24 | throw new QLException("表达式设置错误"); 25 | } 26 | } 27 | return false; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/MacroInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.parse.ExpressNode; 8 | 9 | public class MacroInstructionFactory extends InstructionFactory { 10 | @Override 11 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 12 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception { 13 | ExpressNode[] children = node.getChildrenArray(); 14 | String macroName = children[0].getValue(); 15 | ExpressNode macroRoot = new ExpressNode(expressRunner.getNodeTypeManager().findNodeType("FUNCTION_DEFINE"), 16 | "macro-" + macroName); 17 | for (ExpressNode tempNode : children[1].getChildrenArray()) { 18 | macroRoot.addChild(tempNode); 19 | } 20 | InstructionSet macroInstructionSet = expressRunner.createInstructionSet(macroRoot, InstructionSet.TYPE_MACRO); 21 | result.addMacroDefine(macroName, new FunctionInstructionSet(macroName, "macro", macroInstructionSet)); 22 | return false; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/MethodCallInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.exception.QLException; 8 | import com.ql.util.express.instruction.detail.InstructionOperator; 9 | import com.ql.util.express.instruction.op.OperatorBase; 10 | import com.ql.util.express.instruction.op.OperatorMethod; 11 | import com.ql.util.express.parse.ExpressNode; 12 | 13 | public class MethodCallInstructionFactory extends InstructionFactory { 14 | @Override 15 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 16 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception { 17 | ExpressNode[] children = node.getChildrenArray(); 18 | //处理对象 19 | boolean tmpHas = expressRunner.createInstructionSetPrivate(result, forStack, children[0], false); 20 | boolean returnVal = tmpHas; 21 | //处理方法名称 22 | if (!"CONST_STRING".equalsIgnoreCase(children[1].getNodeType().getName())) { 23 | throw new QLException("对象方法名称不是字符串常量:" + children[1]); 24 | } 25 | String methodName = (String)children[1].getObjectValue(); 26 | //处理方法参数 27 | for (int i = 2; i < children.length; i++) { 28 | tmpHas = expressRunner.createInstructionSetPrivate(result, forStack, children[i], false); 29 | returnVal = returnVal || tmpHas; 30 | } 31 | OperatorBase op = new OperatorMethod(methodName); 32 | result.addInstruction(new InstructionOperator(op, children.length - 1).setLine(node.getLine())); 33 | return returnVal; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/NewInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.ExpressUtil; 7 | import com.ql.util.express.InstructionSet; 8 | import com.ql.util.express.instruction.detail.InstructionOperator; 9 | import com.ql.util.express.instruction.op.OperatorBase; 10 | import com.ql.util.express.parse.ExpressNode; 11 | 12 | public class NewInstructionFactory extends InstructionFactory { 13 | @Override 14 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 15 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception { 16 | OperatorBase op = expressRunner.getOperatorFactory().newInstance("new"); 17 | ExpressNode[] children = node.getChildrenArray(); 18 | if (node.isTypeEqualsOrChild("NEW_ARRAY")) { 19 | StringBuilder tempStr = new StringBuilder(children[0].getValue()); 20 | for (int i = 0; i < children.length - 1; i++) { 21 | tempStr.append("[]"); 22 | } 23 | children[0].setValue(tempStr.toString()); 24 | children[0].setOriginalValue(tempStr.toString()); 25 | children[0].setObjectValue(ExpressUtil.getJavaClass(tempStr.toString())); 26 | } else if (node.isTypeEqualsOrChild("anonymousNewArray")) { 27 | op = expressRunner.getOperatorFactory().newInstance("anonymousNewArray"); 28 | } 29 | 30 | boolean returnVal = false; 31 | 32 | // 需要重新获取数据 33 | children = node.getChildrenArray(); 34 | for (ExpressNode child : children) { 35 | boolean tmpHas = expressRunner.createInstructionSetPrivate(result, forStack, child, false); 36 | returnVal = returnVal || tmpHas; 37 | } 38 | result.addInstruction(new InstructionOperator(op, children.length).setLine(node.getLine())); 39 | return returnVal; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/NewVClassInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.instruction.detail.InstructionNewVirClass; 8 | import com.ql.util.express.parse.ExpressNode; 9 | 10 | public class NewVClassInstructionFactory extends InstructionFactory { 11 | @Override 12 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 13 | Stack forStack, ExpressNode node, boolean isRoot) throws Exception { 14 | ExpressNode[] children = node.getChildrenArray(); 15 | boolean returnVal = false; 16 | String virClassName = children[0].getValue(); 17 | for (int i = 1; i < children.length; i++) { 18 | boolean tmpHas = expressRunner.createInstructionSetPrivate(result, forStack, children[i], false); 19 | returnVal = returnVal || tmpHas; 20 | } 21 | result.addInstruction(new InstructionNewVirClass(virClassName, children.length - 1).setLine(node.getLine())); 22 | return returnVal; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/NullInstructionFactory.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction; 2 | 3 | import java.util.Stack; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.InstructionSet; 7 | import com.ql.util.express.parse.ExpressNode; 8 | 9 | public class NullInstructionFactory extends InstructionFactory { 10 | @Override 11 | public boolean createInstruction(ExpressRunner expressRunner, InstructionSet result, 12 | Stack forStack, ExpressNode node, boolean isRoot) { 13 | return false; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/Instruction.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.RunEnvironment; 6 | 7 | public abstract class Instruction { 8 | private Integer line = 0; 9 | 10 | public Instruction setLine(Integer line) { 11 | this.line = line; 12 | return this; 13 | } 14 | 15 | public Integer getLine() { 16 | return line; 17 | } 18 | 19 | public String getExceptionPrefix() { 20 | return "run QlExpress Exception at line " + line + " :"; 21 | } 22 | 23 | public abstract void execute(RunEnvironment environment, List errorList) throws Exception; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionCallMacro.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.InstructionSet; 6 | import com.ql.util.express.InstructionSetContext; 7 | import com.ql.util.express.InstructionSetRunner; 8 | import com.ql.util.express.OperateData; 9 | import com.ql.util.express.RunEnvironment; 10 | import com.ql.util.express.instruction.OperateDataCacheManager; 11 | 12 | public class InstructionCallMacro extends Instruction { 13 | private final String name; 14 | 15 | public InstructionCallMacro(String name) { 16 | this.name = name; 17 | } 18 | 19 | @Override 20 | public void execute(RunEnvironment environment, List errorList) throws Exception { 21 | InstructionSetContext context = environment.getContext(); 22 | Object functionSet = context.getSymbol(this.name); 23 | 24 | Object result = InstructionSetRunner.execute(context.getExpressRunner(), (InstructionSet)functionSet, 25 | context.getExpressLoader(), context, errorList, environment.isTrace(), false, false, 26 | environment.getContext().isSupportDynamicFieldName(), environment.getExecuteTimeOut()); 27 | if (result instanceof OperateData) { 28 | environment.push((OperateData)result); 29 | } else { 30 | environment.push(OperateDataCacheManager.fetchOperateData(result, null)); 31 | } 32 | 33 | environment.programPointAddOne(); 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "call macro " + this.name; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionClearDataStack.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.RunEnvironment; 6 | 7 | public class InstructionClearDataStack extends Instruction { 8 | @Override 9 | public void execute(RunEnvironment environment, List errorList) { 10 | // 目前的模式,不需要执行任何操作 11 | environment.clearDataStack(); 12 | environment.programPointAddOne(); 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return "clearDataStack"; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionCloseNewArea.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.InstructionSetContext; 6 | import com.ql.util.express.RunEnvironment; 7 | 8 | public class InstructionCloseNewArea extends Instruction { 9 | @Override 10 | public void execute(RunEnvironment environment, List errorList) { 11 | //目前的模式,不需要执行任何操作 12 | environment.setContext((InstructionSetContext)environment.getContext().getParent()); 13 | environment.programPointAddOne(); 14 | } 15 | 16 | @Override 17 | public String toString() { 18 | return "closeNewArea"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionConstData.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.OperateData; 6 | import com.ql.util.express.RunEnvironment; 7 | import com.ql.util.express.instruction.opdata.OperateDataAttr; 8 | 9 | public class InstructionConstData extends Instruction { 10 | private final OperateData operateData; 11 | 12 | public InstructionConstData(OperateData operateData) { 13 | this.operateData = operateData; 14 | } 15 | 16 | public OperateData getOperateData() { 17 | return this.operateData; 18 | } 19 | 20 | @Override 21 | public void execute(RunEnvironment environment, List errorList) throws Exception { 22 | environment.push(this.operateData); 23 | environment.programPointAddOne(); 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | if (this.operateData instanceof OperateDataAttr) { 29 | return "LoadData attr:" + this.operateData; 30 | } else { 31 | return "LoadData " + this.operateData.toString(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionGoTo.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.RunEnvironment; 6 | 7 | public class InstructionGoTo extends Instruction { 8 | /** 9 | * 跳转指令的偏移量 10 | */ 11 | private int offset; 12 | private String name; 13 | 14 | public InstructionGoTo(int offset) { 15 | this.offset = offset; 16 | } 17 | 18 | @Override 19 | public void execute(RunEnvironment environment, List errorList) { 20 | environment.gotoWithOffset(this.offset); 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | String result = (this.name == null ? "" : this.name + ":") + "GoTo "; 26 | if (this.offset >= 0) { 27 | result = result + "+"; 28 | } 29 | result = result + this.offset + " "; 30 | return result; 31 | } 32 | 33 | public int getOffset() { 34 | return offset; 35 | } 36 | 37 | public void setOffset(int offset) { 38 | this.offset = offset; 39 | } 40 | 41 | public String getName() { 42 | return name; 43 | } 44 | 45 | public void setName(String name) { 46 | this.name = name; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionGoToWithNotNull.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.RunEnvironment; 6 | 7 | public class InstructionGoToWithNotNull extends Instruction { 8 | /** 9 | * 跳转指令的偏移量 10 | */ 11 | private final int offset; 12 | private final boolean isPopStackData; 13 | 14 | public InstructionGoToWithNotNull(int offset, boolean isPopStackData) { 15 | this.offset = offset; 16 | this.isPopStackData = isPopStackData; 17 | } 18 | 19 | @Override 20 | public void execute(RunEnvironment environment, List errorList) throws Exception { 21 | Object o; 22 | if (!this.isPopStackData) { 23 | o = environment.peek().getObject(environment.getContext()); 24 | } else { 25 | o = environment.pop().getObject(environment.getContext()); 26 | } 27 | if (o != null) { 28 | environment.gotoWithOffset(this.offset); 29 | } else { 30 | environment.programPointAddOne(); 31 | } 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | String result = "GoToIf[NOTNULL,isPop=" + this.isPopStackData + "] "; 37 | if (this.offset >= 0) { 38 | result = result + "+"; 39 | } 40 | result = result + this.offset; 41 | return result; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionLoadAttr.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.InstructionSet; 6 | import com.ql.util.express.RunEnvironment; 7 | import com.ql.util.express.instruction.opdata.OperateDataAttr; 8 | 9 | public class InstructionLoadAttr extends Instruction { 10 | private final String attrName; 11 | 12 | public InstructionLoadAttr(String name) { 13 | this.attrName = name; 14 | } 15 | 16 | public String getAttrName() { 17 | return this.attrName; 18 | } 19 | 20 | @Override 21 | public void execute(RunEnvironment environment, List errorList) throws Exception { 22 | Object o = environment.getContext().getSymbol(this.attrName); 23 | //是函数,则执行 24 | if (o instanceof InstructionSet) { 25 | InstructionCallMacro macro = new InstructionCallMacro(this.attrName); 26 | macro.execute(environment, errorList); 27 | //注意,此处不能在增加指令,因为在InstructionCallMacro已经调用 environment.programPointAddOne(); 28 | } else { 29 | environment.push((OperateDataAttr)o); 30 | environment.programPointAddOne(); 31 | } 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | return "LoadAttr:" + this.attrName; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionLoadLambda.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.InstructionSet; 6 | import com.ql.util.express.QLambda; 7 | import com.ql.util.express.RunEnvironment; 8 | import com.ql.util.express.instruction.OperateDataCacheManager; 9 | 10 | /** 11 | * 将一个 QLambda 加载到栈上 12 | */ 13 | public class InstructionLoadLambda extends Instruction { 14 | private final InstructionSet lambdaSet; 15 | 16 | public InstructionLoadLambda(InstructionSet lambdaSet) { 17 | this.lambdaSet = lambdaSet; 18 | } 19 | 20 | @Override 21 | public void execute(RunEnvironment environment, List errorList) { 22 | environment.push( 23 | OperateDataCacheManager.fetchOperateData(new QLambda(lambdaSet, environment, errorList), null) 24 | ); 25 | environment.programPointAddOne(); 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "Load Lambda " + lambdaSet.toString() + "Lambda End"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionNewVirClass.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.ArraySwap; 6 | import com.ql.util.express.OperateData; 7 | import com.ql.util.express.RunEnvironment; 8 | import com.ql.util.express.instruction.opdata.OperateDataAttr; 9 | import com.ql.util.express.instruction.opdata.OperateDataVirClass; 10 | 11 | public class InstructionNewVirClass extends Instruction { 12 | private final String className; 13 | private final int opDataNumber; 14 | 15 | public InstructionNewVirClass(String name, int opDataNumber) { 16 | this.className = name; 17 | this.opDataNumber = opDataNumber; 18 | } 19 | 20 | public String getClassName() { 21 | return className; 22 | } 23 | 24 | @Override 25 | public void execute(RunEnvironment environment, List errorList) throws Exception { 26 | ArraySwap parameters = environment.popArray(this.opDataNumber); 27 | 28 | //因为会影响堆栈,要先把对象拷贝出来 29 | OperateData[] list = new OperateData[parameters.length]; 30 | for (int i = 0; i < list.length; i++) { 31 | list[i] = parameters.get(i); 32 | } 33 | 34 | OperateDataVirClass result = new OperateDataVirClass(className); 35 | environment.push(result); 36 | environment.programPointAddOne(); 37 | result.initialInstance(environment, list, errorList, environment.isTrace()); 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return "new VClass[" + this.className + "] OPNUMBER[" + this.opDataNumber + "]"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionOpenNewArea.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.InstructionSetContext; 6 | import com.ql.util.express.RunEnvironment; 7 | import com.ql.util.express.instruction.OperateDataCacheManager; 8 | 9 | public class InstructionOpenNewArea extends Instruction { 10 | @Override 11 | public void execute(RunEnvironment environment, List errorList) { 12 | //目前的模式,不需要执行任何操作 13 | InstructionSetContext parentContext = environment.getContext(); 14 | environment.setContext(OperateDataCacheManager.fetchInstructionSetContext( 15 | true, 16 | parentContext.getExpressRunner(), 17 | parentContext, 18 | parentContext.getExpressLoader(), 19 | parentContext.isSupportDynamicFieldName())); 20 | environment.programPointAddOne(); 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "openNewArea"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionOperator.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.ArraySwap; 6 | import com.ql.util.express.InstructionSetContext; 7 | import com.ql.util.express.OperateData; 8 | import com.ql.util.express.RunEnvironment; 9 | import com.ql.util.express.exception.QLBizException; 10 | import com.ql.util.express.exception.QLException; 11 | import com.ql.util.express.instruction.op.OperatorBase; 12 | import com.ql.util.express.instruction.opdata.OperateDataAttr; 13 | 14 | public class InstructionOperator extends Instruction { 15 | private final OperatorBase operator; 16 | private final int opDataNumber; 17 | 18 | public InstructionOperator(OperatorBase operator, int opDataNumber) { 19 | this.operator = operator; 20 | this.opDataNumber = opDataNumber; 21 | } 22 | 23 | public OperatorBase getOperator() { 24 | return this.operator; 25 | } 26 | 27 | @Override 28 | public void execute(RunEnvironment environment, List errorList) throws Exception { 29 | InstructionSetContext instructionSetContext = environment.getContext(); 30 | ArraySwap parameters = environment.popArray(this.opDataNumber); 31 | try { 32 | OperateData result = this.operator.execute(instructionSetContext, parameters, errorList); 33 | environment.push(result); 34 | environment.programPointAddOne(); 35 | } catch (QLException e) { 36 | throw new QLException(getExceptionPrefix(), e); 37 | } catch (Throwable t) { 38 | throw new QLBizException(getExceptionPrefix(), t); 39 | } 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "OP : " + this.operator.toString() + " OPNUMBER[" + this.opDataNumber + "]"; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/detail/InstructionReturn.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.detail; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.RunEnvironment; 6 | 7 | public class InstructionReturn extends Instruction { 8 | private final boolean haveReturnValue; 9 | 10 | public InstructionReturn(boolean haveReturnValue) { 11 | this.haveReturnValue = haveReturnValue; 12 | } 13 | 14 | @Override 15 | public void execute(RunEnvironment environment, List errorList) throws Exception { 16 | //目前的模式,不需要执行任何操作 17 | if (this.haveReturnValue) { 18 | environment.quitExpress(environment.pop().getObject(environment.getContext())); 19 | } else { 20 | environment.quitExpress(); 21 | } 22 | environment.gotoLastWhenReturn(); 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | if (this.haveReturnValue) { 28 | return "return [value]"; 29 | } else { 30 | return "return"; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/CanClone.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | public interface CanClone { 4 | OperatorBase cloneMe(String name, String errorInfo) throws Exception; 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorAdd.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.OperatorOfNumber; 5 | 6 | public class OperatorAdd extends Operator { 7 | public OperatorAdd(String name) { 8 | this.name = name; 9 | } 10 | 11 | public OperatorAdd(String aliasName, String name, String errorInfo) { 12 | this.name = name; 13 | this.aliasName = aliasName; 14 | this.errorInfo = errorInfo; 15 | } 16 | 17 | @Override 18 | public Object executeInner(Object[] list) throws Exception { 19 | return OperatorOfNumber.add(list[0], list[1], this.isPrecise); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorAlias.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.InstructionSetContext; 5 | import com.ql.util.express.OperateData; 6 | import com.ql.util.express.instruction.opdata.OperateDataAlias; 7 | import com.ql.util.express.instruction.opdata.OperateDataAttr; 8 | 9 | public class OperatorAlias extends OperatorBase { 10 | public OperatorAlias(String name) { 11 | this.name = name; 12 | } 13 | 14 | public OperatorAlias(String aliasName, String name, String errorInfo) { 15 | this.name = name; 16 | this.aliasName = aliasName; 17 | this.errorInfo = errorInfo; 18 | } 19 | 20 | @Override 21 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 22 | String varName = (String)list.get(0).getObjectInner(parent); 23 | OperateDataAttr realAttr = (OperateDataAttr)list.get(1); 24 | OperateDataAttr result = new OperateDataAlias(varName, realAttr); 25 | parent.addSymbol(varName, result); 26 | return result; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorAnd.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.exception.QLException; 5 | 6 | public class OperatorAnd extends Operator { 7 | public OperatorAnd(String name) { 8 | this.name = name; 9 | } 10 | 11 | public OperatorAnd(String aliasName, String name, String errorInfo) { 12 | this.name = name; 13 | this.aliasName = aliasName; 14 | this.errorInfo = errorInfo; 15 | } 16 | 17 | @Override 18 | public Object executeInner(Object[] list) throws Exception { 19 | return executeInner(list[0], list[1]); 20 | } 21 | 22 | public Object executeInner(Object operand1, Object operand2) throws Exception { 23 | boolean r1; 24 | if (operand1 == null) { 25 | r1 = false; 26 | } else if (operand1 instanceof Boolean) { 27 | r1 = (Boolean)operand1; 28 | } else { 29 | String msg = "没有定义类型" + operand1 + "和" + operand2 + " 的 " + this.name + "操作"; 30 | throw new QLException(msg); 31 | } 32 | 33 | boolean r2; 34 | if (operand2 == null) { 35 | r2 = false; 36 | } else if (operand2 instanceof Boolean) { 37 | r2 = (Boolean)operand2; 38 | } else { 39 | String msg = "没有定义类型" + operand1 + "和" + operand2 + " 的 " + this.name + "操作"; 40 | throw new QLException(msg); 41 | } 42 | return r1 && r2; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorAnonymousNewList.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.ql.util.express.ArraySwap; 7 | import com.ql.util.express.InstructionSetContext; 8 | import com.ql.util.express.OperateData; 9 | import com.ql.util.express.instruction.OperateDataCacheManager; 10 | 11 | public class OperatorAnonymousNewList extends OperatorBase { 12 | public OperatorAnonymousNewList(String name) { 13 | this.name = name; 14 | } 15 | 16 | public OperatorAnonymousNewList(String aliasName, String name, String errorInfo) { 17 | this.name = name; 18 | this.aliasName = aliasName; 19 | this.errorInfo = errorInfo; 20 | } 21 | 22 | @Override 23 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 24 | List result = new ArrayList<>(); 25 | for (int i = 0; i < list.length; i++) { 26 | result.add(list.get(i).getObject(parent)); 27 | } 28 | return OperateDataCacheManager.fetchOperateData(result, List.class); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorAnonymousNewMap.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.ql.util.express.ArraySwap; 7 | import com.ql.util.express.InstructionSetContext; 8 | import com.ql.util.express.OperateData; 9 | import com.ql.util.express.instruction.OperateDataCacheManager; 10 | import com.ql.util.express.instruction.opdata.OperateDataKeyValue; 11 | 12 | public class OperatorAnonymousNewMap extends OperatorBase { 13 | public OperatorAnonymousNewMap(String name) { 14 | this.name = name; 15 | } 16 | 17 | public OperatorAnonymousNewMap(String aliasName, String name, String errorInfo) { 18 | this.name = name; 19 | this.aliasName = aliasName; 20 | this.errorInfo = errorInfo; 21 | } 22 | 23 | @Override 24 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 25 | Map result = new HashMap<>(); 26 | for (int i = 0; i < list.length; i++) { 27 | Object key = ((OperateDataKeyValue)list.get(i)).getKey().getObject(parent); 28 | Object value = ((OperateDataKeyValue)list.get(i)).getValue().getObject(parent); 29 | result.put(key, value); 30 | } 31 | return OperateDataCacheManager.fetchOperateData(result, HashMap.class); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorArray.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import java.util.List; 4 | 5 | import com.ql.util.express.ArraySwap; 6 | import com.ql.util.express.InstructionSetContext; 7 | import com.ql.util.express.OperateData; 8 | import com.ql.util.express.exception.QLException; 9 | import com.ql.util.express.instruction.OperateDataCacheManager; 10 | 11 | public class OperatorArray extends OperatorBase { 12 | public OperatorArray(String name) { 13 | this.name = name; 14 | } 15 | 16 | public OperatorArray(String aliasName, String name, String errorInfo) { 17 | this.name = name; 18 | this.aliasName = aliasName; 19 | this.errorInfo = errorInfo; 20 | } 21 | 22 | @Override 23 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 24 | OperateData firstOperateData = list.get(0); 25 | if (firstOperateData == null || firstOperateData.getObject(parent) == null) { 26 | throw new QLException("对象为null,不能执行数组相关操作"); 27 | } 28 | 29 | Object tmpObject = firstOperateData.getObject(parent); 30 | 31 | if (!tmpObject.getClass().isArray()) { 32 | Object property = list.get(1).getObject(parent); 33 | //支持data.get(index) ->data[index] 34 | if (tmpObject instanceof List && property instanceof Number) { 35 | int index = ((Number)property).intValue(); 36 | return OperateDataCacheManager.fetchOperateDataArrayItem(firstOperateData, index); 37 | } 38 | //支持data.code -> data['code'] 39 | if (property instanceof String || property instanceof Character) { 40 | return OperateDataCacheManager.fetchOperateDataField(tmpObject, String.valueOf(property)); 41 | } 42 | } 43 | //支持原生Array:data[index] 44 | int index = ((Number)list.get(1).getObject(parent)).intValue(); 45 | return OperateDataCacheManager.fetchOperateDataArrayItem(firstOperateData, index); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorCast.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.ExpressUtil; 5 | import com.ql.util.express.InstructionSetContext; 6 | import com.ql.util.express.OperateData; 7 | import com.ql.util.express.instruction.OperateDataCacheManager; 8 | 9 | public class OperatorCast extends OperatorBase { 10 | public OperatorCast(String name) { 11 | this.name = name; 12 | } 13 | 14 | @Override 15 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 16 | Class tmpClass = (Class)list.get(0).getObject(parent); 17 | Object castObj = ExpressUtil.castObject(list.get(1).getObject(parent), tmpClass, true); 18 | return OperateDataCacheManager.fetchOperateData(castObj, tmpClass); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorDef.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.InstructionSetContext; 5 | import com.ql.util.express.OperateData; 6 | import com.ql.util.express.instruction.OperateDataCacheManager; 7 | import com.ql.util.express.instruction.opdata.OperateDataLocalVar; 8 | import com.ql.util.express.instruction.opdata.OperateDataVirClass; 9 | 10 | public class OperatorDef extends OperatorBase { 11 | public OperatorDef(String name) { 12 | this.name = name; 13 | } 14 | 15 | public OperatorDef(String aliasName, String name, String errorInfo) { 16 | this.name = name; 17 | this.aliasName = aliasName; 18 | this.errorInfo = errorInfo; 19 | } 20 | 21 | @Override 22 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 23 | Object type = list.get(0).getObject(parent); 24 | String varName = (String)list.get(1).getObject(parent); 25 | Class tmpClass; 26 | if (type instanceof Class) { 27 | tmpClass = (Class)type; 28 | } else { 29 | tmpClass = OperateDataVirClass.class; 30 | } 31 | OperateDataLocalVar result = OperateDataCacheManager.fetchOperateDataLocalVar(varName, tmpClass); 32 | parent.addSymbol(varName, result); 33 | return result; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorDoubleAddReduce.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.ExpressUtil; 5 | import com.ql.util.express.InstructionSetContext; 6 | import com.ql.util.express.OperateData; 7 | import com.ql.util.express.OperatorOfNumber; 8 | import com.ql.util.express.instruction.OperateDataCacheManager; 9 | 10 | public class OperatorDoubleAddReduce extends OperatorBase { 11 | public OperatorDoubleAddReduce(String name) { 12 | this.name = name; 13 | } 14 | 15 | @Override 16 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 17 | Object obj = list.get(0).getObject(parent); 18 | Object result = null; 19 | if ("++".equals(this.getName())) { 20 | result = OperatorOfNumber.add(obj, 1, this.isPrecise); 21 | } else if ("--".equals(this.getName())) { 22 | result = OperatorOfNumber.subtract(obj, 1, this.isPrecise); 23 | } 24 | list.get(0).setObject(parent, result); 25 | 26 | if (result == null) { 27 | return OperateDataCacheManager.fetchOperateData(null, null); 28 | } else { 29 | return OperateDataCacheManager.fetchOperateData(result, ExpressUtil.getSimpleDataType(result.getClass())); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorEvaluate.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.ExpressUtil; 5 | import com.ql.util.express.InstructionSetContext; 6 | import com.ql.util.express.OperateData; 7 | import com.ql.util.express.exception.QLException; 8 | 9 | public class OperatorEvaluate extends OperatorBase { 10 | public OperatorEvaluate(String name) { 11 | this.name = name; 12 | } 13 | 14 | public OperatorEvaluate(String aliasName, String name, String errorInfo) { 15 | this.name = name; 16 | this.aliasName = aliasName; 17 | this.errorInfo = errorInfo; 18 | } 19 | 20 | @Override 21 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 22 | return executeInner(parent, list.get(0), list.get(1)); 23 | } 24 | 25 | public OperateData executeInner(InstructionSetContext parent, 26 | OperateData op1, OperateData op2) throws Exception { 27 | Class targetType = op1.getDefineType(); 28 | Class sourceType = op2.getType(parent); 29 | if (targetType != null) { 30 | if (!ExpressUtil.isAssignable(targetType, sourceType)) { 31 | throw new QLException("赋值时候,类型转换错误:" + ExpressUtil.getClassName(sourceType) + " 不能转换为 " 32 | + ExpressUtil.getClassName(targetType)); 33 | } 34 | 35 | } 36 | Object result = op2.getObject(parent); 37 | if (targetType != null) { 38 | result = ExpressUtil.castObject(result, targetType, false); 39 | } 40 | op1.setObject(parent, result); 41 | return op1; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorExportAlias.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.InstructionSetContext; 5 | import com.ql.util.express.OperateData; 6 | import com.ql.util.express.instruction.opdata.OperateDataAlias; 7 | import com.ql.util.express.instruction.opdata.OperateDataAttr; 8 | 9 | public class OperatorExportAlias extends OperatorBase { 10 | public OperatorExportAlias(String name) { 11 | this.name = name; 12 | } 13 | 14 | public OperatorExportAlias(String aliasName, String name, String errorInfo) { 15 | this.name = name; 16 | this.aliasName = aliasName; 17 | this.errorInfo = errorInfo; 18 | } 19 | 20 | @Override 21 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 22 | String varName = (String)list.get(0).getObjectInner(parent); 23 | OperateDataAttr realAttr = (OperateDataAttr)list.get(1); 24 | OperateDataAttr result = new OperateDataAlias(varName, realAttr); 25 | parent.exportSymbol(varName, result); 26 | return result; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorExportDef.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.InstructionSetContext; 5 | import com.ql.util.express.OperateData; 6 | import com.ql.util.express.instruction.opdata.OperateDataAttr; 7 | 8 | public class OperatorExportDef extends OperatorBase { 9 | public OperatorExportDef(String name) { 10 | this.name = name; 11 | } 12 | 13 | public OperatorExportDef(String aliasName, String name, String errorInfo) { 14 | this.name = name; 15 | this.aliasName = aliasName; 16 | this.errorInfo = errorInfo; 17 | } 18 | 19 | @Override 20 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 21 | Class tmpClass = (Class)list.get(0).getObject(parent); 22 | String varName = (String)list.get(1).getObject(parent); 23 | //OperateDataLocalVar result = new OperateDataLocalVar(varName,tmpClass); 24 | //context.exportSymbol(varName, result); 25 | OperateDataAttr result = (OperateDataAttr)parent.getSymbol(varName); 26 | result.setDefineType(tmpClass); 27 | return result; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorField.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.InstructionSetContext; 5 | import com.ql.util.express.OperateData; 6 | import com.ql.util.express.config.QLExpressRunStrategy; 7 | import com.ql.util.express.instruction.OperateDataCacheManager; 8 | 9 | public class OperatorField extends OperatorBase { 10 | private String filedName; 11 | 12 | public OperatorField() { 13 | this.name = "FieldCall"; 14 | } 15 | 16 | public OperatorField(String fieldName) { 17 | this.name = "FieldCall"; 18 | this.filedName = fieldName; 19 | } 20 | 21 | @Override 22 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 23 | OperateData operateData = list.get(0); 24 | if (operateData == null && QLExpressRunStrategy.isAvoidNullPointer()) { 25 | return null; 26 | } 27 | Object obj = operateData.getObject(parent); 28 | return OperateDataCacheManager.fetchOperateDataField(obj, this.filedName); 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return this.name + ":" + this.filedName; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorIf.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.InstructionSetContext; 5 | import com.ql.util.express.OperateData; 6 | import com.ql.util.express.exception.QLException; 7 | 8 | public class OperatorIf extends OperatorBase { 9 | public OperatorIf(String name) { 10 | this.name = name; 11 | } 12 | 13 | public OperatorIf(String aliasName, String name, String errorInfo) { 14 | this.name = name; 15 | this.aliasName = aliasName; 16 | this.errorInfo = errorInfo; 17 | } 18 | 19 | @Override 20 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 21 | if (list.length < 2) { 22 | throw new QLException("\"" + this.aliasName + "\"操作至少要两个操作数"); 23 | } 24 | Object obj = list.get(0).getObject(parent); 25 | if (obj == null) { 26 | String msg = "\"" + this.aliasName + "\"的判断条件不能为空"; 27 | throw new QLException(msg); 28 | } else if (!(obj instanceof Boolean)) { 29 | String msg = "\"" + this.aliasName + "\"的判断条件 必须是 Boolean,不能是:"; 30 | throw new QLException(msg + obj.getClass().getName()); 31 | } else { 32 | if ((Boolean)obj) { 33 | return list.get(1); 34 | } else { 35 | if (list.length == 3) { 36 | return list.get(2); 37 | } 38 | } 39 | return null; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorInstanceOf.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | 5 | /** 6 | * Created by tianqiao on 17/9/19. 7 | */ 8 | public class OperatorInstanceOf extends Operator { 9 | public OperatorInstanceOf(String anInstanceof) { 10 | this.name = anInstanceof; 11 | } 12 | 13 | @Override 14 | public Object executeInner(Object[] list) { 15 | Object obj = list[0]; 16 | Object cls = list[1]; 17 | if (obj != null && cls instanceof Class) { 18 | Class targetClass = (Class)cls; 19 | Class fromClass = obj.getClass(); 20 | return targetClass.isAssignableFrom(fromClass); 21 | } 22 | return false; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorKeyValue.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.InstructionSetContext; 5 | import com.ql.util.express.OperateData; 6 | import com.ql.util.express.instruction.OperateDataCacheManager; 7 | 8 | public class OperatorKeyValue extends OperatorBase { 9 | public OperatorKeyValue(String name) { 10 | this.name = name; 11 | } 12 | 13 | public OperatorKeyValue(String aliasName, String name, String errorInfo) { 14 | this.name = name; 15 | this.aliasName = aliasName; 16 | this.errorInfo = errorInfo; 17 | } 18 | 19 | @Override 20 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) { 21 | return OperateDataCacheManager.fetchOperateDataKeyValue(list.get(0), list.get(1)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorLike.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | 5 | public class OperatorLike extends Operator { 6 | public OperatorLike(String name) { 7 | this.name = name; 8 | } 9 | 10 | @Override 11 | public Object executeInner(Object[] list) throws Exception { 12 | return executeInner(list[0], list[1]); 13 | } 14 | 15 | public Object executeInner(Object op1, Object op2) throws Exception { 16 | if (op1 == null && op2 == null) { 17 | return true; 18 | } 19 | if (op1 == null || op2 == null) { 20 | return false; 21 | } 22 | String s = op1.toString(); 23 | String pattern = op2.toString(); 24 | 25 | return matchPattern(s, pattern); 26 | } 27 | 28 | protected static boolean matchPattern(String s, String pattern) { 29 | int sPointer = 0, pPointer = 0; 30 | int sLen = s.length(), pLen = pattern.length(); 31 | int sRecall = -1, pRecall = -1; 32 | while (sPointer < sLen) { 33 | if (pPointer < pLen && (s.charAt(sPointer) == pattern.charAt(pPointer))) { 34 | sPointer++; 35 | pPointer++; 36 | } else if (pPointer < pLen && pattern.charAt(pPointer) == '%') { 37 | sRecall = sPointer; 38 | pRecall = pPointer; 39 | pPointer++; 40 | } else if (sRecall >= 0) { 41 | sPointer = ++sRecall; 42 | pPointer = pRecall + 1; 43 | } else { 44 | return false; 45 | } 46 | } 47 | while (pPointer < pLen && pattern.charAt(pPointer) == '%') { 48 | pPointer++; 49 | } 50 | return pPointer == pLen; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorMacro.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.InstructionSetContext; 5 | import com.ql.util.express.OperateData; 6 | import com.ql.util.express.instruction.opdata.OperateDataAlias; 7 | import com.ql.util.express.instruction.opdata.OperateDataAttr; 8 | 9 | public class OperatorMacro extends OperatorBase { 10 | public OperatorMacro(String name) { 11 | this.name = name; 12 | } 13 | 14 | public OperatorMacro(String aliasName, String name, String errorInfo) { 15 | this.name = name; 16 | this.aliasName = aliasName; 17 | this.errorInfo = errorInfo; 18 | } 19 | 20 | @Override 21 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) throws Exception { 22 | String varName = (String)list.get(0).getObjectInner(parent); 23 | OperateDataAttr realAttr = (OperateDataAttr)list.get(1); 24 | OperateDataAttr result = new OperateDataAlias(varName, realAttr); 25 | parent.addSymbol(varName, result); 26 | return result; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorMinMax.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.exception.QLException; 5 | 6 | public class OperatorMinMax extends Operator { 7 | public OperatorMinMax(String name) { 8 | this.name = name; 9 | } 10 | 11 | @Override 12 | public Object executeInner(Object[] list) throws Exception { 13 | if (list.length == 0) { 14 | throw new QLException("操作数异常"); 15 | } 16 | Object result = list[0]; 17 | 18 | for (int i = 1; i < list.length; i++) { 19 | result = executeInner(result, list[i]); 20 | } 21 | return result; 22 | } 23 | 24 | public Object executeInner(Object op1, Object op2) throws Exception { 25 | Object result = null; 26 | int compareResult = Operator.compareData(op1, op2); 27 | if ("min".equals(this.name)) { 28 | if (compareResult < 0) { 29 | result = op1; 30 | } else { 31 | result = op2; 32 | } 33 | } else if ("max".equals(this.name)) { 34 | if (compareResult < 0) { 35 | result = op2; 36 | } else { 37 | result = op1; 38 | } 39 | } 40 | return result; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorMultiplyDivide.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.OperatorOfNumber; 5 | 6 | public class OperatorMultiplyDivide extends Operator { 7 | public OperatorMultiplyDivide(String name) { 8 | this.name = name; 9 | } 10 | 11 | @Override 12 | public Object executeInner(Object[] list) throws Exception { 13 | return executeInner(list[0], list[1]); 14 | } 15 | 16 | public Object executeInner(Object op1, Object op2) throws Exception { 17 | Object result = null; 18 | switch (this.getName()) { 19 | case "*": 20 | result = OperatorOfNumber.multiply(op1, op2, this.isPrecise); 21 | break; 22 | case "/": 23 | result = OperatorOfNumber.divide(op1, op2, this.isPrecise); 24 | break; 25 | case "%": 26 | case "mod": 27 | result = OperatorOfNumber.modulo(op1, op2); 28 | break; 29 | default: 30 | break; 31 | } 32 | return result; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorNor.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | 5 | public class OperatorNor extends Operator { 6 | public OperatorNor(String name) { 7 | this.name = name; 8 | } 9 | 10 | public OperatorNor(String aliasName, String name, String errorInfo) { 11 | this.name = name; 12 | this.aliasName = aliasName; 13 | this.errorInfo = errorInfo; 14 | } 15 | 16 | @Override 17 | public Object executeInner(Object[] list) throws Exception { 18 | return executeInner(list[0], list[1]); 19 | } 20 | 21 | public Object executeInner(Object op1, Object op2) { 22 | if (op1 != null) { 23 | return op1; 24 | } else { 25 | return op2; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorNot.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.exception.QLException; 5 | 6 | public class OperatorNot extends Operator { 7 | public OperatorNot(String name) { 8 | this.name = name; 9 | } 10 | 11 | public OperatorNot(String aliasName, String name, String errorInfo) { 12 | this.name = name; 13 | this.aliasName = aliasName; 14 | this.errorInfo = errorInfo; 15 | } 16 | 17 | @Override 18 | public Object executeInner(Object[] list) throws Exception { 19 | return executeInner(list[0]); 20 | } 21 | 22 | public Object executeInner(Object op) throws Exception { 23 | Object result; 24 | if (op == null) { 25 | throw new QLException("null 不能执行操作:" + this.getAliasName()); 26 | } 27 | if (Boolean.class.equals(op.getClass())) { 28 | result = !(Boolean)op; 29 | } else { 30 | String msg = "没有定义类型" + op.getClass().getName() + " 的 " + this.name + "操作"; 31 | throw new QLException(msg); 32 | } 33 | return result; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorOr.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.exception.QLException; 5 | 6 | public class OperatorOr extends Operator { 7 | public OperatorOr(String name) { 8 | this.name = name; 9 | } 10 | 11 | public OperatorOr(String aliasName, String name, String errorInfo) { 12 | this.name = name; 13 | this.aliasName = aliasName; 14 | this.errorInfo = errorInfo; 15 | } 16 | 17 | @Override 18 | public Object executeInner(Object[] list) throws Exception { 19 | return executeInner(list[0], list[1]); 20 | } 21 | 22 | public Object executeInner(Object op1, Object op2) throws Exception { 23 | boolean r1; 24 | boolean r2; 25 | if (op1 == null) { 26 | r1 = false; 27 | } else if (op1 instanceof Boolean) { 28 | r1 = (Boolean)op1; 29 | } else { 30 | String msg = "没有定义类型" + op1 + "和" + op2 + " 的 " + this.name + "操作"; 31 | throw new QLException(msg); 32 | } 33 | if (op2 == null) { 34 | r2 = false; 35 | } else if (op2 instanceof Boolean) { 36 | r2 = (Boolean)op2; 37 | } else { 38 | String msg = "没有定义类型" + op1 + "和" + op2 + " 的 " + this.name + "操作"; 39 | throw new QLException(msg); 40 | } 41 | return r1 || r2; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorPrint.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.exception.QLException; 5 | 6 | public class OperatorPrint extends Operator { 7 | public OperatorPrint(String name) { 8 | this.name = name; 9 | } 10 | 11 | public OperatorPrint(String aliasName, String name, String errorInfo) { 12 | this.name = name; 13 | this.aliasName = aliasName; 14 | this.errorInfo = errorInfo; 15 | } 16 | 17 | @Override 18 | public Object executeInner(Object[] list) throws Exception { 19 | if (list.length != 1) { 20 | throw new QLException("操作数异常,有且只能有一个操作数"); 21 | } 22 | System.out.print(list[0]); 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorPrintln.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.exception.QLException; 5 | 6 | public class OperatorPrintln extends Operator { 7 | public OperatorPrintln(String name) { 8 | this.name = name; 9 | } 10 | 11 | public OperatorPrintln(String aliasName, String name, String errorInfo) { 12 | this.name = name; 13 | this.aliasName = aliasName; 14 | this.errorInfo = errorInfo; 15 | } 16 | 17 | @Override 18 | public Object executeInner(Object[] list) throws Exception { 19 | if (list.length != 1) { 20 | throw new QLException("操作数异常,有且只能有一个操作数"); 21 | } 22 | System.out.println(list[0]); 23 | return null; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorReduce.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.OperatorOfNumber; 5 | 6 | public class OperatorReduce extends Operator { 7 | public OperatorReduce(String name) { 8 | this.name = name; 9 | } 10 | 11 | public OperatorReduce(String aliasName, String name, String errorInfo) { 12 | this.name = name; 13 | this.aliasName = aliasName; 14 | this.errorInfo = errorInfo; 15 | } 16 | 17 | @Override 18 | public Object executeInner(Object[] list) throws Exception { 19 | return OperatorOfNumber.subtract(list[0], list[1], this.isPrecise); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/op/OperatorRound.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.op; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.OperatorOfNumber; 5 | 6 | public class OperatorRound extends Operator { 7 | public OperatorRound(String name) { 8 | this.name = name; 9 | } 10 | 11 | @Override 12 | public Object executeInner(Object[] list) throws Exception { 13 | return executeInner(list[0], list[1]); 14 | } 15 | 16 | public Object executeInner(Object op1, Object op2) { 17 | return OperatorOfNumber.round(((Number)op1).doubleValue(), ((Number)op2).intValue()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/opdata/OperateClass.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.opdata; 2 | 3 | import com.ql.util.express.InstructionSetContext; 4 | import com.ql.util.express.OperateData; 5 | 6 | public class OperateClass extends OperateData { 7 | private final String name; 8 | private final Class clazz; 9 | 10 | public OperateClass(String name, Class clazz) { 11 | super(null, null); 12 | this.name = name; 13 | this.clazz = clazz; 14 | } 15 | 16 | @Override 17 | public void toResource(StringBuilder builder, int level) { 18 | builder.append(this.name); 19 | } 20 | 21 | @Override 22 | public Object getObjectInner(InstructionSetContext parent) { 23 | return clazz; 24 | } 25 | 26 | public String getName() { 27 | return this.name; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "Class:" + name; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/opdata/OperateDataAlias.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.opdata; 2 | 3 | import com.ql.util.express.InstructionSetContext; 4 | 5 | public class OperateDataAlias extends OperateDataAttr { 6 | private final OperateDataAttr realAttr; 7 | 8 | public OperateDataAlias(String name, OperateDataAttr realAttr) { 9 | super(name, null); 10 | this.realAttr = realAttr; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | try { 16 | return this.name + "[alias=" + this.realAttr.name + "]"; 17 | } catch (Exception e) { 18 | return e.getMessage(); 19 | } 20 | } 21 | 22 | @Override 23 | public Object getObjectInner(InstructionSetContext context) { 24 | try { 25 | return realAttr.getObject(context); 26 | } catch (Exception e) { 27 | throw new RuntimeException(e); 28 | } 29 | } 30 | 31 | @Override 32 | public Class getType(InstructionSetContext context) throws Exception { 33 | return realAttr.getType(context); 34 | } 35 | 36 | @Override 37 | public void setObject(InstructionSetContext context, Object object) { 38 | try { 39 | realAttr.setObject(context, object); 40 | } catch (Exception e) { 41 | throw new RuntimeException(e); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/opdata/OperateDataKeyValue.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.opdata; 2 | 3 | import com.ql.util.express.InstructionSetContext; 4 | import com.ql.util.express.OperateData; 5 | 6 | public class OperateDataKeyValue extends OperateData { 7 | private OperateData key; 8 | private OperateData value; 9 | 10 | public OperateDataKeyValue(OperateData key, OperateData value) { 11 | super(null, null); 12 | this.key = key; 13 | this.value = value; 14 | } 15 | 16 | public void initialDataKeyValue(OperateData key, OperateData value) { 17 | super.initial(null, null); 18 | this.key = key; 19 | this.value = value; 20 | } 21 | 22 | public void clearDataKeyValue() { 23 | super.clear(); 24 | this.key = null; 25 | this.value = null; 26 | } 27 | 28 | public OperateData getKey() { 29 | return key; 30 | } 31 | 32 | public OperateData getValue() { 33 | return value; 34 | } 35 | 36 | @Override 37 | public Object getObjectInner(InstructionSetContext context) { 38 | throw new RuntimeException("没有实现方法:getObjectInner"); 39 | } 40 | 41 | @Override 42 | public Class getType(InstructionSetContext context) { 43 | throw new RuntimeException("没有实现方法:getType"); 44 | } 45 | 46 | @Override 47 | public void setObject(InstructionSetContext parent, Object object) { 48 | throw new RuntimeException("没有实现方法:setObject"); 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return this.key + ":" + this.value; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/instruction/opdata/OperateDataLocalVar.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.instruction.opdata; 2 | 3 | import com.ql.util.express.InstructionSetContext; 4 | 5 | public class OperateDataLocalVar extends OperateDataAttr { 6 | public OperateDataLocalVar(String name, Class type) { 7 | super(name, type); 8 | } 9 | 10 | public void initialDataLocalVar(String name, Class type) { 11 | super.initialDataAttr(name, type); 12 | } 13 | 14 | public void clearDataLocalVar() { 15 | super.clear(); 16 | } 17 | 18 | @Override 19 | public Object getObjectInner(InstructionSetContext context) { 20 | try { 21 | return this.dataObject; 22 | } catch (Exception e) { 23 | throw new RuntimeException(e); 24 | } 25 | } 26 | 27 | @Override 28 | public Class getType(InstructionSetContext context) { 29 | return this.type; 30 | } 31 | 32 | @Override 33 | public void setObject(InstructionSetContext parent, Object value) { 34 | this.dataObject = value; 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | try { 40 | return name + ":localVar"; 41 | } catch (Exception e) { 42 | return e.getMessage(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/match/IDataNode.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.match; 2 | 3 | public interface IDataNode { 4 | void setNodeType(INodeType iNodeType); 5 | 6 | void setTreeType(INodeType iNodeType); 7 | 8 | INodeType getNodeType(); 9 | 10 | INodeType getTreeType(); 11 | 12 | void addChild(IDataNode ref); 13 | 14 | IDataNode createExpressNode(INodeType iNodeType, String value) throws Exception; 15 | 16 | String getValue(); 17 | 18 | void setObjectValue(Object value); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/match/INodeType.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.match; 2 | 3 | /** 4 | * 匹配类型 5 | * 6 | * @author xuannan 7 | */ 8 | public interface INodeType { 9 | String getName(); 10 | 11 | INodeTypeManager getManager(); 12 | 13 | QLPatternNode getPatternNode(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/match/INodeTypeManager.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.match; 2 | 3 | public interface INodeTypeManager { 4 | INodeType findNodeType(String name); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/match/QLMatchResult.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.match; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class QLMatchResult { 7 | private final List matches = new ArrayList<>(); 8 | private int matchLastIndex; 9 | 10 | public void clear() { 11 | this.matchLastIndex = 0; 12 | this.matches.clear(); 13 | } 14 | 15 | public List getMatches() { 16 | return matches; 17 | } 18 | 19 | public QLMatchResult addQLMatchResultTree(QLMatchResultTree tree) { 20 | this.matches.add(tree); 21 | return this; 22 | } 23 | 24 | public QLMatchResult addQLMatchResultTreeList(List qlMatchResultTreeList) { 25 | this.matches.addAll(qlMatchResultTreeList); 26 | return this; 27 | } 28 | 29 | public int getMatchSize() { 30 | return this.matches.size(); 31 | } 32 | 33 | public int getMatchLastIndex() { 34 | return matchLastIndex; 35 | } 36 | 37 | public QLMatchResult setMatchLastIndex(int index) { 38 | this.matchLastIndex = index; 39 | return this; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | StringBuilder builder = new StringBuilder(); 45 | for (QLMatchResultTree item : matches) { 46 | item.printNode(builder, 1); 47 | } 48 | return builder.toString(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/parse/AppendingClassFieldManager.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.parse; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.ql.util.express.Operator; 7 | 8 | /** 9 | * Created by tianqiao on 16/10/16. 10 | */ 11 | public class AppendingClassFieldManager { 12 | private final List appendingFields = new ArrayList<>(); 13 | 14 | public void addAppendingField(String name, Class bindingClass, Class returnType, Operator operator) { 15 | appendingFields.add(new AppendingField(name, bindingClass, returnType, operator)); 16 | } 17 | 18 | public AppendingField getAppendingClassField(Object object, String fieldName) { 19 | for (AppendingField appendingField : appendingFields) { 20 | //object是定义类型的子类 21 | if (fieldName.equals(appendingField.name) && (object.getClass() == appendingField.bindingClass 22 | || appendingField.bindingClass.isAssignableFrom(object.getClass()))) { 23 | return appendingField; 24 | } 25 | } 26 | return null; 27 | } 28 | 29 | public Object invoke(AppendingField appendingField, Object fieldObject) throws Exception { 30 | Operator operator = appendingField.operator; 31 | return operator.executeInner(new Object[] {fieldObject}); 32 | } 33 | 34 | public static class AppendingField { 35 | private final String name; 36 | 37 | private final Class bindingClass; 38 | 39 | private final Operator operator; 40 | 41 | private final Class returnType; 42 | 43 | public AppendingField(String name, Class bindingClass, Class returnType, Operator operator) { 44 | this.name = name; 45 | this.bindingClass = bindingClass; 46 | this.operator = operator; 47 | this.returnType = returnType; 48 | } 49 | 50 | public Class getReturnType() { 51 | return returnType; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/parse/AppendingClassMethodManager.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.parse; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.ql.util.express.ArraySwap; 7 | import com.ql.util.express.InstructionSetContext; 8 | import com.ql.util.express.OperateData; 9 | import com.ql.util.express.instruction.op.OperatorBase; 10 | 11 | /** 12 | * Created by tianqiao on 16/10/16. 13 | */ 14 | public class AppendingClassMethodManager { 15 | private final List methods = new ArrayList<>(); 16 | 17 | public void addAppendingMethod(String name, Class bindingClass, OperatorBase op) { 18 | methods.add(new AppendingMethod(name, bindingClass, op)); 19 | } 20 | 21 | public AppendingMethod getAppendingClassMethod(Object object, String methodName) { 22 | for (AppendingMethod method : methods) { 23 | //object是定义类型的子类 24 | if (methodName.equals(method.name) && (object.getClass() == method.bindingClass 25 | || method.bindingClass.isAssignableFrom(object.getClass()))) { 26 | return method; 27 | } 28 | } 29 | return null; 30 | } 31 | 32 | public OperateData invoke(AppendingMethod method, InstructionSetContext context, ArraySwap list, 33 | List errorList) throws Exception { 34 | OperatorBase op = method.operatorBase; 35 | return op.execute(context, list, errorList); 36 | } 37 | 38 | public static class AppendingMethod { 39 | public final String name; 40 | 41 | public final Class bindingClass; 42 | 43 | public final OperatorBase operatorBase; 44 | 45 | public AppendingMethod(String name, Class bindingClass, OperatorBase op) { 46 | this.name = name; 47 | this.bindingClass = bindingClass; 48 | this.operatorBase = op; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/ql/util/express/parse/Word.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.parse; 2 | 3 | public class Word { 4 | public final String word; 5 | public final int line; 6 | public final int col; 7 | public int index; 8 | 9 | public Word(String word, int line, int col) { 10 | this.word = word; 11 | this.line = line; 12 | this.col = col; 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return this.word;// + "[" + this.line + "," + this.col + "]"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/ExecuteTimeoutTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Author: DQinYuan 9 | */ 10 | public class ExecuteTimeoutTest { 11 | 12 | @Test 13 | public void noTimeoutTest() throws InterruptedException { 14 | assertFalse(ExecuteTimeout.NO_TIMEOUT.isExpired()); 15 | 16 | ExecuteTimeout timeOut = new ExecuteTimeout(20); 17 | Thread.sleep(15); 18 | assertFalse(timeOut.isExpired()); 19 | Thread.sleep(6); 20 | assertTrue(timeOut.isExpired()); 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/annotation/Patient.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.annotation; 2 | 3 | /** 4 | * @author tianqiao@come-future.com 5 | * 2021-11-16 5:02 下午 6 | */ 7 | @QLAlias("患者") 8 | public class Patient extends Person { 9 | 10 | @QLAlias("级别") 11 | private String level = "高危"; 12 | 13 | @QLAlias("患者姓名") 14 | private String name; 15 | 16 | @QLAlias("获取患者年龄") 17 | public int getAge() { 18 | return 2021 - Integer.parseInt(this.getBirth().substring(0, 4)); 19 | } 20 | 21 | public String getLevel() { 22 | return level; 23 | } 24 | 25 | public void setLevel(String level) { 26 | this.level = level; 27 | } 28 | 29 | @Override 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | @Override 35 | public void setName(String name) { 36 | this.name = name; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/annotation/Person.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.annotation; 2 | 3 | /** 4 | * @author tianqiao@come-future.com 5 | * 2021-11-15 5:52 下午 6 | */ 7 | public class Person { 8 | @QLAlias({"出生年月", "生日"}) 9 | private String birth; 10 | 11 | @QLAlias("姓名") 12 | private String name; 13 | 14 | @QLAlias("性别") 15 | private String sex; 16 | 17 | @QLAlias("获取年龄") 18 | public int getAge() { 19 | return 2021 - Integer.parseInt(this.birth.substring(0, 4)); 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public void setName(String name) { 27 | this.name = name; 28 | } 29 | 30 | public String getSex() { 31 | return sex; 32 | } 33 | 34 | public void setSex(String sex) { 35 | this.sex = sex; 36 | } 37 | 38 | @QLAlias({"出生年月", "生日"}) 39 | public String getBirth() { 40 | return birth; 41 | } 42 | 43 | public void setBirth(String birth) { 44 | this.birth = birth; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/annotation/QLAliasContext.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.annotation; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | 5 | /** 6 | * @author tianqiao@come-future.com 7 | * 2021-11-15 8:28 下午 8 | */ 9 | public class QLAliasContext extends DefaultContext { 10 | public void putAutoParams(Object... values) { 11 | for (Object value : values) { 12 | if (value.getClass().isAnnotationPresent(QLAlias.class)) { 13 | QLAlias[] annotations = value.getClass().getAnnotationsByType(QLAlias.class); 14 | for (int i = 0; i < annotations.length; i++) { 15 | String[] name = annotations[i].value(); 16 | for (int j = 0; j < annotations.length; j++) { 17 | super.put(name[j], value); 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/annotation/QLAliasTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.annotation; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | /** 11 | * @author tianqiao@come-future.com 12 | * 2021-11-15 5:51 下午 13 | */ 14 | public class QLAliasTest { 15 | @Test 16 | public void testQLAlias() throws Exception { 17 | ExpressRunner runner = new ExpressRunner(); 18 | String[] exps = new String[] { 19 | "患者.birth", "1987-02-23", 20 | "患者.生日()", "1987-02-23", 21 | "患者.患者姓名", "老王", 22 | "患者.姓名", "老王", 23 | "患者.getBirth()==患者.出生年月()", "true",//方法注解 24 | "患者.生日()==患者.生日", "true",//get方法和字段名字一样是不冲突的 25 | "患者.患者姓名 + ' 今年 '+ 患者.获取年龄() +' 岁'", "老王 今年 34 岁",//任意方法的注解 26 | "患者.级别='低风险';return 患者.级别;", "低风险", 27 | }; 28 | 29 | //1、测试对象的方法,字段上的别名标签 30 | IExpressContext context = new DefaultContext<>(); 31 | Person person = new Patient(); 32 | person.setName("老王"); 33 | person.setSex("男"); 34 | person.setBirth("1987-02-23"); 35 | context.put("患者", person); 36 | for (int i = 0; i < exps.length; i += 2) { 37 | Object result = runner.execute(exps[i], context, null, false, false); 38 | System.out.println(result); 39 | assertEquals(("" + result), exps[i + 1]); 40 | } 41 | 42 | //2、外部业务调用方也可以利用类、参数的QLAlias注解,自动注入ExpressContext 43 | QLAliasContext context2 = new QLAliasContext(); 44 | context2.putAutoParams(person);//等价于context2.put("患者", person); 45 | for (int i = 0; i < exps.length; i += 2) { 46 | Object result = runner.execute(exps[i], context2, null, false, false); 47 | System.out.println(result); 48 | assertEquals(("" + result), exps[i + 1]); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/ArrCallBugFixTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | /** 12 | * Author: DQinYuan 13 | */ 14 | public class ArrCallBugFixTest { 15 | 16 | @Test 17 | public void fieldCallEmbedArrayTest() throws Exception { 18 | ExpressRunner runner = new ExpressRunner(false, true); 19 | DefaultContext context = new DefaultContext<>(); 20 | 21 | Map m1 = new HashMap<>(); 22 | m1.put("b", "bbb"); 23 | 24 | Map> m = new HashMap<>(); 25 | m.put("a", m1); 26 | context.put("l", new Object[] {m}); 27 | String express = "l[0].a.b"; 28 | Object res = runner.execute(express, context, null, false, true); 29 | Assert.assertEquals("bbb", res); 30 | } 31 | 32 | @Test 33 | public void arrayCallEmbedArrayTest() throws Exception { 34 | ExpressRunner runner = new ExpressRunner(false, true); 35 | DefaultContext context = new DefaultContext(); 36 | 37 | Map m = new HashMap<>(); 38 | m.put("a", new String[] {"bbb"}); 39 | context.put("l", new Object[] {m}); 40 | String express = "l[0].a[0]"; 41 | Object res = runner.execute(express, 42 | context, null, false, true); 43 | Assert.assertEquals("bbb", res); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/ArrayMapTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by tianqiao on 17/6/20. 10 | */ 11 | public class ArrayMapTest { 12 | @Test 13 | public void testMinus() throws Exception { 14 | ExpressRunner runner = new ExpressRunner(); 15 | //负数需要加括号来解决,就好比 1+(-1) 16 | String exp = "Map abc = NewMap(1:(-1),2:2); return abc.get(1) + abc.get(2)"; 17 | IExpressContext context = new DefaultContext<>(); 18 | Object result = runner.execute(exp, context, null, false, true); 19 | System.out.println(result); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/AvoidNullPointMockTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.config.QLExpressRunStrategy; 6 | import org.junit.After; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | public class AvoidNullPointMockTest { 11 | public class DemoObject { 12 | private String code; 13 | private DemoObject parent; 14 | 15 | public String getCode() { 16 | return code; 17 | } 18 | 19 | public void setCode(String code) { 20 | this.code = code; 21 | } 22 | 23 | public DemoObject getParent() { 24 | return parent; 25 | } 26 | 27 | public void setParent(DemoObject parent) { 28 | this.parent = parent; 29 | } 30 | } 31 | 32 | @Before 33 | public void before() { 34 | QLExpressRunStrategy.setAvoidNullPointer(true); 35 | } 36 | 37 | @After 38 | public void after() { 39 | QLExpressRunStrategy.setAvoidNullPointer(false); 40 | } 41 | 42 | @Test 43 | public void testNullPoint() throws Exception { 44 | ExpressRunner runner = new ExpressRunner(false, true); 45 | String[] expressionList = new String[] { 46 | "x in(1,2,3)", 47 | "demo.code", 48 | "demo.parent.code", 49 | "demo.parent.getCode()", 50 | "demo.getParent().getCode()", 51 | "demo.getParent().getCode() in (1,2,3)", 52 | }; 53 | for (String expression : expressionList) { 54 | DefaultContext context = new DefaultContext<>(); 55 | System.out.println(expression); 56 | context.put("demo", new DemoObject()); 57 | Object result = runner.execute(expression, context, null, true, false); 58 | System.out.println(result); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/BreakContinueTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.*; 8 | 9 | /** 10 | * Author: DQinYuan 11 | */ 12 | public class BreakContinueTest { 13 | 14 | @Test 15 | public void deadLoopTest() throws Exception { 16 | ExpressRunner expressRunner = new ExpressRunner(); 17 | assertEquals(10, expressRunner.execute("for (i=1;i<10;i++){continue}i", 18 | new DefaultContext<>(), null, false, false)); 19 | assertEquals(1, expressRunner.execute("for (i=1;i<10;i++){break}i", 20 | new DefaultContext<>(), null, false, false)); 21 | } 22 | 23 | @Test 24 | public void doubleContinueTest() throws Exception { 25 | String express = "" + 26 | "m = 4;" + 27 | "for (i = 0; i < 3; i++){" + 28 | " if (i==0) {" + 29 | " continue;" + 30 | " }" + 31 | " int type = 0;" + 32 | " m++;" + 33 | "}" + 34 | "m"; 35 | 36 | ExpressRunner runner = new ExpressRunner(false, true); 37 | DefaultContext context = new DefaultContext<>(); 38 | 39 | Object res = runner.execute(express, context, null, true, true); 40 | assertEquals(6, res); 41 | assertEquals(6, context.get("m")); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/CheckSyntaxTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import java.util.ArrayList; 4 | 5 | import com.ql.util.express.ExpressRunner; 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | 9 | /** 10 | * Created by tianqiao on 18/2/26. 11 | */ 12 | public class CheckSyntaxTest { 13 | @Test 14 | public void testCheckSyntax0() { 15 | ExpressRunner runner = new ExpressRunner(false, true); 16 | String[] expList = new String[] { 17 | "import java.text.SimpleDateFormat;new SimpleDateFormat()", 18 | "a = new java.text.SimpleDateFormat()", 19 | }; 20 | 21 | for (String exp : expList) { 22 | Assert.assertTrue(runner.checkSyntax(exp)); 23 | } 24 | for (String exp : expList) { 25 | ArrayList mockClasses = new ArrayList<>(); 26 | Assert.assertTrue(runner.checkSyntax(exp, true, mockClasses)); 27 | System.out.println("未识别的java类列表:" + mockClasses); 28 | } 29 | } 30 | 31 | @Test 32 | public void testCheckSyntax() { 33 | ExpressRunner runner = new ExpressRunner(false, true); 34 | String[] expList = new String[] { 35 | "import com.taobao.ABC; a = new ABC();", 36 | "import com.taobao.*; a = new ABC();", 37 | "import com.taobao.ABC; a = new com.taobao.ABC();", 38 | "a = new com.taobao.ABC();if('new'.equals(op)){System.out.println('ok');}" 39 | }; 40 | 41 | for (String exp : expList) { 42 | ArrayList mockClasses = new ArrayList<>(); 43 | Assert.assertTrue(runner.checkSyntax(exp, true, mockClasses)); 44 | System.out.println("未识别的java类列表:" + mockClasses); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/CommentTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Author: DQinYuan 10 | */ 11 | public class CommentTest { 12 | 13 | @Test 14 | public void invalidNumInCommitTest() throws Exception { 15 | ExpressRunner runner = new ExpressRunner(true, false); 16 | DefaultContext context = new DefaultContext<>(); 17 | // 定义表达式 18 | String express = "/** 2倍 **/ 1+1"; 19 | Object result = runner.execute(express, context, null, true, true); 20 | Assert.assertEquals(2, result); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/CompareObjectTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import org.junit.Test; 7 | 8 | public class CompareObjectTest { 9 | 10 | @Test 11 | public void test() throws Exception { 12 | System.out.println('a' < 98); 13 | ExpressRunner runner = new ExpressRunner(); 14 | String[] expList = new String[] { 15 | "'a' < 'b'", 16 | "'a' <= 'b'", 17 | "'a' == 'a'", 18 | "test == 'a'", 19 | "test <= 'a'", 20 | "'a' >= test", 21 | }; 22 | IExpressContext context = new DefaultContext<>(); 23 | context.put("test", 'a' + 0); 24 | for (String exp : expList) { 25 | Object result = runner.execute(exp, context, null, true, false); 26 | System.out.println(result); 27 | assert ((Boolean)result); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/ContextMessagePutTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.DefaultContext; 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.IExpressContext; 7 | import com.ql.util.express.InstructionSetContext; 8 | import com.ql.util.express.OperateData; 9 | import com.ql.util.express.instruction.op.OperatorBase; 10 | import org.junit.Test; 11 | 12 | /** 13 | * @骆凡 Created by tianqiao on 17/7/5. 14 | */ 15 | public class ContextMessagePutTest { 16 | class OperatorContextPut extends OperatorBase { 17 | public OperatorContextPut(String name) { 18 | this.name = name; 19 | } 20 | 21 | @Override 22 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) { 23 | String key = list.get(0).toString(); 24 | Object value = list.get(1); 25 | parent.put(key, value); 26 | return null; 27 | } 28 | } 29 | 30 | @Test 31 | public void test() throws Exception { 32 | ExpressRunner runner = new ExpressRunner(); 33 | OperatorBase op = new OperatorContextPut("contextPut"); 34 | runner.addFunction("contextPut", op); 35 | String exp = "contextPut('success','false');contextPut('error','错误信息');contextPut('warning','提醒信息')"; 36 | IExpressContext context = new DefaultContext<>(); 37 | context.put("success", "true"); 38 | Object result = runner.execute(exp, context, null, false, true); 39 | System.out.println(result); 40 | System.out.println(context); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/ErrorColumnTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.ExpressRunner; 4 | import org.junit.Test; 5 | 6 | /** 7 | * @author bingo 2019-05-01 8 | */ 9 | public class ErrorColumnTest { 10 | /** 11 | * 之前的错误:java.lang.Exception: 还有单词没有完成语法匹配:22[if:line=9,col=69] 之后的单词 12 | * 修改后错误:java.lang.Exception: 还有单词没有完成语法匹配:22[if:line=9,col=12] 之后的单词 13 | */ 14 | @Test 15 | public void test() { 16 | try { 17 | String expressName = "bugfix/error-column"; 18 | ExpressRunner expressRunner = new ExpressRunner(false, true); 19 | expressRunner.loadExpress(expressName); 20 | } catch (Exception e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/IgnoreConstCharTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by tianqiao on 18/1/29. 10 | */ 11 | public class IgnoreConstCharTest { 12 | @Test 13 | public void test() throws Exception { 14 | ExpressRunner runner = new ExpressRunner(); 15 | runner.setIgnoreConstChar(true); 16 | String exp = "'1'+'2' == \"12\""; 17 | IExpressContext context = new DefaultContext<>(); 18 | Object result = runner.execute(exp, context, null, false, true); 19 | assert ((Boolean)result); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/ImportClassPathTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | 9 | /** 10 | * Created by tianqiao on 17/6/23. 11 | */ 12 | public class ImportClassPathTest { 13 | @Test 14 | public void test() { 15 | ExpressRunner runner = new ExpressRunner(); 16 | String exp = "return new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").format(new Date())"; 17 | IExpressContext context = new DefaultContext<>(); 18 | try { 19 | runner.execute(exp, context, null, false, false); 20 | Assert.fail(); 21 | } catch (Exception e) { 22 | } 23 | } 24 | 25 | @Test 26 | public void test2() throws Exception { 27 | ExpressRunner runner = new ExpressRunner(); 28 | String exp = "return new java.text.SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").format(new Date())"; 29 | IExpressContext context = new DefaultContext<>(); 30 | Object result; 31 | result = runner.execute(exp, context, null, false, false); 32 | System.out.println(result); 33 | } 34 | 35 | @Test 36 | public void test3() throws Exception { 37 | ExpressRunner runner = new ExpressRunner(); 38 | String exp = "" 39 | + "import java.text.SimpleDateFormat; " 40 | + "return new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\").format(new Date())"; 41 | IExpressContext context = new DefaultContext<>(); 42 | Object result; 43 | result = runner.execute(exp, context, null, false, false); 44 | System.out.println(result); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/InOperatorTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import com.ql.util.express.instruction.op.OperatorIn; 7 | import org.junit.Test; 8 | 9 | /** 10 | * Created by tianqiao on 17/6/15. 11 | */ 12 | public class InOperatorTest { 13 | @Test 14 | public void testAllByFunction() throws Exception { 15 | ExpressRunner runner = new ExpressRunner(); 16 | runner.addOperator("widelyin", new OperatorIn("widelyin") { 17 | @Override 18 | public Object executeInner(Object[] list) throws Exception { 19 | if (list[0] == null) { 20 | return false; 21 | } 22 | return super.executeInner(list); 23 | } 24 | }); 25 | 26 | //注意可以使用 data in (2,3,4) ,但无法使用data widelyin (2,3,4),因为默认addOperator的是二元操作符, 27 | // com.ql.util.express.instruction.InInstructionFactory对语法树做了特殊处理 28 | String exp = "data widelyin [2,3,4]"; 29 | IExpressContext context = new DefaultContext<>(); 30 | context.put("data", 2); 31 | Object result = runner.execute(exp, context, null, false, true); 32 | System.out.println(result); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/InvokeSecurityRiskConstructorsBlackListTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | /** 4 | * @Author TaoKan 5 | * @Date 2024/3/12 1:48 PM 6 | */ 7 | public class InvokeSecurityRiskConstructorsBlackListTest { 8 | } 9 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/Issue179LikeTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Author: DQinYuan 10 | */ 11 | public class Issue179LikeTest { 12 | @Test 13 | public void test() throws Exception { 14 | String express = "'1006' like '6%'"; 15 | ExpressRunner runner = new ExpressRunner(false, true); 16 | DefaultContext context = new DefaultContext<>(); 17 | 18 | Object res = runner.execute(express, context, null, true, true); 19 | Assert.assertFalse((Boolean)res); 20 | } 21 | } -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/LuofanTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by tianqiao on 17/6/29. 10 | */ 11 | public class LuofanTest { 12 | 13 | public class Response { 14 | } 15 | 16 | public static int lenOfAds(Response response) { 17 | return 1; 18 | } 19 | 20 | @Test 21 | public void testDemo() throws Exception { 22 | ExpressRunner runner = new ExpressRunner(); 23 | 24 | runner.addFunctionOfClassMethod("lenOfAds", LuofanTest.class.getName(), "lenOfAds", 25 | new String[] {Response.class.getName()}, null); 26 | String exp = "lenOfAds(resp)"; 27 | IExpressContext context = new DefaultContext<>(); 28 | context.put("resp", new Response()); 29 | Object result = runner.execute(exp, context, null, false, true); 30 | System.out.println(result); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/NullCompareTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.config.QLExpressRunStrategy; 6 | import org.junit.After; 7 | import org.junit.Assert; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | 11 | public class NullCompareTest { 12 | 13 | @Before 14 | public void before() { 15 | QLExpressRunStrategy.setCompareNullLessMoreAsFalse(true); 16 | } 17 | 18 | @After 19 | public void after() { 20 | QLExpressRunStrategy.setCompareNullLessMoreAsFalse(false); 21 | } 22 | 23 | @Test 24 | public void testNullCompare() throws Exception { 25 | ExpressRunner runner = new ExpressRunner(); 26 | String[] expressionArray = new String[] { 27 | "x < 1", 28 | "y > 1", 29 | "x != 2", 30 | }; 31 | for (String expression : expressionArray) { 32 | DefaultContext context = new DefaultContext<>(); 33 | System.out.println(expression); 34 | context.put("x", 2); 35 | Object result = runner.execute(expression, context, null, true, false); 36 | Assert.assertEquals(false, result); 37 | System.out.println(result); 38 | } 39 | 40 | expressionArray = new String[] { 41 | "x > 1", 42 | "y == null", 43 | "x == 2", 44 | }; 45 | for (String exp : expressionArray) { 46 | DefaultContext context = new DefaultContext<>(); 47 | System.out.println(exp); 48 | context.put("x", 2); 49 | Object result = runner.execute(exp, context, null, true, false); 50 | Assert.assertEquals(true, result); 51 | System.out.println(result); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/RecursivelyRunnerTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import com.ql.util.express.DefaultContext; 6 | import com.ql.util.express.ExpressRunner; 7 | import com.ql.util.express.Operator; 8 | import org.junit.Test; 9 | 10 | /** 11 | * 可重入性单元测试 12 | */ 13 | public class RecursivelyRunnerTest { 14 | private static final ExpressRunner runner = new ExpressRunner(); 15 | 16 | @Test 17 | public void testEvalOperator() throws Exception { 18 | runner.addFunction("eval", new EvalOperator()); 19 | String express = "eval('10')+eval('20')+eval('30')"; 20 | Object r = runner.execute(express, null, null, true, false); 21 | System.out.println(r); 22 | } 23 | 24 | @Test 25 | public void testSubRunner() throws Exception { 26 | //bind SubRunner.eval method 27 | SubRunner subRunner = new SubRunner(); 28 | Method[] methods = SubRunner.class.getDeclaredMethods(); 29 | for (Method m : methods) { 30 | String name = m.getName(); 31 | runner.addFunctionOfServiceMethod(name, subRunner, name, m.getParameterTypes(), null); 32 | } 33 | 34 | String express = "eval2('10')+eval2('20')+eval2('30')"; 35 | Object r = runner.execute(express, null, null, true, false); 36 | System.out.println(r); 37 | } 38 | 39 | public static class EvalOperator extends Operator { 40 | @Override 41 | public Object executeInner(Object[] list) throws Exception { 42 | return runner.execute((String)list[0], new DefaultContext(), null, true, false); 43 | } 44 | } 45 | 46 | public static class SubRunner { 47 | public Object eval2(String obj) throws Exception { 48 | return runner.execute(obj, new DefaultContext(), null, true, false); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/RecursivelyTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import com.ql.util.express.Operator; 7 | import org.junit.Test; 8 | 9 | /** 10 | * Created by tianqiao on 17/3/2. 11 | */ 12 | public class RecursivelyTest { 13 | private static final ExpressRunner runner = new ExpressRunner(); 14 | private static final ExpressRunner runnerInner = new ExpressRunner(); 15 | 16 | static { 17 | Operator exeOperator = new Operator() { 18 | @Override 19 | public Object executeInner(Object[] list) throws Exception { 20 | System.out.println("executeInner:r_exeAll"); 21 | IExpressContext context = new DefaultContext<>(); 22 | runnerInner.execute("1+2", context, null, false, true); 23 | System.out.println(list[0]); 24 | return null; 25 | } 26 | }; 27 | 28 | runner.addFunction("r_exeAll", exeOperator); 29 | runnerInner.addFunction("r_exeAll", exeOperator); 30 | } 31 | 32 | @Test 33 | public void testAllByFunction() throws Exception { 34 | String exp = "r_exeAll(1,2,3)"; 35 | IExpressContext context = new DefaultContext<>(); 36 | runner.execute(exp, context, null, false, true); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/StackOverFlowTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import org.junit.Test; 7 | 8 | public class StackOverFlowTest { 9 | @Test 10 | public void test() throws Exception { 11 | String[] expressList = new String[] { 12 | "1", 13 | "1+2", 14 | "max(1,2)", 15 | "max(1,max(2,3))", 16 | "max(1,max(2,max(3,4)))", 17 | "max(1,max(2,max(3,max(4,5))))", 18 | "max(1,max(2,max(3,max(4,max(5,6)))))", 19 | "max(1,max(2,max(3,max(4,max(5,max(6,7))))))", 20 | }; 21 | 22 | for (String express : expressList) { 23 | ExpressRunner runner = new ExpressRunner(); 24 | IExpressContext context = new DefaultContext<>(); 25 | Object result = runner.execute(express, context, null, true, false); 26 | System.out.println(express + " = " + result); 27 | 28 | System.out.println("优化栈深度之后:"); 29 | ExpressRunner runner2 = new ExpressRunner(); 30 | Object result2 = runner2.execute(express, context, null, true, false); 31 | System.out.println(express + " = " + result2); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/bugfix/StringTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.bugfix; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.*; 9 | 10 | /** 11 | * Created by tianqiao on 17/7/5. 12 | */ 13 | public class StringTest { 14 | @Test 15 | public void testFunction() throws Exception { 16 | ExpressRunner runner = new ExpressRunner(); 17 | String exp = "a = \"11111,2222\";p = a.split(\",\");"; 18 | IExpressContext context = new DefaultContext<>(); 19 | Object result = runner.execute(exp, context, null, false, false); 20 | assertArrayEquals(new String[] {"11111", "2222"}, (String[]) result); 21 | } 22 | 23 | @Test 24 | public void stringEscapeTest() throws Exception { 25 | ExpressRunner runner = new ExpressRunner(false, true); 26 | IExpressContext context = new DefaultContext<>(); 27 | 28 | assertEquals("\"aaa\"", runner.execute("\"\\\"aaa\\\"\"", context, null, false, false)); 29 | assertEquals("aaa'aa", runner.execute("'aaa\\'aa'", context, null, false, false)); 30 | assertEquals("aaa\\aa", runner.execute("'aaa\\\\aa'", context, null, false, false)); 31 | 32 | // 不认识的转义符 \a, 默认忽略掉 \ 33 | assertEquals("aaaaa", runner.execute("'aaa\\aa'", context, null, false, false)); 34 | assertEquals("", runner.execute("''", context, null, false, false)); 35 | assertEquals("\n\t\r", runner.execute("'\\n\\t\\r'", context, null, false, false)); 36 | assertEquals("\n\tm\r", runner.execute("'\\n\\t\\m\\r'", context, null, false, false)); 37 | assertEquals("", runner.execute("\"\"", context, null, false, false)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/cfuture/DebugQlScriptTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.cfuture; 2 | 3 | import com.ql.util.express.ArraySwap; 4 | import com.ql.util.express.DefaultContext; 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.IExpressContext; 7 | import com.ql.util.express.InstructionSetContext; 8 | import com.ql.util.express.OperateData; 9 | import com.ql.util.express.instruction.op.OperatorBase; 10 | import org.junit.Test; 11 | 12 | public class DebugQlScriptTest { 13 | @Test 14 | public void testPrintContext() throws Exception { 15 | ExpressRunner runner = new ExpressRunner(); 16 | runner.addFunction("printContext", new OperatorBase() { 17 | @Override 18 | public OperateData executeInner(InstructionSetContext parent, ArraySwap list) { 19 | System.out.println(parent.getParent());//打印对象 20 | return new OperateData(parent.getParent(), parent.getParent().getClass()); 21 | } 22 | }); 23 | 24 | String[][] testList = new String[][] { 25 | new String[] {"a=10;b=20;printContext();a=20;c=30;printContext();", null}, 26 | }; 27 | 28 | IExpressContext context = new DefaultContext<>(); 29 | context.put("name", "test"); 30 | for (String[] test : testList) { 31 | Object r = runner.execute(test[0], context, null, true, false); 32 | System.out.println(r); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/config/QLExpressTimerTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.config; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.exception.QLTimeoutException; 6 | import org.junit.AfterClass; 7 | import org.junit.BeforeClass; 8 | import org.junit.Test; 9 | 10 | /** 11 | * Author: DQinYuan 12 | */ 13 | public class QLExpressTimerTest { 14 | 15 | private static long OLD_TIMER; 16 | 17 | @BeforeClass 18 | public static void before() { 19 | OLD_TIMER = QLExpressTimer.getTimeout(); 20 | QLExpressTimer.setTimeout(20); 21 | } 22 | 23 | @AfterClass 24 | public static void after() { 25 | QLExpressTimer.setTimeout(OLD_TIMER); 26 | } 27 | 28 | @Test 29 | public void timerTest() throws Exception { 30 | ExpressRunner runner = new ExpressRunner(); 31 | DefaultContext context = new DefaultContext<>(); 32 | runner.execute("Thread.sleep(5);a=1", context, null, true, false); 33 | runner.execute("Thread.sleep(18);a=5", context, null, true, false); 34 | } 35 | 36 | @Test(expected = QLTimeoutException.class) 37 | public void timerTimeoutTest() throws Exception { 38 | ExpressRunner runner = new ExpressRunner(); 39 | DefaultContext context = new DefaultContext<>(); 40 | runner.execute("Thread.sleep(21);a=1", context, null, true, false); 41 | } 42 | 43 | /** 44 | * execute 传入参数的超时时间优先 45 | */ 46 | @Test(expected = QLTimeoutException.class) 47 | public void paramFirstTest() throws Exception { 48 | ExpressRunner runner = new ExpressRunner(); 49 | DefaultContext context = new DefaultContext<>(); 50 | runner.execute("Thread.sleep(5);a=1", context, null, true, false, 3); 51 | } 52 | } -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/console/Console.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.console; 2 | 3 | import java.awt.*; 4 | 5 | import javax.swing.*; 6 | 7 | public class Console { 8 | final boolean packFrame = false; 9 | 10 | /** 11 | * Construct and show the application. 12 | */ 13 | public Console() { 14 | ConsoleFrame frame = new ConsoleFrame(); 15 | // Validate frames that have preset sizes 16 | // Pack frames that have useful preferred size info, e.g. from their layout 17 | if (packFrame) { 18 | frame.pack(); 19 | } else { 20 | frame.validate(); 21 | } 22 | 23 | // Center the window 24 | Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 25 | Dimension frameSize = frame.getSize(); 26 | frameSize.height = screenSize.height; 27 | frameSize.width = screenSize.width; 28 | frame.setLocation(0, 0); 29 | frame.setVisible(true); 30 | } 31 | 32 | /** 33 | * Application entry point. 34 | * 35 | * @param args String[] 36 | */ 37 | public static void main(String[] args) { 38 | SwingUtilities.invokeLater(() -> { 39 | try { 40 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 41 | } catch (Exception exception) { 42 | exception.printStackTrace(); 43 | } 44 | 45 | new Console(); 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/console/ExampleDefine.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.console; 2 | 3 | public class ExampleDefine { 4 | private final String script; 5 | private final String context; 6 | 7 | public ExampleDefine(String script, String context) { 8 | this.script = script; 9 | this.context = context; 10 | } 11 | 12 | public String getScript() { 13 | return script; 14 | } 15 | 16 | public String getContext() { 17 | return context; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/console/ReadExample.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.console; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.InputStream; 5 | 6 | import javax.xml.parsers.DocumentBuilder; 7 | import javax.xml.parsers.DocumentBuilderFactory; 8 | import javax.xml.xpath.XPath; 9 | import javax.xml.xpath.XPathConstants; 10 | import javax.xml.xpath.XPathFactory; 11 | 12 | import org.w3c.dom.Document; 13 | import org.w3c.dom.Node; 14 | 15 | public class ReadExample { 16 | public static void main(String[] args) throws Exception { 17 | String fileName = "E:\\taobaocode\\QLExpress\\trunk\\example\\simple.ql"; 18 | InputStream in = new FileInputStream(fileName); 19 | readExampleDefine(in); 20 | } 21 | 22 | public static ExampleDefine readExampleDefine(String fileName) throws Exception { 23 | InputStream in = new FileInputStream(fileName); 24 | return readExampleDefine(in); 25 | } 26 | 27 | public static ExampleDefine readExampleDefine(InputStream in) throws Exception { 28 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 29 | DocumentBuilder dbd = dbf.newDocumentBuilder(); 30 | Document doc = dbd.parse(in); 31 | XPathFactory f = XPathFactory.newInstance(); 32 | XPath path = f.newXPath(); 33 | Node scriptNode = (Node)path.evaluate("example/script", doc, XPathConstants.NODE); 34 | String script = scriptNode.getTextContent().trim(); 35 | Node contextNode = (Node)path.evaluate("example/context", doc, XPathConstants.NODE); 36 | String context = contextNode.getTextContent().trim(); 37 | return new ExampleDefine(script, context); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/example/CustBean.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.example; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | 5 | public class CustBean { 6 | private long id; 7 | private String name; 8 | private int age; 9 | 10 | public CustBean(long id) { 11 | this.id = id; 12 | } 13 | 14 | public long getId() { 15 | return id; 16 | } 17 | 18 | public void setId(long id) { 19 | this.id = id; 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public void setName(String name) { 27 | this.name = name; 28 | } 29 | 30 | public int getAge() { 31 | return age; 32 | } 33 | 34 | public void setAge(int age) { 35 | this.age = age; 36 | } 37 | 38 | public static String firstToUpper(String value) { 39 | if (StringUtils.isBlank(value)) { 40 | return ""; 41 | } 42 | value = StringUtils.trim(value); 43 | String f = StringUtils.substring(value, 0, 1); 44 | String s = ""; 45 | if (value.length() > 1) { 46 | s = StringUtils.substring(value, 1); 47 | } 48 | return f.toUpperCase() + s; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/example/RiskBean.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.example; 2 | 3 | public class RiskBean { 4 | 5 | public static void riskMethod() { 6 | 7 | } 8 | 9 | public static void secureMethod() { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/example/operator/AddNOperator.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.example.operator; 2 | 3 | import com.ql.util.express.Operator; 4 | 5 | /** 6 | * 定义连加的操作符 7 | */ 8 | public class AddNOperator extends Operator { 9 | @Override 10 | public Object executeInner(Object[] list) { 11 | int r = 0; 12 | for (Object item : list) { 13 | r = r + (Integer)item; 14 | } 15 | return r; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/example/operator/AddTwiceOperator.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.example.operator; 2 | 3 | import com.ql.util.express.Operator; 4 | 5 | public class AddTwiceOperator extends Operator { 6 | @Override 7 | public Object executeInner(Object[] list) { 8 | int a = (Integer)list[0]; 9 | int b = (Integer)list[1]; 10 | return a + b + b; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/example/operator/ApproveOperator.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.example.operator; 2 | 3 | import com.ql.util.express.Operator; 4 | 5 | public class ApproveOperator extends Operator { 6 | private final int operator; 7 | 8 | public ApproveOperator(int op) { 9 | this.operator = op; 10 | } 11 | 12 | @Override 13 | public Object executeInner(Object[] list) { 14 | if (this.operator == 1) { 15 | System.out.println(list[0] + "审批:金额:" + list[1]); 16 | return ((Integer)list[1]) <= 6000; 17 | } else if (this.operator == 2) { 18 | System.out.println("报销入卡:金额:" + list[0]); 19 | } else { 20 | System.out.println("重填:申请人:" + list[0]); 21 | } 22 | return true; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/issue/Issue187InEqualitySignTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.issue; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author gjx 10 | */ 11 | public class Issue187InEqualitySignTest { 12 | @Test 13 | public void test() throws Exception { 14 | ExpressRunner runner = new ExpressRunner(false, true); 15 | DefaultContext context = new DefaultContext<>(); 16 | 17 | String express = "1 <> 2"; 18 | Object result = runner.execute(express, context, null, true, true); 19 | Assert.assertTrue((Boolean)result); 20 | 21 | } 22 | } -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/issue/Issue284LikeTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.issue; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author 冰够 10 | */ 11 | public class Issue284LikeTest { 12 | @Test 13 | public void test() throws Exception { 14 | ExpressRunner runner = new ExpressRunner(false, true); 15 | DefaultContext context = new DefaultContext<>(); 16 | 17 | String express = "param1 like \"%abc\""; 18 | Object result = runner.execute(express, context, null, true, true); 19 | Assert.assertFalse((Boolean)result); 20 | 21 | express = "\"abc\" like param2"; 22 | result = runner.execute(express, context, null, true, true); 23 | Assert.assertFalse((Boolean)result); 24 | 25 | express = "param1 like param2"; 26 | result = runner.execute(express, context, null, true, true); 27 | Assert.assertTrue((Boolean)result); 28 | } 29 | } -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/issue/Issue337CommentInImportTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.issue; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author gjx 10 | */ 11 | public class Issue337CommentInImportTest { 12 | @Test 13 | public void testCommentInImport() throws Exception { 14 | String express = "" 15 | + "/** 注释 **/;" 16 | + "import java.util.ArrayList;" 17 | + "return true;"; 18 | ExpressRunner runner = new ExpressRunner(false, true); 19 | DefaultContext context = new DefaultContext<>(); 20 | Object result = runner.execute(express, context, null, false, true); 21 | Assert.assertTrue((Boolean)result); 22 | } 23 | } -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/AClassDefineSingleTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Test; 6 | 7 | public class AClassDefineSingleTest { 8 | @Test 9 | public void testABC() throws Exception { 10 | String expressDefine = "" 11 | + "class ABC(com.ql.util.express.test.BeanExample bean, String name) {" 12 | + " 整数值:bean.intValue;" 13 | + "};"; 14 | 15 | String express = "" 16 | + "ABC example = new ABC(new com.ql.util.express.test.BeanExample(), 'xuannan');" 17 | + "example.整数值 =100 + 100;" 18 | + "print(example.整数值);"; 19 | 20 | ExpressRunner expressRunner = new ExpressRunner(false, true); 21 | DefaultContext context = new DefaultContext<>(); 22 | expressRunner.loadMultiExpress("", expressDefine); 23 | expressRunner.loadMultiExpress("ClassTest", express); 24 | Object result = expressRunner.executeByExpressName("ClassTest", context, null, true, false); 25 | System.out.println("result = " + result); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ATempTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Test; 6 | 7 | public class ATempTest { 8 | @Test 9 | public void test2Java() throws Exception { 10 | //String express = "2 in (1,2,3)"; 11 | //String express = "include Test; max(1,2,3)"; 12 | String express = "when 1==2 then println(100000)"; 13 | ExpressRunner runner = new ExpressRunner(false, true); 14 | DefaultContext context = new DefaultContext<>(); 15 | Object r = runner.execute(express, context, null, false, false); 16 | System.out.println(r); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/AddMacroDefineTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Test; 6 | 7 | public class AddMacroDefineTest { 8 | @Test 9 | public void test2Java() throws Exception { 10 | ExpressRunner runner = new ExpressRunner(false, true); 11 | runner.addFunctionOfClassMethod("abc", BeanExample.class.getName(), "testLong", new String[] {"long"}, null); 12 | runner.addMacro("玄难", "abc(100);"); 13 | String express = "玄难 + \" - Test\";"; 14 | DefaultContext context = new DefaultContext<>(); 15 | Object r = runner.execute(express, context, null, false, true); 16 | System.out.println(r); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ArrayLenCheckTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.config.QLExpressRunStrategy; 6 | import com.ql.util.express.exception.QLException; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | /** 11 | * Author: DQinYuan 12 | */ 13 | public class ArrayLenCheckTest { 14 | 15 | @Test 16 | public void checkTest() throws Exception { 17 | QLExpressRunStrategy.setMaxArrLength(10); 18 | ExpressRunner runner = new ExpressRunner(); 19 | String code = "byte[] a = new byte[11];"; 20 | try { 21 | runner.execute(code, new DefaultContext<>(), null, false, false, 20); 22 | Assert.fail(); 23 | } catch (QLException e) { 24 | } 25 | 26 | QLExpressRunStrategy.setMaxArrLength(-1); 27 | runner.execute(code, new DefaultContext<>(), null, false, false, 20); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/BeanExampleChild.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | public class BeanExampleChild { 4 | public String a = "qh"; 5 | 6 | public String getA() { 7 | return a; 8 | } 9 | 10 | public void setA(String a) { 11 | this.a = a; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/CallWithNullParameterTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | public class CallWithNullParameterTest { 9 | @Test 10 | public void testABC() throws Exception { 11 | String express = "new com.ql.util.express.test.BeanExample().testLongObject(null);"; 12 | ExpressRunner runner = new ExpressRunner(); 13 | DefaultContext context = new DefaultContext<>(); 14 | Object r = runner.execute(express, context, null, false, true); 15 | System.out.println(r); 16 | Assert.assertTrue("数组操作实现错误", r.toString().equalsIgnoreCase("toString-LongObject:null")); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/DateTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by tianqiao on 16/12/20. 10 | */ 11 | public class DateTest { 12 | @Test 13 | public void testDateCompare() throws Exception { 14 | String express = "a = new Date(); b = a; a == b;"; 15 | DefaultContext context = new DefaultContext<>(); 16 | ExpressRunner runner = new ExpressRunner(); 17 | Object r = runner.execute(express, context, null, false, false); 18 | Assert.assertTrue("testDateCompare", (Boolean)r); 19 | } 20 | 21 | @Test 22 | public void testDateCompare1() throws Exception { 23 | String express = "a = new Date(); for(i = 0; i < 1000; i++) {f = f + i;} b = new Date(); a <= b;"; 24 | DefaultContext context = new DefaultContext<>(); 25 | ExpressRunner runner = new ExpressRunner(); 26 | Object r = runner.execute(express, context, null, false, false); 27 | Assert.assertTrue("testDateCompare", (Boolean)r); 28 | } 29 | 30 | @Test 31 | public void testDateCompare2() throws Exception { 32 | String express = "a = new Date(); for(i = 0; i < 1000; i++){f = f + i;} b = new Date(); b > a;"; 33 | DefaultContext context = new DefaultContext<>(); 34 | ExpressRunner runner = new ExpressRunner(); 35 | Object r = runner.execute(express, context, null, false, false); 36 | Assert.assertTrue("testDateCompare", (Boolean)r); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/DynamicFieldTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.ql.util.express.*; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | public class DynamicFieldTest { 11 | 12 | @Test 13 | public void testField() throws Exception { 14 | String express = "" 15 | + "String 用户 = \"张三\";" 16 | + "费用.用户 = 100;" 17 | + "用户 = \"李四\";" 18 | + "费用.用户 = 200;"; 19 | 20 | ExpressRunner runner = new ExpressRunner(false, true); 21 | DefaultContext context = new DefaultContext<>(); 22 | Map fee = new HashMap<>(); 23 | context.put("费用", fee); 24 | InstructionSet set = runner.parseInstructionSet(express); 25 | InstructionSetRunner.executeOuter(runner, set, null, context, 26 | null, true, false, true, -1); 27 | runner.execute(express, context, null, false, true); 28 | System.out.println(context.get("费用")); 29 | Assert.assertEquals("动态属性错误", "100", fee.get("张三").toString()); 30 | Assert.assertEquals("动态属性错误", "200", fee.get("李四").toString()); 31 | } 32 | 33 | @Test 34 | public void testLoadFromFile() throws Exception { 35 | ExpressRunner runner = new ExpressRunner(true, true); 36 | runner.loadExpress("testFunctionParameterType"); 37 | DefaultContext context = new DefaultContext<>(); 38 | context.put("auctionUtil", new BeanExample()); 39 | Object r = runner.executeByExpressName("testFunctionParameterType", context, null, false, false); 40 | System.out.println(r); 41 | System.out.println(context); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ExportDefineTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | public class ExportDefineTest { 9 | @Test 10 | public void testABC() throws Exception { 11 | String express = "" 12 | + "function initial() {" 13 | + " exportAlias qh example.child;" 14 | + " exportDef int abc = 100;" 15 | + "}; " 16 | + "initial();" 17 | + "abc = abc + 10000;" 18 | + "System.out.println(abc);" 19 | + "{" 20 | + " alias qh example.child.a;" 21 | + " qh =qh + \"-ssss\";" 22 | + "};" 23 | + "qh.a = qh.a +\"-qh\";" 24 | + "return example.child.a;"; 25 | ExpressRunner runner = new ExpressRunner(false, true); 26 | DefaultContext context = new DefaultContext<>(); 27 | context.put("example", new BeanExample()); 28 | Object r = runner.execute(express, context, null, false, true); 29 | System.out.println(r); 30 | Assert.assertTrue("别名export实现 错误", r.toString().equalsIgnoreCase("qh-ssss-qh")); 31 | Assert.assertTrue("别名export实现 错误", ((BeanExample)context.get("example")).child.a.equalsIgnoreCase( 32 | "qh-ssss-qh")); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ExpressContextExample.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.ql.util.express.IExpressContext; 7 | import org.springframework.context.ApplicationContext; 8 | 9 | @SuppressWarnings("serial") 10 | public class ExpressContextExample extends HashMap implements IExpressContext { 11 | 12 | private final ApplicationContext applicationContext; 13 | 14 | public ExpressContextExample(ApplicationContext applicationContext) { 15 | this.applicationContext = applicationContext; 16 | } 17 | 18 | public ExpressContextExample(Map properties, ApplicationContext applicationContext) { 19 | super(properties); 20 | this.applicationContext = applicationContext; 21 | } 22 | 23 | /** 24 | * 抽象方法:根据名称从属性列表中提取属性值 25 | */ 26 | @Override 27 | public Object get(Object name) { 28 | Object result; 29 | if (((String)name).equalsIgnoreCase("三星卖家")) { 30 | result = Boolean.TRUE; 31 | } else if (((String)name).equalsIgnoreCase("消保用户")) { 32 | result = Boolean.TRUE; 33 | } else { 34 | result = super.get(name); 35 | } 36 | try { 37 | if (result == null && this.applicationContext != null 38 | && this.applicationContext.containsBean((String)name)) { 39 | //如果在Spring容器中包含bean,则返回String的Bean 40 | result = this.applicationContext.getBean((String)name); 41 | } 42 | } catch (Exception e) { 43 | throw new RuntimeException(e); 44 | } 45 | return result; 46 | } 47 | 48 | @Override 49 | public Object put(String name, Object object) { 50 | if (name.equalsIgnoreCase("myDbData")) { 51 | throw new RuntimeException("没有实现"); 52 | } 53 | return super.put(name, object); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ExpressRemoteCacheTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRemoteCacheRunner; 5 | import com.ql.util.express.ExpressRunner; 6 | import com.ql.util.express.IExpressContext; 7 | import com.ql.util.express.LocalExpressCacheRunner; 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | 11 | public class ExpressRemoteCacheTest { 12 | @Test 13 | public void test_cache() { 14 | ExpressRunner runner = new ExpressRunner(); 15 | ExpressRemoteCacheRunner cacheRunner = new LocalExpressCacheRunner(runner); 16 | cacheRunner.loadCache("加法计算", "a+b"); 17 | cacheRunner.loadCache("减法计算", "a-b"); 18 | 19 | IExpressContext context = new DefaultContext<>(); 20 | context.put("a", 1); 21 | context.put("b", 2); 22 | 23 | if (cacheRunner.getCache("加法计算") != null) { 24 | Object result = cacheRunner.execute("加法计算", context, null, false, true); 25 | Assert.assertTrue("加法计算", result.toString().equalsIgnoreCase("3")); 26 | System.out.println(result); 27 | } 28 | if (cacheRunner.getCache("加法计算") != null) { 29 | Object result = cacheRunner.execute("减法计算", context, null, false, true); 30 | Assert.assertTrue("减法计算", result.toString().equalsIgnoreCase("-1")); 31 | System.out.println(result); 32 | } 33 | if (cacheRunner.getCache("乘法计算") != null) { 34 | Object result = cacheRunner.execute("乘法计算", context, null, false, true); 35 | Assert.assertTrue("乘法计算", result.toString().equalsIgnoreCase("2")); 36 | System.out.println(result); 37 | } else { 38 | System.out.println("没有定义乘法计算器."); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ForFlowFunctionTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.After; 6 | import org.junit.Assert; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import java.io.ByteArrayOutputStream; 11 | import java.io.OutputStream; 12 | import java.io.PrintStream; 13 | 14 | public class ForFlowFunctionTest { 15 | @Before 16 | public void setUpStreams() { 17 | System.setOut(new PrintStream(new ByteArrayOutputStream())); 18 | } 19 | 20 | @After 21 | public void restoreStreams() { 22 | System.setOut(System.out); 23 | } 24 | 25 | @Test 26 | public void testABC() throws Exception { 27 | String express = "" 28 | + "for(i = 0; i < 1; i = i + 1){" 29 | + " 打印(70);" 30 | + "}" 31 | + "打印(70);" 32 | + "return 10;"; 33 | ExpressRunner runner = new ExpressRunner(false, true); 34 | runner.addFunctionOfServiceMethod("打印", System.out, "println", new String[] {"int"}, null); 35 | DefaultContext context = new DefaultContext<>(); 36 | Object r = runner.execute(express, context, null, false, true); 37 | Assert.assertEquals("for循环后面跟着一个函数的时候错误", "10", r.toString()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/FunctionDescTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.instruction.op.OperatorBase; 6 | import com.ql.util.express.instruction.op.OperatorSelfDefineClassFunction; 7 | import org.junit.Test; 8 | 9 | public class FunctionDescTest { 10 | @Test 11 | public void testFunctionDesc() throws Exception { 12 | String express = "isVIP(\"qianghui\")"; 13 | ExpressRunner runner = new ExpressRunner(); 14 | DefaultContext context = new DefaultContext<>(); 15 | runner.addFunctionOfClassMethod("isVIP", BeanExample.class.getName(), 16 | "isVIP", new String[] {"String"}, new String[] {"用户名称"}, new String[] {"UserName"}, "$1不是VIP用户"); 17 | OperatorBase op = runner.getFunction("isVIP"); 18 | System.out.println(op.getOperateDataDesc()); 19 | System.out.println(op.getOperateDataAnnotation()); 20 | 21 | Object r = runner.execute(express, context, null, false, false); 22 | System.out.println(r); 23 | 24 | runner.replaceOperator("isVIP", new OperatorSelfDefineClassFunction("isVIP", 25 | BeanExample.class.getName(), "isVIPTwo", new String[] {"String"}, null, null, null)); 26 | Object r2 = runner.execute(express, context, null, false, false); 27 | System.out.println(r2); 28 | //Assert.assertTrue("属性操作错误", r.toString().equalsIgnoreCase("ffff")); 29 | //Assert.assertTrue("属性操作错误", ((BeanExample)context.get("example")).child.a.toString().equalsIgnoreCase 30 | // ("ssssssss")); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/GetExpressAttrNamesTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | public class GetExpressAttrNamesTest { 9 | @Test 10 | public void testABC() throws Exception { 11 | String express = "" 12 | + "alias qh 100;" 13 | + "exportAlias fff qh;" 14 | + "int a = b;" 15 | + "c = a;" 16 | + "macro 惩罚 {100 + 100};" 17 | + "惩罚;" 18 | + "qh;" 19 | + "fff;"; 20 | ExpressRunner runner = new ExpressRunner(true, true); 21 | String[] names = runner.getOutVarNames(express); 22 | for (String s : names) { 23 | System.out.println("var : " + s); 24 | } 25 | Assert.assertEquals("获取外部属性错误", 2, names.length); 26 | Assert.assertTrue("获取外部属性错误", names[0].equalsIgnoreCase("b")); 27 | Assert.assertTrue("获取外部属性错误", names[1].equalsIgnoreCase("c")); 28 | } 29 | 30 | @Test 31 | public void testABCD() throws Exception { 32 | String express = "if(a!=null) return a;"; 33 | ExpressRunner runner = new ExpressRunner(true, true); 34 | String[] names = runner.getOutVarNames(express); 35 | runner.execute(express, new DefaultContext<>(), null, false, false); 36 | for (String s : names) { 37 | System.out.println("var : " + s); 38 | } 39 | Assert.assertEquals("获取外部属性错误", 1, names.length); 40 | Assert.assertTrue("获取外部属性错误", names[0].equalsIgnoreCase("a")); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/GroupOperator.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.Operator; 4 | import com.ql.util.express.OperatorOfNumber; 5 | 6 | class GroupOperator extends Operator { 7 | public GroupOperator(String name) { 8 | this.name = name; 9 | } 10 | 11 | @Override 12 | public Object executeInner(Object[] list) throws Exception { 13 | Object result = 0; 14 | for (int i = 0; i < list.length; i++) { 15 | result = OperatorOfNumber.add(result, list[i], false); 16 | } 17 | return result; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/HTMLTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.ExpressRunner; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | public class HTMLTest { 8 | @Test 9 | public void testABC() throws Exception { 10 | //String express ="\"
经费收入(\""; 11 | ExpressRunner runner = new ExpressRunner(false, true); 12 | String express = "\"经\\\"费收\\\"入\\\"aaa-\" + 100"; 13 | Object r = runner.execute(express, null, null, false, true); 14 | System.out.println(r); 15 | System.out.println("经\"费收\"入\"aaa-100"); 16 | Assert.assertEquals("字符串解析错误:", "经\"费收\"入\"aaa-100", r); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ImportTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | public class ImportTest { 9 | @Test 10 | public void testImport() throws Exception { 11 | String express = "" 12 | + "import java.math.*;" 13 | + "import com.ql.util.express.test.BeanExample;" 14 | + "abc = new BeanExample(\"张三\").unionName(\"李四\") ;" 15 | + "return new BigInteger(\"1000\");"; 16 | ExpressRunner runner = new ExpressRunner(false, true); 17 | DefaultContext context = new DefaultContext<>(); 18 | Object r = runner.execute(express, context, null, false, true); 19 | Assert.assertEquals("import 实现错误", "1000", r.toString()); 20 | System.out.println(r); 21 | System.out.println(context); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/InTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.ql.util.express.DefaultContext; 7 | import com.ql.util.express.ExpressRunner; 8 | import org.junit.Test; 9 | 10 | public class InTest { 11 | @Test 12 | public void testOperatorIn() throws Exception { 13 | String express1 = "2 in (2, 3) "; 14 | String express2 = "2 in a"; 15 | String express3 = "2 in b"; 16 | 17 | ExpressRunner runner = new ExpressRunner(true, true); 18 | DefaultContext context = new DefaultContext<>(); 19 | int[] a = {1, 2, 3}; 20 | context.put("a", a); 21 | List b = new ArrayList<>(); 22 | b.add(2); 23 | b.add(3); 24 | 25 | context.put("b", b); 26 | System.out.println(runner.execute(express1, context, null, false, false)); 27 | System.out.println(runner.execute(express2, context, null, false, false)); 28 | System.out.println(runner.execute(express3, context, null, false, false)); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/InstanceOfTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by tianqiao on 17/9/19. 10 | */ 11 | public class InstanceOfTest { 12 | @Test 13 | public void test() throws Exception { 14 | ExpressRunner runner = new ExpressRunner(false, true); 15 | DefaultContext context = new DefaultContext<>(); 16 | String express = "s = ''; return s instanceof String;"; 17 | Object r = runner.execute(express, context, null, false, true); 18 | Assert.assertEquals("InstanceOfTest 出错", "true", r.toString()); 19 | System.out.println(r); 20 | 21 | express = "s = ''; return s instanceof Object;"; 22 | r = runner.execute(express, context, null, false, true); 23 | Assert.assertEquals("InstanceOfTest 出错", "true", r.toString()); 24 | System.out.println(r); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/LoadExpressFromFileTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExportItem; 5 | import com.ql.util.express.ExpressRunner; 6 | import org.junit.Test; 7 | 8 | public class LoadExpressFromFileTest { 9 | @Test 10 | public void testLoadFromFile() throws Exception { 11 | ExpressRunner runner = new ExpressRunner(false, false); 12 | runner.loadExpress("functionDef"); 13 | runner.loadExpress("main"); 14 | ExportItem[] exports = runner.getExportInfo(); 15 | for (ExportItem item : exports) { 16 | System.out.println(item.getGlobeName()); 17 | } 18 | DefaultContext context = new DefaultContext<>(); 19 | Object r = runner.executeByExpressName("main", context, null, false, false); 20 | System.out.println("运行结果" + r); 21 | System.out.println("context:" + context); 22 | 23 | context = new DefaultContext<>(); 24 | r = runner.execute("initial;累加;累加;return qh;", context, null, true, false); 25 | 26 | System.out.println("运行结果" + r); 27 | System.out.println("context:" + context); 28 | } 29 | 30 | @Test 31 | public void testLoadInclude() throws Exception { 32 | ExpressRunner runner = new ExpressRunner(false, true); 33 | runner.loadExpress("includeRoot"); 34 | DefaultContext context = new DefaultContext<>(); 35 | Object r = runner.executeByExpressName("includeRoot", context, null, false, false); 36 | System.out.println(r); 37 | System.out.println(context); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/LoveOperator.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.Operator; 4 | 5 | class LoveOperator extends Operator { 6 | public LoveOperator(String name) { 7 | this.name = name; 8 | } 9 | 10 | @Override 11 | public Object executeInner(Object[] list) { 12 | String op1 = list[0].toString(); 13 | String op2 = list[1].toString(); 14 | return op2 + "{" + op1 + "}" + op2; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/MapTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.ql.util.express.DefaultContext; 7 | import com.ql.util.express.ExpressRunner; 8 | import com.ql.util.express.IExpressContext; 9 | import org.junit.Assert; 10 | import org.junit.Test; 11 | 12 | public class MapTest { 13 | @Test 14 | public void testInt2Object() throws Exception { 15 | String express = "Map a = new HashMap(); a.put(\"a\", 100 - 10); return a.get(\"a\")"; 16 | ExpressRunner runner = new ExpressRunner(); 17 | DefaultContext context = new DefaultContext<>(); 18 | Object r = runner.execute(express, context, null, false, true); 19 | Assert.assertTrue("Map读取错误", r.toString().equalsIgnoreCase("90")); 20 | } 21 | 22 | @Test 23 | public void test_main() throws Exception { 24 | IExpressContext expressContext = new IExpressContext() { 25 | final Map map = new HashMap<>(); 26 | 27 | @Override 28 | public Object put(String name, Object object) { 29 | return map.put(name, object); 30 | } 31 | 32 | @Override 33 | public Object get(Object key) { 34 | return map.get(key); 35 | } 36 | }; 37 | 38 | Map map = new HashMap<>(); 39 | map.put("key1", 1); 40 | expressContext.put("map", map); 41 | 42 | String expression = "map.key1"; 43 | ExpressRunner runner = new ExpressRunner(false, true); 44 | Object r = runner.execute(expression, expressContext, null, true, true); 45 | Assert.assertTrue("Map读取错误", r.toString().equalsIgnoreCase("1")); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/MinusOperatorTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.IExpressContext; 6 | import org.junit.Test; 7 | 8 | /** 9 | * Created by tianqiao on 17/11/13. 10 | */ 11 | public class MinusOperatorTest { 12 | @Test 13 | public void operatorReturn() throws Exception { 14 | ExpressRunner runner = new ExpressRunner(false, true); 15 | IExpressContext context = new DefaultContext<>(); 16 | String test1 = "return -50"; 17 | System.out.println(runner.execute(test1, context, null, true, false)); 18 | } 19 | 20 | @Test 21 | public void operatorThreeLogic() throws Exception { 22 | ExpressRunner runner = new ExpressRunner(false, true); 23 | IExpressContext context = new DefaultContext<>(); 24 | String test1 = "2 > -1 ? -1 : -2;"; 25 | System.out.println(runner.execute(test1, context, null, true, false)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/NullableOperatorEqualsLessMore.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.instruction.op.OperatorEqualsLessMore; 4 | 5 | /** 6 | * Created by tianqiao on 18/4/3. 7 | */ 8 | public class NullableOperatorEqualsLessMore extends OperatorEqualsLessMore { 9 | public NullableOperatorEqualsLessMore(String name) { 10 | super(name); 11 | } 12 | 13 | public NullableOperatorEqualsLessMore(String aliasName, String name, String errorInfo) { 14 | super(aliasName, name, errorInfo); 15 | } 16 | 17 | @Override 18 | public Object executeInner(Object op1, Object op2) throws Exception { 19 | return executeInner(this.name, op1, op2); 20 | } 21 | 22 | public static boolean executeInner(String opStr, Object obj1, Object obj2) throws Exception { 23 | if (obj1 == null || obj2 == null) { 24 | return false; 25 | } 26 | return OperatorEqualsLessMore.executeInner(opStr, obj1, obj2); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ObjectBean.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | public class ObjectBean { 4 | private int amount; 5 | private int volume; 6 | 7 | public ObjectBean(int amount, int volume) { 8 | this.amount = amount; 9 | this.volume = volume; 10 | } 11 | 12 | public int getAmount() { 13 | return amount; 14 | } 15 | 16 | public int getAmount(int a) { 17 | return amount; 18 | } 19 | 20 | public void setAmount(int amount) { 21 | this.amount = amount; 22 | } 23 | 24 | public int getVolume() { 25 | return volume; 26 | } 27 | 28 | public void setVolume(int volume) { 29 | this.volume = volume; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ObjectTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | public class ObjectTest { 9 | @Test 10 | public void testABC() throws Exception { 11 | String express = "object.amount * 2 + object.volume"; 12 | ExpressRunner runner = new ExpressRunner(false, true); 13 | DefaultContext context = new DefaultContext<>(); 14 | ObjectBean tempObject = new ObjectBean(100, 60); 15 | context.put("object", tempObject); 16 | Object result = runner.execute(express, context, null, false, true); 17 | System.out.println(result); 18 | Assert.assertNotSame("数据执行错误", 200, result); 19 | } 20 | 21 | @Test 22 | public void testABC2() throws Exception { 23 | String express = "object.getAmount(1)"; 24 | ExpressRunner runner = new ExpressRunner(false, true); 25 | DefaultContext context = new DefaultContext<>(); 26 | ObjectBean tempObject = new ObjectBean(100, 60); 27 | context.put("object", tempObject); 28 | Object result = runner.execute(express, context, null, false, true); 29 | System.out.println(result); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/PreloadExpressTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | public class PreloadExpressTest { 9 | @Test 10 | public void preloadExpress() throws Exception { 11 | ExpressRunner runner = new ExpressRunner(); 12 | String express = "" 13 | + "function add(int a, int b) {" 14 | + " return a + b;" 15 | + "}" 16 | + "function sub(int a, int b) {" 17 | + " return a - b;" 18 | + "}"; 19 | runner.loadMultiExpress(null, express); 20 | DefaultContext context = new DefaultContext<>(); 21 | context.put("m", 1); 22 | context.put("n", 1); 23 | Object object = runner.execute("add(m, n) + sub(2, -2)", context, null, true, false); 24 | System.out.println(object); 25 | Assert.assertEquals(6, (int)(Integer)object); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/PrintLineExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.InputStream; 5 | import java.io.InputStreamReader; 6 | import java.nio.charset.StandardCharsets; 7 | 8 | import com.ql.util.express.DefaultContext; 9 | import com.ql.util.express.ExpressRunner; 10 | import com.ql.util.express.IExpressContext; 11 | import org.junit.Assert; 12 | import org.junit.Test; 13 | 14 | /** 15 | * Created by tianqiao on 17/4/1. 16 | */ 17 | public class PrintLineExceptionTest { 18 | @Test 19 | public void testLoadFromFile() throws Exception { 20 | String script = getResourceAsStream("lineTest.ql"); 21 | ExpressRunner runner = new ExpressRunner(false, false); 22 | IExpressContext context = new DefaultContext<>(); 23 | try { 24 | Object obj = runner.execute(script, context, null, true, false); 25 | System.out.println(obj); 26 | } catch (Exception e) { 27 | Assert.assertTrue(e.toString().contains("at line 7")); 28 | } 29 | } 30 | 31 | public static String getResourceAsStream(String path) throws Exception { 32 | InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(path); 33 | if (inputStream == null) { 34 | throw new Exception("classLoader中找不到资源文件:" + path); 35 | } 36 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); 37 | StringBuilder stringBuilder = new StringBuilder(); 38 | String line; 39 | while ((line = bufferedReader.readLine()) != null) { 40 | stringBuilder.append(line).append("\n"); 41 | } 42 | bufferedReader.close(); 43 | inputStream.close(); 44 | return stringBuilder.toString(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/ReplaceCompareOperatorTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.ExpressRunner; 4 | import com.ql.util.express.instruction.op.OperatorLike; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by tianqiao on 18/4/3. 9 | */ 10 | public class ReplaceCompareOperatorTest { 11 | @Test 12 | public void testReplaceOperatorTest() throws Exception { 13 | String express = "null > 1 || null < 1 || null == 1 || null >= 1 || null <= 1 ||null like '%222%'"; 14 | ExpressRunner runner = new ExpressRunner(); 15 | runner.replaceOperator("<", new NullableOperatorEqualsLessMore("<")); 16 | runner.replaceOperator(">", new NullableOperatorEqualsLessMore(">")); 17 | runner.replaceOperator("<=", new NullableOperatorEqualsLessMore("<=")); 18 | runner.replaceOperator(">=", new NullableOperatorEqualsLessMore(">=")); 19 | runner.replaceOperator("==", new NullableOperatorEqualsLessMore("==")); 20 | runner.replaceOperator("!=", new NullableOperatorEqualsLessMore("!=")); 21 | runner.replaceOperator("<>", new NullableOperatorEqualsLessMore("<>")); 22 | runner.replaceOperator("like", new NullableOperatorLike("like")); 23 | Object r = runner.execute(express, null, null, false, false); 24 | System.out.println(r); 25 | } 26 | 27 | public class NullableOperatorLike extends OperatorLike { 28 | public NullableOperatorLike(String name) { 29 | super(name); 30 | } 31 | 32 | @Override 33 | public Object executeInner(Object op1, Object op2) throws Exception { 34 | if (op1 == null || op2 == null) { 35 | return false; 36 | } 37 | return super.executeInner(op1, op2); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/SerializableTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import java.io.FileInputStream; 4 | import java.io.FileOutputStream; 5 | import java.io.ObjectInputStream; 6 | import java.io.ObjectOutputStream; 7 | 8 | import com.ql.util.express.ExpressRunner; 9 | import com.ql.util.express.InstructionSet; 10 | import org.junit.Ignore; 11 | import org.junit.Test; 12 | 13 | public class SerializableTest { 14 | @Test 15 | @Ignore("不在实现Serializable接口,因此不能序列化") 16 | public void testSerializable() throws Exception { 17 | ExpressRunner runner = new ExpressRunner(); 18 | InstructionSet instructionSet = runner.parseInstructionSet("1+1"); 19 | ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("target/qlcache.dat")); 20 | objectOutputStream.writeObject(instructionSet); 21 | objectOutputStream.close(); 22 | 23 | ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("target/qlcache.dat")); 24 | InstructionSet newInstructionSet = (InstructionSet)objectInputStream.readObject(); 25 | objectInputStream.close(); 26 | System.out.print(newInstructionSet); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/SetTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Test; 6 | 7 | /** 8 | * Created by tianqiao on 16/9/13. 9 | */ 10 | public class SetTest { 11 | @Test 12 | public void testSet() throws Exception { 13 | ExpressRunner runner = new ExpressRunner(false, false); 14 | DefaultContext context = new DefaultContext<>(); 15 | String express = "abc = NewMap(1:1, 2:2); return abc.get(1) + abc.get(2);"; 16 | Object r = runner.execute(express, context, null, false, false); 17 | System.out.println(r); 18 | express = "abc = NewList(1, 2, 3); return abc.get(1) + abc.get(2)"; 19 | r = runner.execute(express, context, null, false, false); 20 | System.out.println(r); 21 | express = "abc = [1, 2, 3]; return abc[1] + abc[2];"; 22 | r = runner.execute(express, context, null, false, false); 23 | System.out.println(r); 24 | express = "abc = NewMap(1:(-1), 2:2); return abc.get(1) + abc.get(2);"; 25 | r = runner.execute(express, context, null, false, false); 26 | System.out.println(r); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/StaticMethodTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Test; 6 | 7 | public class StaticMethodTest { 8 | @Test 9 | public void testStaticMethod() throws Exception { 10 | String[] expressArray = new String[] { 11 | "StaticUtils.ITEM_DIM_MASTER", 12 | "StaticUtils.isVirtualSCItem(1L)", 13 | StaticUtils.class.getName() + ".ITEM_DIM_MASTER", 14 | StaticUtils.class.getName() + ".isVirtualSCItem(1L)" 15 | }; 16 | ExpressRunner runner = new ExpressRunner(false, true); 17 | DefaultContext context = new DefaultContext<>(); 18 | context.put("StaticUtils", StaticUtils.class); 19 | for (String express : expressArray) { 20 | Object r = runner.execute(express, context, null, false, true); 21 | System.out.println(r); 22 | } 23 | } 24 | 25 | public static class StaticUtils { 26 | public static long ITEM_DIM_MASTER = 0x01; 27 | 28 | public static final long ITEM_DIM_VIRTUAL = 0x02; 29 | 30 | public static boolean isVirtualSCItem(Long itemDim) { 31 | return itemDim != null && (itemDim & 0x0f) == ITEM_DIM_VIRTUAL; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/SubtractTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | public class SubtractTest { 9 | @Test 10 | public void testMax() throws Exception { 11 | //String express = "return max(max(0.0,1) - 0.95,0);"; 12 | String express = "-3 - (-5 * -7 - 9) - (9 - 2);"; 13 | ExpressRunner runner = new ExpressRunner(false, true); 14 | DefaultContext context = new DefaultContext<>(); 15 | Object r = runner.execute(express, context, null, false, true); 16 | System.out.println(r); 17 | Assert.assertEquals("\"-\"号测试", "-36", r.toString()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/TimeoutExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test; 2 | 3 | import com.ql.util.express.DefaultContext; 4 | import com.ql.util.express.ExpressRunner; 5 | import com.ql.util.express.exception.QLTimeoutException; 6 | import org.junit.Test; 7 | 8 | /** 9 | * @author tianqiao@taobao.com 10 | * @since 2019/6/18 10:52 AM 11 | */ 12 | public class TimeoutExceptionTest { 13 | private static final String[] expressList = new String[] { 14 | "sum = 0; for(i = 0; i < 1000000000; i++) {sum = sum + i;} return sum;", 15 | "for(i = 1; i < 10; i++) {System.out.println('loop time:' + i); Thread.sleep(300);}" 16 | }; 17 | 18 | @Test 19 | public void test() throws Exception { 20 | ExpressRunner runner = new ExpressRunner(); 21 | DefaultContext context = new DefaultContext<>(); 22 | 23 | for (String express : expressList) { 24 | try { 25 | Object r = runner.execute(express, context, null, true, false, 1000); 26 | System.out.println(r); 27 | throw new Exception("没有捕获到超时异常"); 28 | } catch (QLTimeoutException e) { 29 | e.printStackTrace(); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/custom/SelfDefineObject1.java: -------------------------------------------------------------------------------- 1 | //package com.ql.util.express.test.custom; 2 | // 3 | ///** 4 | // * 注:此类虽然已注释,但是请勿删除,用于测试自定义ClassLoader使用 5 | // * 6 | // * @author bingo 7 | // */ 8 | //public class SelfDefineObject1 { 9 | // public static String getValue() { 10 | // return "success1"; 11 | // } 12 | //} 13 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/custom/SelfDefineObject2.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test.custom; 2 | 3 | /** 4 | * @author bingo 5 | */ 6 | public class SelfDefineObject2 { 7 | public static String getValue() { 8 | return "success2"; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/rating/RatingTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test.rating; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.ql.util.express.DefaultContext; 7 | import com.ql.util.express.ExpressRunner; 8 | import org.junit.Test; 9 | 10 | /** 11 | * 分成配置范例 12 | * 13 | * @author xuannan 14 | */ 15 | public class RatingTest { 16 | @SuppressWarnings({"rawtypes", "unchecked"}) 17 | @Test 18 | public void testRating() throws Exception { 19 | Map logisticsOrder = new HashMap(); 20 | Map tcOrder = new HashMap(); 21 | Map goodsOrder = new HashMap(); 22 | Map subjectValue = new HashMap(); 23 | //设置物流订单信息 24 | logisticsOrder.put("重量", 4); 25 | logisticsOrder.put("仓储TP", "玄难"); 26 | logisticsOrder.put("物流TP", "云殊"); 27 | logisticsOrder.put("包装TP", "千绝"); 28 | //建立计算器 29 | ExpressRunner runner = new ExpressRunner(true, true); 30 | //增加自定义函数 31 | runner.addFunction("费用科目", new SubjectOperator("费用科目")); 32 | //装载分成规则rating.ql文件 33 | runner.loadExpress("rating"); 34 | //设置上下文 35 | DefaultContext context = new DefaultContext<>(); 36 | context.put("物流订单", logisticsOrder); 37 | context.put("交易订单", tcOrder); 38 | context.put("仓储订单", goodsOrder); 39 | context.put("费用科目", subjectValue); 40 | //执行指令 41 | runner.executeByExpressName("rating", context, null, false, false); 42 | //runner.executeByExpressName("rating", context, null, false, false, null); 43 | //while (true) { 44 | // runner.executeByExpressName("rating", context, null, false, false, null); 45 | //} 46 | //输出分成结果 47 | System.out.println("----------分成结果----------------"); 48 | for (Object item : subjectValue.values()) { 49 | System.out.println(item); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/rating/RatingWithPropertyTest.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test.rating; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.ql.util.express.DefaultContext; 7 | import com.ql.util.express.ExpressRunner; 8 | import org.junit.Test; 9 | 10 | /** 11 | * 分成配置范例,通过动态属性来实现 12 | * 13 | * @author xuannan 14 | */ 15 | public class RatingWithPropertyTest { 16 | @SuppressWarnings({"rawtypes", "unchecked"}) 17 | @Test 18 | public void testRating() throws Exception { 19 | Map logisticsOrder = new HashMap(); 20 | Map tcOrder = new HashMap(); 21 | Map goodsOrder = new HashMap(); 22 | //设置物流订单信息 23 | logisticsOrder.put("重量", 4); 24 | logisticsOrder.put("仓储TPID", "玄难"); 25 | logisticsOrder.put("物流TPID", "云殊"); 26 | logisticsOrder.put("包装TPID", "千绝"); 27 | //建立计算器 28 | ExpressRunner runner = new ExpressRunner(); 29 | //增加自定义函数 30 | runner.addFunction("费用科目", new SubjectOperator("费用科目")); 31 | //装载分成规则rating.ql文件 32 | runner.loadExpress("ratingWithProperty"); 33 | //设置上下文 34 | DefaultContext context = new DefaultContext<>(); 35 | context.put("物流订单", logisticsOrder); 36 | context.put("交易订单", tcOrder); 37 | context.put("仓储订单", goodsOrder); 38 | SubjectManager subjectManager = new SubjectManager(); 39 | context.put("费用", subjectManager); 40 | 41 | runner.executeByExpressName("ratingWithProperty", context, null, false, false); 42 | //输出分成结果 43 | System.out.println("----------分成结果----------------"); 44 | for (Object item : subjectManager.getSubjectValues()) { 45 | System.out.println(item); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/rating/SubjectValue.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test.rating; 2 | 3 | /** 4 | * 科目数据 5 | * 6 | * @author xuannan 7 | */ 8 | public class SubjectValue { 9 | public Object userId; 10 | public Object subjectId; 11 | public double value; 12 | 13 | public String toString() { 14 | return "科目[" + userId + "," + subjectId + "] = " + value; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/spring/BizLogicBean.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test.spring; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * Created by tianqiao on 17/3/8. 7 | */ 8 | public class BizLogicBean { 9 | public UserDO getUserInfo(String nick) { 10 | if (nick.equals("小王")) { 11 | UserDO userDO = new UserDO(); 12 | userDO.setNick(nick); 13 | userDO.setGmtCreate(new Date()); 14 | userDO.setUserId(10086L); 15 | userDO.setPosition("salesman"); 16 | userDO.setSalary(5000.0); 17 | return userDO; 18 | } else if (nick.equals("马总")) { 19 | UserDO userDO = new UserDO(); 20 | userDO.setNick(nick); 21 | userDO.setGmtCreate(new Date()); 22 | userDO.setUserId(1L); 23 | userDO.setPosition("boss"); 24 | userDO.setSalary(999999999999.0); 25 | return userDO; 26 | } 27 | return null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/spring/QLExpressContext.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test.spring; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.ql.util.express.IExpressContext; 7 | import org.springframework.context.ApplicationContext; 8 | 9 | @SuppressWarnings("serial") 10 | public class QLExpressContext extends HashMap implements IExpressContext { 11 | private final ApplicationContext applicationContext; 12 | 13 | public QLExpressContext(ApplicationContext applicationContext) { 14 | this.applicationContext = applicationContext; 15 | } 16 | 17 | public QLExpressContext(Map properties, ApplicationContext applicationContext) { 18 | super(properties); 19 | this.applicationContext = applicationContext; 20 | } 21 | 22 | /** 23 | * 抽象方法:根据名称从属性列表中提取属性值 24 | */ 25 | @Override 26 | public Object get(Object name) { 27 | Object result; 28 | result = super.get(name); 29 | try { 30 | if (result == null && this.applicationContext != null 31 | && this.applicationContext.containsBean((String)name)) { 32 | // 如果在Spring容器中包含bean,则返回String的Bean 33 | result = this.applicationContext.getBean((String)name); 34 | } 35 | } catch (Exception e) { 36 | throw new RuntimeException(e); 37 | } 38 | return result; 39 | } 40 | 41 | @Override 42 | public Object put(String name, Object object) { 43 | return super.put(name, object); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/com/ql/util/express/test/spring/UserDO.java: -------------------------------------------------------------------------------- 1 | package com.ql.util.express.test.spring; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * Created by tianqiao on 17/3/8. 7 | */ 8 | public class UserDO { 9 | private String nick; 10 | 11 | private Long userId; 12 | 13 | private Date gmtCreate; 14 | 15 | private String position; 16 | 17 | private Double salary; 18 | 19 | public String getNick() { 20 | return nick; 21 | } 22 | 23 | public void setNick(String nick) { 24 | this.nick = nick; 25 | } 26 | 27 | public Long getUserId() { 28 | return userId; 29 | } 30 | 31 | public void setUserId(Long userId) { 32 | this.userId = userId; 33 | } 34 | 35 | public Date getGmtCreate() { 36 | return gmtCreate; 37 | } 38 | 39 | public void setGmtCreate(Date gmtCreate) { 40 | this.gmtCreate = gmtCreate; 41 | } 42 | 43 | public String getPosition() { 44 | return position; 45 | } 46 | 47 | public void setPosition(String position) { 48 | this.position = position; 49 | } 50 | 51 | public Double getSalary() { 52 | return salary; 53 | } 54 | 55 | public void setSalary(Double salary) { 56 | this.salary = salary; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/resources/bugfix/error-column.ql: -------------------------------------------------------------------------------- 1 | if (a != null) { 2 | return a; 3 | } 4 | 5 | if (b != null) { 6 | return b; 7 | } 8 | 9 | c = a + b ;if (c != null { 10 | return c; 11 | } 12 | 13 | /** println("<> result:" + (2 <> 3)); **/ 14 | return "a b c all is null"; -------------------------------------------------------------------------------- /src/test/resources/classes/com/ql/util/express/test/custom/SelfDefineObject1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/QLExpress/2f02edac5c168e14b0a5400bad3b408e176b660b/src/test/resources/classes/com/ql/util/express/test/custom/SelfDefineObject1.class -------------------------------------------------------------------------------- /src/test/resources/com/ql/util/express/console/closeFile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/QLExpress/2f02edac5c168e14b0a5400bad3b408e176b660b/src/test/resources/com/ql/util/express/console/closeFile.png -------------------------------------------------------------------------------- /src/test/resources/com/ql/util/express/console/help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/QLExpress/2f02edac5c168e14b0a5400bad3b408e176b660b/src/test/resources/com/ql/util/express/console/help.png -------------------------------------------------------------------------------- /src/test/resources/com/ql/util/express/console/openFile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/QLExpress/2f02edac5c168e14b0a5400bad3b408e176b660b/src/test/resources/com/ql/util/express/console/openFile.png -------------------------------------------------------------------------------- /src/test/resources/com/ql/util/express/console/run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alibaba/QLExpress/2f02edac5c168e14b0a5400bad3b408e176b660b/src/test/resources/com/ql/util/express/console/run.png -------------------------------------------------------------------------------- /src/test/resources/example/approve.ql: -------------------------------------------------------------------------------- 1 | function 审批通过(String a, int b) { 2 | System.out.println(a + "审批:金额:" + b); 3 | return true; 4 | } 5 | 6 | function 报销入账(int a) { 7 | System.out.println("报销入卡:金额:" + a); 8 | } 9 | 10 | function 打回修改(String a) { 11 | System.out.println("重填:申请人:" + a); 12 | } 13 | 14 | 如果 (审批通过(经理, 金额)) { 15 | 如果 (金额 大于 5000) { 16 | 如果 (审批通过(总监, 金额)) { 17 | 如果 (审批通过(财务, 金额)) { 18 | 报销入账(金额) 19 | } 否则 { 20 | 打回修改(申请人) 21 | } 22 | } 否则 { 23 | 打回修改(申请人) 24 | } 25 | } 否则 { 26 | 如果 (审批通过(财务, 金额)) { 27 | 报销入账(金额) 28 | } 否则 { 29 | 打回修改(申请人) 30 | } 31 | } 32 | } 否则 { 33 | 打回修改(申请人) 34 | } 35 | 打印("完成") 36 | -------------------------------------------------------------------------------- /src/test/resources/example/approve1.ql: -------------------------------------------------------------------------------- 1 | 如果 (审批通过(经理, 金额)) { 2 | 如果 (金额 大于 5000) { 3 | 如果 (审批通过(总监, 金额)) { 4 | 如果 (审批通过(财务, 金额)) { 5 | 报销入账(金额) 6 | } 否则 { 7 | 打回修改(申请人) 8 | } 9 | } 否则 { 10 | 打回修改(申请人) 11 | } 12 | } 否则 { 13 | 如果 (审批通过(财务, 金额)) { 14 | 报销入账(金额) 15 | } 否则 { 16 | 打回修改(申请人) 17 | } 18 | } 19 | } 否则 { 20 | 打回修改(申请人) 21 | } 22 | 打印("完成") 23 | -------------------------------------------------------------------------------- /src/test/resources/example/approve2.ql: -------------------------------------------------------------------------------- 1 | function 审批通过(String a, int b){ 2 | System.out.println(a + "审批:金额:" + b); 3 | if(b > 6000) 4 | return false; 5 | return true; 6 | } 7 | 8 | function 报销入账(int a){ 9 | System.out.println("报销入卡:金额:" + a); 10 | } 11 | 12 | function 打回修改(String a){ 13 | System.out.println("重填:申请人:" + a); 14 | } 15 | -------------------------------------------------------------------------------- /src/test/resources/functionDef.ql: -------------------------------------------------------------------------------- 1 | function add(int a,int b){ 2 | return a+b; 3 | }; 4 | 5 | function sub(int a,int b){ 6 | return a - b; 7 | }; 8 | 9 | macro 累加 {qh = qh + 100;}; 10 | 11 | macro initial { 12 | exportDef int qh; 13 | exportAlias a qh; 14 | a = 0; 15 | }; 16 | 17 | -------------------------------------------------------------------------------- /src/test/resources/includeFunction.ql: -------------------------------------------------------------------------------- 1 | function add(int a,int b){ 2 | return a+b; 3 | }; 4 | 5 | function sub(int a,int b){ 6 | return a - b; 7 | }; 8 | 9 | -------------------------------------------------------------------------------- /src/test/resources/includeMacro.ql: -------------------------------------------------------------------------------- 1 | macro 累加 {qh = qh + 100;}; 2 | 3 | macro initial { 4 | exportDef int qh; 5 | exportAlias a qh; 6 | a = 0; 7 | }; 8 | 9 | -------------------------------------------------------------------------------- /src/test/resources/includeRoot.ql: -------------------------------------------------------------------------------- 1 | 2 | if(true)then {1==1} else{ 3==3} ; 3 | 4 | include includeFunction; 5 | 6 | exportDef int mm =1000; 7 | 8 | include includeMacro; 9 | 10 | initial; 11 | 累加; 12 | 累加; 13 | 累加; 14 | 15 | mm = mm + 1; 16 | a = a + 1000000; 17 | System.out.println(a); 18 | return add(a,4) + sub(a,9); 19 | -------------------------------------------------------------------------------- /src/test/resources/lineTest.ql: -------------------------------------------------------------------------------- 1 | event = new java.util.HashMap(); 2 | auction = new java.util.HashMap(); 3 | list = new ArrayList(); 4 | 5 | if(2>1){ 6 | for(i=0;i<10;i++){ 7 | for(j=0;j<10;a=1/0){ 8 | if(2>1){ 9 | auction.put("title","title"); 10 | } 11 | } 12 | } 13 | } 14 | auction.put("title","title"); 15 | auction.put("category","123456"); 16 | return auction; 17 | -------------------------------------------------------------------------------- /src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.appender.file=org.apache.log4j.DailyRollingFileAppender 2 | log4j.appender.file.File=Test_LOG4j.log 3 | log4j.appender.file.layout=org.apache.log4j.PatternLayout 4 | log4j.appender.file.layout.ConversionPattern=[%d] [%t] (%F:%L) %-5p %c - %m%n 5 | 6 | log4j.appender.console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 8 | log4j.appender.console.layout.ConversionPattern=[%d] [%t] (%F:%L) %-5p %c - %m%n 9 | 10 | log4j.appender.html=org.apache.log4j.DailyRollingFileAppender 11 | log4j.appender.html.File=Test_LOG4j.log 12 | log4j.appender.html.layout=org.apache.log4j.HTMLLayout 13 | 14 | log4j.rootLogger=error,console 15 | log4j.logger.com.ql=debug 16 | log4j.logger.org.springframework=error 17 | -------------------------------------------------------------------------------- /src/test/resources/main.ql: -------------------------------------------------------------------------------- 1 | initial; 2 | 累加; 3 | 累加; 4 | 累加; 5 | 6 | if(true)then {1==1} else{ 3==3} ; 7 | exportDef int mm =1000; 8 | mm = mm + 1; 9 | a = a + 1000000; 10 | System.out.println(a); 11 | return add(a,4) + sub(a,9); 12 | -------------------------------------------------------------------------------- /src/test/resources/rating.ql: -------------------------------------------------------------------------------- 1 | 费用科目(物流订单.仓储TP,"仓储费")= 物流订单.重量 * 0.5 ; 2 | 3 | if(物流订单.重量 > 5) then{ 4 | 费用科目(物流订单.物流TP,"运输费")= 3.0 + (物流订单.重量 - 5 ) * 1.5 ; 5 | } else { 6 | 费用科目(物流订单.物流TP,"运输费")= 3.0; 7 | }; 8 | 费用科目(物流订单.包装TP,"包装费")= 物流订单.重量 * 2.5 ; 9 | -------------------------------------------------------------------------------- /src/test/resources/ratingWithProperty.ql: -------------------------------------------------------------------------------- 1 | alias 仓储TP 物流订单.仓储TPID; 2 | alias 物流TP 物流订单.物流TPID; 3 | alias 包装TP 物流订单.包装TPID; 4 | 仓储费 = 100; 5 | 费用.仓储TP.仓储费 = 物流订单.重量 * 0.5 ; 6 | 费用.物流TP.运输费= 3.0; 7 | 费用.包装TP.包装费= 物流订单.重量 * 2.5 ; 8 | -------------------------------------------------------------------------------- /src/test/resources/spring-express-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/test/resources/testFunctionParameterType.ql: -------------------------------------------------------------------------------- 1 | java.util.Map event = new java.util.HashMap(); 2 | 3 | java.util.Map auction = new java.util.HashMap(); 4 | auction.put("title","title"); 5 | auction.put("category","123456"); 6 | event.put("auction",auction); 7 | System.out.println(auctionUtil.getText(event.auction.title,event.auction.category)); 8 | --------------------------------------------------------------------------------