第4章 Business Central における DRL ルールの作成

Business Central で、プロジェクトに対して DRL ルールを作成して管理できます。パッケージに作成またはインポートするデータオブジェクトに基づいて、各 DRL ファイルで、ルールの条件、アクション、そしてルールに関連するその他のコンポーネントを定義します。

手順

  1. Business Central で、MenuDesignProjects に移動して、プロジェクト名をクリックします。
  2. Add AssetDRL file をクリックします。
  3. 参考となる DRL ファイル 名を入力し、適切な パッケージ を選択します。指定するパッケージは、必要なデータオブジェクトが割り当てられているか、またはこれから割り当てるパッケージにする必要があります。

    ドメイン固有言語 (DSL) アセットがプロジェクトに定義されている場合は、Show declared DSL sentences を選択することもできます。これらの DSL アセットは、DRL デザイナーで定義する条件およびアクションに使用できるオブジェクトです。

  4. OK をクリックして、ルールアセットを作成します。

    新しい DRL ファイルが、Project ExplorerDRL パネルに追加されます。Show declared DSL sentences オプションを選択した場合は、DSLR パネルに追加されます。この DRL ファイルを割り当てたパッケージは、ファイルの上部にリストされます。

  5. DRL デザイナーの左パネルの Fact types リストで、ルールに必要なすべてのデータオブジェクトとデータオブジェクトフィールドがリストされていることを確認します (それぞれを展開します)。リストされていない場合は、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"
    
    ...

    • package: (自動) これは、DRL ファイルを作成し、パッケージを選択すると定義されます。
    • import: このパッケージ、または DRL ファイルで使用する別のパッケージのデータオブジェクトを指定します。パッケージとデータオブジェクトは packageName.objectName の形式で指定し、複数のインポートは別々の行に指定します。

      データオブジェクトのインポート

      import org.mortgages.LoanApplication;

    • function: (任意) DRL ファイルのルールが使用する関数を指定します。DRL ファイルの関数は、Java クラスにではなくルールのソースファイルにセマンティックコードを追加します。関数は、特に、ルールのアクション (then) 部分が繰り返し使用され、パラメーターだけがルールごとに異なる場合に便利です。DRL ファイルのルールで、関数を宣言したり、静的メソッドを関数としてインポートしたりして、ルールの アクション (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 ファイルにクエリー定義を追加してから、アプリケーションコードで合致する結果を取得します。クエリーは、定義した条件セットを検索するため、when または then を指定する必要はありません。クエリー名は KIE ベースでグローバルとなるため、プロジェクトにあるその他のすべてのルールクエリーと重複しないようにする必要があります。クエリーの結果に戻るには、ksession.getQueryResults("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" );

    • declare: (任意) DRL ファイルのルールが使用する新しいファクトタイプを宣言します。Red Hat Process Automation Manager の java.lang パッケージのデフォルトは Object ですが、必要に応じて 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 ファイルのルールの上にグローバル変数を宣言してから、これをルールのアクション部分 (then) で使用します。グローバル変数が複数ある場合には、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

      警告

      グローバル変数に定数イミュータブル値がない場合には、ルールの条件設定にグローバル変数を使用しないでください。グローバル変数はデシジョンエンジンのワーキングメモリーに挿入されないため、デシジョンエンジンでは変数の値の変更を追跡できません。

      グローバル変数を使用してルール間でデータを共有しないでください。ルールは常に、ワーキングメモリーの状態に関して推論し、これに対応するので、ルールからルールにデータを渡す必要がある場合には、データをファクトとしてデシジョンエンジンのワーキングメモリーにアサートしてください。

    • rule: DRL ファイルで各ルールを定義します。ルールは、rule "name" 形式のルール名に、ルールの動作 (salienceno-loop など) を定義する任意の属性、when および then 定義が続きます。ルールのパッケージ内の各ルールには一意の名前が必要です。ルールの when 部分には、アクションを実行するために満たす必要のある条件が含まれます。たとえば、銀行が、ローンの申し込みを 21 歳以上に限定した場合、"Underage" ルールの when 条件は Applicant( age < 21 ) になります。ルールの then 部分には、ルールの条件部分が満たされる場合に実行するアクションが含まれます。たとえば、ローンの申請者が 21 歳に満たない場合、then アクションは setApproved( false ) になり、申込者が年齢条件を満たしていないためにローンの申し込みは承認されません。

      申込者の年齢制限に関するルール

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

      少なくても、各 DRL ファイルは package コンポーネント、import コンポーネント、rule コンポーネントを指定する必要があります。他のすべてのコンポーネントは任意です。

      以下は、ローン申し込みのデシジョンサービスの DRL ファイルの例です。

      ローン申し込みの 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

      図4.1 Business Central のロール申し込み用の DRL ファイルの例

      Example DRL file with required components
  7. ルールのすべてのコンポーネントを定義したら、DRL デザイナーの右上ツールバーで Validate をクリックし、DRL ファイルを検証します。検証に失敗したら、エラーメッセージに記載された問題に対応し、DRL ファイルの構文およびコンポーネントをすべて見直し、エラーが表示されなくなるまでファイルを検証します。
  8. DRL デザイナーで Save をクリックして、設定した内容を保存します。

4.1. DRL ルールへの WHEN 条件の追加

ルールの when 部分には、アクションを実行するのに必要な条件が含まれます。たとえば、銀行のローン申し込みに年齢制限 (21 歳以上) を満たす必要がある場合、"Underage" ルールの when 条件は Applicant( age < 21 ) となります。条件は、パッケージで利用可能なデータオブジェクトに基づいて、指定した一連のパターンおよび制約と、任意のバインディングその他のサポートされる DRL 要素で構成されます。

前提条件

  • package は DRL ファイルに上部に定義されます。これはファイルの作成時に実行されているはずです。
  • ルールで使用したデータオブジェクトの import リストが、DRL ファイルの package 行の下に定義されます。データオブジェクトは、このパッケージか、または別の Business Central のパッケージから使用できます。
  • rule 名は、packageimport、または DRL ファイル全体に適用されるその他の行の下に rule "name" という形式で定義されます。同じパッケージでルール名を重複させることはできません。ルールの動作を定義する任意のルール属性 (salienceno-loop など) は、ルール名の下の when セクションの前に定義します。

手順

  1. DRL デザイナーで、ルールに when を入力して、条件ステートメントを追加します。when セクションは、ルールの条件を定義するファクトパターンで構成されますが、ファクトパターンが 1 つも追加されない場合もあります。

    when セクションを空にすると、条件は true であると見なされ、デシジョンエンジンで fireAllRules() 呼び出しが最初に実施された場合に、then セクションのアクションが実行されます。これは、デシジョンエンジンの状態を設定するルールを使用する場合に便利です。

    条件のないルール例

    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 セクションのアクションを発生させるのに必要な条件を定義します。

    • 単純なパターン: 制約のない単純なパターンは、指定したタイプのファクトに一致します。たとえば、次は、申込者が存在することだけが条件になります。

      when
        Applicant()
    • 制約のあるパターン: 制約を持つパターンは、指定したタイプのファクトと、追加制限を括弧で指定したパターン (true または false) に一致します。たとえば、次は、申込者が 21 歳に満たないことを条件としています。

      when
        Applicant( age < 21 )
    • バインディングのあるパターン: パターンのバインディングは簡単な参照となり、ルールのその他のコンポーネントが、定義したバターンに戻って参照します。たとえば、次の例では、LoanApplication のバインディング a が、underage の申込者に関連するアクションとして使用されます。

      when
        $a : LoanApplication()
        Applicant( age < 21 )
      then
        $a.setApproved( false );
        $a.setExplanation( "Underage" )
  3. このルールに適用するすべての条件パターンの定義を継続します。以下は、DRL 条件を定義するいくつかのキーワードオプションです。

    • and: 条件コンポーネントを論理積に分類します。接中辞および接頭辞の and がサポートされます。デフォルトでは、結合演算子を指定しないと、リストされているパターンがすべて and で結合されます。

      // 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 ))
    • or: 条件コンポーネントを論理和に分類します。接中辞および接頭辞の or がサポートされます。

      // 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: 存在している必要のあるファクトおよび制約を指定します。このオプションは、初回の一致についてのみトリガーされ、後続の一致については無視されます。この要素を複数のパターンで使用する場合は、これらのパターンを括弧 () で囲みます。

      exists ( Bankruptcy( yearOfOccurrence > 1990 || amountOwed > 10000 ) )
    • not: 存在するべきでないファクトおよび制約を指定します。

      not ( Applicant( age < 21 ) )
    • forall: 最初のパターンに一致するすべてのファクトが残りのすべてのパターンに一致するかどうかを検証します。forall 構成が満たされると、このルールが true と評価されます。

      forall( $app : Applicant( age < 21 )
                    Applicant( this == $app, status = 'underage' ) )
    • from: パターンのデータソースを指定します。

      Applicant( ApplicantAddress : address )
      Address( zipcode == "23920W" ) from ApplicantAddress
    • entry-point: パターンのデータソースに対応する エントリーポイント を定義します。通常は from と共に使用されます。

      Applicant() from entry-point "LoanApplication"
    • collect: ルールを条件の一部として使用できる、オブジェクトのコレクションを定義します。この例では、指定したそれぞれのローンについてデシジョンエンジンで保留されているすべての申し込みが List に分類されます。保留中の申し込みが 3 つ以上ある場合は、このルールが実行されます。

      $m : Mortgage()
      $a : List( size >= 3 )
          from collect( LoanApplication( Mortgage == $m, status == 'pending' ) )
    • accumulate: オブジェクトのコレクションを処理し、各要素のカスタムアクションを実行し、(制約が true と評価されると) 結果オブジェクトを 1 つ以上返します。このオプションは、collect よりも強力で、柔軟性が高いオプションです。accumulate( <source pattern>; <functions> [;<constraints>] ) 形式を使用します。この例では、minmax、および average は累積関数で、各センサーのすべての測定値から、最低気温、最高気温、平均気温の値を計算します。その他のサポートされる関数には、countsumvariancestandardDeviationcollectList、および collectSet があります。

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

    DRL ルール条件の詳細については、「DRL のルール条件 (WHEN) 」 を参照してください。

  4. ルールの条件コンポーネントをすべて定義したら、DRL デザイナーの右上のツールバーの Validate をクリックして、DRL ファイルの妥当性を確認します。ファイルの妥当性確認に失敗したら、エラーメッセージに記載された問題に対応し、DRL ファイルの構文およびコンポーネントをすべて見直し、エラーが表示されなくなるまで再度、ファイルを検証します。
  5. DRL デザイナーで Save をクリックして、設定した内容を保存します。

4.2. DRL ルールへの THEN アクションの追加

ルールの then 部分には、ルールの条件部分が満たされる場合に実行するアクションが含まれます。たとえば、ローンの申請者が 21 歳に満たない場合は、"Underage" ルールの then アクションが setApproved( false ) となり、年齢が基準に達していないためローンの申し込みは承認されません。アクションは、ルールの条件とパッケージで利用可能オブジェクトに基づいて結果を実行する 1 つ以上のメソッドで構成されます。ルールアクションの主な目的は、デシジョンエンジンのワーキングメモリーでデータの挿入、削除、または変更を行うことです。

前提条件

  • package は DRL ファイルに上部に定義されます。これはファイルの作成時に実行されているはずです。
  • ルールで使用したデータオブジェクトの import リストが、DRL ファイルの package 行の下に定義されます。データオブジェクトは、このパッケージか、または別の Business Central のパッケージから使用できます。
  • rule 名は、packageimport、または DRL ファイル全体に適用されるその他の行の下に rule "name" という形式で定義されます。同じパッケージでルール名を重複させることはできません。ルールの動作を定義する任意のルール属性 (salienceno-loop など) は、ルール名の下の when セクションの前に定義します。

手順

  1. DRL デザイナーで、ルールの when セクションの後に then を入力して、アクションステートメントを追加します。
  2. ルールの条件に基づいて、ファクトパターンに対して実行するアクションを 1 つ以上入力します。

    以下は、DRL アクションを定義するためのキーワードオプションの例です。

    • set: これを使用してフィールドの値を設定します。

      $application.setApproved ( false );
      $application.setExplanation( "has been bankrupt" );
    • modify: ファクトの変更するフィールドを指定し、デシジョンエンジンに変更を通知します。このメソッドを使用することで、ファクトの更新に対する構造化されたアプローチを提供します。このメソッドは、update 操作とオブジェクトフィールドを変更する setter 呼び出しを組み合わせたものです。

      modify( LoanApplication ) {
              setAmount( 100 ),
              setApproved ( true )
      }
    • update: フィールドと、更新される関連ファクト全体を指定して、その変更をデシジョンエンジンに通知します。ファクトが変更されたら、更新された値の影響を受ける可能性がある別のファクトを変更する前に update を呼び出す必要があります。この追加設定を回避するには、代わりに modify メソッドを使用します。

      LoanApplication.setAmount( 100 );
      update( LoanApplication );
    • insert: new ファクトをデシジョンエンジンに挿入します。

      insert( new Applicant() );
    • insertLogical: デシジョンエンジンに new ファクトを論理挿入する場合に使用します。デシジョンエンジンはファクトの挿入、取り消しに対して論理的な決定を行う役割を担います。通常の挿入または記述による挿入の後は、ファクトは明示的に取り消される必要があります。論理挿入後にファクトを挿入したルールの条件が true ではなくなった場合、挿入されたファクトは自動的に取り消されます。

      insertLogical( new Applicant() );
    • delete: デシジョンエンジンからオブジェクトを削除します。キーワード retract も DRL でサポートされており、同じアクションを実行しますが、DRL のコードでは、キーワード insert との整合性を考慮して delete が通常推奨されます。

      delete( Applicant );
    注記

    DRL ルールアクションの詳細については、「DRL におけるルールアクション (THEN)」 を参照してください。

  3. ルールのアクションコンポーネントをすべて定義したら、DRL デザイナーの右上のツールバーの Validate をクリックして、DRL ファイルの妥当性を確認します。ファイルの妥当性確認に失敗したら、エラーメッセージに記載された問題に対応し、DRL ファイルの構文およびコンポーネントをすべて見直し、エラーが表示されなくなるまでファイルを検証します。
  4. DRL デザイナーで Save をクリックして、設定した内容を保存します。