A lightweight Java-like grammar rule engine used as an embedded rule engine in business systems. Make business rule definition simple and flexible. Enable business people to define business rules. Standard JAVA syntax is supported, as well as support for custom action symbols, action symbol overloading, function definitions, macro definitions, data lazy loading, and more.

QLExpress has a strong influence within Ali Group and is widely used in the e-shopping scene, which often needs the support of rules engine in the flexible and changeable business scenarios.

The official address is github.com/alibaba/QLE…

The project has given a lot of use cases, but if you don’t run it yourself, it is not easy to realize its usage and power. This time, we mainly give a QLExpress run case, which can really run the various official case codes.

case

Description:

/** * execute a piece of text * @param expressString program text * @param Context Execution context produces intermediate data during execution, * @param errorList Error message output List * @param isCache whether to use the Cache instruction set * @param isTrace Whether to output detailed execution instruction information * @return
 * @throws Exception
 */
   public Object execute(String expressString, IExpressContext<String,Object> context,
         List<String> errorList, boolean isCache, boolean isTrace) throws Exception {
      return this.execute(expressString, context, errorList, isCache, isTrace, null);
   }
Copy the code

Operating Cases:

package me.aihe.demo.qlexpress;

import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.ql.util.express.Operator;


import java.util.HashMap;

