第18章 Business Central における DRL ルールの作成
Business Central で、プロジェクトに対して DRL ルールを作成して管理できます。パッケージに作成またはインポートするデータオブジェクトに基づいて、各 DRL ファイルで、ルールの条件、アクション、そしてルールに関連するその他のコンポーネントを定義します。
手順
-
Business Central で、Menu
Design Projects に移動して、プロジェクト名をクリックします。 -
Add Asset
DRL file をクリックします。 参考となる DRL ファイル 名を入力し、適切な パッケージ を選択します。指定するパッケージは、必要なデータオブジェクトが割り当てられている、またはこれから割り当てるパッケージにする必要があります。
ドメイン固有言語 (DSL) アセットがプロジェクトに定義されている場合は、Show declared DSL sentences を選択することもできます。この DSL アセットは、DRL デザイナーで定義する条件およびアクションに使用できるオブジェクトです。
OK をクリックして、ルールアセットを作成します。
新しい DRL ファイルが、Project Explorer の DRL パネルに追加されます。Show declared DSL sentences オプションを選択した場合は、DSLR パネルに追加されます。この DRL ファイルを割り当てたパッケージは、ファイルの上位にリストされます。
-
DRL デザイナーの左パネルの Fact types リストで、ルールに必要なすべてのデータオブジェクトとデータオブジェクトフィールドがリストされていることを確認します (それぞれを展開します)。リストされていない場合は、DRL ファイルの
import
命令文を使用して、その他のパッケージから関連するデータオブジェクトをインポートするか、パッケージに データオブジェクトを作成 します。 データオブジェクトをすべて配置したら、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"
形式のルール名、ルールの動作 (salience
、no-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
図18.1 Business Central のロール申し込み用の DRL ファイルの例
-
- ルールのコンポーネントをすべて定義したら、DRL デザイナーの右上ツールバーで Validate をクリックし、DRL ファイルの妥当性を確認します。ファイルの妥当性確認に失敗したら、エラーメッセージに記載された問題に対応し、DRL ファイルの構文およびコンポーネントをすべて見直し、エラーが表示されなくなるまで再度、ファイルを検証します。
- DRL デザイナーで Save をクリックして、設定した内容を保存します。
18.1. DRL ルールへの WHEN 条件の追加
ルールの when
部分には、アクションを実行するのに必要な条件が含まれます。たとえば、銀行のローンの申し込みに年齢制限 (21 歳以上) が必要な場合、"Underage"
ルールの when
条件は Applicant( age < 21 )
となります。パッケージで利用可能なデータオブジェクトに基づいて、指定した一連のパターンおよび制約と、任意のバインディング、その他のサポートされる DRL 要素で設定されます。
前提条件
-
package
は DRL ファイルに定義されます。これは、ファイルの作成時に行われます。 -
ルールで使用したデータオブジェクトの
import
リストが、DRL ファイルのpackage
行の下に定義されます。データオブジェクトは、このパッケージ、または別の Business Central パッケージから使用できます。 -
rule
名は、package
、import
、または DRL ファイル全体に適用されるその他の行の下に、rule "name"
という形式で定義されます。同じパッケージでルール名を重複させることはできません。ルールの動作 (salience
、no-loop
など) を定義する任意のルール属性は、ルール名の下、when
セクションの前に定義します。
手順
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
一致させる最初の条件のパターンを入力し、任意で制約、バインディング、およびサポートされる 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" )
引き続き、このルールに適用する条件パターンをすべて定義します。以下は、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>] )
形式を使用します。この例では、min
、max
、およびaverage
は累積関数で、各センサーのすべての測定値から、最低気温、最高気温、および平均気温の値を計算します。その他のサポートされる関数には、count
、sum
、variance
、standardDeviation
、collectList
、および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)」 を参照してください。
- ルールの条件コンポーネントをすべて定義したら、DRL デザイナーの右上のツールバーの Validate をクリックして、DRL ファイルの妥当性を確認します。ファイルの妥当性確認に失敗したら、エラーメッセージに記載された問題に対応し、DRL ファイルの構文およびコンポーネントをすべて見直し、エラーが表示されなくなるまで再度、ファイルを検証します。
- DRL デザイナーで Save をクリックして、設定した内容を保存します。