使用Drools声明本地规则变量

时间:2011-01-28 15:45:33

标签: scope drools rule-engine

可以使用Drools规则引擎在本地规则定义中创建局部变量吗?

我写了一个示例代码,但它没有编译。这个例子只是为了揭示关于本地声明的想法(我知道这是错误的)

/*...*/
    rule "Test local Variable"
        when
            String $departmentName = "Music";
        then
            System.out.println($departmentName);
    end
/*...*/

错误消息是:

org.drools.CheckedDroolsException: There were errors in the rule source: [ERR 101] Line 25:2 no viable alternative at input 'String' in rule "Test local Variable"

位置[25,2]由行定义:

String $departmentName = "Music";

2 个答案:

答案 0 :(得分:4)

从Drools 5开始,无法在条件中声明任意变量。您可以将变量绑定到事实和属性:

when
   Person( $name : name )
then
   // $name is bound to each name of each person in the working memory
end

答案 1 :(得分:2)

Drools 5只能为Facts或Fact字段规则定义局部变量:

when
    $city : City()               // a Fact
    Person ($name : firstName)   // a Fact property
then
    System.out.println("city="+$city+", name="+$name);
end

但是,您可以使用Edson的答案建议的地图模拟任意局部变量(即不是Fact或Fact属性):

when
    $myParamList : eval(DroolsRuleLocalVariable.setVariable("myParamList", Arrays.asList(1,2,3) ))
    // warn: you must use eval() and not a Drools condition because the Drools condition will be cached so the setVariable method will not be called
then
    System.out.println("myParamList="+(List<Integer>)DroolsRuleLocalVariable.getVariable("myParamList"));

    // remember to cleanup the variables for the next rule to be executed
    DroolsRuleLocalVariable.clear(); 
end

DroolsRuleLocalVariable类如下:

package com.mypackage;

import java.util.HashMap;
import java.util.Map;

/**
 * Manage Drools rule local variables.
 * A local variable can be read/written in the "when" (CONDITION) and in the "then" (consequence/ACTION) parts.
 * The "then" part must cleanup the local variables otherwise they are available for the next executed rule.
 * 
 * Note: Drools 5 cannot create rule local variables, see
 * http://stackoverflow.com/questions/4830117/declare-local-rule-variable-using-drools
 * 
 *
 */
public class DroolsRuleLocalVariable {
    private static Map<String,Object> ruleLocalVariables = new HashMap<>();

    /**
     * Sets the variable variableName to the variableValue value. If the
     * variable is not defined, create a new variable.
     * The method returns true in order to be evaluated in Drools CONDITION, e.g.:
     *  
     *  eval(DroolsRuleLocalVariable.setVariable("myParamList", Arrays.asList($param) ))
     * 
     * @see #clear() the clear method should be called in the ACTION of the decision table
     * @param variableName the variable name
     * @param variableValue the variable value
     * @return always true
     */
    public static boolean setVariable(String variableName, Object variableValue) {
        ruleLocalVariables.put(variableName, variableValue);
        return true;
    }

    /**
     * Returns the variable value or null if the variable is not defined.
     * The variable must be casted to the original type.
     * Usage:
     *  eval(DroolsRuleLocalVariable.getVariable("myParamList"))
     * 
     * @param variableValue
     * @return
     */
    public static Object getVariable(String variableName) {
        Object value = ruleLocalVariables.get(variableName);
        return value;
    }

    /**
     * Clears the local variables. This method MUST be called in the ACTION part of the decision table.
     */
    public static void clear() {
        ruleLocalVariables.clear();
    }
}