16.8. DRL のルール条件 (WHEN)
DRL ルールの when 部分 (ルールの左辺 (LHS)とも言う) には、アクションを実行するのに満たされなければならない条件が含まれます。条件は、パッケージ内で使用可能なデータオブジェクトに基づいて、指定された一連の パターン および 制約、オプションの バインディング およびサポートされるルール条件要素 (キーワード) で設定されます。たとえば、銀行のローンの申し込みに年齢制限 (21 歳以上) が必要な場合、"Underage" ルールの when 条件は Applicant( age < 21 ) となります。
DRL は if ではなく when を使用します。これは、if が一般に手続き型の実行フローの一部であり、条件が特定の時点でチェックされるためです。一方、when は、条件の評価が特定の評価シーケンスや時点に限定されず、いつでも継続的に行われることを示しています。条件が満たされるたびに、これらのアクションが実施されます。
when セクションを空にすると、条件は true であると見なされ、デシジョンエンジンで fireAllRules() 呼び出しが最初に実施された場合に、then セクションのアクションが実行されます。これは、デシジョンエンジンのステートを設定するルールを使用する場合に便利です。
以下のルール例では、空の条件を使用して、ルールが実行するたびにファクトを挿入します。
条件のないルール例
ルールの条件が、定義されたキーワード接続詞 (and、or、または not など) なしで複数のパターンを使用する場合、デフォルトの接続詞は and になります。
キーワード接続詞なしのルールの例
16.8.1. パターンと制約 リンクのコピーリンクがクリップボードにコピーされました!
DRL ルール条件の パターン は、デシジョンエンジンによって照合されるセグメントです。パターンは、デシジョンエンジンのワーキングメモリーに挿入される各ファクトと一致する可能性があります。パターンには 制約 を含めることもでき、これにより一致するファクトをより詳細に定義できます。
制約のない最も単純なフォームでは、パターンは指定されたタイプのファクトに一致します。以下の例ではタイプが Person であるため、このパターンはデシジョンエンジンのワーキングメモリーのすべての Person オブジェクトに一致します。
ファクトタイプが 1 つの場合のパターン例
Person()
Person()
このタイプは、ファクトオブジェクトの実際のクラスである必要はありません。パターンは、複数の異なるクラスのファクトと一致する可能性のあるスーパーユーザーやインターフェイスも参照できます。たとえば、以下のパターンは、デシジョンエンジンのワーキングメモリーにあるすべてのオブジェクトと一致します。
すべてのオブジェクトの場合のパターン例
Object() // Matches all objects in the working memory
Object() // Matches all objects in the working memory
パターンの括弧は制約を囲みます (以下のユーザーの年齢に関する制約など)。
制約のあるパターンの例
Person( age == 50 )
Person( age == 50 )
制約は、true または false を返す式です。DRL 内のパターンの制約は、基本的にはプロパティーのアクセスなどの拡張が設定された Java の式ですが、== および != に対する equals() および !equals() セマンティクスなど、若干の違いがあります (通常の same および not same セマンティクスではありません)。
JavaBean プロパティーはパターンの制約から直接アクセスできます。Bean プロパティーは、引数を使用せずに何かを返す標準の JavaBeans の getter を使用して内部的に公開されます。たとえば、age プロパティーは、DRL で getter の getAge() ではなく、age として記述されます。
JavaBeans プロパティーを使用した DRL 制約構文
Person( age == 50 ) // This is the same as the following getter format: Person( getAge() == 50 )
Person( age == 50 )
// This is the same as the following getter format:
Person( getAge() == 50 )
Red Hat Process Automation Manager は標準の JDK leavingspector クラスを使用してこのマッピングを行うため、標準の JavaBeans 仕様に従います。デシジョンエンジンのパフォーマンスの最適化には、getAge() のように getter を明示的に使用するのではなく、age のようなプロパティーアクセスの形式を使用します。
デシジョンエンジンは効率化のために呼び出し間で一致した結果をキャッシュするため、プロパティーアクセサーを使用してルールに影響を与える可能性がある方法でオブジェクトの状態を変更しないでください。
たとえば、プロパティーアクセサーを以下のように使用しないでください。
public int getAge() {
age++; // Do not do this.
return age;
}
public int getAge() {
age++; // Do not do this.
return age;
}
public int getAge() {
Date now = DateUtil.now(); // Do not do this.
return DateUtil.differenceInYears(now, birthday);
}
public int getAge() {
Date now = DateUtil.now(); // Do not do this.
return DateUtil.differenceInYears(now, birthday);
}
2 番目の例に従う代わりに、ワーキングメモリーに現在の日付をラップするファクトを挿入し、必要に応じてそのファクトを fireAllRules() の間で更新します。
ただし、プロパティーの getter が見つからなかった場合、コンパイラーは、以下のようにこのプロパティー名をフォールバックメソッド名として引数なしで使用します。
オブジェクトが見つからない場合のフォールバックメソッド
Person( age == 50 ) // If `Person.getAge()` does not exist, the compiler uses the following syntax: Person( age() == 50 )
Person( age == 50 )
// If `Person.getAge()` does not exist, the compiler uses the following syntax:
Person( age() == 50 )
以下の例のように、パターンでアクセスプロパティーをネストすることもできます。ネストされたプロパティーにはデシジョンエンジンでインデックス化されます。
ネストされたプロパティーアクセスを使用するパターンの例
Person( address.houseNumber == 50 ) // This is the same as the following format: Person( getAddress().getHouseNumber() == 50 )
Person( address.houseNumber == 50 )
// This is the same as the following format:
Person( getAddress().getHouseNumber() == 50 )
ステートフルな KIE セッションでは、ネストされたアクセサーの使用に注意が必要です。デシジョンエンジンのワーキングメモリーではネストされた値は認識されず、これらの値の変更は検出されません。ネストされた値の親参照がワーキングメモリーに挿入されている場合はこれらの値を不変と見なすか、ネストされた値を変更する必要がある場合は、すべての外部ファクトを更新済みとしてマークします。前の例では、houseNumber プロパティーが変更された場合は、この Address が指定された Person は更新済みとしてマークされる必要があります。
パターンの括弧内では boolean 値を制約として返す任意の Java 式を使用できます。Java 式は、プロパティーアクセスなどの他の式の拡張機能と組み合わせることができます。
プロパティーアクセスと Java 式を使用する制約が設定されたパターンの例
Person( age == 50 )
Person( age == 50 )
評価の優先度は、論理式や数式のように括弧を使用して変更できます。
制約の評価順序の例
Person( age > 100 && ( age % 10 == 0 ) )
Person( age > 100 && ( age % 10 == 0 ) )
以下の例のように、制約で Java メソッドを再利用することもできます。
再利用される Java メソッドによる制約の例
Person( Math.round( weight / ( height * height ) ) < 25.0 )
Person( Math.round( weight / ( height * height ) ) < 25.0 )
デシジョンエンジンは効率化を図るために呼び出し間で一致の結果をキャッシュするため、ルールに影響を与える可能性のある方法でオブジェクトの状態を変更するために制約を使用しないでください。ルール条件のファクトで実行されるメソッドは、読み取り専用のメソッドである必要があります。また、ファクトの状態は、ファクトがワーキングメモリーで更新済みとしてマークされているのでない限り、毎回変更されるたびにルールの呼び出し間で変更されません。
たとえば、以下のような方法でパターンの制約を使用しないでください。
Person( incrementAndGetAge() == 10 ) // Do not do this.
Person( incrementAndGetAge() == 10 ) // Do not do this.
Person( System.currentTimeMillis() % 1000 == 0 ) // Do not do this.
Person( System.currentTimeMillis() % 1000 == 0 ) // Do not do this.
DRL 内の制約演算子には、標準の Java 演算子の優先順位が適用されます。DRL 演算子は、== および != 演算子を除き、標準の Java セマンティクスに従います。
== 演算子は、通常の same セマンティクスではなく、null 安全な equals() セマンティクスを使用します。たとえば、Person( firstName == "John" ) というパターンは java.util.Objects.equals(person.getFirstName(), "John") と同様であり、"John" は null でないため、このパターンは "John".equals(person.getFirstName()) にも似ています。
!= 演算子は、通常の not same セマンティクスではなく null 安全な !equals() セマンティクスを使用します。たとえば、Person( firstName != "John" ) というパターンは、!java.util.Objects.equals(person.getFirstName(), "John") に似ています。
フィールドと制約の値が異なるタイプの場合、デシジョンエンジンは型強制 (type coercion) を使用して競合を解決し、コンパイルエラーを減らします。たとえば、"ten" が数値エバリュエーターで文字列として指定される場合は、コンパイルエラーが発生しますが、"10" は数値 10 に型強制されます。型強制では、フィールドのタイプは常に値のタイプより優先されます。
型強制された値を使用する制約の例
Person( age == "10" ) // "10" is coerced to 10
Person( age == "10" ) // "10" is coerced to 10
制約のグループの場合は、コンマ区切り (,) を使って、暗黙的な and の接続的なセマンティクスを使用することができます。
複数の制約があるパターンの例
// Person is at least 50 years old and weighs at least 80 kilograms: Person( age > 50, weight > 80 ) // Person is at least 50 years old, weighs at least 80 kilograms, and is taller than 2 meters: Person( age > 50, weight > 80, height > 2 )
// Person is at least 50 years old and weighs at least 80 kilograms:
Person( age > 50, weight > 80 )
// Person is at least 50 years old, weighs at least 80 kilograms, and is taller than 2 meters:
Person( age > 50, weight > 80, height > 2 )
&& 演算子および , 演算子のセマンティクスは同じですが、これらは異なる優先順位で解決されます。&& 演算子は || 演算子より優先され、&& 演算子および || 演算子はどちらも , 演算子より優先されます。デシジョンエンジンのパフォーマンスと人による可読性を最適化するために、コンマ演算子は最上位レベルの制約で使用してください。
括弧内など、複合制約式にコンマ演算子を埋め込むことはできません。
複合制約式での不適切なコンマの例
// Do not use the following format: Person( ( age > 50, weight > 80 ) || height > 2 ) // Use the following format instead: Person( ( age > 50 && weight > 80 ) || height > 2 )
// Do not use the following format:
Person( ( age > 50, weight > 80 ) || height > 2 )
// Use the following format instead:
Person( ( age > 50 && weight > 80 ) || height > 2 )
16.8.2. パターンと制約でバインドされた変数 リンクのコピーリンクがクリップボードにコピーされました!
パターンおよび制約に変数をバインドして、ルールの他の部分で一致するオブジェクトを参照することができます。バインドされた変数は、ルールをより効率的に、かつデータモデルでのファクトへのアノテーションの付け方と一貫した方法で定義するのに役立ちます。(とくに複雑なルールの場合に) ルール内で変数とフィールドを簡単に区別するには、変数に対して標準の形式である $variable を使用します。この規則は便利ですが、DRL で必須ではありません。
たとえば、以下の DRL ルールでは、Person ファクトが指定されたパターンに対して変数 $p が使用されています。
バインドされた変数が使用されているパターン
同様に、以下の例のように、パターンの制約で変数をプロパティーにバインドすることもできます。
// Two persons of the same age: Person( $firstAge : age ) // Binding Person( age == $firstAge ) // Constraint expression
// Two persons of the same age:
Person( $firstAge : age ) // Binding
Person( age == $firstAge ) // Constraint expression
より明確で効率的なルールを定義するには、制約のバインディングと制約式を必ず分離します。バインディングと式の組み合わせはサポートされますが、パターンが複雑になり、評価の効率に影響が及ぶ可能性があります。
// Do not use the following format: Person( $age : age * 2 < 100 ) // Use the following format instead: Person( age * 2 < 100, $age : age )
// Do not use the following format:
Person( $age : age * 2 < 100 )
// Use the following format instead:
Person( age * 2 < 100, $age : age )
デシジョンエンジンは同じ宣言に対するバインディングをサポートしませんが、複数のプロパティー間での引数の ユニフィケーション をサポートします。位置引数は、常にユニフィケーションで常に処理され、名前付き引数の場合はユニフィケーション記号 := が使用されます。
以下のパターンの例では、2 つの Person ファクト間で age プロパティーを統合します。
ユニフィケーションが使用されるパターンの例
Person( $age := age ) Person( $age := age )
Person( $age := age )
Person( $age := age )
ユニフィケーションは、シーケンスオカレンスのバインドされたフィールドの同じ値に対して、最初のオカレンスと制約のバインディングを宣言します。
16.8.3. ネストされた制約とインラインキャスト リンクのコピーリンクがクリップボードにコピーされました!
以下の例のように、ネストされたオブジェクトの複数のプロパティーにアクセスしなければならない場合があります。
複数のプロパティーにアクセスするパターンの例
Person( name == "mark", address.city == "london", address.country == "uk" )
Person( name == "mark", address.city == "london", address.country == "uk" )
以下の例のように、これらのプロパティーのアクセサーを、.( <constraints> ) という構文を使用してネストされたオブジェクトに対してグループ化することで、ルールを読みやすくすることができます。
グループ化された制約を使用したパターンの例
Person( name == "mark", address.( city == "london", country == "uk") )
Person( name == "mark", address.( city == "london", country == "uk") )
ピリオドのプリフィックス . は、メソッド呼び出しとネストされたオブジェクト制約を区別します。
パターンでネストされたオブジェクトを使用する場合は、構文 <type>#<subtype> を使用してサブタイプにキャストし、親タイプの getter をサブタイプに対して利用可能にします。以下の例のように、オブジェクト名または完全修飾クラス名のいずれかを使用して、1 つまたは複数のサブタイプにキャストできます。
サブタイプへのインラインキャストを使用したパターンの例
これらのパターン例では、Address を LongAddress に、さらに最後の例にある DetailedCountry にキャストし、各ケースのサブタイプで親の getter を利用可能にします。
以下の例のように、instanceof 演算子を使用して、パターンを使用した後続のフィールドで指定されたタイプの結果を推測できます。
Person( name == "mark", address instanceof LongAddress, address.country == "uk" )
Person( name == "mark", address instanceof LongAddress, address.country == "uk" )
インラインキャストが使用できない場合 (たとえば instanceof が false を返す場合)、評価は false と見なされます。
16.8.4. 制約内の日付リテラル リンクのコピーリンクがクリップボードにコピーされました!
デフォルトで、デシジョンエンジンは dd-mmm-yyyy という日付形式をサポートします。この日付形式 (必要に応じて時間形式マスクを含む) は、システムプロパティー drools.dateformat="dd-mmm-yyyy hh:mm" を使用して、別の形式マスクを指定することによってカスタマイズすることができます。日付形式は、drools.defaultlanguage および drools.defaultcountry システムプロパティーを使用し、言語ロケールを変更することによってカスタマイズすることもできます (たとえば、タイのロケールは drools.defaultlanguage=th および drools.defaultcountry=TH と設定します)。
日付のリテラル制限を使用したパターンの例
Person( bornBefore < "27-Oct-2009" )
Person( bornBefore < "27-Oct-2009" )
16.8.5. DRL のパターン制約でサポートされている演算子 リンクのコピーリンクがクリップボードにコピーされました!
DRL では、パターン制約の演算子で標準の Java セマンティクスがサポートされていますが、いくつかの例外があり、追加となる DRL 固有の演算子もいくつかあります。以下の一覧は、標準の Java セマンティクスとは異なる方法で処理される DRL の制約の演算子や DRL の制約に固有の演算子をまとめています。
.(),#.()演算子を使用すると、プロパティーのアクセサーをネストされたオブジェクトにグループ化でき、#演算子を使用すると、ネストされたオブジェクトのサブタイプにキャストできます。サブタイプにキャストすることで、親タイプの getter をサブタイプに対して使用できるようになります。オブジェクト名または完全修飾クラス名のいずれかを使用でき、1 つまたは複数のサブタイプにキャストできます。ネストされたオブジェクトが使用されるパターンの例
// Ungrouped property accessors: Person( name == "mark", address.city == "london", address.country == "uk" ) // Grouped property accessors: Person( name == "mark", address.( city == "london", country == "uk") )
// Ungrouped property accessors: Person( name == "mark", address.city == "london", address.country == "uk" ) // Grouped property accessors: Person( name == "mark", address.( city == "london", country == "uk") )Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注記ピリオドのプリフィックス
.は、メソッド呼び出しとネストされたオブジェクト制約を区別します。サブタイプへのインラインキャストを使用したパターンの例
Copy to Clipboard Copied! Toggle word wrap Toggle overflow !.この演算子を使用すると、null 安全な方法でプロパティーを逆参照します。パターンマッチングの適切な結果を得るには、
!.演算子の左側の値を null にすることはできません (!= nullと解釈される)。null 安全な逆参照を使用した制約の例
Person( $streetName : address!.street ) // This is internally rewritten in the following way: Person( address != null, $streetName : address.street )
Person( $streetName : address!.street ) // This is internally rewritten in the following way: Person( address != null, $streetName : address.street )Copy to Clipboard Copied! Toggle word wrap Toggle overflow []この演算子を使用して、インデックスで
List値にアクセスするか、またはキーでMap値にアクセスします。ListおよびMapアクセスを使用する制約の例// The following format is the same as `childList(0).getAge() == 18`: Person(childList[0].age == 18) // The following format is the same as `credentialMap.get("jdoe").isValid()`: Person(credentialMap["jdoe"].valid)// The following format is the same as `childList(0).getAge() == 18`: Person(childList[0].age == 18) // The following format is the same as `credentialMap.get("jdoe").isValid()`: Person(credentialMap["jdoe"].valid)Copy to Clipboard Copied! Toggle word wrap Toggle overflow <、<=、>、>=これらの演算子は、自然順序付けのあるプロパティーに使用されます。たとえば、
<演算子は、Dateフィールドでは 前 を意味し、Stringフィールドでは アルファベット順で前 であることを意味します。これらのプロパティーは、比較可能なプロパティーにのみ適用されます。before演算子を使用した制約の例Person( birthDate < $otherBirthDate ) Person( firstName < $otherFirstName )
Person( birthDate < $otherBirthDate ) Person( firstName < $otherFirstName )Copy to Clipboard Copied! Toggle word wrap Toggle overflow ==,!=制約では、これらの演算子を、通常の
sameおよびnot sameセマンティクスではなく、equals()および!equals()メソッドとして使用します。null 安全な等価性を使用する制約の例
Copy to Clipboard Copied! Toggle word wrap Toggle overflow null 安全な非等価性を使用する制約の例
Person( firstName != "John" ) // This is similar to the following format: !java.util.Objects.equals(person.getFirstName(), "John")
Person( firstName != "John" ) // This is similar to the following format: !java.util.Objects.equals(person.getFirstName(), "John")Copy to Clipboard Copied! Toggle word wrap Toggle overflow &&,||これらの演算子を使用して、フィールドに複数の制約を追加する略記組合せ比較条件を作成します。再帰的な構文パターンを作成するには、括弧
()を使用して制約をグループ化します。略記組合せ比較を使用する制約の例
Copy to Clipboard Copied! Toggle word wrap Toggle overflow matches,not matchesこれらの演算子を使用して、指定された Java 正規表現にフィールドが一致するか、または一致しないかを示します。一般に、正規表現は
Stringリテラルですが、有効な正規表現に解決される変数もサポートされます。これらの演算子はStringプロパティーのみに適用されます。null値に対してmatchesを使用する場合は、結果の評価が常にfalseになります。null値に対してnot matchesを使用する場合は、結果の評価が常にtrueになります。Java の場合のように、Stringリテラルとして記述された正規表現は二重のバックスラッシュ\\を使用してエスケープする必要があります。正規表現と一致する制約または一致しない制約の例
Person( country matches "(USA)?\\S*UK" ) Person( country not matches "(USA)?\\S*UK" )
Person( country matches "(USA)?\\S*UK" ) Person( country not matches "(USA)?\\S*UK" )Copy to Clipboard Copied! Toggle word wrap Toggle overflow contains,not containsこれらの演算子を使用して、フィールドの
ArrayまたはCollectionが指定された値を含むか、または含まないかを検証します。これらの演算子はArrayプロパティーまたはCollectionプロパティーに適用されますが、これらの演算子をString.contains()および!String.contains()の制約チェックの代わりとして使用することもできます。コレクションに対して
containsおよびnot containsが使用された制約の例Copy to Clipboard Copied! Toggle word wrap Toggle overflow String リテラルに対して
containsおよびnot containsが使用された制約の例Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注記下位互換性を確保するため、
excludes演算子はnot containsの同義語としてサポートされます。memberOf,not memberOfこれらの演算子を使用して、フィールドが変数として定義されている
ArrayまたはCollectionのメンバーであるかどうかを検証します。ArrayまたはCollectionは変数でなければなりません。コレクションと
memberOfおよびnot memberOfを使用する制約の例FamilyTree( person memberOf $europeanDescendants ) FamilyTree( person not memberOf $europeanDescendants )
FamilyTree( person memberOf $europeanDescendants ) FamilyTree( person not memberOf $europeanDescendants )Copy to Clipboard Copied! Toggle word wrap Toggle overflow soundslikeこの演算子を使用して、ある単語を英語で発音した場合に、指定された値と発音がほぼ同じであるかどうかを検証します (
matches演算子に類似)。この演算子は Soundex アルゴリズムを使用します。soundslikeを使用した制約の例// Match firstName "Jon" or "John": Person( firstName soundslike "John" )
// Match firstName "Jon" or "John": Person( firstName soundslike "John" )Copy to Clipboard Copied! Toggle word wrap Toggle overflow strこの演算子を使用して、
Stringであるフィールドが指定された値で開始しているか、または終了しているかを検証します。この演算子を使用して、Stringの長さを検証することもできます。strを使用する制約の例Copy to Clipboard Copied! Toggle word wrap Toggle overflow in、notinこれらの演算子を使用して、制約の中で一致する可能性がある複数の値を指定します (複合値の制約)。複合値の制約についての機能をサポートするのは
in演算子およびnot in演算子のみです。これらの演算子の 2 番目のオペランドは、括弧で囲み、コンマ区切り値の一覧で指定する必要があります。値は変数、リテラル、戻り値、または修飾された識別子として指定できます。これらの演算子は、==または!=演算子を使用し、複数の制約のリストとして内部に再書き込みされます。inおよびnotinを使用した制約の例Person( $color : favoriteColor ) Color( type in ( "red", "blue", $color ) ) Person( $color : favoriteColor ) Color( type notin ( "red", "blue", $color ) )
Person( $color : favoriteColor ) Color( type in ( "red", "blue", $color ) ) Person( $color : favoriteColor ) Color( type notin ( "red", "blue", $color ) )Copy to Clipboard Copied! Toggle word wrap Toggle overflow
16.8.6. DRL のパターン制約における演算子の優先順位 リンクのコピーリンクがクリップボードにコピーされました!
DRL では、適用可能な制約演算子の場合は標準的な Java 演算子の優先順位をサポートしていますが、一部の例外と、DRL に固有の追加の演算子がいくつかあります。以下の表には、適用可能な DRL 演算子を優先順位の高いものから低いものの順で記載しています。
| 演算子のタイプ | 演算子 | 注記 |
|---|---|---|
| ネストされているか、null 安全なプロパティーアクセス |
| 標準の Java セマンティクスではない |
|
|
| 標準の Java セマンティクスではない |
| 制約のバインディング |
| 標準の Java セマンティクスではない |
| 乗法 |
| |
| 加法 |
| |
| シフト |
| |
| リレーショナル |
| |
| 等価性 |
|
標準の Java の |
|
非短絡 (Non-short-circuiting) |
| |
|
非短絡の排他的 |
| |
|
非短絡の包含的 |
| |
|
論理 |
| |
|
論理 |
| |
| 三項 |
| |
|
コンマ区切り |
| 標準の Java セマンティクスではない |
16.8.7. DRL でサポートされるルール条件要素 (キーワード) リンクのコピーリンクがクリップボードにコピーされました!
DRL では、DRL のルール条件で定義するパターンで使用できる以下のルール条件要素 (キーワード) がサポートされます。
and条件コンポーネントを論理積に分類します。インフィックスおよびプリフィックスの
andがサポートされます。括弧()を使用することにより、パターンを明示的にグループ化できます。デフォルトでは、結合演算子を指定しないと、リストされているパターンがすべてandで結合されます。andを使用したパターンの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注記先頭の宣言のバインディングには
andキーワードを使用しないでください (orなどは使用できます)。宣言が参照できるのは一度に 1 つのファクトのみであり、andと宣言のバインディングを使用すると、andが満たされた場合にこの要素が両方のファクトと一致してしまうため、エラーが発生します。andの誤った使用例// Causes compile error: $person : (Person( name == "Romeo" ) and Person( name == "Juliet"))
// Causes compile error: $person : (Person( name == "Romeo" ) and Person( name == "Juliet"))Copy to Clipboard Copied! Toggle word wrap Toggle overflow または条件コンポーネントを論理和にグループ化します。インフィックスおよびプリフィックスの
orがサポートされます。括弧()を使用することにより、パターンを明示的にグループ化できます。orと共にパターンバインディングを使用することもできますが、各パターンは個別にバインディングする必要があります。orを使用したパターンの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow orとパターンのバインディングを使用したパターンの例pensioner : (Person( sex == "f", age > 60 ) or Person( sex == "m", age > 65 )) (or pensioner : Person( sex == "f", age > 60 ) pensioner : Person( sex == "m", age > 65 ))pensioner : (Person( sex == "f", age > 60 ) or Person( sex == "m", age > 65 )) (or pensioner : Person( sex == "f", age > 60 ) pensioner : Person( sex == "m", age > 65 ))Copy to Clipboard Copied! Toggle word wrap Toggle overflow or条件要素の動作は、制約や、フィールド制約の制限を対象とした接続演算子 (||) とは異なります。デシジョンエンジンはor要素を直接解釈しませんが、論理変換を使用して、orが使用されているルールを複数のサブルールに書き換えます。このプロセスにより、最終的には、ルートノードおよび各条件要素のサブルールとして、1 つのorを使用するルールが生成されます。サブルール間での操作や、特別な動作なしに、各サブルールは通常のルールと同様に有効にされ、実行されます。したがって、
or条件要素については複数の類似したルールを生成するための近道であり、複数の論理和が true である場合は、複数のアクティベーションが作成される可能性があることに留意してください。exists存在している必要のあるファクトおよび制約を指定します。このオプションは、最初に一致したものだけが適用され、その後一致するものは無視されます。この要素を複数のパターンで使用する場合は、これらのパターンを括弧
()で囲みます。existsを使用したパターンの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow not存在していてはならないファクトと制約を指定します。この要素を複数のパターンで使用する場合は、これらのパターンを括弧
()で囲みます。notを使用したパターンの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow forall最初のパターンと一致するすべてのファクトが残りのパターンのすべてと一致するかどうかを検証します。
forall設定が満たされると、このルールがtrueと評価されます。この要素は範囲の区切りであるため、以前にバインドされたすべての変数を使用できますが、内部でバインドされた変数を外部で使用することはできません。forallを使用したルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow この例では、ルールによってタイプが
"fulltime"であるすべてのEmployeeオブジェクトが選択されます。このパターンに一致するそれぞれのファクトに対して、ルールは、従うパターン (バッジの色) を評価し、一致すると、ルールはtrueと評価されます。デシジョンエンジンのワーキングメモリー内の特定のタイプのすべてのファクトが一連の制約と一致する必要があることを示すために、単純化するために単一のパターンで
forallを使用できます。forallと 1 つのパターンを使用するルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow 複数のパターンと
forall設定を使用するか、not要素設定内など他の条件要素でネスト化することができます。forallと複数のパターンを使用するルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow forallとnotを使用するルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注記forall( p1 p2 p3 …)の形式はnot( p1 and not( and p2 p3 … ) )と等価です。fromこれを使用してパターンのデータソースを指定します。これにより、デシジョンエンジンがワーキングメモリーにないデータに対して推論できるようになります。データソースには、バインドされた変数のサブフィールド、またはメソッド呼び出しの結果を指定できます。オブジェクトソースの定義に使用される式として、通常の MVEL 構文に準拠する任意の式を使用できます。このため、
from要素により、オブジェクトプロパティーのナビゲーションを使用して、メソッド呼び出しを実行し、マップとコレクション要素にアクセスすることが簡単にできます。fromおよびパターンのバインディングを使用するルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow fromとグラフ表記を使用するルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow すべてのオブジェクトに対して反復処理される
fromのルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注記オブジェクトの大規模なコレクションの場合は、デシジョンエンジンが頻繁に繰り返す必要がある大きなグラフを持つオブジェクトを追加するのではなく、次の例に示すように、コレクションを直接 KIE セッションに追加して、コレクションを条件に結合します。
when $order : Order() OrderItem( value > 100, order == $order )
when $order : Order() OrderItem( value > 100, order == $order )Copy to Clipboard Copied! Toggle word wrap Toggle overflow fromおよびlock-on-activeルール属性を使用するルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow 重要fromとlock-on-activeのルール属性を同時に使用すると、ルールが実行しなくなります。この問題に対しては、以下のいずれかの方法で対処できます。-
すべてのファクトをデシジョンエンジンのワーキングメモリーに挿入したり、制約式でネストされたオブジェクト参照を使用したりする場合は、
from要素は使用しないでください。 -
ルール条件の最後の文として、
modify()ブロックで使用される変数を配置します。 -
同じルールフローグループ内のルールがアクティベーションを相互に組み込む方法を明示的に管理できる場合は、
lock-on-activeルール属性を使用しないでください。
from句を含むパターンの後に、括弧から始まる別のパターンを使用することはできません。この制限がある理由は、DRL パーサーがfrom式を"from $l (String() or Number())"として読み取り、この式を関数呼び出しと区別できないためです。この最も単純な回避策は、以下の例に示すように、from句を括弧でラップする方法です。fromが適切に使用されていないルールと適切に使用されているルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow -
すべてのファクトをデシジョンエンジンのワーキングメモリーに挿入したり、制約式でネストされたオブジェクト参照を使用したりする場合は、
entry-pointエントリーポイントまたはパターンのデータソースに対応した イベントストリーム を定義します。この要素は通常、
from条件要素と共に使用します。イベントのエントリーポイントを宣言し、デシジョンエンジンがそのエントリーポイントからのデータのみを使用してルールを評価することが可能です。エントリーポイントは、DRL ルールで参照することで暗黙的に宣言することも、Java アプリケーションで明示的に宣言することもできます。from entry-pointを使用したルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow EntryPoint オブジェクトが使用され、ファクトが挿入された Java アプリケーションコードの例
Copy to Clipboard Copied! Toggle word wrap Toggle overflow collectルールで条件の一部として使用できるオブジェクトのコレクションを定義します。このルールは、指定されたソースまたはデシジョンエンジンのワーキングメモリーのいずれかからコレクションを取得します。
collect要素の結果パターンには、java.util.Collectionインターフェイスを実装し、デフォルトの引数を持たないパブリックコンストラクターを指定する任意の具象クラスを使用できます。List、LinkedList、およびHashSetのような Java コレクションを使用することも、独自のクラスを使用することもできます。条件内でcollect要素の前に変数がバインドされている場合は、その変数を使用してソースおよび結果パターンの両方を制限することができます。ただし、collect要素内で作成されるバインディングをその外部で使用することはできません。collectを使用するルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow この例では、ルールは指定された各システムのデシジョンエンジンのワーキングメモリーの保留中のすべてのアラームを評価し、それらを
Listにグループ化します。指定されたシステムについての 3 つ以上のアラームが見つかると、ルールが実行します。以下の例のように、ネストされた
from要素と共にcollect要素を使用することもできます。collectとネストされたfromを使用するルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow accumulateオブジェクトのコレクションを反復処理し、各要素に対してカスタムアクションを実行し、結果オブジェクトを返します (制約が
trueに評価される場合)。この要素は、collect条件要素のより柔軟性が高い、強化された形式です。accumulate条件で事前に定義した関数を使用するか、必要に応じてカスタム関数を実装できます。また、ルール条件でaccumulateの短縮形であるaccを使用することもできます。以下の形式を使用して、ルールに
accumulate条件を定義します。accumulateの推奨形式accumulate( <source pattern>; <functions> [;<constraints>] )
accumulate( <source pattern>; <functions> [;<constraints>] )Copy to Clipboard Copied! Toggle word wrap Toggle overflow 注記デシジョンエンジンは下位互換性を確保するために
accumulate要素の代替形式をサポートしますが、この形式は、ルールとアプリケーションの最適なパフォーマンスという点ではより適しています。デシジョンエンジンは、以下の事前に定義された
accumulate関数をサポートします。これらの関数は、任意の式を入力として受け入れます。-
average -
min -
max -
count -
sum -
collectList -
collectSet
以下のルールの例では、
min、max、およびaverageはaccumulate関数であり、各センサーの読み取り値での最低、最高、および平均の温度値を算出します。温度値を算出する
accumulateを使用したルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow 以下のルールの例では、
accumulateを指定したaverage関数を使用して、ある注文のすべてのアイテムの平均収益を計算します。平均収益を計算する
accumulateを使用したルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow accumulateの条件でカスタムかつドメイン固有の関数を使用するには、org.kie.api.runtime.rule.AccumulateFunctionインターフェイスを実装する Java クラスを作成します。たとえば、以下の Java クラスはAverageData関数のカスタム実装を定義します。average関数がカスタムで実装された Java クラスの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow DRL ルールでカスタム関数を使用するため、
import accumulateステートメントを使用してその関数をインポートします。カスタム関数をインポートするための形式
import accumulate <class_name> <function_name>
import accumulate <class_name> <function_name>Copy to Clipboard Copied! Toggle word wrap Toggle overflow インポートされた
average関数を使用するルールの例Copy to Clipboard Copied! Toggle word wrap Toggle overflow -
16.8.8. DRL ルール条件内でオブジェクトのグラフが使用される OOPath 構文 リンクのコピーリンクがクリップボードにコピーされました!
OOPath は、DRL ルールの条件の制約でオブジェクトのグラフを参照するために設計された XPath のオブジェクト指向構文の拡張です。OOPath は、コレクションおよびフィルター制約を処理する間に XPath からのコンパクト表記を使用して関連要素を移動します。また、OOPath は特にオブジェクトグラフの場合に役に立ちます。
ファクトのフィールドがコレクションである場合は、from 条件要素 (キーワード) を使用してバインドし、そのコレクションのすべての項目を 1 つずつ判断することができます。ルール条件制約でオブジェクトのグラフを参照する必要がある場合は、from 条件要素を過度に使用すると、以下の例のように冗長かつ繰り返しの多い構文になります。
from を使用してオブジェクトのグラフを参照するルールの例
この例では、ドメインモデルには Student オブジェクトと学習の Plan が含まれています。Plan には、ゼロ以上の Exam インスタンスを指定でき、Exam にはゼロ以上の Grade インスタンスを指定できます。このルール設定が機能するためにデシジョンエンジンのワーキングメモリーに存在する必要があるのは、グラフのルートオブジェクト (この例では Student) のみです。
from ステートメントを使用するより効率的な別の方法として、以下の例のように短縮された OOPath 構文を使用できます。
OOPath 構文でオブジェクトのグラフを参照するルールの例
通常、OOPath 式の中核となる文法は、以下のように拡張された Backus-Naur form (EBNF) 表記で定義されます。
OOPath 式の EBNF 表記
OOPExpr = [ID ( ":" | ":=" )] ( "/" | "?/" ) OOPSegment { ( "/" | "?/" | "." ) OOPSegment } ;
OOPSegment = ID ["#" ID] ["[" ( Number | Constraints ) "]"]
OOPExpr = [ID ( ":" | ":=" )] ( "/" | "?/" ) OOPSegment { ( "/" | "?/" | "." ) OOPSegment } ;
OOPSegment = ID ["#" ID] ["[" ( Number | Constraints ) "]"]
OOPath 式の実際の特性および機能は以下のとおりです。
-
非リアクティブな OOPath 式の場合は、スラッシュ
/または疑問符とスラッシュ?/で始まります (このセクションで後述します)。 -
オブジェクトの単一プロパティーを、ピリオド
.演算子を使用して逆参照できます。 -
オブジェクトの複数のプロパティーをスラッシュ
/演算子を使用して逆参照できます。コレクションが返される場合、この式はコレクションの値を反復処理します。 1 つまたは複数の制約を満たさない、走査されたオブジェクトをフィルターで除外できます。この制約は、以下の例のように、角括弧内の述語式として記述されます。
述語式としての制約
Student( $grade: /plan/exams[ course == "Big Data" ]/grades )
Student( $grade: /plan/exams[ course == "Big Data" ]/grades )Copy to Clipboard Copied! Toggle word wrap Toggle overflow 汎用コレクションで宣言されたクラスのサブクラスに走査されたオブジェクトをダウンキャストできます。以下の例に示すように、後続の制約も、このサブクラスで宣言されたプロパティーにのみ安全にアクセスすることができます。このインラインキャストで指定されたクラスのインスタンスではないオブジェクトは、自動的にフィルターで除外されます。
ダウンキャストオブジェクトが使用される制約
Student( $grade: /plan/exams#AdvancedExam[ course == "Big Data", level > 3 ]/grades )
Student( $grade: /plan/exams#AdvancedExam[ course == "Big Data", level > 3 ]/grades )Copy to Clipboard Copied! Toggle word wrap Toggle overflow 現在の反復処理されたグラフの前に走査されたグラフのオブジェクトを前方参照できます。たとえば、以下の OOPath 式は、合格した試験の平均を上回るグレードにのみ一致します。
前方参照オブジェクトを使用する制約
Student( $grade: /plan/exams/grades[ result > ../averageResult ] )
Student( $grade: /plan/exams/grades[ result > ../averageResult ] )Copy to Clipboard Copied! Toggle word wrap Toggle overflow 以下の例のように、別の OOPath 式を再帰的に使用できます。
再帰的な制約式
Student( $exam: /plan/exams[ /grades[ result > 20 ] ] )
Student( $exam: /plan/exams[ /grades[ result > 20 ] ] )Copy to Clipboard Copied! Toggle word wrap Toggle overflow 以下の例のように、角括弧
[]内のオブジェクトのインデックスを使用することにより、そのオブジェクトにアクセスすることができます。Java の規則に従うために、OOPath のインデックスは 0 をベースとし、XPath のインデックスは 1 をベースとします。インデックスによるオブジェクトへのアクセスが設定された制約
Student( $grade: /plan/exams[0]/grades )
Student( $grade: /plan/exams[0]/grades )Copy to Clipboard Copied! Toggle word wrap Toggle overflow
OOPath 式は、リアクティブまたは非リアクティブにできます。デシジョンエンジンは、深くネスト化されており、OOPath 式の評価中に走査されたオブジェクトを含む更新には反応しません。
これらのオブジェクトが変更に反応するようにするには、org.drools.core.phreak.ReactiveObject クラスを拡張するようにオブジェクトを変更します。オブジェクトを変更して ReactiveObject クラスを拡張すると、ドメインオブジェクトはいずれかのフィールドが更新されている場合に、以下のように継承されたメソッド notifyModification を呼び出して、デシジョンエンジンに通知します。
試験が別のコースに移動したことをデシジョンエンジンに通知するオブジェクトメソッドの例
public void setCourse(String course) {
this.course = course;
notifyModification(this);
}
public void setCourse(String course) {
this.course = course;
notifyModification(this);
}
次の対応する OOPath 式を使すると、試験が別のコースに移動された場合にルールが再実行され、そのルールに一致するグレードのリストが再計算されます。
Big Data ルールの OOPath 式の例
Student( $grade: /plan/exams[ course == "Big Data" ]/grades )
Student( $grade: /plan/exams[ course == "Big Data" ]/grades )
以下の例に示すように、/ セパレーターの代わりに ?/ セパレーターを使用して、OOPath 式の一部のみについてリアクティビティーを無効にすることもできます。
部分的に非リアクティブである OOPath 式の例
Student( $grade: /plan/exams[ course == "Big Data" ]?/grades )
Student( $grade: /plan/exams[ course == "Big Data" ]?/grades )
この例では、デシジョンエンジンは試験に対して実施された変更や、計画に試験が追加された場合に反応しますが、既存の試験に新しいグレードが追加された場合には反応しません。
OOPath の一部が非リアクティブである場合は、OOPath 式の残りの部分も非リアクティブになります。たとえば、以下の OOPath 式は完全に非リアクティブです。
完全に非リアクティブである OOPath 式の例
Student( $grade: ?/plan/exams[ course == "Big Data" ]/grades )
Student( $grade: ?/plan/exams[ course == "Big Data" ]/grades )
こうした理由から、同じ OOPath 式内で ?/ セパレーターを複数回使用することはできません。たとえば、以下の式はコンパイルエラーの原因となります。
重複した非リアクティビティーマーカーを使用する OOPath 式の例
Student( $grade: /plan?/exams[ course == "Big Data" ]?/grades )
Student( $grade: /plan?/exams[ course == "Big Data" ]?/grades )
OOPath 式のリアクティビティーを有効にするもう 1 つの方法は、Red Hat Process Automation Manager で List インターフェイスおよび Set インターフェイスの専用の実装を使用することです。これらの実装は、ReactiveList クラスおよび ReactiveSet クラスです。また、ReactiveCollection クラスも使用できます。これらの実装により、Iterator クラスおよび ListIterator クラスを使用した可変操作の実行もリアクティブにサポートされます。
以下のクラスの例では、これらのクラスを使用して OOPath 式のリアクティビティーを設定します。
OOPath 式のリアクティビティーを設定する Java クラスの例