Oracle Fusion Middleware Oracle Business Rulesランゲージ・リファレンス・ガイド 11g リリース1(11.1.1) B56239-01 |
|
戻る |
次へ |
この章には、Oracle Business Rules RL Language(RL Language)の構文、セマンティクスおよび組込み関数の完全なリファレンスが含まれています。
文法ルールでRL Languageが定義されています。各文法ルールでは、::=
記号の左側に記述された非終端記号が、::=
記号の右側に記述された1つ以上の非終端記号および終端記号に関して定義されています。
予約語
aggregate、boolean、break、byte、catch、char、class、constant、continue、double、else、exists、extends、fact、factpath、false、final、finally、float、for、function、hide、if、import、include、instanceof、int、long、modify、new、null、property、public、query、return、returns、rule、rulegroup、ruleset、short、supports、synchronized、throw、true、try、while、var
注意: 太字で記述されている予約語は、現行のリリースに適用されています。太字で記述されていない予約語(break、continueおよびqueryが該当)は、RL Languageの今後のリリースで使用される予定です。 |
ルールセットでは一連の定義がグループ化されます。ルールセットは、すべて同時に評価されることを意図したルールとその他の定義の集まりです。また、実行可能なアクションおよびその他のルールセットを含めたり、Javaのクラスやパッケージをインポートすることもできます。
フォーマット
ruleset ::= named-ruleset | unnamed-ruleset
named-ruleset ::= ruleset ruleset-name { unnamed-ruleset }
unnamed-ruleset ::= ( import | include | named-ruleset | definition | action | fact-class | rulegroup)*
ruleset-name ::= identifier
使用方法
named-rulesetでは、ruleset-nameという名前の指定したルールセットに定義が作成されるか、または定義が追加されます。
unnamed-rulesetでは、main
という名前のデフォルトのルールセットに定義が追加されます。
ルールセットはネストされる場合があります。つまり、他のルールセットが含まれている場合があります。ネストはルールセットのネーミングには影響を与えませんが、Javaのインポートがパッケージの参照可能性に影響を与えるのと同様に、ルールセットの参照可能性には影響を与えます。
ルールセットは、RL LanguageコマンドラインまたはJava RuleSession APIを使用して実行できます。
named-ruleset ruleset-nameは、RuleSession
内で一意であることが必要です。
例
例2-1には、2つの定義enterRoom
およびsayHello
と2つのアクション(assertおよびrun)が含まれています。
例2-1で示されているルールは、次の条件が満たされるまで起動されません。
enterRoom
ファクトがアサートされる。
run関数が実行される。つまり、ルールの包含ルールセットであるhello
がルールセット・スタックに追加される。
例2-1 名前付きルールセットの使用
ruleset hello { class enterRoom { String who; } rule sayHello { if (fact enterRoom) { println("Hello " + enterRoom.who); } } assert(new enterRoom(who: "Bob")); run("hello"); }
例2-2で、ルールセットR2がルールセットR1内にネストされている場合、名前R2はルール・セッション内で一意であることが必要です。R2の名前は、R1との相関で設定されているわけではありません。たとえば、R2で定義されるクラスC2のグローバル名はR2.C2であり、R1.R2.C2ではありません。R2がR1内にネストされている場合、R1で定義されているパブリック・クラスC1は、完全名R1.C1または短縮名C1(R2でC1が定義されていないと仮定した場合)を使用してR2で参照できます。
例2-2 ネストされたルールセットの使用
ruleset R1 { public class C1 { public String s; } C1 apple = new C1(s: "apple"); ruleset R2 { public class C2 { public String s; } C1 c1 = apple; // finds C1 and apple in containing ruleset R1 c1.s = "delicious"; C2 c2 = new C2(s: "pear"); } R2.C2 pear = R2.c2; // finds R2.C2 and R2.c2 because they are fully qualified println(apple.s + " " + pear.s); // prints "delicious pear" pear = c2; // UndefinedException: c2 not in R1 or a containing ruleset }
RL Languageは、厳密な型指定の言語です。各変数と値には指定された型があります。
フォーマット
type ::= simple-type [ [ ] ]
simple-type ::= primitive | object-type
primitive ::= boolean | numeric
numeric ::= int | double | float | long | short | byte | char
object-type ::= class-definition-name | Java-class-name
class-definition-name ::= qname
Java-class-name ::= qname
型変換
String
連結演算子+
を使用した、任意の型からString
への変換。
コンテキストからの暗黙的変換。たとえば、int
をdouble
に加算する場合は、最初にint
がdouble
に変換され、その後で2つのdouble
が加算されます。
2つの数値型間のキャスト。
継承で関連付けられた2つのクラス間のキャスト。
変換を実行する関数またはメソッドの起動。例: toString
表2-1は、様々な型の暗黙的変換の要約です。各行は、「変換元」列の型が、「変換先」列の型リストに示されているように暗黙的に変換される可能性があることを示しています。
表2-1 暗黙的な型変換
変換元 | 変換先 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注意: オブジェクトはJavaまたはRL Languageのクラスまたは配列のインスタンスです。型変換が可能であるのは、クラスが継承(実装または拡張)で関連付けられている場合のみです。 |
表2-2は、様々な型について許可されているキャスト変換の要約です。キャストを使用すると、ビット数の多いプリミティブ型をビット数の少ないプリミティブ型に、例外をスローすることなく変換できます。
表2-2に示されている型変換には、明示的なキャスト演算子が必要です。例を次に示します。
int i = 1; short s = (short)i;
注意: 表2-2に示されているような数値型を含む型変換では、上位ビットが失われる可能性があり、オブジェクトが関係するこのような変換では、RLClassCastExeption がスローされる場合があります。 |
表2-2 明示的な型変換
変換元 | 変換先 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
キャストを使用して、ビット数の多いプリミティブ型をビット数の少ないプリミティブ型に変換するとき、RL Languageでは、例外はスローされずに多い分の上位ビットが切り捨てられます。
例を次に示します。
short s = -134; byte b = (byte)s; println("s = " + s + ", b = " + b); prints: s = -134, b = 122
プリミティブ型
int
。32ビットの整数。リテラル値はjava.lang.Integer.parseInt
で解析されます。
long
。リテラル値はjava.lang.Long.parseLong
で解析されます。
short
。リテラル値はjava.lang.Short.parseShort
で解析されます。
byte
。リテラル値はjava.lang.Byte.parseByte
で解析されます。
char
。
double
。リテラル値はjava.lang.Double.parseDouble
で解析されます。
float
。リテラル値はjava.lang.Float.parseFloat
で解析されます。
boolean
。true
またはfalse
。
オブジェクト型
JavaのObject
。そのクラスの修飾名qnameで識別されます。例: java.lang.String
RL LanguageのObject
。そのクラスの修飾名qnameで識別されます。例: ruleset1.Class1
文字列型
RL LanguageではJava文字列が使用されます。この場合は次のように処理されます。
文字列はクラスjava.lang.String
のインスタンスです。
文字列リテラルは二重引用符で区切られます("string")。
文字列内に二重引用符を含める場合は\"を使用します。
文字列は、+
演算子を使用して次のように連結されます。
+
演算子のオペランドが文字列の場合は、残りのオペランドが文字列に変換され、各オペランドが連結されます。
オブジェクトは、そのtoString
メソッドを使用して文字列に変換されます。
RL Languageクラスのインスタンスは、組込み変換を使用して文字列に変換されます。
配列型
大カッコ([
]
)は配列を示します。RL Languageの配列の構文およびセマンティクスは、Javaの1次元配列と同じです。
注意: RL Languageではマルチディメンション配列はサポートされていません。 |
RL Languageでは、識別子および名前空間パッケージについてJavaとXMLバリアントの両方がサポートされます。XMLバリアントを使用するには、識別子を逆引用符で囲む必要があります。
フォーマット
identifier ::= java-identifier | xml-identifier
java-identifier ::= valid-Java-identifier
xml-identifier ::= `valid-xml-identifierまたはURI `
内容は次のとおりです。
valid-Java-identifier: 有効なJava識別子。例: JLd_0
valid-xml-identifier: 有効なXML識別子。例: x-1
URI: 有効なUniform Resource Identifier(URI)。例: http://www.oracle.com/rules
使用方法
xml-identifierには、無効なJava識別子文字(例: 「:」および「-」)を含めることができます。 JAXB仕様では、XML識別子からJava識別子への標準マッピングが定義されており、先頭大文字表記のJava表記規則も保持されています。JAXB仕様では、スキーマのターゲット名前空間URIからJavaパッケージ名への標準マッピング、および無名型からJava静的ネスト・クラスへのマッピングも定義されます。
例
RL Languageでは、識別子および名前空間またはパッケージについてJavaバリアントとXMLバリアントの両方がサポートされます。XMLバリアントを使用するには、例2-3で示すように、識別子を逆引用符で囲みます。
逆引用符の表記法は、RL Languageで識別子またはパッケージ名が有効であるすべての場所で使用できます。assertXPathのString
引数で識別子のXMLバリアントを使用する場合、逆引用符は必要ありません。
表2-3は、RL Languageのリテラルの要約です。リテラルはJavaリテラルと同じです。
表2-3 RL Languageのリテラル
リテラル | 割当て可能な変数の型 |
---|---|
範囲0〜127の整数、または範囲0〜127のUCS2エンコーディングの |
|
範囲0〜65535の整数または |
|
範囲-128〜127の整数 |
|
範囲-32768〜32767の整数 |
|
整数 |
|
末尾が |
|
浮動小数点定数 |
|
末尾が |
|
""で囲まれた文字列 |
|
ルールセット内の定義が実行されると、誤りがないかチェックされ、ルール・セッションで後で使用するために保存されます。
フォーマット
definition ::= variable | rule | rl-class-definition | function
name ::= identifier
qname ::= [ ruleset-or-packagename. ]name
ruleset-or-packagename ::= qname
使用方法
各定義の名前は包含ルールセット内で一意であるため、修飾名qnameはルール・セッション内で一意です。
ルールセット・レベルで定義された変数はグローバルです。グローバル変数は、ルールセットに含まれているすべての式で変数名を使用して参照可能であり、他のルールセット内の式では変数のqnameを使用して参照可能です。関数およびパブリック・クラスも、それぞれのqnameを使用して他のルールセットから参照できます。
Javaクラスとそのメソッドおよびプロパティにもqnameがあります。
例
例2-4のクラス定義のqnameはhello.enterRoom
です。
例2-4 名前付きルールセット内のクラス定義
ruleset hello { class enterRoom { String who; } rule sayHello { if (fact enterRoom) { println("Hello " + enterRoom.who); } } assert(new enterRoom(who: "Bob")); run("hello"); }
変数はJavaと同様に宣言されますが、必ず初期化する必要があります。
フォーマット
variable ::= [ final ] ( numeric name = numeric-expression
| boolean name = boolean-expression
| type [ ] name = array-expression | null
| object-type name = object-expression | null )
) ;
使用方法
array-expressionで初期化される配列の型は、配列要素に対して指定されたtypeと同じであることが必要です。
変数には、プリミティブ型、Javaクラス名またはRL Languageクラス名を使用でき、同じ型の要素の配列にもできます。
object-expressionの型は、宣言対象の変数のobject-typeと同じであることが必要です。クラス・インスタンスまたは配列はnullに初期化できます。
変数はスコープ内でローカルまたはグローバルです。初期化式が必要です。ローカル変数はファイナルにはできません。
ルールセットの直後に囲まれている(つまり定義内の)変数は、スコープ内のルール・セッションに対してグローバルです。ファイナル・グローバル変数の初期化式は、グローバル変数の定義時に実行されます。
非ファイナル・グローバル変数の初期化式は次の両方の場合に実行されます。
グローバル変数の定義時
reset
関数の毎コール時
ファイナルとして宣言されたグローバル変数は、初期化後変更できません。
ルール条件(fact-set-condition)で参照されるグローバル変数はファイナルであることが必要です。
例
例2-5は、reset関数によって非ファイナル・グローバル変数i
の初期化が実行されることを示しています。したがって、この例では1ではなく0(ゼロ)が出力されます。
二次的作用のある関数でグローバル変数を初期化する場合には注意が必要です。resetのコール時に二次的作用が繰り返されないようにする場合は、変数をfinal
として宣言する必要があります。たとえば、例2-6では"once"は2回出力され、例2-7では"once"は1回出力されます。
例2-6 resetの二次的作用を受けるグローバル変数の初期化
RL> clear; RL> function once() returns int { println("once"); return 1; } RL> int i = once(); once RL> reset(); once RL>
例2-7 resetの二次的作用を回避するファイナル・グローバル変数の初期化
RL> clear; RL> function once() returns int { println("once"); return 1; } RL> final int i = once(); once RL> reset(); RL>
Oracle Rules Engineでは、ルール・セッション内のすべてのルールのfact-set-conditionに対してファクトが照合され、実行するルールのアジェンダが作成されます。ファクト・セットの行は、ルールの条件をtrueにするファクトの組合せです。アクティブ化は、ルールのaction-blockに関して組み合されたファクト・セットの行です。アジェンダは、ルール・セッション内の全アクティブ化のリストです。Oracle Rules Engineでは、作業メモリーの状態が変化した場合(通常はファクトがアサートまたは取り消された場合)に、ファクトおよびルールが照合されます。
run、runUntilHaltおよびstep関数によってアクティブ化が実行されます。アクティブ化は、実行後にアジェンダから削除されます。またはファクト・セット行で参照されるファクトが、ルールの条件と一致しなくなるように変更または取り消されると削除されます。
アクティブ化はルールセット・スタックの順に実行されます。ルールセット・スタックは、getRulesetStack、clearRulesetStack、pushRulesetおよびpopRuleset関数で管理できます。
ルールが起動するには、次の3つの事項が発生する必要があります。
そのルールのアクティブ化がアジェンダに存在すること。
包含ルールセットがルールセット・スタックの最上位にあること。
run、runUntilHaltまたはstepが実行されること。
fact-set-conditionで生成されるファクト・セットは、ルール・アクションで使用できます。ファクト・セット内の各行について、action-blockは次のようにアクティブ化されます。
ルールのaction-blockは、指定したルールのpriorityで実行されるようにスケジュールされます。
action-blockから一致ファクトへの参照は、現在の行にバインドされます。
action-blockの実行前に一致ファクトが取り消された場合、依存アクティブ化は破棄(アジェンダから削除)されます。
フォーマット
rule ::= rule rule-name { property* fact-set-condition action-block }
rule-name ::= name
property ::= priority | autofocus | logical | active
priority ::= priority = numeric-expression
autofocus ::= autofocus = boolean-literal
logical ::= logical = ( boolean-literal | positive-integer-literal )
active ::= active = boolean-literal
effectiveDateForm ::= effectiveDateForm =oracle.rules.rl.Ruleで定義された値(EDFORM_DATE、EDFORM_DATETIMEまたはEDFORM_TIME)のいずれかに制限されるint
effectiveStartDate ::= effectiveStartDate =型java.util.Calendar
の式
effectiveEndDate ::= effectiveEndDate =型java.util.Calendar
の式
内容は次のとおりです。
positive-integer-literal: 0(ゼロ)より大きい整数リテラル
使用方法
priorityプロパティでは、ルールの優先度が指定されます。同じルールセットのルールのアクティブ化セット内では、アクティブ化は優先度順に実行されます(「ルール起動の順序付け」を参照)。ルールの優先度が異なる場合、優先度の高いルールが優先度の低いルールより先にアクティブ化されます。デフォルトの優先度は0(ゼロ)です。同じ優先度のルールのアクティブ化セット内では、最後に追加されたアクティブ化が最初に実行されますが、この動作は変更できます(getStrategy関数およびsetStrategy関数を参照)。
autofocusプロパティがtrue
のルールでは、ルールがアクティブ化されたときに包含ルールセットがルールセット・スタックに自動的に追加されます。
logicalプロパティが使用されているルールは、ルールのアクション・ブロックでアサートされたすべてのファクトが、ルールの条件によって照合された一部のファクトまたはすべてのファクトに依存するようにします。logicalプロパティに整数値nを指定すると、ルール条件内にある最初のn個の上位&&
edファクト・セット式に対する依存性が作成されます。logicalプロパティにブール値true
を指定すると、条件のファクト・セット式に対する依存性が作成されます。ファクト・セットの行内で参照されるファクトが、ルールの論理条件に該当しなくなるように変更された場合はいつでも、そのファクト・セット行に関連付けられているアクティブ化によってアサートされたファクトは自動的に取り消されます。 logicalプロパティが有効になっているルールは、ルールのアクション・ブロックでアサートされたすべてのファクトが、ルール条件で照合されたファクトに依存するようにします。 ルール条件で参照されるファクトが変更され、ルールの条件に該当しなくなった場合はいつでも、そのルール条件によってアサートされたファクトは自動的に取り消されます。
activeプロパティは、デフォルトでtrue
に設定されます。
effectiveStartDateの日付は、デフォルトでnullに設定されます。
effectiveEndDateの日付は、デフォルトでnullに設定されます。
effectiveDateFormは、デフォルトでRule.EDFORM_DATETIME
に設定されます。
例
例2-8は、推論(ソクラテスは人間である。これはソクラテスは男性であるというファクトに依存する)のあるルールを示しています。
例2-8 ルールallMenAreMortalの定義および使用
RL> clear; RL> class Man {String name;} RL> class Mortal {String name;} RL> Mortal lastMortal = null; RL> rule allMenAreMortal { logical = true; if (fact Man) { assert(lastMortal = new Mortal(name: Man.name)); } } RL> watchAll(); RL> Man socrates = new Man(name: "Socrates"); RL> assert(socrates); ==> f-1 main.Man (name : "Socrates") ==> Activation: main.allMenAreMortal : f-1 RL> run(); Fire 1 main.allMenAreMortal f-1 ==> f-2 main.Mortal (name : "Socrates") <== Focus main, Ruleset stack: {} RL> retract(socrates); <== f-1 main.Man (name : "Socrates") <== f-2 main.Mortal (name : "Socrates") RL> showFacts(); f-0 initial-fact()
例2-9は、同じファクトを複数のルールでアサートすること、または最上位のルールセット・アクションまたは関数でアサートすることが可能であることを示しています。このようなファクトは、すべてのアサータに自動取消をコールする論理句がないかぎり、自動的に取り消されません。最上位のアクションまたは関数でアサートされているファクトは、自動的に取り消されることはありません。
ソクラテスが人間であるというファクトは取り消されないことに注意してください。これは、ソクラテスが男性であるというファクトに依存していない最上位のアクションでアサートされているためです。
例2-9 ファクトの無条件アサート
RL> assert(socrates); ==> f-3 main.Man(name : "Socrates") ==> Activation: main.allMenAreMortal : f-3 RL> run(); Fire 1 main.allMenAreMortal f-3 ==> f-4 main.Mortal(name : "Socrates") <== Focus main, Ruleset stack: {} RL> assert(lastMortal); <=> f-4 main.Mortal(name : "Socrates") RL> retract(socrates); <== f-3 main.Man(name: "Socrates") RL> showFacts(); f-0 initial-fact() f-2 main.Mortal(name: "Socrates")
参照クラスはすべて、RL Languageクラス定義で定義されているか、またはJavaクラスパスに存在している(Javaクラスがインポートされている)必要があります。
RL LanguageクラスとJavaクラスの両方で、提供されているxpathでsupportsキーワードを使用してxpathをサポートできます。
フォーマット
rl-class-definition ::= [ public ] [ final ] class name [ extends ] [ supports ] { type-property* }
type-property ::= [ public ] type name [ = expression ] ;
extends ::= extends qname extended-class-name
extended-class-name ::= qname
使用方法
オプションの初期化expressionの型は、プロパティの型またはその型に暗黙的に変換可能な型と同じであることが必要です。
パブリック・クラスはすべてのルールセットから参照可能です。非パブリック・クラスは、包含ルールセット内でのみ参照可能です。
ファイナル・クラスは拡張できません。
拡張クラスは、インポートされたJavaクラスではなく、定義済のRL Languageクラスであることが必要です。
各プロパティにオプションのイニシャライザを設定できます。イニシャライザは、クラスがnewでインスタンス化されるときに評価されます。newに初期値も渡された場合、クラス定義内のイニシャライザによって計算された値は、newに渡された値によって上書きされます。
パブリック・プロパティはすべてのルールセットから参照可能です。非パブリック・プロパティは、包含ルールセット内でのみ参照可能です。
例
RL Languageでは、プロパティのタイプは包含クラス定義の名前の場合があります(例2-10を参照)。RL Languageでは、Javaとは異なり、クラス定義の前方参照はサポートされていません(例2-11を参照)。
RL LanguageクラスとJavaクラスの両方でxpathがサポートされています。
XML識別子は、xpath内では逆引用符で囲む必要はありません。
組込みのassertXPath関数では、オブジェクトのツリーをファクトとしてアサートするための簡単なxpathに似た構文がサポートされます。ツリーのノードは、xpathをサポートする同じパッケージまたはルールセット内のクラスのオブジェクトです。親ノードと子ノードの間のリンクはXLink
クラスのインスタンスです。xpathをサポートするクラス内のすべてのプロパティをxpath式で使用できます。
フォーマット
xpath ::= first-step next-step*
first-step ::= ( .| /* | [ // ] ( identifier | * ) ) predicate*
predicate ::= [ identifier xrelop literal ]
next-step ::= ( / | // ) ( identifier | * ) predicate*
xrelop ::= eq | lt | gt | le | ge | ne | == | < | > | <= | >= | !=
literal ::= integer-literal | decimal-literal | double-literal | string-literal | true | false | dateTime-literal | date-literal | time-literal
integer-literal ::= [-] d+
d ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
decimal-literal ::= [-] ( .d+ | d+ .d*)
double-literal ::= [-] ( .d+ | d+ [ .d* ] ) ( e | E ) [+ | -] d+
string-literal ::= " char* " | ' char* '
dateTime-literal ::= local-date T time-literal
date-literal ::= local-date [ time-zone ]
time-zone ::= Z | ( + | - ) d d : d d
local-date ::= d d d d - d d - d d
time-literal ::= d d : d d : d d [. d+] [ time-zone ]
使用方法
RL Languageのxpathサポートは、Java XML Binding(JAXB)1.0標準に準拠するクラスで動作するように設計されました。特定のルートからxpathで選択された要素までを含めてすべてのJAXB要素がアサートされます。アサート要素間の親子関係に関するルールを記述できるように、追加のXLinkファクトがアサートされます。
JAXB要素が取り消されるか、またはassertを使用して再アサートされた場合、そのすべての子およびXLinkが取り消されます。再アサートするかわりに、assertXPathを再度使用してください。
RL LanguageのXpathは、W3C Xpath 2.0の正確なサブセットではありません。次の相違点があることに注意してください。
lt
と<
、gt
と>
がRL Languageでは同義ですが、W3Cでは異なります。
W3Cでは、日付リテラルでxs:date()
およびその他のコンストラクタを使用する必要があります。
コンストラクタはRL Languageではサポートされていません。文字列リテラル以外のリテラルはRL Languageでは引用できません。
例
表2-4は、組込みのassertXPath関数で使用するxpath選択オプションを示しています。この説明部分で、選択とは、要素がファクトとしてアサートされ、アサート要素を表す要素プロパティがあるXLinkの選択プロパティがtrue
であることを意味します。選択した要素の祖先は、ルート要素まで含めて常にアサートされますが、必ずしも選択されるわけではありません。
表2-4 xpath選択文字列
xpath選択文字列 | 選択の説明 |
---|---|
//* |
ルートを含めてすべての要素を選択 |
.//* |
ルート以外のすべての要素を選択 |
. |
ルートのみを選択 |
//foo |
fooという名前のプロパティの値であるすべてのオブジェクトを選択 |
.[x==1]/y |
ルートに、名前がxで1と等しい子要素または属性がある場合にのみ、ルートの子または属性で名前がyであるものを選択 |
例2-12では、PersonというRL Languageクラスがインスタンス化され、次のようなファミリ・ツリーが作成されます。
First Generation Second Generation Third Generation Ida Mary Fred John Rachel Sally Evan
例2-12では、2つのxpathでassertXPath関数が2回使用されています。
//kids[male==true] //kids[male==false]
例2-12では、次の2つのルールが定義されます。
sibling
: 兄弟姉妹関係のすべてのペアを出力
brotherSister
: 兄弟のすべてのペアおよび姉妹のすべてのペアを出力
例2-12 supports xpathを使用したファミリ・ツリー・ルールの例
import java.util.*; ruleset xp { public class Person supports xpath { public String name; public boolean male; public List kids; } // Build the Family Tree Person p = new Person(name: "Fred", male: true); List k = new ArrayList(); k.add(p); p = new Person(name: "John", male: true); k.add(p); p = new Person(name: "Mary", male: false, kids: k); Person gramma = new Person(name: "Ida", male: false, kids: new ArrayList()); gramma.kids.add(p); p = new Person(name: "Sally", male: false); k = new ArrayList(); k.add(p); p = new Person(name: "Evan", male: true); k.add(p); p = new Person(name: "Rachel", male: false, kids: k); gramma.kids.add(p); // test for siblings. // Note the test id(p1) < id(p2) halves the Cartesian product p1 X p2. rule sibling { if (fact Person p1 && fact Person p2 && id(p1) < id(p2) && exists(fact XLink(element: p1) x && fact XLink(element: p2, parent: x.parent))) { println(p1.name + " is sibling of " + p2.name); } } // test for brothers and sisters, given the following 2 assertXPath() calls rule brotherSister { if (fact Person p1 && fact Person p2 && id(p1) < id(p2) && exists(fact XLink(element: p1, selected: true) x && fact XLink(element: p2, selected: true, parent: x.parent) y && x.samePath(y))) { println(p1.name + " and " + p2.name + " are " + (p1.male ? "brothers" : "sisters")); } } assertXPath("xp", gramma, "//kids[male==true]"); assertXPath("xp", gramma, "//kids[male==false]"); run("xp"); }
例2-13 ファミリ・ツリーの例の実行結果
Mary and Rachel are sisters Evan is sibling of Sally Fred and John are brothers Fred is sibling of John Mary is sibling of Rachel
例2-14は、assertXPath
でアサートされた要素を取り消すと、そのすべての子孫も取り消されることを示しています。
結果は次のようになります。
f-0 initial-fact()
合計1ファクトの場合。
例2-15では、祖先のすべてのペアが出力されます。最初に、ファミリ・ツリーがアサートされます。例2-16は、例2-15のコードの実行結果を示しています。
例2-15 クラスAncestorを使用した祖先のペアの出力
assertXPath("xp", xp.gramma, "//*"); class Ancestor { Object element; Object ancestor; } rule parents { if (fact XLink x) { assert(new Ancestor(element: x.element, ancestor: x.parent)); } } rule ancestors { if (fact XLink x && fact Ancestor(ancestor: x.element) a) { assert(new Ancestor(element: a.element, ancestor: x.parent)); } } rule printAncestor { if (fact xp.Person p && fact xp.Person a && fact Ancestor(element: p, ancestor: a) { println(a.name + " is an ancestor of " p.name); } } run();
例2-16 Ancestorの例の実行結果
Mary is an ancestor of John Ida is an ancestor of John Mary is an ancestor of Fred Ida is an ancestor of Fred Ida is an ancestor of Mary Rachel is an ancestor of Evan Ida is an ancestor of Evan Rachel is an ancestor of Sally Ida is an ancestor of Sally Ida is an ancestor of Rachel
フォーマット
function ::= function name parameters [ returns type ] action-block
parameters ::= ( [ type identifier ( , type identifier )* ] )
使用方法
action-blockによって、定義されている関数を起動できます。ただし、action-blockには、まだ定義されていない関数の前方参照を含めることはできません(例2-17および例2-18を参照)。
関数はオーバーロード可能です。たとえば、組込みのprintln関数はオーバーロードされています。
例
すべてのJavaクラスを、ファクト・コンテキスト内でRL Languageファクトとして使用できます。
ファクト・コンテキストは次のいずれかです。
fact-class宣言のクラス
fact-set-patternのクラス
assert関数の引数の宣言クラス
retract関数の引数の宣言クラス
assertXPath関数の要素引数の宣言クラス
クラスまたはインタフェースB
がクラスまたはインタフェースA
を実装または拡張するとき、A
とB
の両方がファクト・コンテキスト内に出現する場合は、A
がB
の前に出現する必要があります。このルールに従わない場合はFactClassException
が発生します。
ファクト・クラス定義は、RL Languageクラスを使用する場合は必要ありません。
xpathサポートについては、RL Languageクラス定義のsupports xpath句を使用します。
フォーマット
fact-class ::= fact class class-name [ supports ] ( fact-class-body | ; )
class-name ::= qname
fact-class-body ::= { [ hidden-properties | properties ]}
hidden-properties ::= hide property * ; | ( hide property ( ( name , )* name | * ) ; )+
properties ::= property * ; | ( property ( ( name , )* name | * ) ; )+
使用方法
fact-class-bodyは、fact-class宣言ではオプションです。デフォルトのfact-class-bodyは次のとおりです。
{ property *; }
property
またはhide property
キーワードのいずれかを本体で使用できますが、両方は使用できません。
hide property
がプロパティ名のリストを指定して使用されている場合、これらのプロパティ名は非表示になり、RL Languageでは使用できません。
hide property
がワイルドカード*を指定して使用されている場合、スーパークラスまたはスーパーインタフェースで公開されているプロパティ以外のプロパティはRL Languageで使用できません。
property
がプロパティ名のリストを指定して使用されている場合、これらのプロパティは公開され、RL Languageで使用できます。propertyがワイルドカード*
を指定して使用されている場合、スーパークラスまたはスーパーインタフェースで非表示にされているプロパティ以外のすべてのプロパティをRL Languageで使用できます。
サブクラスで非表示のプロパティがスーパークラスで公開されている場合、またはスーパークラスで非表示のプロパティがサブクラスで公開されている場合は、HiddenPropertyException
がスローされます。
例
JavaクラスVehicle
にサブクラスCar
とTruck
があるとします。例2-19で示されるルールmatchVehicle
では、FactClassException
をラップするTypeCheckException
が生成されます。これは、スーパークラスの前にサブクラスが参照されるためです。ラップは、FactClassException
とMultipleInheritanceException
の両方に対するサブクラス化のかわりに使用されます。これは、ファクト・コンテキストによっては、これらの例外が実行時までスローされず、RLRuntimeException
でラップされるためです。
例2-19 スーパークラスの前に参照されるサブクラスがあるmatchVehicleルール
assert(new Car()); // fact context for Car assert(new Truck()); // fact context for Truck rule matchVehicle { if (fact Vehicle v) { // fact context for Vehicle - too late! if (v instanceof Car) { println("car"); } else { println("truck"); } } } // generates a TypeCheckException wrapping a FactClassException
例2-20では、matchVehicle
ルールがスーパークラスに対する最初の参照であるため、例外はスローされません。
例2-20 最初にスーパークラスの参照があるmatchVehicleルール
clear; rule matchVehicle { if (fact Vehicle v) { if (v instanceof Car) { println("car"); } else { println("truck"); } } } assert(new Car()); assert(new Truck()); run(); // prints "truck" then "car"
例2-21では、ファクト・クラス宣言がスーパークラスに対する最初の参照であるため、例外はスローされません。
例2-21 最初にスーパークラスの参照があるファクト・クラス宣言を含むmatchVehicleルール
clear; fact class Vehicle; assert(new Car()); assert(new Truck()); rule matchVehicle { if (fact Vehicle v) { if (v instanceof Car) { println("car"); } else { println("truck"); } } } run(); // prints "truck" then "car"
ファクトでは多重継承はサポートされません。例2-22に示されたJavaクラスとインタフェースについて考えてみます。
例2-22 Javaクラスと多重継承の例
package example; public class Car {} public interface Sporty {} public class SportsCar extends Car implements Sporty {}
コマンドラインで入力された例2-23の結果、MultipleInheritanceException
をラップするTypeCheckException
がスローされます。TypeCheckException
でgetCause
メソッドを使用すると、ラップされたMultipleInheritanceException
例外を取得できます。
例2-23 ファクトに対するMultipleInheritance例外
import example.*; fact class Sporty; fact class Car; fact class SportsCar; // throws TypeCheckException wrapping a MultipleInheritanceException
例2-24は、Oracle Rules Engineでrx8
オブジェクトをアサートしようとしたときに、その実際の型がObject
ではなくSportsCar
であることが検出された場合に、実行時に発生する例外を示しています。MultipleInheritanceException
を回避するには、ファクト・クラス・コンテキストでSporty
を使用するかまたはCar
を使用するかを選択する必要があります。両方を使用することはできません。
例2-24 MultipleInheritanceExceptionをラップするRLRuntimeException
import example.*; fact class Sporty; fact class Car; Object rx8 = new SportsCar(); assert(rx8); // throws RLRuntimeException wrapping a MultipleInheritanceException
例2-25 FactClassExceptionの考えられる原因
oracle.rules.rl.FactClassException: fact class for 'X' should be declared earlier in rule session
ファクト・コンテキスト・ルールは、次のとおりです。
XがYのサブクラスまたはサブインタフェースである場合、Yはファクト・コンテキストでXの前に出現する必要があります。ファクト・コンテキストは、fact-class宣言、ルール・ファクト・パターン、またはassert、assertXPath、retractの引数です。
場合によっては、ファクト・コンテキストを考慮する必要があります。たとえば、次のようなXMLスキーマがあるとします。
<schema> <element name=A type=T/> <complexType name=T> <sequence> <element name=B type=T/> </sequence> </complexType> </schema>
JAXBでは次のように生成されます。
interface T { List getB(); // List has TImpl objects } interface A extends T; class AImpl implements A extends TImpl; class TImpl implements T;
ファクト・コンテキスト内の出現順が次のようになる例の場合
fact
class
T
assertXPath
AImpl
assert
TImpl
(assertXPath
実装で内部的に実行)
AImpl
は順序付けでTImpl
より前にありますが、AImpl
はTImpl
を拡張します。このため例外が発生します。このファクト・コンテキストの修正は、手順2の前の任意の場所でfact class TImpl;
を明示的に発行することです。
import文では、Javaクラスの参照時にパッケージ名修飾を省略できます。
フォーマット
import ::= import ( Java-class-name | Java-package-name.* ) ;
Java-package-name ::= qname
使用方法
インポート・コマンドはルールセット内に配置でき、インポートのスコープがimportが置かれているルールセットであることを暗黙的に示しますが、実際にはグローバルに適用されます。 たとえば、次のコードでインポートのスコープがルールセットに限定されている場合は、r2
のPrintWriter
参照はコンパイルされません。
class X { } ruleset rl { import java.io.*; rule A { if ( fact X ) {
@ PrintWriter pw = null; } } } ruleset r2 { rule B { if ( fact X ) { @ PrintWriter pw = null; } } }
フォーマット
内容は次のとおりです。
URL: 有効なUniform Resource Locator。
使用方法
file:
およびhttp:
スキームがサポートされています。
例
include file:example.rl;
RL Languageの式では、一般的なJava構文が使用されます(これから説明するような多少の違いはあります)。例を次に示します。
(a + 1) * (b - 2)
式は条件またはアクションで使用しますが、いくつか制限事項があります。式は厳密に型指定されます。
フォーマット
expression ::= boolean-expression
| fact-set-expression | object-expression
フォーマット
boolean-expression ::= boolean-assignment
| boolean-expression ? boolean-expression : boolean-expression
| boolean-expression || boolean-expression
| boolean-expression && boolean-expression
| numeric-expression equal-op numeric-expression
| object-expression equal-op object-expression
| boolean-expression equal-op boolean-expression
| object-expression instanceof type-name
| numeric-expression relop numeric-expression
| string-expression relop string-expression
boolean-assignment ::= boolean-target-expression = boolean-expression
type-name ::= qname
使用方法
文字列に対して、<
はUnicode UCS2コード・ポイントの順序です。
オブジェクトに対して!=
を使用すると、オブジェクト参照が等価でないことはテストされず、equalsメソッドの否定になります。
次の文について考えてみます。
if (object1 != object2){}
これは、次の文と同じです。
if (! (object1.equals(object2)){}
Javaとは異なり、RL Languageはオブジェクト参照が等価であることのテストをサポートしていません。
例
例2-26に、RL Languageでのブール式の使用方法を示します。
例2-26 RLブール式
if ( (true ? "a" < "b" : false) && (1 == 0 || 1.0 > 0) && "x" instanceof Object ) { println("all true"); };
数式では、Javaと同じく、他のオペランドが浮動小数点の場合、整数オペランドは浮動小数点に暗黙的に変換されます。表2-1に、その他の暗黙的な変換が示されています。
フォーマット
numeric-expression ::= numeric-assignment
| boolean-expression ?numeric-expression : numeric-expression
| numeric-expression( + | - ) numeric-expression
| numeric-expression ( * | / | % ) numeric-expression
| numeric-expression ** numeric-expression
| ( numeric-cast ) numeric-expression
| ( + | - ) numeric-expression
| ( ++ | -- ) numeric-primary-expression
| numeric-primary-expression [ ++ | -- ]
numeric-assignment ::= numeric-target-expression ( = | += | -= | *= | /= | %= ) numeric-expression
numeric-cast ::= numeric
使用方法
表2-5は、numeric-expressionの優先順位を降順に示しています。
表2-5 式演算子の優先順位
記号 | カテゴリ | 説明 |
---|---|---|
|
後置インクリメントまたは後置デクリメント |
numeric-primary-expression [ ++ | -- ] |
|
前置インクリメントまたは前置デクリメント |
( ++ | -- ) numeric-primary-expression |
- + |
単項マイナスまたは単項プラス |
( + | - ) numeric-expression |
(型) |
型キャスト |
( numeric cast ) numeric-expression |
|
指数 |
|
|
乗算または除算または剰余 |
numeric-expression ( * | / | % ) numeric-expression |
|
加算または減算 |
numeric-expression( + | - ) numeric-expression |
条件 |
||
= |
代入演算子 |
numeric-target-expression ( = | += | -= | *= | /= | %= ) numeric-expression |
Javaと同様に、式は連結演算子+
を使用して文字列に変換できます。RL Languageでは、Javaと異なり、配列が文字列に変換されるとき、配列の目次が文字列に変換され、配列の要素はカンマで区切られて中カッコで囲まれます。RL Languageクラスのインスタンスが文字列に変換されるときは、クラス名の後に、プロパティ値のペアが、カンマで区切られ、カッコで囲まれて表示されます。このRL Languageの機能は、ロギング、トレースおよびデバッグに便利です。
String
であるオペランドに+
演算子が適用されると、すべてのオペランドがStrings
に変換され、オペランドが連結されます。
フォーマット
string-expression ::= string-assignment
| boolean-expression ? string-expression : string-expression
| string-expression + expression
| expression + string-expression
|
string-assignment ::= string-target-expression ( = | += ) string-expression
例
例2-27に、RL Languageでの文字列式の使用方法を示します。この例では、"1 2.0 true {1,2}"と出力されます。
例2-27 RL文字列式
int i = 1; double f = 2.0; boolean b = true; int[] v = new int[]{i, 2}; println(i + " " + f + " " + b + " " + v);
RL Languageの配列はJavaの配列と同様に動作しますが、1次元に制限されています。配列のベース型は、配列のメンバーの型です。すべてのメンバーが同じ型であることが必要です。配列の要素に配列を含めることができますが、これが可能であるのは、包含配列の型がObject[]
の場合のみです。
注意: RL Languageではマルチディメンション配列は直接サポートされていません。 |
フォーマット
array-expression ::= array-assignment
| boolean-expression ?array-expression : array-expression
| ( array-cast ) ( array-expression | object-expression )
array-assignment ::= array-target-expression = array-expression
array-cast ::= type
使用方法
array-castの型は配列型であることが必要です。
fact-set-expressionでは、作業メモリーからのファクトの照合、フィルタ処理およびファクトを戻す処理が実行されます。fact-set-expressionはrule fact-set-conditionでのみ有効です。if
キーワードはfact-set-conditionを示しますが、fact-set-conditionはifアクションとは異なります。ルールのfact-set-conditionでは、fact-set-conditionと一致するファクト・セット内のすべての行が反復されます。ifアクションではブール式がテストされます。
フォーマット
fact-set-condition ::= if fact-set-expression
fact-set-expression ::= fact-set-expression || fact-set-expression
| fact-set-expression && fact-set-expression
| fact-set-expression && boolean-expression
| exists fact-set-expression
fact-set-pattern ::= fact [ ( property-pattern ( , property-pattern )* ) ]
[ var ] local-object-variable
local-object-variable ::= identifier
property-pattern ::= property-name : field-pattern
field-pattern ::= var local-property-variable | constraint
local-property-variable ::= identifier
simple-expression ::= string literal
| numeric literal
constraint ::= simple-expression
property-name ::= name
aggregate ::= aggregate fact-set-expression : aggregate-spec ( , aggregate-spec )*
aggregate-spec ::= aggregate-function [ var ] identifier
average ( numeric-expression )
| sum ( numeric-expression )
| minimum ( comparable-expression )
| maximum ( comparable-expression )
| count ()
| collection ( object-expression )
| user-defined ( expression type Tin )
user-defined ::= qname
使用方法
fact-set-expressionでは、戻すファクトを制限できます。この制限には、制約としてfact-set-patternでsimple-expressionを使用するか、またはfact-set-expressionでサポートされている演算子を使用します。
fact-set-expressionには次のものを含めることはできません。
演算子の優先順位はJavaと同様です。優先順位を指定するにはカッコを使用します。例を次に示します。
fact person var p && (p.age < 21 || p.age > 65)
カッコがない場合は、p.age
のp
は未定義です(演算子の優先順位の詳細は表2-5を参照)。
local-object-variableまたはlocal-property-variableは、パターンに続いていて、&&
演算子で連結されるパターンに続くすべての式に対するスコープ内にあります。パターンがexists
、||
または!
式に含まれていない場合は、変数もルールのaction-blockのスコープ内にあります。&&
'ed式では、戻されるファクトをフィルタ処理して、フィルタで除外されなかったファクトのみを戻すことができます。
ファクト・セット・パターン - 作業メモリーからのフェッチ
最も基本的なfact-set-expressionは、作業メモリーにアサートされている特定クラスのファクトの一部またはすべてを戻すfact-set-patternです。fact-set-patternでは、作業メモリーが検索され、特定クラスのファクト、およびプロパティ値にオプションのconstraintがあるファクトが検出されます。戻されるファクト・セットには、各一致ファクトに対する行が含まれます。各行を表すようにローカル行変数を定義するか、または行内のフィールドを表すようにローカル・フィールド変数を定義できます。ローカル行変数が指定されない場合は、各行を表すためにクラスのqnameの名前部分を使用できます(例2-31を参照)。
結合演算子
&&
演算子では、2つのfact-set-expressionオペランドのクロス積(結合)が定義されます。fact-set-expression &&
演算子の左側はファクト・セットであることが必要です。結合演算子の右側は別のfact-set-expressionです。2つのファクト・セットに&&
演算子を適用した結果は結合ファクト・セットです。
フィルタ演算子
&&
演算子では、左側のfact-set-expression内のファクトの中で、右側のboolean-expressionと一致しないファクトを排除するフィルタ演算子が定義されます。フィルタの左側はfact-set-expressionであることが必要です。フィルタの右側はboolean-expressionです。
フィルタの右側には、var
キーワードを使用して、左側で定義されている変数の参照を含めることができます。
和集合演算子
||
演算子では、2つのfact-set-expressionオペランドの和集合が定義されます。||
演算子をfact-set-expressionに適用するときは、次の点に注意してください。
式のvar
は、包含式の外部で参照できません。
||
は、その入力ファクト・セットの連結を戻しますが、生成されたファクト・セットの内容にはアクセスできません。 したがって、||
は通常、!
またはexists
式で使用されます。条件内で最上位の||
を使用するかわりに、条件で定義されているvar
をaction-block内で参照できるように、最上位の&&
演算子で2つ以上のルールを使用することをお薦めします。
注意: 次の構成について考えてみます。if (fact X || fact W) {}
|
空演算子
!
演算子では、fact-set-expressionが空であるかどうかがテストされます。 !
をfact-set-expressionに適用するときは、次の点に注意してください。
式のvar
は、包含!
式の外部で参照できません。
!
演算子では、fact-set-expressionが空である場合は単一の行が戻され、空でない場合は空のファクト・セットが戻されます。
存在(非空)演算子
exists
演算子では、fact-set-expressionが空でないかどうかがテストされます。
exists
演算子をfact-set-expressionに適用するときは、次の点に注意してください。
式のvar
は、包含exists
式の外部で参照できません。
exists
では、式が空でない場合は単一の行が戻され、空の場合は空のファクト・セットが戻されます。
varキーワード
var
を使用するときは、ファクトは、(元の名前を使用するのではなく)var
で定義された変数を使用してのみ参照可能であることに注意してください。したがって、次の例はaction.kind
が定義されていると仮定して動作します。
if (fact action) { println(action.kind); }
しかし、次の例の場合、var a
が定義された後では、action.kind
参照で構文エラーが発生します。これは、var a
の定義後はa.kind
を使用する必要があるためです。
if (fact action var a) { println(action.kind); }
集計
表2-6 集計関数
関数 | 説明 |
---|---|
|
一致するファクトの平均を計算します。結果は |
|
一致するファクトの合計を計算します。結果は |
|
結果は |
|
一致するファクトの最小値を計算します。 |
|
一致するファクトの最大値を計算します。 |
|
結果はファクトの |
ユーザー定義 |
結果の型がToutのユーザー定義関数。 |
RL Languageでは、1つ以上の集計関数をfactRowCollection
に適用し、集計結果をパターン変数にバインドする集計パターンがサポートされています。 通常のSQL組込み集計関数がサポートされており、ユーザー指定のJavaクラスが提供されている場合はユーザー定義の集計関数がサポートされます。
集計関数でプリミティブ型のラッパー型(Long、Doubleなど)を使用する場合、それらのラッパー型は、結果のバインド変数に適切なRAWプリミティブ型が設定されるように変換されます。
集計関数のファクト式が空の場合、ルールは起動されません。 したがって、式に対する一致ファクトがない場合は、集計関数では、そのコンテキスト内で意味を持たない数値は戻されません。 たとえば、サイズがゼロ(0)に設定されたプロパティを合計しても意味がありません。
たとえば、平均より高い給与が支払われている従業員の名前を出力します。
if fact Emp emp && aggregate fact Emp(salary: var sal) : average(sal) var avgSal && emp.salary > avgSal { println(emp.name); }
給与が100,000ドルを超える従業員の平均給与より高い給与が支払われている従業員の名前を出力します。
if fact Emp emp && aggregate fact Emp(salary: var sal) && Emp.salary > 100000 average(sal) var avgSal && emp.salary > avgSal { println(emp.name); }
ユーザー定義の集計関数をサポートするには、次の内容を実装した、引数のないパブリック・コンストラクタを持つuser-defined
という名前のパブリック・クラスを用意します。
public interface IncrementalAggregate<Tin, Tout> extends Serializable { public void initialize(); public void add(Tin value); public void remove(Tin value); public Tout getResult(); public boolean isValid(); }
実装では次の起動順序をサポートする必要があります。
new (initialize (add|remove)+ isValid getResult)*
isValid
では、ユーザー定義の集計の結果が有効のときはtrue
、無効のときはfalse
が戻される必要があります。
例
例2-28は、値が1のすべてのCounter
ファクトに対してアクションがアジェンダに配置されることを示しています。
例2-28 Counter.valueに対するファクト・セット式
class Counter { int id; int value; } rule ex1a { if (fact Counter c && c.value == 1) { println("counter id " + c.id + " is 1"); } }
例2-29は、constraintを使用して例2-28のルールを表す同等の方法を示しています。
例2-29 ファクト・セット制約の使用
rule ex1b { if (fact Counter(value: 1) c) { println("counter id " + c.id + " is 1"); } } assert(new Counter(id: 99, value: 1)); run(); // prints twice, once for each rule
例2-30は、ファクト・セットの無効な使用方法を示しています。これは、c
が定義前に使用されているためです。
例2-30 ファクト・セットの無効な使用方法
rule ex2 { if (c.value == 1 && fact Counter c) { println("counter id " + c.id + " is 1"); } }
例2-31は、プロパティa2==0
で、相当する最初の要素であるCounterと一致しないすべてのAttFacts
に対してアクションがアジェンダに配置されることを示しています。
例2-31 Counterファクトについて&&を使用したファクト・セットの使用
class AttFact {int a1; int a2;} rule ex3 { if (fact AttFact(a2: 0) && ! fact Counter(id: AttFact.a1)) { println(AttFact.a1); } } assert(new AttFact()); // will match because a1=a2=0 assert(new AttFact(a1: 1, a2: 0)); // will not match run(); // rule fires once
例2-32は、条件if (fact Ca a && fact Cb(v: a.v) b)
が次のように解釈されることを示しています。
fact Ca a
では、a(v: 1), a(v: 2), a(v: 3)
を含んだファクト・セットが戻されます。
&&
演算子では、2つの行{a(v: 1),b(v: 1)}, {a(v: 2),b(v: 2)}
を含んだファクト・セットが戻されます。
例2-32 &&演算子を使用したファクト・セットの使用
class Ca {int v;} assert(new Ca(v: 1)); assert(new Ca(v: 2)); assert(new Ca(v: 3)); class Cb {int v;} assert(new Cb(v: 0)); assert(new Cb(v: 1)); assert(new Cb(v: 2)); rule r { if (fact Ca a && fact Cb(v: a.v) b) { println("row: " + a + " " + b); } } run(); // prints 2 rows
比較式では、==、!=、<、<=、>および>=演算子を使用して、java.lang.Comparableを実装するオブジェクトを比較できます。この式を使用すると、日付を簡単に比較できます。また、金額を表すために通常使用されるBigDecimal
をこの式で比較できます。
フォーマット
qname(java.lang.Comparableを実装する型の変数) | (java.lang.Comparableを実装する型の)member
フォーマット
object-expression ::= object-assignment | ( ob-cast ) object-expression | boolean-expression ? object-expression : object-expression
object-assignment ::= object-target-expression = object-primary-expression
ob-cast ::= object-type
1次式には、変数、プロパティ、配列要素、クラス・メンバー、およびその他の密バインディングの式構文(リテラル、メソッドや関数のコール、オブジェクトやファクトの構成など)の代入ターゲットが含まれます。構文は、記述されている場合を除いてJavaとほぼ同じです。
フォーマット
primary-expression ::= array-primary-expression
| (配列を戻す)function-call
| (1次元のJava配列を戻す)method-call*
| ( array-expression )
simple-type [ numeric-expression integer ]
| numeric [ ] { numeric-expression ( , numeric-expression )* }(数式は暗黙的にベースに変換可能であることが必要)
| boolean [ ] { boolean-expression ( , boolean-expression )* }
| object-type [ ] { object-expression ( , object-expression )* }
)
qname(配列型の変数)
| (配列型の)member
| array-primary-expression(ベース型はObject)[ numeric-expression int ]
文字列リテラル (「リテラル」を参照)
| object-primary-expression(オブジェクトはjava.lang.String)
string-target-expression ::= object-target-expression(オブジェクトはjava.lang.String)
numeric-primary-expression ::=
数値リテラル
| (数値を戻す)function-call
| (数値を戻す)method-call
| array-primary-expression . length
| ( numeric-expression )
qname(数値型の変数)
| (数値型の)member
| array-primary-expression(ベース型は数値) [ numeric-expression ]
boolean-primary-expression ::=
| (ブールを戻す)function-call
| (ブールを戻す)method-call
| ( boolean-expression )
boolean-literal ::= true | false
qname(ブール型の変数)
| (ブール型の)member
| array-primary-expression(ベース型はブール)[ numeric-expression int ]
new class-definition-name ( [ expression ( , expression )* ] 引数リスト)
| new class-definition-name ( [ property-pattern ( , property-pattern )* ] プロパティと値のペア)
| (Javaオブジェクトを戻す)function-call
| (Javaオブジェクトを戻す)method-call
qname(オブジェクト型の変数)
| (Javaオブジェクト型の)member
| array-primary-expression(ベース型はオブジェクト) [ numeric-expression int ]
function-call ::= qname関数名( [ expression ( , expression )* ] 引数リスト)
method-call ::= object-primary-expression .identifier メソッド名( [ expression ( , expression )* ] 引数リスト)
member ::= object-primary-expression .identifier メンバー名
例
例2-33は、RL Languageリテラル構文(Javaと同じです)を示しています。
メソッドおよび関数はオーバーロードできます。ただし、Javaとは異なり、RL Languageでは、実際の引数リストとオーバーロード関数の照合に前詰め法が使用されます。
例2-34にオーバーロードの例を示します。
例2-34 オーバーロード
function f(int i); function f(Object o); function f(String s); // can never be called f(1); // calls first f f("a"); // calls second f, because "a" is an Object
RL Languageクラスにはユーザー定義コンストラクタはありません。デフォルト・コンストラクタによって、プロパティはデフォルト値に初期化されます。RL Languageのnew
演算子では、一部のプロパティ値を指定できます(Java Beanのプロパティに対しても動作します)。
Java Beanのプロパティにはgetterはありsetterがない場合があります。このようなプロパティは変更できません。
例
Javaと異なり、RL Languageにはアクション・ブロックが必要であり、単一のセミコロンの終了アクションは許可されていません。
フォーマット
action ::= action-block | if | while | for | try | synchronized | return | throw
| assign | incr-decr-expression | primary-action
action-block ::= { ( variable | action )* }
使用方法
アクション・ブロックは、任意の数のローカル変数宣言とアクションです。変数は、同じアクション・ブロック内の後続の変数初期化式およびアクションで参照可能です。
RL Languageでは、Javaとは異なり、すべてのローカル変数が宣言時に初期化される必要があります。ローカル変数はファイナルにはできません。
終了するには、アクション内からSystem.exit(int)メソッドを起動できます。
例
if elseアクションを使用すると、テストがtrue
の場合は最初のアクション・ブロックが実行され、テストがfalse
の場合はオプションのelse部分(別のifアクションまたはアクション・ブロックの場合があります)が実行されます。
Javaと異なり、RL Languageにはアクション・ブロックが必要であり、単一のセミコロンの終了アクションは許可されていません。
フォーマット
if ::= if if-test action-block [ else if | action-block ]
if-test ::= boolean-expression
例
例2-37は、RL Languageのif elseアクション・ブロックを示しています。例2-38は、アクション・ブロックが必要であることを示しています。
例2-37 if elseアクションの例
String s = "b"; if (s=="a") { println("no"); } else if (s=="b") { println("yes");} else { println("no"); }
テストがtrue
の間はアクション・ブロックが実行されます。return、throwまたはhaltでアクション・ブロックを終了できます。
フォーマット
while ::= while while-test action-block
while-test ::= boolean-expression
使用方法
Javaと異なり、RL Languageにはアクション・ブロックが必要であり、単一のセミコロンの終了アクションは許可されていません。
例
例2-39では"bye"が2回出力されます。
RL Languageには、Javaと同じくforループがあります。forアクション・ブロックを使用すると、for-initが実行され、その後boolean-expressionがtrue
の間は、指定のアクション・ブロックが最初に実行された後、for-updateが実行されます。return、throwまたはhaltでアクション・ブロックを終了できます。
フォーマット
for ::= for ( for-init ; boolean-expression ; for-update ) action-block
for-init ::= variable | for-update
for-update ::= incr-decr-expression | assign | primary-expression
使用方法
RL Languageでは、for init
またはfor update句内でカンマ区切りの式リストは使用できません(Javaでは使用できます)。
例
例2-41は、int[]
をdouble[]
に変換するRL Languageコードを示しています。
例2-41 forアクション
int[] is = new int[]{1,2,3}; double[] fs = is; // error! double[] fs = new double[3]; for (int i = 0; i < is.length; ++i) { fs[i] = is[i]; } println(fs);
最初のアクション・ブロックが実行されます。実行時にスローされた、catch句のThrowable
クラスと一致する例外が捕捉されます。最初の一致については、関連付けられたcatchアクション・ブロックが実行されます。Throwable
クラス・インスタンスが特定の識別子にバインドされ、catchアクション・ブロックで使用できるようになります。tryアクション・ブロックで例外がスローされるかどうかに関係なく、finallyアクション・ブロックが指定されている場合は、finallyアクション・ブロックが実行されます。
捕捉されない例外は、RL Languageコマンドラインを使用しているときはエラー・メッセージとして出力され、RuleSessionのexecuteRuleset
またはcallFunction
メソッドのいずれかを使用しているときはRLExceptions
としてスローされます。RL Languageのtry
、catch
およびfinally
は、構文およびセマンティクスの両方においてJavaと類似しています。少なくとも1つのcatch
またはfinally
句が必要です。
フォーマット
try ::= try action-block
( catch (class-implementing-throwable identifier ) action-block )*
[ finally action-block ]
class-implementing-throwable ::= qname
使用方法
RL Languageで例外を補足する方法を完全に理解するには、ルール実行時にスタック・フレームがどのようにネストされているかを理解する必要があります。ルールでは、関数またはメソッドで他の関数またはメソッドがコールされるように他のルールはコールされません。したがって、あるルールのアクション・ブロックでcatchブロックを使用して、別のルールのアクション・ブロックの例外を補足することはできません。ルール起動時にスローされた例外は、起動ルールのアクション・ブロックで処理されるか、またはルールの起動元であるrun、runUntilHaltまたはstep関数のコール元で処理される必要があります。
例
例2-42は、try catchおよびfinallyアクションを示しています。この例の実行結果は次のとおりです。
exception in invoked Java method this is really bad! but at least it's over!
例2-42 try catchおよびfinallyアクション・ブロック
try { throw new Exception("this is really bad!"); } catch (Exception e) { println(e.getMessage()); println(e.getCause().getMessage()); } finally { println("but at least it's over!"); }
RL Languageでは、明示的にスローされたException ("this is really bad!")
は、起動されたJavaメソッドの例外として処理され、Exception
はJavaException
にラップされます。明示的にスローされたException
は、JavaException
の原因として使用できます。
Javaと同様に、synchronizedアクションは、複数スレッドのアクションの同期化に役立ちます。synchronizedアクション・ブロックを使用すると、指定したオブジェクトのロックを取得してからaction-blockを実行し、実行後にロックを解放できます。
フォーマット
synchronized ::= synchronized object-primary-expression action-block
例
例2-43は、Person
オブジェクトの名前を変更し、旧姓をニックネームに追加し、Javaオブジェクトの同時読取りユーザー(同時に同期化中)がPerson
の一貫したビューを参照するように同期化します(Person
Beanの詳細は例2-12を参照)。
例2-43 synchronizedアクション
import example.Person; // this Java bean is defined in example J1 function changeName(Person p, String first, String last) { synchronized(p) { java.util.Set s = p.getNicknames(); s.add(p.getFirstName()); s.add(p.getLastName()); p.setFirstName(first); p.setLastName(last); } assert(p); } Person person = new Person("Elmer", "Fudd", new String[]{"Wabbit Wuver"}); println(person.nicknames.toArray()); changeName(person, "Bugs", "Bunny"); println(person.nicknames.toArray());
modifyアクションでは、関連付けられた式を使用して名前付きプロパティが更新されます。また、関連付けられたシャドウ・ファクト(ある場合)も更新され、更新対象プロパティを参照し、true
と評価される条件を含むルールがアクティブ化されます。更新対象プロパティを参照しない条件を含むルールはアクティブ化されません。
変更対象のオブジェクトの引数には、すでにアサートされているオブジェクトを指定する必要があります。そうすれば、そのオブジェクトの値が更新され、スロット固有のセマンティクスを使用してネットワークが更新されます。結果はオブジェクトで、ネットワークは一貫した状態となります。
フォーマット
modify ::= modify (object-expression , property-update ( , property-update )* )
property-update ::= property-name : expression.
使用方法
通常、ファクトには、ルールによって設定または変更されるプロパティがあります。たとえば、あるアプリケーションの顧客には、""、"silver"または"gold"のステータスが設定されます。このステータスは、顧客の他のプロパティや関連ファクト(過去の注文など)を調べるルールによって設定されます。また、通常、これらの計算されたプロパティは、追加のルール条件で使用されます。たとえば、goldの顧客には10%の割引を与える場合があります。ファクトを変更しそのファクトを再アサートするルールでは、ルール自体が何度も繰り返してリアクティブされないように、追加の条件を付加する必要があります。たとえば、次のルールは1回起動されると、その後何度も繰り返して起動されます。
if fact Customer c && c.pastYearSpend > 1000 { c.status = "gold"; assert(c); }
次のルール定義を使用すると、このループを修正できます。
if fact Customer c && c.pastYearSpend > 1000 && c.status != "gold" { c.status = "gold"; assert(c); }
例2-44では、ループは回避されますが、goldの顧客を検索するルールがアクティブ化されません。
例2-44 避ける必要がある不適切なルール・プログラミング方法を示す例
if fact Customer c && c.pastYearSpend > 1000 { c.status = "gold"; }
例2-44は不適切なルール・プログラミング方法を示しています。顧客オブジェクトの値を変更しますが、そのシャドウである顧客ファクトの値を変更しないため不適切です。modifyアクションを使用すると、オブジェクトとファクトを同時に変更できます。modifyアクションでは、変更対象プロパティをテストするルールもアクティブ化されますが、変更対象でないプロパティをテストするルールはアクティブ化されません。
if fact Customer c && c.pastYearSpend > 1000 { modify(c, status: "gold"); }
このルールは、テスト対象プロパティと変更対象プロパティが別々であるため、ループしません。このルールは、ステータス=="gold"をテストする後続のルールを起動するための推論で使用できます。
次のルールは、無限ループを示す別のルールです。
所得が50,000ドル以上の従業員には、5%の昇給を適用します。
if Employee emp && emp.sal > 50000 { modify(emp, sal: sal * 1.05); }
このルールは、変更対象プロパティと同じプロパティ(sal
)をテストし、変更後にテストがtrue
となるため、modifyを使用しても自己トリガーします。この場合、ループを回避するために、次のようにraise
プロパティをテストに追加することもできます。
if Employee emp && emp.sal > 50000 && !emp.raise { modify(emp, sal: emp.sal * 1.05, raise: true); }
また、この場合のループを回避するために、raiseを処理するファクトを追加することもできます。例を次に示します。
public class RaiseGiven { Employee emp; // or possibly just an employee ID } if Employee emp && emp.sal > 500000 && !RaiseGiven(emp: emp) { modify(emp, sal: sal * 1.05); assert(new RaiseGiven(emp: emp)); }
returnアクションでは、関数またはルールのアクション・ブロックから制御が戻されます。
ルール内のreturnアクションでは、ルールセット・スタックからルールセットが削除されるため、実行は、現在ルールセット・スタックの最上位にあるルールセットからのアジェンダに存在するアクティブ化で続行されます。
ルールの実行がrunまたはstep関数で開始され、returnアクションによってルールセット・スタックから最後のルールセットが削除された場合、制御はrun
またはstep関数のコール元に戻されます。
ルールの実行がrunUntilHalt関数で開始された場合、returnアクションではルールセット・スタックから最後のルールセットは削除されません。最後のルールセットは、残っているアクティブ化がなくなったときにrunUntilHaltで削除されます。その後、Oracle Rules Engineは次のアクティブ化の出現を待機します。アクティブ化が出現すると、ルールセットの起動が再開される前に、ルールセット・スタックに最後のルールセットが配置されます。
フォーマット
return ::= return [ return-value] ;
return-value ::= expression
関数にreturns
句がある場合、return-valueが指定され、その型がreturns
句で指定されている型であることが必要です。
使用方法
ルールまたはfunction
内でreturns
句が指定されていないreturnアクションでは、return-valueは指定しないでください。
例外がスローされます。例外は、java.lang.Throwable
を実装するJavaオブジェクトであることが必要です。スローされた例外は、tryアクション・ブロック内のcatch
で捕捉できます。
フォーマット
throw ::= throw throwable ;
throwable ::= object-primary-expression
RL Languageの代入は、Javaと同様に、アクションとして出現可能な式です。
フォーマット
assign ::= assignment-expression ;
assignment-expression ::= boolean-assignment
例
例2-45は、RL Languageの代入式の使用方法を示しています。この例では"6 5
"と出力されます。
RL Languageのインクリメントまたはデクリメントは、Javaと同様に、アクションとして出現可能な式です。
フォーマット
incr-decr ::= incr-decr-expression ;
incr-decr-expression ::= ( ++ | -- ) numeric-target-expression | numeric-target-expression ( ++ | -- )
例
例2-46は、RL Languageのデクリメント・アクションの使用方法を示しています。この例では"0
"と出力されます。
基本アクションは、関数コール、assertまたはJavaメソッド・コールなど、その二次的作用のために実行される基本的な式です。たとえば、println
関数は基本アクションとしてよく使用されます。
フォーマット
primary-action ::= primary-expression ;
ルールグループでは、デシジョン表のオーバーライドがサポートされます。これにより、1つのルールで1つ以上の別のルールをオーバーライドするというデシジョン表の機能がサポートされます。
フォーマット
rulegroup ::= rulegroup rulegroup-name { rulegroup-property* ( rule | rulegroup )* }
rulegroup-name ::= identifier
rulegroup-property ::= mutex
mutex ::= mutex = boolean-literal ;
使用方法
ルールグループ構成は、ルールセットの最上位の構成です。ルールグループには、オプションのbooleanプロパティがあります。
mutex: mutexプロパティでは、ルール間での相互排他が可能です。mutexをtrueに設定した同一のルールグループに複数のルールが存在する場合がよくあります。より複雑なルールグループ階層の場合、最も近くにある共通の祖先のルールグループのmutexをtrueに設定すると、2つのルールが相互に除外されます。ルールが起動されると、相互に除外されるルールの既存のアクティブ化がアジェンダから削除され、起動されなくなります。これらのアクティブ化は、それらをアジェンダに配置した一連のファクトによる識別どおりに直接関連付ける必要があります。このことから、相互に除外されるすべてのルールの条件は、同じ順序で指定された同じファクト句を持つという要件が生じます。当然デシジョン表の場合も必要です。
例
例2-47は、mutexプロパティを含むルールグループの使用方法を示しています。r2とr3は、ルール条件で同じ一連のファクト・タイプを同じ順序で参照していることに注意してください。これは、mutexグループ内では必須です。パターンのテストは、異なる場合があります。mutexグループのルール条件の形式に対する制限は、その子孫グループにも適用されます。したがって、ルールr4およびr5も、同じ一連のファクト・タイプを同じ順序で参照する必要があります。Aの1つのインスタンスとBの1つのインスタンスがアサートされており、r1、r2、r3、r4およびr5がアジェンダにアクティブ化を持つものと想定します。r3は、より優先度が高いため起動されます。r2のアクティブ化は、起動されることなく削除されます。これは、r2がmutex=trueを指定したグループ内にあるためです。グループ2はグループ1のメンバーであるため、r4およびr5のアクティブ化も起動されることなく削除されます。ルールr1は、起動されます。ここで、r2、r4およびr5がアジェンダにアクティブ化を持ち、r4が最初に起動されるものと想定します。r2のアクティブ化は、起動されることなく削除されます。これは、相互に起動されているグループ2のすべてのルールでr2とr3の両方が除外されるためです。r5は起動されます。グループ2ではmutex=trueを指定していないため、これは相互に除外されません。
例2-47 ファクト参照順序が指定されたルールグループを含むルールセット
ruleset set1 { rule r1 { ... } rulegroup group1 { mutex = true; rule r2 { if fact A && fact B ... { ... }} rule r3 { priority = 2; if fact A && fact B ... { ... }} rulegroup group2 { rule r4 { if fact A && fact B ... { ... }} rule r5 { if fact A && fact B ... { ... }} } } }
この項では、次のRL Language組込み関数について説明します。
assert、assertTree、assertXPath、clearRule、clearRulesetStack、clearWatchRules、clearWatchActivations、clearWatchFacts、clearWatchFocus、clearWatchCompilations、clearWatchAll、contains、getCurrentDate、getEffectiveDate、getFactsByType、getRulesetStack、getRuleSession、getStrategy、halt、id、object、println、popRuleset、pushRuleset、retract、reset、run、runUntilHalt、setCurrentDate、setEffectiveDate、setRulesetStack、setStrategy、showActivations、showFacts、step、watchRules、watchActivations、watchFacts、watchFocus、watchCompilations
提供オブジェクトobjのプロパティに基づいて、ファクトを作業メモリーに追加するか、またはすでに作業メモリーにあるファクトを更新します。提供オブジェクトobjがJavaインスタンスの場合、プロパティは、関連付けられたBeanInfo
クラスまたはgetterメソッドとsetterメソッドの存在によって定義されるJava Beanプロパティです。objがRL Languageクラス・インスタンスの場合、プロパティはクラスのフィールドです。
フォーマット
function assert(Object obj);
使用方法
作業メモリー内のファクトは、提供オブジェクトobjのシャドウであり、このシャドウには、各プロパティpropのコピー、クローンまたは参照が含まれています。propがプリミティブ型である場合、propはシャドウのコピーです。propでJava Cloneable
インタフェースが実装される場合、propのクローン(シャロー・コピー)がシャドウ化されます。それ以外の場合、propの参照のみがシャドウ化されます。シャドウでそのオブジェクトのプロパティをコピーできる量が多いほど、複数のファクトに関するルールがより最適化されます。
RL LanguageでObject
に適用されるときの==
および!=
では、常にObject
equalsメソッドが起動されるため、シャドウにコピー、クローンまたは参照が含まれているかどうかは、RL Languageプログラムには透過的です。
アサートはアジェンダに影響を与える可能性があります。新規ファクトが原因でファクト・セットが戻されるようになった条件があるルールによって、アクティブ化がアジェンダに配置されます。!
を使用してファクトが存在しないことをテストするアクティブ化が、アジェンダから削除される可能性があります。ファクトの更新はアジェンダに影響を与える場合があります。変更されたファクトと一致しなくなったルール条件があるアクティブ化は、アジェンダから削除されます。変更されたファクトが原因でファクト・セットが戻される条件があるルールによって、アクティブ化がアジェンダに配置されます。
アサートは、objの状態の一部が更新され、ルール条件に影響を与える可能性がある場合に、作業メモリー内のファクトを更新するために使用してください。ただし、objがJava Beanであり登録プロパティ変更リスナーをサポートしている場合、および変更内容がすべてBeanプロパティの値である場合を除きます。
例
例2-48では"Pavi has highest salary 65000.0"と出力され、例2-49では"dept 10 has no employees!"と出力されます。
例2-48 highestSalaryルールでのassert関数の使用
class Emp { String ename; double salary; } rule highestSalary { if (fact Emp hi && !(fact Emp e && e.salary > hi.salary)) { println(hi.ename + " has highest salary " + hi.salary); } } Emp e1 = new Emp(ename: "Pavi", salary: 55000.00); assert(e1); // put in working memory Emp e2 = new Emp(ename: "Fred", salary: 60000.00); assert(e2); // put in working memory e1.salary += 10000.00; // Pavi is now the highest paid assert(e1); // MUST re-assert before allowing rules to fire run();
例2-49 emptyDeptルールでのassert関数の使用
import java.util.*; class Dept { int deptno; List emps = new ArrayList(); } rule emptyDept { if (fact Dept d && d.emps.isEmpty()) { println("dept " + d.deptno + " has no employees!"); } } Dept d = new Dept(deptno: 10); d.emps.add(e1); assert(d); // put in working memory with 1 employee d.emps.remove(0); assert(d); // MUST re-assert before allowing rules to fire run();
関連項目
assertTree組込み関数では、オブジェクト・ツリーのオブジェクトがファクトとしてアサートされます。
assertTree組込み関数では、JAXB 2.0がサポートされます。
フォーマット
assertTree(Object root)
assertTree(String spec, Object root)
使用方法
assertTree()シグネチャには、次の2つがあります。
assertTree(Object root)は、SDK2と一緒に使用する必要があります。このフォーマットでは、SDK2で生成された内部メタデータの指示に従って、オブジェクト・グラフが横断され、オブジェクトがアサートされます。
assertTree(String spec, Object root)は、SDK2を起動していないときに使用する必要があります。assertXPathと同様、specは、複数のパッケージをコロンで区切って指定できるように拡張されたパッケージ仕様です。このフォーマットでは、指定したパッケージのいずれかにオブジェクトが含まれる場合に、オブジェクトがアサートされ、オブジェクトのBeanプロパティが横断されます。通常、このパッケージ仕様は、JAXBContextを設定するときに使用されるものと同じです。
assertTree関数では、次のことが実行されます。
ルートで始まるオブジェクト、およびそのルートから参照されるすべてのファクト(参照可能なファクト・タイプが宣言されているオブジェクト)を再帰的にアサートします。
検出されたJAXBElementインスタンスをアサートし、それに含まれる値クラス・オブジェクトを抽出して続行します。
関連項目
assertXPath関数は非推奨です。かわりにassertTreeを使用してください。
指定した要素をルートとして使用してファクトのツリーを作業メモリーに追加し、XMLのxpathに似た式でツリー内のオブジェクトを定義します。pkgは、ツリー内のオブジェクトのクラスが含まれるJavaパッケージまたはRL Languageルールセットです。ツリー内のすべてのオブジェクトが同じパッケージまたはルールセット内に存在する必要があります。
要素および選択した子をアサートする以外に、親オブジェクトと子オブジェクトをリンクするXLinkファクトがアサートされます。ツリー内のすべてのオブジェクトのクラスで、RLクラス(rl-class-definition)またはfact-class宣言のsupports xpath(supports)句を使用する必要があります。
フォーマット
function assertXPath(String pkg, Object element, String xpath);
関連項目
名前付きのルールをルール・セッションから消去します。ルールのアクティブ化はすべてアジェンダから削除されます。
フォーマット
function clearRule(String name);
関連項目
フォーマット
function clearRulesetStack();
関連項目
getRulesetStack、getStrategy、popRuleset、pushRuleset、run、setStrategy
clearWatch関数は、デバッグ情報の出力を停止します。
フォーマット
function clearWatchRules();
function clearWatchActivations();
function clearWatchFacts();
function clearWatchFocus();
function clearWatchCompilations();
function clearWatchAll();
関連項目
watchRules、watchActivations、watchFacts、watchFocus、watchCompilations
contains()
関数はJava Collection
のcontains()
メソッドに似ていますが、コレクション内のJAXBElementの存在を処理する機能を持っています。
フォーマット
contains(Collection c, Object o) returns boolean
使用方法
contains()
は、コレクションc
内でJAXBElementを検出すると、そのJAXBElementから値クラスを取得して、オブジェクトo
と比較します。
関連項目
getCurrentDate関数では、CurrentDateファクトに関連付けられている日付が戻されます。
フォーマット
getCurrentDate() returns Calendar
使用方法
有効日と現在の日付は、直交する2つのアイテムです。 有効日は、有効開始日および有効終了日のプロパティに従って有効になっているルールを判別するのに使用します。 CurrentDateファクトでは、ルール・エンジンが管理している現在の日付を表すファクトを推論の対象にできます。
現在の日付を設定しても、有効日のセマンティクスには影響を与えません。
日付を推論の対象にするためのルールをルール内に明示的に作成する場合は、CurrentDateファクトを使用します。 有効開始日または有効終了日、あるいはその両方をルールに割り当て、データ内の日付から判別されるルールを有効にする場合は、setEffectiveDate()
を使用します。
関連項目
setCurrentDate、getEffectiveDate、setEffectiveDate
getEffectiveDate関数では、有効日の現在値が戻されます。
フォーマット
getEffectiveDate() returns Calendar
使用方法
有効日と現在の日付は、直交する2つのアイテムです。 有効日は、有効開始日および有効終了日のプロパティに従って有効になっているルールを判別するのに使用します。 CurrentDateファクトでは、エンジンが管理している現在の日付を表すファクトを推論の対象にできます。 どちらも明示的に設定できます。
現在の日付を設定しても、有効日のセマンティクスには影響を与えません。 有効日を設定しても、CurrentDateファクトには影響を与えません。
日付を推論の対象にするためのルールをルール内に明示的に作成する場合は、CurrentDate(setCurrentDate()
)を使用します。 有効開始日または有効終了日、あるいはその両方をルールに割り当て、データ内の日付から判別されるルールを有効にする場合は、setEffectiveDate()
を使用します。
関連項目
setEffectiveDate、getCurrentDate、setCurrentDate
指定したクラスのインスタンスである、作業メモリー内のすべてのファクトのリストが戻されます。
フォーマット
function getFactsByType(String className) returns List
関連項目
showFacts、watchRules、watchActivations、watchFacts、watchFocus、watchCompilations
ルールセット・スタックをルールセット名の配列として戻します。
フォーマット
function getRulesetStack() returns String[];
使用方法
戻り値: ルールセット名の配列としてのルールセット・スタック
スタックの最上位であるエントリ0(ゼロ)はフォーカス・ルールセットです。フォーカス・ルールセットは、後続のrun、runUntilHaltまたはstep関数の実行によってアクティブ化が最初に起動されるルールセットです。
関連項目
clearRulesetStack、getStrategy、popRuleset、pushRuleset、setRulesetStack、setStrategy
Java RuleSession
オブジェクトを戻します。RL Languageプログラムでは、このRuleSession
を使用して、新規のクラス、ルール、関数または変数を動的に定義できます。
フォーマット
function getRuleSession() returns RuleSession;
例
rule learn { if (fact f1 && …) { RuleSession rs = getRuleSession(); rs.executeRuleset("rule newRule { if fact f1 && fact f2 && … { … } }"); } }
関連項目
現在の方針を戻します。表2-7に、使用可能な方針の値が示されています。
フォーマット
function getStrategy() returns String;
関連項目
clearRulesetStack、getRulesetStack、popRuleset、pushRuleset、setStrategy
halt関数では、現在起動中のルールの実行が停止され、停止されたルールの実行元であるrun、runUntilHaltまたはstep関数に制御が戻されます。アジェンダはそのままであるため、後続のrun、runUntilHaltまたはstepを実行するとルールの起動を再開できます。
halt関数は、run、runUntilHaltまたはstep関数のコンテキスト外で起動された場合は効果がありません。
フォーマット
function halt();
関連項目
オブジェクトobjに関連付けられているファクトIDを戻します。objがファクトに関連付けられていない場合は、-1が戻されます。
フォーマット
function id(Object obj) returns int;
関連項目
特定のファクトIDに関連付けられているオブジェクトを戻します。ファクトIDがない場合は、nullが戻されます。
フォーマット
function object(int factId) returns Object;
関連項目
フォーマット
function println(char c);
function println(char[] ca);
function println(int i);
function println(long l);
function println(float f);
function println(double d);
function println(boolean b);
function println(Object obj);
スタックが空の場合、popRuleset
ではRLRuntimeException
がスローされます。スタックが空でない場合、popRuleset
ではスタックからフォーカスが削除され、戻されます。
すべてのエントリの位置が1つずつ下に移動します。新しいフォーカスは、スタックの新しい最上位であるエントリ0(ゼロ)です。
スタックの最上位であるエントリ0(ゼロ)はフォーカス・ルールセットです。フォーカス・ルールセットは、後続のrun、runUntilHaltまたはstep関数の実行によってアクティブ化が最初に起動されるルールセットです。
フォーマット
function popRuleset() returns String;
関連項目
clearRulesetStack、getRulesetStack、getStrategy、pushRuleset、setStrategy
特定のルールセットをスタックに追加し、そのルールセットをフォーカスにします。すでにフォーカスであるルールセットを追加するとエラーが発生します(このエラーについてはRLIllegalArgumentException
がスローされます)。
スタックの最上位であるエントリ0(ゼロ)はフォーカス・ルールセットです。フォーカス・ルールセットは、後続のrun、runUntilHaltまたはstep関数の実行によってアクティブ化が最初に起動されるルールセットです。
フォーマット
function pushRuleset(String focus);
例
例2-51は、pushRuleset
関数を使用したRL Languageを示しています。 例2-52は、popRuleset
関数を使用したRL Languageを示しています。
例2-51 pushRulesetの使用 - RLIllegalArgumentExceptionのスロー
clearRulesetStack(); pushRuleset("main"); // focus is "main" pushRuleset("main"); // RLIllegalArgumentException
例2-52 popRulesetの使用 - RLRuntimeExceptionのスロー
clearRulesetStack(); popRuleset(); // RLRuntimeException
関連項目
clearRulesetStack、getRulesetStack、getStrategy、popRuleset、setStrategy
オブジェクトobjに関連付けられているファクトを作業メモリーから削除します。
フォーマット
function retract(Object obj);
使用方法
取消しはアジェンダに影響を与える可能性があります。取り消されたファクトに依存するアクティブ化はアジェンダから削除されます。
(!
を使用して)ファクトが存在しないことをテストする条件があるルールによって、アジェンダに新しいアクティブ化が配置される可能性があります。
関連項目
作業メモリーからすべてのファクトを消去し、アジェンダからすべてのアクティブ化を消去して、非ファイナル・グローバル変数の初期化式を再評価します。
フォーマット
function reset();
関連項目
アジェンダに存在するルール・アクティブ化を、次の条件に該当するまで起動します。
ルール・アクションでhaltが直接または間接的にコールされるまで。たとえば、ルール・アクションによってコールされた関数でhaltがコールされる場合です。
アジェンダが空になるまで。
ルールセット・スタックが空になるまで。
フォーマット
function run() returns int;
function run(String rulesetName) returns int;
使用方法
引数rulesetNameが指定された場合は、ルールの起動前に、名前付きルールセットがルールセット・スタックの最上位に追加されます。
nullのrulesetNameが指定された場合、ルールセット・スタックはルールの起動前に変更されません。
rulesetNameが指定されず、デフォルトのmain
ルールセットがルールセット・スタック上に存在しない場合は、ルールの起動前に、main
がルールセット・スタックの最下位に配置されます。
戻り値: int
。起動されたルールの数。
関連項目
この関数では、haltがコールされるまでルール・アクティブ化が起動されます。runおよびstepとは異なり、runUntilHaltは、アジェンダが空になっても戻りません。また、runUntilHaltでは、ルールセット・スタックから最下位のルールセット名は削除されません。かわりに、アジェンダにアクティブ化が格納されるのを待機します。
フォーマット
function runUntilHalt() returns int;
使用方法
メインのRuleSessionスレッドがビジーであるときにアクティブ化をアジェンダに追加する唯一の方法であるrunUntilHaltの実行は、2番目のスレッドに対して行われ、次のいずれかが実行されます。
PropertyChangeListeners
を使用したJava Beanファクトの変更
assertまたはretract
関数の実行
runUntilHaltの使用時はルールを注意して設計する必要があります。たとえば、プロパティが最小値のファクトを検出しようとするルールは、ファクトの最初のインスタンスがアサートされたときに起動され、その後は、それより小さい値のプロパティが設定された別のインスタンスがアサートされるたびに起動されます。
関連項目
setCurrentDate
関数では、エンジンが管理している現在の日付を表すファクトを推論の対象にするための日付が設定されます(CurrentDate
ファクトを使用)。
フォーマット
setCurrentDate(Calendar newDate)
使用方法
RLIllegalArgumentException
例外は、newDate引数がnullの場合にスローされます。
ルール内で日付を明示的に推論の対象にする必要がある場合は、CurrentDate
ファクトを使用します。 有効開始日および有効終了日をルールに割り当て、データ内の日付から判別されるルールを有効にする場合は、setEffectiveDateを使用する必要があります。 setEffectiveDate関数は、CurrentDate
ファクトに影響を与えません。
デフォルトでは、現在の日付の値はルール・エンジンによって暗黙的に管理されます。 CurrentDate
ファクトの値は、組込み関数のrunファミリのいずれかが起動されると、現在のシステム日付に更新され、内部的に(再)アサートされます。 これは、任意のルールが起動される前に実行されます。そのため、新しい現在の日付はルール条件で評価されます。runUntilHaltの場合は、アジェンダにあるルールが0個から1個以上に遷移するたびに、この更新が実行されます。
一度setCurrentDate
関数を呼び出すと、現在の日付を必要に応じて更新する作業はユーザーの役割になります。ルール・エンジンでは、有効日が暗黙的に管理されなくなります。この状態は、reset関数を起動するまで存続します。 setCurrentDate
を使用して現在の日付を明示的に設定した場合、時間を逆戻りさせる(前の時点に設定される)ことになるsetCurrentDate
関数を起動すると、必ずエラーが発生し、RLIllegalArgumentException
がスローされます。 reset関数を起動すると、現在の日付が任意の値に設定される場合があります。
関連項目
getCurrentDate、getEffectiveDate、setEffectiveDate
setEffectiveDate関数では、ルール・エンジンの有効日が更新されます。
デフォルトでは、有効日の値はルール・エンジンによって暗黙的に管理されます。 この場合、組込み関数のrunファミリのいずれかが起動されると、有効日が現在のシステム日付に更新されます。これは、任意のルールが起動される前に実行されます。そのため、新しい有効日は、ルールの起動が開始される前に適用されます。runUntilHalt
の場合は、アジェンダにあるルールのアクティブ化が0個から1個以上に遷移するたびに、この更新が実行されます。
フォーマット
setEffectiveDate(Calendar newDate)
使用方法
有効日を変更する唯一の方法は、setEffectiveDateを起動することです。reset関数を起動すると、有効日は任意の値に設定される場合があります。
RLIllegalArgumentException
例外は、newDate引数がnullの場合にスローされます。
一度setEffectiveDate関数を呼び出すと、有効日を必要に応じて更新する作業がアプリケーションの役割になります。ルール・エンジンでは、有効日が暗黙的に管理されなくなります。
この状態は、reset関数を起動するまで存続します。
これは、デバッグや特定時点でのルール評価の実行、または有効日をアプリケーションで制御する必要があるその他のユースケースで役立ちます。
関連項目
getEffectiveDate、getCurrentDate、setCurrentDate
ルールセット・スタックをルールセット名の特定の配列に設定します。
スタックの最上位であるエントリ0(ゼロ)はフォーカス・ルールセットです。フォーカス・ルールセットは、後続のrun、runUntilHaltまたはstep関数の実行によってアクティブ化が最初に起動されるルールセットです。
フォーマット
function setRulesetStack(String[] rulesetStack)
関連項目
clearRulesetStack、getRulesetStack、getStrategy、popRuleset、pushRuleset、setStrategy
方針では、同じルールセット内の優先度が同じアクティブ化の実行順序が指定されます。表2-7は、有効な方針の値を示しています。
表2-7 setStrategyおよびgetStrategy関数の方針の値
方針 | 説明 |
---|---|
queue |
アクティブ化は、古い方から順に起動されます。 |
stack |
アクティブ化は、新しい方から順に起動されます。 |
フォーマット
function setStrategy(String strategy);
関連項目
clearRulesetStack、getRulesetStack、getStrategy、popRuleset、pushRuleset
show関数では、ルール・セッションの状態が出力ライターに出力されます。表示可能な状態は、アジェンダ上のすべてのアクティブ化です。
フォーマット
function showActivations();
関連項目
clearWatchRules、clearWatchActivations、clearWatchFacts、clearWatchFocus、clearWatchCompilations、clearWatchAll、showFacts、watchRules、watchActivations、watchFacts、watchFocus、watchCompilations
show関数では、ルール・セッションの状態が出力ライターに出力されます。表示可能な状態は、作業メモリー内のすべてのファクトです。
フォーマット
function showFacts();
関連項目
clearWatchRules、clearWatchActivations、clearWatchFacts、clearWatchFocus、clearWatchCompilations、clearWatchAll、showActivations、watchRules、watchActivations、watchFacts、watchFocus、watchCompilations
アジェンダに存在するルール・アクティブ化を、次の条件に該当するまで起動します。
指定した数のルール・アクティブ化numRulesToFireが起動されるまで。
ルール・アクションでhaltが直接または間接的にコールされるまで。たとえば、ルール・アクションによってコールされた関数でコールされる場合です。
アジェンダが空になるまで。
ルールセット・スタックが空になるまで。
フォーマット
function step(int numRulesToFire) returns int;
function step(int numRulesToFire, String rulesetName) returns int;
使用方法
ルールセット名が指定されず、main
ルールセットがルールセット・スタック上に存在しない場合は、ルールの起動前に、main
ルールセットがルールセット・スタックの最下位に配置されます。
rulesetNameというルールセットが指定された場合は、ルールの起動前に、指定されたルールセットがルールセット・スタックの最上位に追加されます。nullのルールセット名が指定された場合、ルールセット・スタックはルールの起動前に変更されません。
戻り値: 起動されたルールの数。
関連項目
watch関数は、重要なルール・セッション・イベントに関する情報の出力を有効にします。情報は、イベントが発生するたびに出力ライターに出力されます。出力を無効にするには、clearWatch関数を使用します。
表2-8で、使用可能なデバッグ情報について説明します。
表2-8 watch関数のイベントの説明
デバッグwatch | ルール・セッション・イベントの説明 |
---|---|
watch |
ルール・セッション・イベントの説明 |
Rules |
ルールの起動(アクティブ化の実行)に関する情報 |
Activations |
アジェンダに対するアクティブ化の追加または削除 |
Facts |
作業メモリー内のファクトのアサート、取消しまたは変更 |
Focus |
ルールセット・スタックに対するルールセットの追加または削除。ルールセット・スタックの最上位はフォーカス・ルールセットと呼ばれます。フォーカス・ルールセットのアジェンダに存在するすべてのアクティブ化が起動された後、フォーカスが削除され、スタック上の次のルールセットがフォーカスになります。 |
Compilations |
ルールの条件がReteネットワークに追加されると、条件の一部が既存のルールとどのように共有されるかに関する情報が出力されます。"="は共有を示します。ルールの定義順序が共有に影響を与える場合があるため、パフォーマンスにも影響を与える可能性があります。 |
All |
watch Rules、watch Activations、watch Facts、watch Compilationsおよびwatch Focusで示される情報が含まれます。 |
フォーマット
function watchRules();
function watchActivations();
function watchFacts();
function watchFocus();
function watchCompilations();
function watchAll();
関連項目
clearWatchRules、clearWatchActivations、clearWatchFacts、clearWatchFocus、clearWatchCompilations、clearWatchAll、showActivations、showFacts