java-8 - 如何在 drools 规则中定义和初始化变量

标签 java-8 drools

我使用的是drools 6.1。我有一个流口水文件。我想做这样的事情。

import static com.softech.vu360.autoalert.util.Utility.getCurrentDate;
import static com.softech.vu360.autoalert.util.Utility.getDate;
import static com.softech.vu360.autoalert.util.Utility.getMonthNameFromInt;
import static com.softech.vu360.autoalert.util.Utility.getExpiryDate;
import static com.softech.vu360.autoalert.util.Utility.getEmailDate;
import static com.softech.vu360.autoalert.util.Utility.getWeekOfYear;
import com.softech.vu360.autoalert.model.LicenseCredential;
import com.softech.vu360.autoalert.model.Learner;
import com.softech.vu360.autoalert.CsvFileWriter;
import java.time.LocalDate;
import java.util.Date;

global com.softech.vu360.autoalert.CsvFileWriter learnerCsvFileWriter;

function void processData(LicenseCredential licenseCredential, CsvFileWriter learnerCsvFileWritern, LocalDate expiryDate, LocalDate emailDate){

    Learner learner = new Learner();
    learner.setFirstName(licenseCredential.getFirstName());
    ...
    learnerCsvFileWriter.add(learner);

}

rule "Renewal alert for 60 days"
when
    licenseCredential : LicenseCredential()

    $courseCompletionDate : licenseCredential.getCourseCompletionDate()
    $renewalDeadlineDay : licenseCredential.getRenewalDeadlineDay()
    $renewalDeadlineMonth : licenseCredential.getRenewalDeadlineMonth()
    $currentDate : getCurrentDate()
    $dayOfMonth : $courseCompletionDate.getDate()
    $month : $courseCompletionDate.getMonth()
    $expiryDate : getExpiryDate(licenseCredential)
    $emailDate : getEmailDate(2, licenseCredential)
    $localDate : LocalDate.now()
    $intRenewalDeadlineDay : Integer.valueOf($renewalDeadlineDay)
    $intRenewalDeadlineMonth : Integer.valueOf($renewalDeadlineMonth)

    (
        eval($renewalDeadlineDay == "0" && $renewalDeadlineMonth == "0") && 
        eval($currentDate.after(getDate(2, $dayOfMonth, $month + 1))) && 
        eval($currentDate.before(getDate(1, $dayOfMonth, $month + 1 ))) &&
        eval(getWeekOfYear($localDate.toString()) == getWeekOfYear($emailDate.toString()))
     ) ||
    (
        eval($currentDate.after(getDate(2, $intRenewalDeadlineDay, $intRenewalDeadlineMonth))) &&
        eval($currentDate.before(getDate(1, $intRenewalDeadlineDay, $intRenewalDeadlineMonth))) &&
        eval(getWeekOfYear($localDate.toString()) == getWeekOfYear($emailDate.toString())) 
    )
then
    System.out.println("Rule For 60 Days Called");      
    processData(licenseCredential, learnerCsvFileWriter, $expiryDate, $emailDate);
end

