第 18 章 在 Business Central 中创建 DRL 规则

您可以在 Business Central 中为您的项目创建和管理 DRL 规则。在每个 DRL 规则文件中,您可以根据您在软件包中创建的或导入的数据对象定义规则条件、操作和其他与该规则相关的组件。

流程

  1. 在 Business Central 中,前往 MenuDesignProjects 并点项目名称。
  2. Add AssetDRL 文件
  3. 输入信息式 DRL 文件名 并选择相应的 软件包。您指定的软件包必须是分配或将被分配所需数据对象的同一软件包。

    如果项目中已定义了任何域特定语言( DSL)资产,您也可以选择 Show 声明 DSL 句子。这些 DSL 资产将作为在 DRL 设计器中定义的条件和操作可以使用的对象。

  4. Ok 创建规则资产。

    新的 DRL 文件现已列在 Project ExplorerDRL 面板中,如果您选择了 Show 声明 DSL 句子选项,则在 DSL R 面板中列出。分配此 DRL 文件的软件包列在文件的顶部。

  5. 在 DRL 设计器左侧面板中的 fact 类型 列表中,确认您的规则需要的所有数据对象和数据对象字段(每个)。如果没有,您可以使用 DRL 文件中的 import 语句从其他软件包中导入相关数据对象,或者在您的软件包中创建 数据对象
  6. 在所有数据对象都就位后,返回到 DRL 设计器的 Model 选项卡,并使用以下任何组件定义 DRL 文件:

    DRL 文件中的组件

    package
    
    import
    
    function  // Optional
    
    query  // Optional
    
    declare   // Optional
    
    global   // Optional
    
    rule "rule name"
        // Attributes
        when
            // Conditions
        then
            // Actions
    end
    
    rule "rule2 name"
    
    ...

    • 软件包:(automatic)会在创建 DRL 文件并选择软件包时为您定义。
    • 导入 :使用它来识别来自此软件包或要在 DRL 文件中要使用的其他软件包的数据对象。以 packageName.objectName 格式指定软件包和数据对象,并在单独的行中指定多个导入。

      导入数据对象

      import org.mortgages.LoanApplication;

    • 功能 :(可选)使用它在 DRL 文件中包含规则使用的功能。DRL 文件中的功能将语义代码放在规则源文件中,而不是在 Java 类中。如果规则中的某个部分被重复使用并且每个规则的参数不同,则功能特别有用。在 DRL 文件中的规则上方,您可以声明函数或导入帮助程序类的静态方法作为功能,然后在规则的操作( then )部分中按名称使用函数(then)。

      使用规则(选项 1)声明并使用函数.

      function String hello(String applicantName) {
          return "Hello " + applicantName + "!";
      }
      
      rule "Using a function"
        when
          // Empty
        then
          System.out.println( hello( "James" ) );
      end

      通过规则导入并使用函数(选项 2)

      import function my.package.applicant.hello;
      
      rule "Using a function"
        when
          // Empty
        then
          System.out.println( hello( "James" ) );
      end

    • query:(可选)使用此命令搜索与 DRL 文件中规则相关的事实。您可以在 DRL 文件中添加查询定义,然后获取应用程序代码的匹配结果。查询搜索一组定义的条件,且不需要在或 随后 指定规格时使用。查询名称对于 KIE 基础是全局的,因此,在项目中的所有规则查询中必须是唯一的。要返回查询的结果,请使用 ksession.get QueryResults ("name") 构造传统的 QueryResults 定义,其中 "name" 是查询名称。这会返回一个查询结果列表,允许您检索与查询匹配的对象。在 DRL 文件中定义规则之上的查询和查询结果参数。

      DRL 文件中的查询定义示例

      query "people under the age of 21"
          $person : Person( age < 21 )
      end

      获取查询结果的应用程序代码示例

      QueryResults results = ksession.getQueryResults( "people under the age of 21" );
      System.out.println( "we have " + results.size() + " people under the age  of 21" );

    • 声明:(可选)使用它声明由 DRL 文件中的规则使用的新事实类型。Red Hat Process Automation Manager 的 java.lang 包中的默认事实类型是 对象,但您可以根据需要声明 DRL 文件中的其他类型。在 DRL 文件中声明事实类型可让您直接在决策引擎中定义新的事实模型,而无需在 Java 等低级别语言中创建模型。

      声明并使用新的事实类型

      declare Person
        name : String
        dateOfBirth : java.util.Date
        address : Address
      end
      
      rule "Using a declared type"
        when
          $p : Person( name == "James" )
        then   // Insert Mark, who is a customer of James.
          Person mark = new Person();
          mark.setName( "Mark" );
          insert( mark );
      end

    • global: (可选)使用它在 DRL 文件中包括规则要使用的全局变量。全局变量通常提供规则的数据或服务,如规则结果中使用的应用程序服务,并从规则返回数据,如规则中添加的日志或值。通过 KIE 会话配置或 REST 操作在决策引擎的工作内存中设置全局值,声明 DRL 文件中的规则以外的全局变量,然后在规则的操作(然后)部分使用。对于多个全局变量,请在 DRL 文件中使用单独的行。

      为决策引擎设置全局列表配置

      List<String> list = new ArrayList<>();
      KieSession kieSession = kiebase.newKieSession();
      kieSession.setGlobal( "myGlobalList", list );

      在规则中定义全局列表

      global java.util.List myGlobalList;
      
      rule "Using a global"
        when
          // Empty
        then
          myGlobalList.add( "My global list" );
      end

      警告

      不要使用全局变量在规则中建立条件,除非全局变量具有恒定的不可变值。全局变量不会插入到决策引擎的工作内存中,因此决策引擎无法跟踪变量的值更改。

      不要使用全局变量在规则间共享数据。规则始终原因并响应正常工作的内存状态。因此,如果要将数据从规则传递给规则,请向决策引擎的工作内存中断言数据。

    • 规则 :使用这个方法在 DRL 文件中定义每个规则。规则包含格式规则 "name" 的规则,后跟定义规则行为的可选属性(如 salienceno-loop),后面是 whenthen 定义。每个规则必须在规则软件包中具有唯一的名称。规则的 when 部分包含必须符合执行操作的条件。例如,如果银行需要 loan applicants 已有 21 余年,则 "Underage" 规则的 when 条件将是适用的 (age < 21)。规则的 then 部分包含满足规则条件部分时要执行的操作。例如,当 loan applicant 旧有 21 年时,然后 操作将被 设置( false ),因为申请者处于年龄之内。

      loan Application age 限值的规则

      rule "Underage"
        salience 15
        when
          $application : LoanApplication()
          Applicant( age < 21 )
        then
          $application.setApproved( false );
          $application.setExplanation( "Underage" );
      end

      每个 DRL 文件必须至少指定 软件包、导入、导入 和规则 组件。所有其他组件都是可选的。

      以下是 loan 应用程序决策服务中的 DRL 文件示例:

      loan application 的 DRL 文件示例

      package org.mortgages;
      
      import org.mortgages.LoanApplication;
      import org.mortgages.Bankruptcy;
      import org.mortgages.Applicant;
      
      rule "Bankruptcy history"
      	salience 10
      	when
      		$a : LoanApplication()
      		exists (Bankruptcy( yearOfOccurrence > 1990 || amountOwed > 10000 ))
      	then
      		$a.setApproved( false );
      		$a.setExplanation( "has been bankrupt" );
      		delete( $a );
      end
      
      rule "Underage"
      	salience 15
      	when
      		$application : LoanApplication()
      		Applicant( age < 21 )
      	then
      		$application.setApproved( false );
      		$application.setExplanation( "Underage" );
      		delete( $application );
      end

      图 18.1. Business Central 中 loan application 的 DRL 文件示例

      带有所需组件的 DRL 文件示例
  7. 在定义了规则的所有组件后,在 DRL 设计器右上角点击 Validate 来验证 DRL 文件。如果文件验证失败,解决错误消息中描述的任何问题,查看 DRL 文件中的所有语法和组件,并尝试验证文件,直到文件通过为止。
  8. 点 DRL 设计器中的 Save 保存您的更改。

