14.9. DRL におけるルールアクション (THEN)
ルールの then 部分 (または、ルールの 右辺 (RHS)) には、ルールの条件部分が満たされる場合に実行されるアクションが含まれます。アクションは、1 つ以上の メソッド で設定されます。これらのメソッドは、ルール条件とパッケージ内で使用できる利用可能なデータオブジェクトに応じて結果を実行します。たとえば、銀行がローン申請者が 21 歳を超えていることが要件となっているにもかかわらず (ルール条件が Applicant( age < 21 ))、ローン申請者が 21 歳未満の場合は、"Underage" ルールの then アクションが setApproved( false ) となり、年齢が基準に達していないためローンの申し込みは承認されません。
ルールアクションの主な目的は、デシジョンエンジンのワーキングメモリーでデータの挿入、削除、または変更を行うことです。有効なルールアクションは小規模かつ宣言的で、可読性があるものです。ルールアクションで必須または条件付きコードを使用する必要がある場合は、ルールを小規模かつより宣言的な複数のルールに分割します。
申込者の年齢制限に関するルールの例
rule "Underage"
when
application : LoanApplication()
Applicant( age < 21 )
then
application.setApproved( false );
application.setExplanation( "Underage" );
end
14.9.1. DRL でサポートされるルールアクションメソッド
DRL では DRL ルールアクションで使用できる以下のルールアクションメソッドがサポートされます。これらのメソッドを使用することで、最初にワーキングメモリーインスタンスを参照せずに、デシジョンエンジンのワーキングメモリーを変更できます。これらのメソッドは Red Hat Process Automation Manager ディストリビューションの KnowledgeHelper クラスで提供されるメソッドへのショートカットとして機能します。
すべてのルールアクションメソッドについては、Red Hat カスタマーポータル から ZIP ファイル Red Hat Process Automation Manager 7.9.1 Source Distribution をダウンロードし、~/rhpam-7.9.1-sources/src/drools-$VERSION/drools-core/src/main/java/org/drools/core/spi/KnowledgeHelper.java に移動してください。
setこれを使用してフィールドの値を設定します。
set<field> ( <value> )
ローン申し込みの承認の値を設定するルールアクションの例
$application.setApproved ( false ); $application.setExplanation( "has been bankrupt" );
modifyファクトの変更するフィールドを指定し、デシジョンエンジンに変更を通知します。このメソッドは、ファクトの更新に対する構造化されたアプローチを提供します。このメソッドは、
update操作とオブジェクトフィールドを変更する setter 呼び出しを組み合わせたものです。modify ( <fact-expression> ) { <expression>, <expression>, ... }ローン申し込み件数および承認を変更するルールアクションの例
modify( LoanApplication ) { setAmount( 100 ), setApproved ( true ) }updateフィールドと更新される関連ファクト全体を指定して、その変更をデシジョンエンジンに通知します。ファクトが変更したら、更新した値の影響を受ける可能性がある別のファクトを変更する前に、
updateを呼び出す必要があります。この追加設定を回避するには、modifyメソッドを代わりに使用します。update ( <object, <handle> ) // Informs the decision engine that an object has changed update ( <object> ) // Causes `KieSession` to search for a fact handle of the object
ローンの申し込み件数および承認を更新するルールアクションの例
LoanApplication.setAmount( 100 ); update( LoanApplication );
注記property-change リスナーを指定する場合は、オブジェクトの変更時にこのメソッドを呼び出す必要はありません。property-change リスナーの詳細については、Red Hat Process Automation Manager のデシジョンエンジン を参照してください。
insertnewファクトをデシジョンエンジンのワーキングメモリーに挿入し、ファクトに必要な結果として生成されるフィールドと値を定義します。insert( new <object> );
新しいローン申請者オブジェクトを挿入するルールアクションの例
insert( new Applicant() );
insertLogicalデシジョンエンジンに
newファクトを論理挿入する場合に使用します。デシジョンエンジンは、ファクトの挿入および取り消しに対して論理的な決断を行います。通常の挿入または記述による挿入の後には、ファクトは明示的に取り消される必要があります。論理挿入の後、挿入されたファクトは、ファクトを挿入したルールの条件が true でなくなると自動的に取り消されます。insertLogical( new <object> );
新しいローン申請者オブジェクトを論理的に挿入するルールアクションの例
insertLogical( new Applicant() );
deleteデシジョンエンジンからオブジェクトを削除します。キーワード
retractも DRL でサポートされており、同じアクションを実行しますが、DRL のコードでは、キーワードinsertとの整合性を考慮してdeleteが通常推奨されます。delete( <object> );
ローン申請者オブジェクトを削除するルールアクションの例
delete( Applicant );
14.9.2. drools および kcontext 変数のその他のルールアクションメソッド
標準のルールアクションメソッドに加えて、デシジョンエンジンでは、ルールアクションで使用できる事前定義された drools 変数および kcontext 変数と組み合わせて使用できるメソッドもサポートしています。
drools 変数を使用して、Red Hat Process Automation Manager ディストリビューションの KnowledgeHelper クラスからメソッドを呼び出すことができます。これは、標準のアクションメソッドのベースとなるクラスでもあります。すべての drools ルールアクションのオプションについては、Red Hat Customer Portal から ZIP ファイル Red Hat Process Automation Manager 7.9.1 Source Distribution をダウンロードし、~/rhpam-7.9.1-sources/src/drools-$VERSION/drools-core/src/main/java/org/drools/core/spi/KnowledgeHelper.java に移動してください。
以下の例は、drools 変数と共に使用できる一般的なメソッドです。
-
drools.halt(): ユーザーまたはアプリケーションで以前にfireUntilHalt()が呼び出されている場合は、ルールの実行を終了します。ユーザーまたはアプリケーションがfireUntilHalt()を呼び出す場合、デシジョンエンジンは アクティブモード で開始し、ユーザーまたはアプリケーションがhalt()を明示的に呼び出すまでルールの評価を継続します。それ以外の場合、デシジョンエンジンはデフォルトで パッシブモード で実行し、ユーザーまたはアプリケーションが明示的にfireAllRules()を呼び出す場合にのみルールを評価します。 -
drools.getWorkingMemory():WorkingMemoryオブジェクトを返します。 -
drools.setFocus( "<agenda_group>" ): ルールが属する指定されたアジェンダグループにフォーカスを設定します。 -
drools.getRule().getName(): ルールの名前を返します。 -
drools.getTuple()、drools.getActivation(): 現在実行されているルールに一致するTupleを返し、対応するActivationを提供します。これらの呼び出しは、ロギングやデバッグを行う場合に役立ちます。
kcontext 変数を getKieRuntime() メソッドと共に使用して、KieContext クラスや、拡張によりご使用の Red Hat Process Automation Manager ディストリビューションの RuleContext クラスから別のメソッドを呼び出すことができます。完全な Knowledge Runtime API は kcontext 変数を通じて公開され、詳細なルールアクションメソッドを提供します。kcontext ルールアクションのすべてのオプションについては、Red Hat Customer Portal から ZIP ファイル Red Hat Process Automation Manager 7.9.1 Source Distribution をダウンロードし、~/rhpam-7.9.1-sources/src/kie-api-parent-$VERSION/kie-api/src/main/java/org/kie/api/runtime/rule/RuleContext.java に移動してください。
以下の例は、kcontext.getKieRuntime() の変数とメソッドの組み合わせで使用できる一般的なメソッドです。
-
kcontext.getKieRuntime().halt(): ユーザーまたはアプリケーションで以前にfireUntilHalt()が呼び出されている場合は、ルールの実行を終了します。このメソッドは、drools.halt()メソッドと同等です。ユーザーまたはアプリケーションがfireUntilHalt()を呼び出す場合、デシジョンエンジンは アクティブモード で開始し、ユーザーまたはアプリケーションがhalt()を明示的に呼び出すまでルールの評価を継続します。それ以外の場合、デシジョンエンジンはデフォルトで パッシブモード で実行し、ユーザーまたはアプリケーションが明示的にfireAllRules()を呼び出す場合にのみルールを評価します。 kcontext.getKieRuntime().getAgenda(): KIE セッションAgendaへの参照を返し、次にルールアクティベーショングループ、ルールアジェンダグループ、およびルールフローグループにアクセスできるようにします。アジェンダグループ CleanUp にアクセスしてフォーカスを設定する呼び出しの例
kcontext.getKieRuntime().getAgenda().getAgendaGroup( "CleanUp" ).setFocus();
この例は、
drools.setFocus( "CleanUp" )と同等です。-
kcontext.getKieRuntime().getQueryResults(<string> query): クエリーを実行し、結果を返します。このメソッドはdrools.getKieRuntime().getQueryResults()と同等です。 -
kcontext.getKieRuntime().getKieBase():KieBaseオブジェクトを返します。KIE ベースはルールシステムのすべてのナレッジのソースであり、現在の KIE セッションの開始元です。 -
kcontext.getKieRuntime().setGlobal()、~.getGlobal()、~.getGlobals(): グローバル変数を設定するか、または取得します。 -
kcontext.getKieRuntime().getEnvironment(): 使用するオペレーティングシステム環境と類似したランタイムのEnvironmentを返します。
14.9.3. 条件付きおよび名前付きの結果を伴う高度なルールアクション
一般的に、有効なルールアクションは小規模かつ宣言的であり、可読性があります。ただし、場合によっては、ルールごとに結果を 1 つに制限することが困難であり、以下のルールの例のように、ルールの構文が冗長になったり、繰り返しが多くなる可能性があります。
冗長で繰り返しの構文の多いルールの例
rule "Give 10% discount to customers older than 60"
when
$customer : Customer( age > 60 )
then
modify($customer) { setDiscount( 0.1 ) };
end
rule "Give free parking to customers older than 60"
when
$customer : Customer( age > 60 )
$car : Car( owner == $customer )
then
modify($car) { setFreeParking( true ) };
end
繰り返しを部分的に解決する手段として、以下の変更例にあるように、2 番目のルールで最初のルールを拡張します。
拡張された条件を使用して部分的に強化されたルールの例
rule "Give 10% discount to customers older than 60"
when
$customer : Customer( age > 60 )
then
modify($customer) { setDiscount( 0.1 ) };
end
rule "Give free parking to customers older than 60"
extends "Give 10% discount to customers older than 60"
when
$car : Car( owner == $customer )
then
modify($car) { setFreeParking( true ) };
end
より効率的な代替方法として、以下の例に示すように、変更した条件およびラベルが付与された対応するルールアクションを使用して、2 つのルールを 1 つのルールに統合することができます。
条件および名前付きの結果を使用した統合されたルールの例
rule "Give 10% discount and free parking to customers older than 60"
when
$customer : Customer( age > 60 )
do[giveDiscount]
$car : Car( owner == $customer )
then
modify($car) { setFreeParking( true ) };
then[giveDiscount]
modify($customer) { setDiscount( 0.1 ) };
end
このルールの例では、通常のデフォルトアクションと、giveDiscount という名前のもう 1 つの別のアクションが使用されています。giveDiscount アクションは、KIE ベースで年齢が 60 歳を超えた顧客が見つかると、その顧客が車を所有しているかどうかにかかわらず、キーワード do でアクティブにされます。
名前付きの結果のアクティベーションは、次の例の if ステートメントのように、追加の条件を使用して設定できます。if ステートメント内の条件は、その直前にあるパターンで常に評価されます。
追加の条件が指定される統合されたルールの例
rule "Give free parking to customers older than 60 and 10% discount to golden ones among them"
when
$customer : Customer( age > 60 )
if ( type == "Golden" ) do[giveDiscount]
$car : Car( owner == $customer )
then
modify($car) { setFreeParking( true ) };
then[giveDiscount]
modify($customer) { setDiscount( 0.1 ) };
end
以下のより複雑な例のように、ネストされた if および else if 設定を使用して、さまざまなルール条件を評価することもできます。
より複雑な条件を使用して統合されたルールの例
rule "Give free parking and 10% discount to over 60 Golden customer and 5% to Silver ones"
when
$customer : Customer( age > 60 )
if ( type == "Golden" ) do[giveDiscount10]
else if ( type == "Silver" ) break[giveDiscount5]
$car : Car( owner == $customer )
then
modify($car) { setFreeParking( true ) };
then[giveDiscount10]
modify($customer) { setDiscount( 0.1 ) };
then[giveDiscount5]
modify($customer) { setDiscount( 0.05 ) };
end
このルールの例では、60 歳を超えた Golden 顧客には 10% の割引きと無料駐車サービスが提供されますが、Silver 顧客に提供されるのは 5% の割引きのみで、無料駐車サービスは提供されません。このルールでは、do ではなく break というキーワードによって、giveDiscount5 という名前の結果がアクティブにされます。キーワード do は、デシジョンエンジンのアジェンダで結果をスケジュール設定し、ルール条件の残りの部分が引き続き評価されるようにします。一方、break は追加の条件の評価を行いません。名前付きの結果が do のいずれの条件にも一致せず、break でアクティブにされる場合は、ルールの条件部分に到達することはないため、ルールはコンパイルされません。