public class QLExpressionDemo {
    public static void main(String[] args) throws Exception {
        ExpressRunner runner = new ExpressRunner();
//        getStarted(runner);

//        basicStatement(runner);

//        collectionStatement(runner);

//        objectStatement(runner);

//        functionStatement(runner); // macronStatement(runner); // workWithJavaStatement(runner); // extendOperatorStatement(runner); customOperatorStatement(runner); } /** * Use of custom operators * @param Runner */ private static void customOperatorStatement(ExpressRunner Runner) throws Exception { class JoinOperator extends Operator { public Object executeInner(Object[] list) throws Exception { Object opdata1 = list[0]; Object opdata2 = list[1];if(opdata1 instanceof java.util.List){
                    ((java.util.List)opdata1).add(opdata2);
                    return opdata1;
                }else{
                    java.util.List result = new java.util.ArrayList();
                    result.add(opdata1);
                    result.add(opdata2);
                    returnresult; }} // Return the result [1, 2, 3] //(1)addOperator DefaultContext<String, Object> context = new DefaultContext<String, Object>(); runner.addOperator("join",new JoinOperator());
        Object r = runner.execute("1 join 2 join 3", context, null, false.false); System.out.println(r); [1, 2] runner. AddFunction ()"joinfunc",new JoinOperator());
        r = runner.execute("Joinfunc (1, 2, 3)", context, null, false.false); System.out.println(r); [1, 2, 3] runner. ReplaceOperator ("+",new JoinOperator());
        r = runner.execute("1 + 2 + 3", context, null, false.false); System.out.println(r); } /** *; Private static void extendOperatorStatement(ExpressRunner runner) throws Exception {* @param Runner */ private static void extendOperatorStatement(ExpressRunner runner) throws Exception { runner.addOperatorWithAlias("如果"."if",null);
        runner.addOperatorWithAlias("则"."then",null);
        runner.addOperatorWithAlias("Otherwise"."else",null);

        IExpressContext<String, Object> context =new DefaultContext<String, Object>();
        context.put("Chinese", 88);
        context.put("Mathematics", 99);
        context.put("English", 95);

        String exp = "If (language + math + English >270) {return 1; } otherwise {return 0; }";
//        DefaultContext<String, Object> context = new DefaultContext<String, Object>();
        Object result = runner.execute(exp, context, null, false.false, null); System.out.println(result); } /** * bind some methods already written in Java to our custom variables, the most common part of the business. * @param runner */ private static void workWithJavaStatement(ExpressRunner Runner) throws Exception {// An object is created when used runner.addFunctionOfClassMethod("Take the absolute value", Math.class.getName(), "abs",
                new String[] { "double"}, null); / / object already exists, direct runner. The call object method addFunctionOfServiceMethod ("Print", System.out, "println",new String[] { "String" }, null);

        String exp = "A = take the absolute value (-100); Print (\ "Hello World \"); Print (a.t oString ())";
        DefaultContext<String, Object> context = new DefaultContext<>();
        runner.execute(exp, context,null,false.false); System.out.println(context); } /** * Macro definition, that is, to pre-define something, * @param Runner */ Private static void macronStatement(ExpressRunner Runner) throws Exception  { runner.addMacro("Calculate grade averages"."(Chinese + Math + English)/3.0");
        runner.addMacro("Is it good?"."Calculate average grade >90");

        IExpressContext<String, Object> context =new DefaultContext<String, Object>();
        context.put("Chinese", 88);
        context.put("Mathematics", 99);
        context.put("English", 95);
        Object result = runner.execute("Is it good?", context, null, false.false); System.out.println(result); } /** * The last sentence of the general statement is to return the result * @param runner */ private static voidfunctionStatement(ExpressRunner runner) throws Exception {
        String functionStatement = "function add(int a,int b){\n" +
                "  return a+b;\n" +
                "}; \n" +
                "\n" +
                "function sub(int a,int b){\n" +
                "  return a - b;\n" +
                "}; \n" +
                "\n" +
                "a=10; \n" +
                "add(a,4) + sub(a,9);";

        Object result = runner.execute(functionStatement, new DefaultContext<>(), null, false.false);
//        runner.execute(functionStatement, new DefaultContext<>(), null, true.false, 1000); System.out.println(result); } /** * Import java.lang.*,import java.util.*; * @param runner */ private static void objectStatement(ExpressRunner runner) throws Exception { // TradeEvent tradeEvent  = new TradeEvent(); / / tradeEvent. SetPrice (20.0); // tradeEvent.setName("Shopping"); // tradeEvent.setId(UUID.randomUUID().toString()); // // String objectStatement ="import me.aihe.demo.trade.TradeEvent; \n" +
                " tradeEvent = new TradeEvent(); \n" +
                "TradeEvent. SetPrice (20.0); \n" +
                " tradeEvent.id=UUID.randomUUID().toString(); \n" +
                " System.out.println(tradeEvent.getId()); \n" +
                " System.out.println(tradeEvent.price);";
        runner.execute(objectStatement, new DefaultContext<>(), null, false.false); Keys = new ArrayList<String>(); keys = new ArrayList<String>(); * deviceName2Value = new HashMap<String,String>(7); * String[] deviceNames = {"ng"."si"."umid"."ut"."mac"."imsi"."imei"}; * int[] mins = {5,30}; * keys = new ArrayList(); * deviceName2Value = new HashMap(); * deviceNames = ["ng"."si"."umid"."ut"."mac"."imsi"."imei"]; * mins = [5, 30]; * focdecisionreqdto reqDTO = param.getreqdto (); * / * reqDTO = param.getreqdto (); * // Java syntax: array traversal *for(GRCRouteLineResultDTO item: list) {*} * //qlfor(i=0; i<list.size(); i++){ * item = list.get(i); } * * // Java syntax: map traversal *for(String key : map.keySet()) { * System.out.println(map.get(key)); KeySet = map.keyset (); * objArr = keySet.toArray(); *for(i=0; i<objArr.length; i++) { * key = objArr[i]; * System.out.println(map.get(key)); * } * @param runner */ private static void collectionStatement(ExpressRunner runner) throws Exception { DefaultContext<String, Object> defaultContext = new DefaultContext<>(); HashMap<String, String> mapData = newHashMap(){{
            put("a"."hello");
            put("b"."world");
            put("c".! "" @ # $");
        }};
        defaultContext.put("map",mapData); / / ql is not supportedfor(obj:list){} syntax, can only be accessed by subscript. String mapTraverseStatement =" keySet = map.keySet(); \n" +
                "  objArr = keySet.toArray();\n" +
                " for (i=0; i +
                "  key = objArr[i];\n" +
                " System.out.println(map.get(key)); \n" +
                "}";
        runner.execute(mapTraverseStatement,defaultContext,null,false.false); System.out.println(defaultContext); /** * ExpressRunner = new ExpressRunner(false.false);
         *         DefaultContext<String, Object> context = new DefaultContext<String, Object>();
         *         String express = "ABC = NewMap (1:1, 2:2); return abc.get(1) + abc.get(2);";
         *         Object r = runner.execute(express, context, null, false.false);
         *         System.out.println(r);
         *         express = "ABC = NewList (1, 2, 3); return abc.get(1)+abc.get(2)";
         *         r = runner.execute(express, context, null, false.false);
         *         System.out.println(r);
         *         express = "ABC = [1, 2, 3]; return abc[1]+abc[2];";
         *         r = runner.execute(express, context, null, false.false); * System.out.println(r); Try {}catch{} java8 lambda expressions are not supported * lambda expressions are not supportedforLoop set operationfor(GRCRouteLineResultDTO item: list) * weak type language, please do not define type declaration * do not use Templete (Map<String, list > etc.) * Array declaration is different * min, Max,round,print,println,like,inAre the keywords of the system default function, Do not use this as a variable name * @param runner */ private static void basicStatement(ExpressRunner runner) throws Exception { DefaultContext<String, Object> defaultContext = new DefaultContext<>(); // defaultContext.put("n", 10); // Passing context directly from Java is equivalent to passing context String loopStatement = in an expression"sum=0; n=10;" +
                "for(i=0; i +
                "sum=sum+i; \n" +
                "}\n" +
                "return sum;";
        Object result = runner.execute(loopStatement, defaultContext, null, false.false); System.out.println(result); // Note that using the same defaultContext, the intermediate variable executed by the previous statement is passed to the next statement, String maxmiumStatement ="a=1; \n" +
                "b=2; \n" +
                "maxnum = a>b? a:b;";
        result = runner.execute(maxmiumStatement, defaultContext, null, false.false); System.out.println(result); Private static void getStarted(ExpressRunner runner) throws Exception {DefaultContext<String, Object> context = new DefaultContext<String, Object>(); context.put("a", 1); context.put("b", 2); context.put("c", 3); String express ="a+b*c";
        Object r = runner.execute(express, context, null, true.true); System.out.println(r); }}Copy the code

instructions

The method that binds Java classes or objects is often used in business, so you can focus on it and run the rest to see how it works.

Reference:

Github.com/alibaba/QLE…