18.1. 在 DRL 规则中添加 WHEN 条件

规则的 when 部分包含必须符合执行操作的条件。例如,如果银行需要 loan applicants 已有 21 余年,那么 "Underage" 规则的 when 条件将是适用的 (年龄 < 21 )。条件由一系列指定模式和约束组成,具有可选的绑定和其他支持的 DRL 元素,它们基于软件包中的可用数据对象。

先决条件

  • 软件包在 DRL 文件的顶部定义。在创建该文件时,应该已为您完成这一操作。
  • 规则中使用的数据对象 导入 列表在 DRL 文件的 package 行中定义。数据对象可从这个软件包,或者从 Business Central 中的其他软件包中获取。
  • 规则 名称在 软件包 下面以 "name" 的格式定义,导入,以及应用到整个 DRL 文件的其他行。同一软件包中不能多次使用相同的规则名称。可选的规则属性(如 sali ence 或 no-loop)在 when 部分前定义规则名称下。

流程

  1. 在 DRL 设计程序中,在规则中输入以开始添加条件语句。when 部分包含零个或更多事实模式,它们为规则定义条件。

    如果 when 部分为空,则条件被视为 true,在决策引擎中第一次执行 fireAllRules() 调用。如果要使用规则设置决策引擎状态,这很有用。

    没有条件的规则示例

    rule "Always insert applicant"
      when
        // Empty
      then   // Actions to be executed once
        insert( new Applicant() );
    end
    
    // The rule is internally rewritten in the following way:
    
    rule "Always insert applicant"
      when
        eval( true )
      then
        insert( new Applicant() );
    end

  2. 输入第一个条件的模式,带有可选的限制、绑定和其他支持的 DRL 元素。基本模式格式为 < patternBinding> : <patternType>(<constraints>)。模式基于软件包中的可用数据对象,并定义要在 then 部分中触发操作的条件。

    • 简单模式: 没有约束的简单模式与给定类型的事实匹配。例如,以下条件仅存在 applicant。

      when
        Applicant()
    • 具有限制的模式: 具有约束的模式与给定类型的事实匹配,以及以括号括起的额外限制。例如,以下条件是 applicant 为 21 的年龄。

      when
        Applicant( age < 21 )
    • 带有绑定模式: 模式的绑定是规则的其他组件可以使用的简写引用来引用定义的模式。例如,以下绑定到 LoanApplication 的相关操作适用于age applicants。

      when
        $a : LoanApplication()
        Applicant( age < 21 )
      then
        $a.setApproved( false );
        $a.setExplanation( "Underage" )
  3. 继续定义适用于此规则的所有条件模式。以下是定义 DRL 条件的一些关键字选项:

    • :使用这个条件组件将条件组件分组到逻辑中。支持在fix 前缀中。默认情况下,所有列出的模式都与 和 结合使用,并且 未指定任何组合。

      // All of the following examples are interpreted the same way:
      $a : LoanApplication() and Applicant( age < 21 )
      
      $a : LoanApplication()
      and Applicant( age < 21 )
      
      $a : LoanApplication()
      Applicant( age < 21 )
      
      (and $a : LoanApplication() Applicant( age < 21 ))
    • :使用这个条件组件将条件组件分组到逻辑不满中。支持在修复和 前缀或 支持中。

      // All of the following examples are interpreted the same way:
      Bankruptcy( amountOwed == 100000 ) or IncomeSource( amount == 20000 )
      
      Bankruptcy( amountOwed == 100000 )
      or IncomeSource( amount == 20000 )
      
      (or Bankruptcy( amountOwed == 100000 ) IncomeSource( amount == 20000 ))
    • 存在 :使用它来指定必须存在的事实和约束。这个选项仅在第一个匹配项中触发,而不是后续匹配项。如果您将这个元素与多个模式搭配使用,请将模式与括号 () 括起。

      exists ( Bankruptcy( yearOfOccurrence > 1990 || amountOwed > 10000 ) )
    • Not :使用它来指定必须不存在的事实和约束。

      not ( Applicant( age < 21 ) )
    • all :使用这个方法验证所有与第一个模式匹配的事实是否与所有剩余的模式匹配。当 满足总 结构时,该规则将评估为 true

      forall( $app : Applicant( age < 21 )
                    Applicant( this == $app, status = 'underage' ) )
    • :使用这个方法为模式指定数据源。

      Applicant( ApplicantAddress : address )
      Address( zipcode == "23920W" ) from ApplicantAddress
    • 入口点 :使用此定义与模式匹配的 Entry Point。通常与 一同使用。

      Applicant() from entry-point "LoanApplication"
    • collect :使用它来定义规则可用作条件的一部分的对象集合。在示例中,每个给定影片的决定引擎中所有待处理的应用程序都分组到 列表中。如果找到三个或更多待处理的应用程序,则会执行该规则。

      $m : Mortgage()
      $a : List( size >= 3 )
          from collect( LoanApplication( Mortgage == $m, status == 'pending' ) )
    • accumulate :使用它迭代对象集合,为每个元素执行自定义操作,并返回一个或多个结果对象(如果限制评估为 true)。这个选项是更灵活且强大的 收集 形式。使用 accumulate (<source pattern>; <functions> [;<constraints>])。在示例中,minmaxaverage 是积累的功能,它计算每个传感器的所有读取的最小、最大值和平均温度值。其他支持的功能包括 countsum、lari ance、StandardDev iation、collectListcollectSet

      $s : Sensor()
      accumulate( Reading( sensor == $s, $temp : temperature );
                  $min : min( $temp ),
                  $max : max( $temp ),
                  $avg : average( $temp );
                  $min < 20, $avg > 70 )
    注意

    有关 DRL 规则状况的更多信息,请参阅 第 16.8 节 “DRL 中的规则条件(WHEN)”

  4. 在定义了规则的所有条件组件后,在 DRL 设计器右上角点击 Validate 来验证 DRL 文件。如果文件验证失败,解决错误消息中描述的任何问题,查看 DRL 文件中的所有语法和组件,并尝试验证文件,直到文件通过为止。
  5. 点 DRL 设计器中的 Save 保存您的更改。