我想在循环中声明局部变量。 LicenseCredential 基本上是一个列表。当我运行此规则时,我收到错误

 text=Unable to resolve ObjectType 'licenseCredential.getCourseCompletionDate'], Message [id=2, level=ERROR, path=drools/rules/Rule.drl, line=71, column=0
   text=Unable to resolve ObjectType 'licenseCredential.getRenewalDeadlineDay'], Message [id=3, level=ERROR, path=drools/rules/Rule.drl, line=72, column=0
   text=Unable to resolve ObjectType 'licenseCredential.getRenewalDeadlineMonth'], Message [id=4, level=ERROR, path=drools/rules/Rule.drl, line=73, column=0
   text=Unable to resolve ObjectType 'getCurrentDate'], Message [id=5, level=ERROR, path=drools/rules/Rule.drl, line=74, column=0
   text=Unable to resolve ObjectType '$courseCompletionDate.getDate'], Message [id=6, level=ERROR, path=drools/rules/Rule.drl, line=75, column=0
   text=Unable to resolve ObjectType '$courseCompletionDate.getMonth'], Message [id=7, level=ERROR, path=drools/rules/Rule.drl, line=76, column=0
   text=Unable to resolve ObjectType 'getExpiryDate'], Message [id=8, level=ERROR, path=drools/rules/Rule.drl, line=77, column=0
   text=Unable to resolve ObjectType 'getEmailDate'], Message [id=9, level=ERROR, path=drools/rules/Rule.drl, line=78, column=0
   text=Unable to resolve ObjectType 'LocalDate.now'], Message [id=10, level=ERROR, path=drools/rules/Rule.drl, line=79, column=0
   text=Unable to resolve ObjectType 'Integer.valueOf'], Message [id=11, level=ERROR, path=drools/rules/Rule.drl, line=80, column=0
   text=Unable to resolve ObjectType 'Integer.valueOf'], Message [id=12, level=ERROR, path=drools/rules/Rule.drl, line=36, column=0

如果我在每个变量的末尾加上分号,例如

$courseCompletionDate : licenseCredential.getCourseCompletionDate();
    $renewalDeadlineDay : licenseCredential.getRenewalDeadlineDay();
    $renewalDeadlineMonth : licenseCredential.getRenewalDeadlineMonth();
    $currentDate : getCurrentDate();
    $dayOfMonth : $courseCompletionDate.getDate();
    $month : $courseCompletionDate.getMonth();
    $expiryDate : getExpiryDate(licenseCredential);
    $emailDate : getEmailDate(2, licenseCredential);
    $localDate : LocalDate.now();
    $intRenewalDeadlineDay : Integer.valueOf($renewalDeadlineDay);
    $intRenewalDeadlineMonth : Integer.valueOf($renewalDeadlineMonth);

并运行规则,我收到错误

$renewalDeadlineDay cannot be resolved to a variable
$renewalDeadlineMonth cannot be resolved to a variable
$currentDate cannot be resolved
$dayOfMonth cannot be resolved to a variable
$month cannot be resolved to a variable
$currentDate cannot be resolved
$dayOfMonth cannot be resolved to a variable
$month cannot be resolved to a variable
$localDate cannot be resolved
$emailDate cannot be resolved
$currentDate cannot be resolved
$intRenewalDeadlineDay cannot be resolved to a variable
$intRenewalDeadlineMonth cannot be resolved to a variable
$currentDate cannot be resolved
$intRenewalDeadlineDay cannot be resolved to a variable
$intRenewalDeadlineMonth cannot be resolved to a variable
$localDate cannot be resolved
$emailDate cannot be resolved
$expiryDate cannot be resolved to a variable
$emailDate cannot be resolved to a variable], Message [id=14, level=ERROR, path=drools/rules/Rule.drl, line=-1, column=0

如何定义局部变量。我该如何做到这一点?

谢谢

<强>-------------------------------- 编辑

这是我如何触发规则

List<LicenseCredential> objectList = dao.select();
BusinessRuleProcessor ruleProcessor = (BusinessRuleProcessor)context.getBean("businessRuleProcessor");
ruleProcessor.configureAndApplyRulesOnObject(objectList);

public class BusinessRuleProcessor {
    ....
    public void configureAndApplyRulesOnObject(List<LicenseCredential> objectList){

        statelessKieSession.setGlobal("learnerCsvFileWriter", csvFileWriter);
        statelessKieSession.execute(objectList);

    }
}

<强>-------------- 编辑2:

尝试了这个并收到错误

rule "Renewal alert for 60 days"
when
    licenseCredential : LicenseCredential()

    $licenseCredentialCC : LicenseCredential($courseCompletionDate : courseCompletionDate)
    $licenseCredentialRDLD : LicenseCredential($renewalDeadlineDay : renewalDeadlineDay)
    $licenseCredentialRDLM : LicenseCredential($renewalDeadlineMonth : renewalDeadlineMonth)
    $licenseCredentialCD : LicenseCredential($currentDate : getCurrentDate())
    $licenseCredentialDOM : LicenseCredential($dayOfMonth : $licenseCredentialCC.getDate())
    $licenseCredentialM : LicenseCredential($month : $licenseCredentialCC.getMonth())
    $licenseCredentialEXD : LicenseCredential($expiryDate : getExpiryDate(licenseCredential))
    $licenseCredentialEMD : LicenseCredential($emailDate : getEmailDate(2, licenseCredential))
    $licenseCredentialLD : LicenseCredential($localDate : LocalDate.now())
    $licenseCredentialIRDLD : LicenseCredential($intRenewalDeadlineDay :  Integer.valueOf($licenseCredentialRDLD))
    $licenseCredentialIRDLM : LicenseCredential($intRenewalDeadlineMonth : Integer.valueOf($licenseCredentialRDLM))

    (
        eval($renewalDeadlineDay == "0" && $renewalDeadlineMonth == "0") && 
        eval($currentDate.after(getDate(2, $dayOfMonth, $month + 1))) && 
        eval($currentDate.before(getDate(1, $dayOfMonth, $month + 1 ))) &&
        eval(getWeekOfYear($localDate.toString()) == getWeekOfYear($emailDate.toString()))
     ) ||
    (
        eval($currentDate.after(getDate(2, $intRenewalDeadlineDay, $intRenewalDeadlineMonth))) &&
        eval($currentDate.before(getDate(1, $intRenewalDeadlineDay, $intRenewalDeadlineMonth))) &&
        eval(getWeekOfYear($localDate.toString()) == getWeekOfYear($emailDate.toString())) 
    )
then
    System.out.println("Rule For 60 Days Called");      
    processData(licenseCredential, learnerCsvFileWriter, $expiryDate, $emailDate);
end

错误:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'autoalert-ksession-stateless': Cannot resolve reference to bean 'autoalert-kbase' while setting bean property 'kBase'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'autoalert-kbase': Invocation of init method failed; nested exception is java.lang.RuntimeException: Error while creating KieBase[Message [id=1, level=ERROR, path=drools/rules/Rule.drl, line=76, column=0
   text=Unable to Analyse Expression $licenseCredentialCC.getDate():
[Error: unable to resolve method using strict-mode: com.softech.vu360.autoalert.model.LicenseCredential.getDate()]
[Near : {... $licenseCredentialCC.getDate() ....}]
                              ^
[Line: 76, Column: 2]], Message [id=2, level=ERROR, path=drools/rules/Rule.drl, line=76, column=0
   text=Unable to analyze expression '$licenseCredentialCC.getDate()'], Message [id=3, level=ERROR, path=drools/rules/Rule.drl, line=77, column=0
   text=Unable to Analyse Expression $licenseCredentialCC.getMonth():
[Error: unable to resolve method using strict-mode: com.softech.vu360.autoalert.model.LicenseCredential.getMonth()]
[Near : {... $licenseCredentialCC.getMonth() ....}]
                              ^
[Line: 77, Column: 2]], Message [id=4, level=ERROR, path=drools/rules/Rule.drl, line=77, column=0
   text=Unable to analyze expression '$licenseCredentialCC.getMonth()'], Message [id=5, level=ERROR, path=drools/rules/Rule.drl, line=78, column=0
   text=Variables can not be used inside bindings. Variable   [licenseCredential] is being used in binding 'getExpiryDate(licenseCredential)'], Message [id=6, level=ERROR, path=drools/rules/Rule.drl, line=79, column=0
   text=Variables can not be used inside bindings. Variable [licenseCredential] is being used in binding 'getEmailDate(2, licenseCredential)'], Message [id=7, level=ERROR, path=drools/rules/Rule.drl, line=81, column=0
   text=Unable to Analyse Expression Integer.valueOf($licenseCredentialRDLD):
[Error: unable to resolve method using strict-mode: java.lang.Integer.valueOf(com.softech.vu360.autoalert.model.LicenseCredential)]
[Near : {... Integer.valueOf($licenseCredentialRDLD ....}]
                 ^
[Line: 81, Column: 2]], Message [id=8, level=ERROR, path=drools/rules/Rule.drl, line=81, column=0
   text=Unable to analyze expression 'Integer.valueOf($licenseCredentialRDLD)'], Message [id=9, level=ERROR, path=drools/rules/Rule.drl, line=82, column=0
   text=Unable to Analyse Expression Integer.valueOf($licenseCredentialRDLM):
    [Error: unable to resolve method using strict-mode: java.lang.Integer.valueOf(com.softech.vu360.autoalert.model.LicenseCredential)]
    [Near : {... Integer.valueOf($licenseCredentialRDLM ....}]
                 ^
    [Line: 82, Column: 2]], Message [id=10, level=ERROR, path=drools/rules/Rule.drl, line=82, column=0
   text=Unable to analyze expression 'Integer.valueOf($licenseCredentialRDLM)'], Message [id=11, level=ERROR, path=drools/rules/Rule.drl, line=60, column=0
   text=[ function processDataprocessData (line:60): learnerCsvFileWriter cannot be resolved
 ]],     Message [id=12, level=ERROR, path=drools/rules/Rule.drl, line=68, column=0
       text=Rule Compilation error The import drools.rules.ProcessData cannot be resolved
The operator + is undefined for the argument type(s) Object, int
The operator + is undefined for the argument type(s) Object, int
The method getDate(int, int, int) in the type Utility is not applicable for the arguments (int, Object, Object)
The method getDate(int, int, int) in the type Utility is not applicable for the arguments (int, Object, Object)
$expiryDate cannot be resolved to a variable
$emailDate cannot be resolved to a variable], Message [id=13, level=ERROR, path=drools/rules/Rule.drl, line=-1, column=0

编辑3

rule "Renewal alert for 60 days"
when
    licenseCredential : LicenseCredential()

    $licenseCredential1 : LicenseCredential($courseCompletionDate : courseCompletionDate)
    $licenseCredential2 : LicenseCredential($renewalDeadlineDay : renewalDeadlineDay)
    $licenseCredential3 : LicenseCredential($renewalDeadlineMonth : renewalDeadlineMonth)
    $licenseCredential4 : LicenseCredential($currentDate : getCurrentDate())
    //$licenseCredential5 : LicenseCredential($dayOfMonth : licenseCredential.getCourseCompletionDate().getDate())
    //$licenseCredential6 : LicenseCredential($month : licenseCredential.getCourseCompletionDate().getMonth())
    //$licenseCredential7 : LicenseCredential($expiryDate : getExpiryDate(licenseCredential))
    //$licenseCredential8 : LicenseCredential($emailDate : getEmailDate(2, licenseCredential))
    $licenseCredential9 : LicenseCredential($localDate : LocalDate.now())

    (
        eval($renewalDeadlineDay == "0" && $renewalDeadlineMonth == "0") && 
        eval($currentDate.after(getDate(2, licenseCredential.getCourseCompletionDate().getDate(), licenseCredential.getCourseCompletionDate().getMonth() + 1))) && 
        eval($currentDate.before(getDate(1, licenseCredential.getCourseCompletionDate().getDate(), licenseCredential.getCourseCompletionDate().getMonth() + 1 ))) &&
        eval(getWeekOfYear($localDate.toString()) == getWeekOfYear(getEmailDate(2, licenseCredential).toString()))
     ) ||
    (
        eval($currentDate.after(getDate(2, Integer.valueOf($renewalDeadlineDay), Integer.valueOf($renewalDeadlineMonth)))) &&
        eval($currentDate.before(getDate(1, Integer.valueOf($renewalDeadlineDay), Integer.valueOf($renewalDeadlineMonth)))) &&
        eval(getWeekOfYear($localDate.toString()) == getWeekOfYear(getEmailDate(2, licenseCredential).toString())) 
    )

then
    System.out.println("Rule For 60 Days Called");      
    processData(licenseCredential, learnerCsvFileWriter, 2);
end

<强>------------------ 编辑4

这是我的 LicenseCredential 类

public class LicenseCredential {
    private String learnerName;
    protected String firstName;
    protected String lastName;
    protected String learnerEmailAddress;
    private String userGUID;
    private Integer vu360UserId;
    private Integer courseId;
    protected String courseName;
    protected Date courseCompletionDate;
    private Integer credentialId;
    protected String officialLicenseName;
    private String shortLicenseName;
    private String renewalDeadLineType;
    private String renewalFrequency;
    private String renewalDeadlineDay;
    private String renewalDeadlineMonth; 
    private String hardDeadLineYear;
    private String staggeredBy;
    private String staggeredTo;
    protected String jurisdiction;
    protected String storefrontURL;

    //  setters and getters
}

这是我的实用程序类

public class Utility {
    public static Date getDate(int monthsToBeSubtracted, int date, int month) throws Exception{
        Calendar c = Calendar.getInstance();        
        c.set(Calendar.MONTH, month-1);
        c.set(Calendar.DATE, date);
        c.set(Calendar.MONTH, c.get(Calendar.MONTH)-monthsToBeSubtracted);
        c.set(Calendar.YEAR, getCurrentDate().getYear()+1900);
        return c.getTime();
    }

    public static Date getCurrentDate(){
        Calendar c = Calendar.getInstance();
        return c.getTime();
    }

    public static int getWeekOfYear(String date) throws Exception{
        Date currentDate = new SimpleDateFormat("yyyy-MM-dd").parse(date);
        String weekOfYear = new SimpleDateFormat("w").format(currentDate);
        return Integer.valueOf(weekOfYear);
    }    

    public static LocalDate getExpiryDate(LicenseCredential licenseCredential) {

        if (licenseCredential.getRenewalDeadlineDay() == "0" && licenseCredential.getRenewalDeadlineMonth() == "0") {
            Date courseCompletionDate = licenseCredential.getCourseCompletionDate();
            ...
            return expiryDate;
        } else {
            ...
            return expiryDate;
        }

    }
}

以前这个规则是这样的

rule "Renewal alert for 60 days"
when
    licenseCredential : LicenseCredential()
    (
        eval(licenseCredential.getRenewalDeadlineDay() == "0" && licenseCredential.getRenewalDeadlineMonth() == "0") && 
        eval(getCurrentDate().after(getDate(2, licenseCredential.getCourseCompletionDate().getDate(), licenseCredential.getCourseCompletionDate().getMonth()+1))) && 
        eval(getCurrentDate().before(getDate(1, licenseCredential.getCourseCompletionDate().getDate(), licenseCredential.getCourseCompletionDate().getMonth()+1))) 
     ) ||
    (
        eval(getCurrentDate().after(getDate(2, Integer.valueOf(licenseCredential.getRenewalDeadlineDay()), Integer.valueOf(licenseCredential.getRenewalDeadlineMonth()) ))) &&
        eval(getCurrentDate().before(getDate(1, Integer.valueOf(licenseCredential.getRenewalDeadlineDay()), Integer.valueOf(licenseCredential.getRenewalDeadlineMonth() )))) 
    )
then
    System.out.println("Rule For 60 Days Called");      
    processData(licenseCredential, "templates/Template.vm", "60Days", messageProducer);
end

最佳答案

虽然我不知道规则应该评估什么,但这更像是您的规则应该编写的样式。我不知道 LicenseCredential 是如何声明的,也不知道那些 Util.getXyz 函数,所以这可能不起作用。另外,我跳过了最后一个条件。

rule "Renewal alert for 60 days"
when
licenseCredential : LicenseCredential(
      $courseCompletionDate : courseCompletionDate,
      $renewalDeadlineDay : renewalDeadlineDay == "0",
      $renewalDeadlineMonth : renewalDeadlineMonth == "0",
      $currentDate : currentDate after 
              getDate(2, $courseCompletionDate.getDate(),
                         $courseCompletionDate.getMonth()+1 ),
              && before
              getDate(1, $courseCompletionDate.getDate(),
                         $courseCompletionDate.getMonth()+1 ) )
then
    System.out.println("Rule For 60 Days Called");      
    processData(licenseCredential, learnerCsvFileWriter, 2);
end

关于java-8 - 如何在 drools 规则中定义和初始化变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28879563/

相关文章:

java - Drools 专家 + Spring MVC

java - 将多个同一类的java对象插入到java中的drools中

包上的 Drools DRL 文件无法读取

java - 在 Collection<A> 中获取 max(A.x) 的最简洁方法

java - Eclipse:类型推断期间为 "Unknown error"

java - 在java中迭代2个列表

tomcat - "java.lang.RuntimeException: Cannot find KieModule"在使用 Tomcat 设置 Drool 中

java-8 - Java 8 流和 RxJava 可观察量之间的区别

java - 在 Java 8 中限制 groupBy

Java : Spark iterate through custom objects