ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Business Rulesランゲージ・リファレンス・ガイド
11gリリース1 (11.1.1.7)
B56239-05
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次
索引へ移動
索引

前
 
次
 

2 Ruleランゲージ・リファレンス

この章には、Oracle Business Rules RL Language (RL Language)の構文、セマンティクスおよび組込み関数の完全なリファレンスが含まれています。

文法ルールでRL Languageが定義されています。各文法ルールでは、::=記号の左側に記述された非終端記号が、::=記号の右側に記述された1つ以上の非終端記号および終端記号に関して定義されています。

予約語

aggregateboolean、break、bytecatchcharclassconstant、continue、doubleelseexistsextendsfactfactpath、falsefinalfinallyfloatforfunctionhideifimportincludeinstanceofintlongmodify、newnullpropertypublic、query、returnreturnsrulerulegroup、rulesetshortsupportssynchronizedthrowtruetrywhilevar


注意:

太字で記述されている予約語は、現行のリリースに適用されています。太字で記述されていない予約語(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で示されているルールは、次の条件が満たされるまで起動されません。

  1. enterRoomファクトがアサートされる。

  2. 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

型変換

値をある型から別の型に変換する方法はいくつかあります。

  1. String連結演算子+を使用した、任意の型からStringへの変換。

  2. コンテキストからの暗黙的変換。たとえば、intdoubleに加算する場合は、最初にintdoubleに変換され、その後で2つのdoubleが加算されます。

  3. 2つの数値型間のキャスト。

  4. 継承で関連付けられた2つのクラス間のキャスト。

  5. 変換を実行する関数またはメソッドの起動。例: toString

表2-1は、様々な型の暗黙的変換の要約です。各行は、「変換元」列の型が、「変換先」列の型リストに示されているように暗黙的に変換される可能性があることを示しています。

表2-1 暗黙的な型変換

変換元 変換先

int

doublefloatlong

float

double

long

doublefloat

short

intdoublefloatlong

byte

intdoublefloatlongshort

char

intdoublefloatlong

String

Object

Object

Object(変換元オブジェクトが変換先オブジェクトのサブクラスの場合)

fact set

boolean

array

Object



注意:

オブジェクトはJavaまたはRL Languageのクラスまたは配列のインスタンスです。型変換が可能であるのは、クラスが継承(実装または拡張)で関連付けられている場合のみです。


表2-2は、様々な型について許可されているキャスト変換の要約です。キャストを使用すると、ビット数の多いプリミティブ型をビット数の少ないプリミティブ型に、例外をスローすることなく変換できます。

表2-2に示されている型変換には、明示的なキャスト演算子が必要です。例を次に示します。

int i = 1;
short s = (short)i;

注意:

表2-2に示されているような数値型を含む型変換では、上位ビットが失われる可能性があり、オブジェクトが関係するこのような変換では、RLClassCastExeptionがスローされる場合があります。


表2-2 明示的な型変換

変換元 変換先

double

floatlongintshortbytechar

float

longintshortbytechar

long

intshortbytechar

short

bytechar

byte

char

char

byte


キャストを使用して、ビット数の多いプリミティブ型をビット数の少ないプリミティブ型に変換するとき、RL Languageでは、例外はスローされずに多い分の上位ビットが切り捨てられます。

例を次に示します。

short s = -134;
byte b = (byte)s;
println("s = " + s + ", b = " + b);
prints: s = -134, b = 122

プリミティブ型

プリミティブ型は次のいずれかです。

オブジェクト型

オブジェクト型は次のいずれかです。

文字列型

RL LanguageではJava文字列が使用されます。この場合は次のように処理されます。

配列型

大カッコ([])は配列を示します。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で識別子またはパッケージ名が有効であるすべての場所で使用できます。assertXPathString引数で識別子のXMLバリアントを使用する場合、逆引用符は必要ありません。

例2-3 逆引用符を使用したXML識別子のマッピングの例

`http://www.example.com/po.xsd` -> com.mycompany.po
`my-attribute` -> myAttribute
`Items/item` -> Items$ItemType

リテラル

表2-3は、RL Languageのリテラルの要約です。リテラルはJavaリテラルと同じです。

表2-3 RL Languageのリテラル

リテラル 割当て可能な変数の型

範囲0から127の整数、または範囲0から127のUCS2エンコーディングのchar

bytecharshortintlongfloatdouble

範囲0から65535の整数またはchar

charintlongfloatdouble

範囲-128から127の整数

byteshortintlongfloatdouble

範囲-32768から32767の整数

shortintlongfloatdouble

整数

intlongfloatdouble

末尾がLの整数

longfloatdouble

浮動小数点定数

double

末尾がFの浮動小数点定数

floatdouble

""で囲まれた文字列

StringObject



定義

ルールセット内の定義が実行されると、誤りがないかチェックされ、ルール・セッションで後で使用するために保存されます。

フォーマット

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のクラス定義のqnamehello.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に初期化できます。

変数はスコープ内でローカルまたはグローバルです。初期化式が必要です。ローカル変数はファイナルにはできません。

グローバル変数

ルールセットの直後に囲まれている(つまり定義内の)変数は、スコープ内のルール・セッションに対してグローバルです。ファイナル・グローバル変数の初期化式は、グローバル変数の定義時に実行されます。

非ファイナル・グローバル変数の初期化式は次の両方の場合に実行されます。

ファイナルとして宣言されたグローバル変数は、初期化後変更できません。

ルール条件(fact-set-condition)で参照されるグローバル変数はファイナルであることが必要です。

例2-5は、reset関数によって非ファイナル・グローバル変数iの初期化が実行されることを示しています。したがって、この例では1ではなく0(ゼロ)が出力されます。

例2-5 reset関数後の非ファイナル・グローバル変数の初期化

RL> int i = 0;
RL> i++;
RL> reset();
RL> println(i);

二次的作用のある関数でグローバル変数を初期化する場合には注意が必要です。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では、作業メモリーの状態が変化した場合(通常はファクトがアサートまたは取り消された場合)に、ファクトおよびルールが照合されます。

runrunUntilHaltおよびstep関数によってアクティブ化が実行されます。アクティブ化は、実行後、またはファクト・セット行で参照されるファクトが変更または取り消され、ルールの条件と一致しなくなると、アジェンダから削除されます。

アクティブ化はルールセット・スタックの順に実行されます。ルールセット・スタックは、getRulesetStackclearRulesetStackpushRulesetおよびpopRuleset関数で管理できます。

ルールが起動するには、次の3つの事項が発生する必要があります。

  1. そのルールのアクティブ化がアジェンダに存在すること。

  2. 包含ルールセットがルールセット・スタックの最上位にあること。

  3. runrunUntilHaltまたはstepが実行されること。

fact-set-conditionで生成されるファクト・セットは、ルール・アクションで使用できます。ファクト・セット内の各行について、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を参照)。

例2-10 包含クラスの名前のプロパティ・タイプを使用したクラス定義

class C0 {
  C0 next;
}

例2-11 前方参照のあるクラス定義が許可されない例

class C1 {
  C2 c2;  // causes an UndefinedException
}
class C2 {
  C1 c1;
}

xpathサポート


注意:

xpathサポートは非推奨となりました。詳細は、「assertTree」を参照してください。


RL LanguageクラスとJavaクラスの両方でxpathがサポートされています。

XML識別子は、xpath内では逆引用符で囲む必要はありません。

組込みのassertXPath関数では、オブジェクトのツリーをファクトとしてアサートするための簡単なxpathに似た構文がサポートされます。ツリーのノードは、xpathをサポートする同じパッケージまたはルールセット内のクラスのオブジェクトです。親ノードと子ノードの間のリンクはXLinkクラスのインスタンスです。xpathをサポートするクラス内のすべてのプロパティをxpath式で使用できます。

フォーマット

supports ::= supports 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の正確なサブセットではありません。次の相違点に注意してください。

表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つのルールが定義されます。

例2-13は、例2-12の実行結果を示しています。

例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-14 ファミリ・ツリーの取消し

retract(xp.gramma);
showFacts();

例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

関数の定義

関数はJavaの静的メソッドと同じです。

フォーマット

function ::= function name parameters [ returns type ] action-block

parameters ::= ( [ type identifier ( , type identifier )* ] )

使用方法

action-blockによって、定義されている関数を起動できます。ただし、action-blockには、まだ定義されていない関数の前方参照を含めることはできません(例2-17および例2-18を参照)。

関数はオーバーロード可能です。たとえば、組込みのprintln関数はオーバーロードされています。

例2-17 再帰的参照が含まれた有効な関数の定義

function factorial(long x) returns long {
  if (x <= 1) { return 1; }
  else { return x * factorial(x - 1); }
}

例2-18 未定義関数の参照が含まれた無効な関数の定義

function f1() {
  f2();  // causes an UndefinedException
}
function f2() {
}

ファクト・クラス宣言

すべてのJavaクラスを、ファクト・コンテキスト内でRL Languageファクトとして使用できます。

ファクト・コンテキストは次のいずれかです。

クラスまたはインタフェースBがクラスまたはインタフェースAを実装または拡張するとき、ABの両方がファクト・コンテキスト内に出現する場合は、ABの前に出現する必要があります。このルールに従わない場合は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にサブクラスCarTruckがあるとします。例2-19で示されるルールmatchVehicleは、FactClassExceptionをラップするTypeCheckExceptionを生成します。これは、スーパークラスの前にサブクラスが参照されるためです。ラップは、FactClassExceptionMultipleInheritanceExceptionの両方に対するサブクラス化のかわりに使用されます。これは、ファクト・コンテキストによっては、これらの例外が実行時までスローされず、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がスローされます。TypeCheckExceptiongetCauseメソッドを使用すると、ラップされた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宣言、ルール・ファクト・パターン、またはassertassertXPathretractの引数です。

場合によっては、ファクト・コンテキストを考慮する必要があります。たとえば、次のような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;

ファクト・コンテキスト内の出現順が次のようになる例の場合

  1. fact class T

  2. assertXPath AImpl

  3. assert TImpl (assertXPath実装で内部的に実行)

AImplは順序付けでTImplより前にありますが、AImplTImplを拡張し、このため例外が発生します。このファクト・コンテキストの修正は、手順2の前の任意の場所でfact class TImpl;を明示的に発行することです。


import文

import文では、Javaクラスの参照時にパッケージ名修飾を省略できます。

フォーマット

import ::= import ( Java-class-name | Java-package-name.* ) ;

Java-package-name ::= qname

使用方法

インポート・コマンドはルールセット内に配置でき、インポートのスコープがimportが置かれているルールセットであることを暗黙的に示しますが、実際にはグローバルに適用されます。たとえば、次のコードでインポートのスコープがルールセットに限定されている場合は、r2PrintWriter参照はコンパイルされません。

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;
    }
  }
}

Include文

URLで指定された位置のルールセットをインクルードします。

フォーマット

include ::= include URL ;

内容は次のとおりです。

URL: 有効なUniform Resource Locator。

使用方法

file:およびhttp:スキームがサポートされています。

include file:example.rl;

式の使用

RL Languageの式では、一般的なJava構文が使用されます(これから説明するような多少の違いはあります)。例を次に示します。

(a + 1) * (b - 2)

式は条件またはアクションで使用しますが、いくつか制限事項があります。式は厳密に型指定されます。

フォーマット

expression ::= boolean-expression

| numeric-expression

| string-expression

| array-expression

| fact-set-expression | object-expression

| comparable-expression


ブール式

ブール式は、Javaと同じくtrueまたはfalseです。

フォーマット

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-expression

| boolean-primary-expression

boolean-assignment ::= boolean-target-expression = boolean-expression

equal-op ::= == | !=

relop ::= < | > | <= | >=

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-expression( + | - ) numeric-expression


条件

boolean-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-primary-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-primary-expression

array-assignment ::= array-target-expression = array-expression

array-cast ::= type

使用方法

array-castの型は配列型であることが必要です。


ファクト・セット式

fact-set-expressionでは、作業メモリーからのファクトの照合、フィルタ処理およびファクトを戻す処理が実行されます。fact-set-expressionrule fact-set-conditionでのみ有効です。ifキーワードはfact-set-conditionを示しますが、fact-set-conditionifアクションとは異なります。ルールの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

| ! fact-set-expression

| exists fact-set-expression

| fact-set-pattern

| (fact-set-expression)

| aggregate

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

| object-target-expression

| numeric literal

| numeric-target-expression

| boolean-literal

| boolean-target-expression

constraint ::= simple-expression

property-name ::= name

aggregate ::= aggregate fact-set-expression : aggregate-spec ( , aggregate-spec )*

aggregate-spec ::= aggregate-function [ var ] identifier

aggregate-function ::=

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-patternsimple-expressionを使用するか、またはfact-set-expressionでサポートされている演算子を使用します。

fact-set-expressionには次のものを含めることはできません。

演算子の優先順位はJavaと同様です。優先順位を指定するにはカッコを使用します。例を次に示します。

fact person var p && (p.age < 21 || p.age > 65)

カッコがない場合は、p.agepは未定義です(演算子の優先順位の詳細は表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に適用するときは、次の点に注意してください。


注意:

次の構成について考えてみます。

if (fact X || fact W) {}

XWの両方がアサートされている場合、このルールは各ファクトごとに1回、合計2回起動されます。


空演算子

!演算子では、fact-set-expressionが空であるかどうかがテストされます。!fact-set-expressionに適用するときは、次の点に注意してください。

存在(非空)演算子

exists演算子では、fact-set-expressionが空でないかどうかがテストされます。

exists演算子をfact-set-expressionに適用するときは、次の点に注意してください。

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 集計関数

関数 説明

average()

一致するファクトの平均を計算します。結果はdoubleです。

sum()

一致するファクトの合計を計算します。結果はdoubleまたはlongです。

count()

結果はlongです。

minimum()

一致するファクトの最小値を計算します。

maximum()

一致するファクトの最大値を計算します。

collection()

結果はファクトのjava.util.Listです。

ユーザー定義

結果の型が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: 1, value: 99));
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)が次のように解釈されることを示しています。

例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をこの式で比較できます。

フォーマット

comparable-expression ::=

java.lang.Comparableを実装する型のjava.lang.Comparable | memberを実装する型のqname変数


オブジェクト式

オブジェクトに対する式演算子は、代入とキャストのみです。

フォーマット

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次式

1次式には、変数、プロパティ、配列要素、クラス・メンバー、およびその他の密バインディングの式構文(リテラル、メソッドや関数のコール、オブジェクトやファクトの構成など)の代入ターゲットが含まれます。構文は、記述されている場合を除いてJavaとほぼ同じです。

フォーマット

primary-expression ::= array-primary-expression

| string-primary-expression

| numeric-primary-expression

| boolean-primary-expression

| object-primary-expression

array-primary-expression ::=

array-constructor

| (配列を戻す)function-call

| (1次元のJava配列を戻す)method-call*

| ( array-expression )

| array-target-expression

array-constructor ::= new (

simple-type [ numeric-expression integer ]

| numeric [ ] { numeric-expression ( , numeric-expression )* }(数式は暗黙的にベースに変換可能であることが必要)

| boolean [ ] { boolean-expression ( , boolean-expression )* }

| object-type [ ] { object-expression ( , object-expression )* }

)

array-target-expression ::=

qname(配列型の変数)

| (配列型の)member

| array-primary-expression(ベース型はObject)[ numeric-expression int ]

string-primary-expression ::=

文字列リテラル (「リテラル」を参照)

| 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 )

| numeric-target-expression

numeric-target-expression ::=

qname(数値型の変数)

| (数値型の)member

| array-primary-expression(ベース型は数値) [ numeric-expression ]

boolean-primary-expression ::=

boolean-literal

| (ブールを戻す)function-call

| (ブールを戻す)method-call

| ( boolean-expression )

| boolean-target-expression

boolean-literal ::= true | false

boolean-target-expression ::=

qname(ブール型の変数)

| (ブール型の)member

| array-primary-expression(ベース型はブール)[ numeric-expression int ]

object-primary-expression ::=

new class-definition-name ( [ expression ( , expression )* ] 引数リスト)

| new class-definition-name ( [ property-pattern ( , property-pattern )* ] プロパティと値のペア)

| (Javaオブジェクトを戻す)function-call

| (Javaオブジェクトを戻す)method-call

| object-target-expression

object-target-expression ::=

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と同じです)を示しています。

例2-33 リテラルの使用

String s = "This is a string."
int i = 23;
double f = 3.14;
boolean b = false;

メソッドおよび関数はオーバーロードできます。ただし、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

new

RL Languageクラスにはユーザー定義コンストラクタはありません。デフォルト・コンストラクタによって、プロパティはデフォルト値に初期化されます。RL Languageのnew演算子では、一部のプロパティ値を指定できます(Java Beanのプロパティに対しても動作します)。

Java Beanのプロパティにはgetterはありsetterがない場合があります。このようなプロパティは変更できません。

例2-35 new演算子を使用した初期化

class C { int i = 1; int j = 2; }
C c = new C();  
println(c); // c.i == 1 and c.j == 2
c = new C(i: 3); 
println(c); // c.i == 3 and c.j == 2
c = new C(i: 0, j: 0);
println(c); // c.i == c.j == 0

アクションおよびアクション・ブロック

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)メソッドを起動できます。

例2-36 アクション・ブロックの例

RL> {
  int i = 2;
  while (i-- > 0) { println("bye"); }
}
bye
bye
RL>

if elseアクション・ブロック

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"); }

例2-38 アクション・ブロックのない無効なifアクション

if (s=="a") println("no");

whileアクション・ブロック

テストがtrueの間はアクション・ブロックが実行されます。returnthrowまたはhaltでアクション・ブロックを終了できます。

フォーマット

while ::= while while-test action-block

while-test ::= boolean-expression

使用方法

Javaと異なり、RL Languageにはアクション・ブロックが必要であり、単一のセミコロンの終了アクションは許可されていません。

例2-39では"bye"が2回出力されます。

例2-39 whileアクションの例

int i = 2;
while (i-- > 0) {
  println("bye");
}

例2-40 アクション・ブロックのない無効なwhileアクション

while (i-- > 0) println("no");

forアクション・ブロック

RL Languageには、Javaと同じくforループがあります。forアクション・ブロックを使用すると、for-initが実行され、その後boolean-expressiontrueの間は、指定のアクション・ブロックが最初に実行された後、for-updateが実行されます。returnthrowまたは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);


try catch finallyアクション・ブロック

最初のアクション・ブロックが実行されます。実行時にスローされた、catch句のThrowableクラスと一致する例外が捕捉されます。最初の一致については、関連付けられたcatchアクション・ブロックが実行されます。Throwableクラス・インスタンスが特定の識別子にバインドされ、catchアクション・ブロックで使用できるようになります。tryアクション・ブロックで例外がスローされるかどうかに関係なく、finallyアクション・ブロックが指定されている場合は、finallyアクション・ブロックが実行されます。

捕捉されない例外は、RL Languageコマンドラインを使用しているときはエラー・メッセージとして出力され、RuleSessionのexecuteRulesetまたはcallFunctionメソッドを使用しているときはRLExceptionsとしてスローされます。RL Languageのtrycatchおよび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ブロックを使用して、別のルールのアクション・ブロックの例外を補足することはできません。ルール起動時にスローされた例外は、起動ルールのアクション・ブロックで処理されるか、またはルールの起動元であるrunrunUntilHaltまたは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メソッドの例外として処理され、ExceptionJavaExceptionにラップされます。明示的にスローされたExceptionは、JavaExceptionの原因として使用できます。


synchronizedアクション・ブロック

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アクション

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アクションでは、関数またはルールのアクション・ブロックから制御が戻されます。

ルール内の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は指定しないでください。


throwアクション

例外がスローされます。例外は、java.lang.Throwableを実装するJavaオブジェクトであることが必要です。スローされた例外は、tryアクション・ブロック内のcatchで捕捉できます。

フォーマット

throw ::= throw throwable ;

throwable ::= object-primary-expression


assignアクション

RL Languageの代入は、Javaと同様に、アクションとして出現可能な式です。

フォーマット

assign ::= assignment-expression ;

assignment-expression ::= boolean-assignment

| numeric-assignment

| string-assignment

| object-assignment

| array-assignment

例2-45は、RL Languageの代入式の使用方法を示しています。この例では"6 5"と出力されます。

例2-45 代入式

clear;
int i = 1;
int j = 2;
i += j += 3;
println(i + " " + j);

インクリメントまたはデクリメント式

RL Languageのインクリメントまたはデクリメントは、Javaと同様に、アクションとして出現可能な式です。

フォーマット

incr-decr ::= incr-decr-expression ;

incr-decr-expression ::= ( ++ | -- ) numeric-target-expression | numeric-target-expression ( ++ | -- )

例2-46は、RL Languageのデクリメント・アクションの使用方法を示しています。この例では"0"と出力されます。

例2-46 デクリメント・アクション

clear;
int i = 1;
--i;
println(i);

基本アクション

基本アクションは、関数コール、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プロパティがあります。

例2-47は、mutexプロパティを持つルールグループの使用方法を示しています。r2およびr3は、ルール条件内で同じファクト・タイプ・セットを同じ順序で参照していることに注意してください。これはmutexグループ内で必要になります。パターン内のテストは同じでなくてもかまいません。mutexグループ内のルール条件の形状に関する制限は、下位グループにも適用されます。したがって、ルールr4とr5も同じファクト・タイプ・セットを同じ順序で参照する必要があります。Aの1つのインスタンスとBの1つのインスタンスがアサートされており、r1、r2、r3、r4およびr5はアジェンダにアクティブ化があるとします。r3は優先度が高いため起動されます。r2はmutex=trueのグループ内にあるため、r2のアクティブ化は起動することなく削除されます。group2はgroup1のメンバーであるため、r4とr5のアクティブ化も起動することなく削除されます。ルールr1は起動します。ここで、r2、r4およびr5はアジェンダにアクティブ化があり、r4が最初に起動するとします。相互に起動するgroup2内のルールはr2とr3の両方を除外するため、r2のアクティブ化は起動することなく削除されます。r5は起動します。group2には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組込み関数について説明します。

assertassertTreeassertXPathclearRuleclearRulesetStackclearWatchRules、clearWatchActivations、clearWatchFacts、clearWatchFocus、clearWatchCompilations、clearWatchAllcontainsgetCurrentDategetDecisionTracegetDecisionTraceLevelgetDecisionTraceLimitgetEffectiveDategetFactByTypegetFactsByTypegetRulesetStackgetRuleSessiongetStrategyhaltidisErrorInRuleConditionSuppressedobjectprintlnpopRulesetpushRulesetretractresetrunrunUntilHaltsetCurrentDatesetDecisionTraceLevelsetDecisionTraceLimitsetErrorInRuleConditionSuppressedsetEffectiveDatesetRulesetStacksetStrategyshowActivationsshowFactsstepwatchRules、watchActivations、watchFacts、watchFocus、watchCompilations


assert

提供オブジェクト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();

関連項目

assertTreeidobjectretract


assertTree

assertTree組込み関数では、オブジェクト・ツリーのオブジェクトがファクトとしてアサートされます。

assertTree組込み関数では、JAXB 2.0がサポートされます。

フォーマット

assertTree(Object root)

assertTree(String spec, Object root)

使用方法

assertTree()シグネチャには、次の2つがあります。

assertTree関数では、次のことが実行されます。

関連項目

assert


assertXPath

assertXPath関数は非推奨です。かわりにassertTreeを使用してください。

ルートとして指定した要素とXMLのxpathに似た式を使用して、ファクトのツリーを作業メモリーに追加し、ツリー内のオブジェクトを定義します。pkgは、ツリー内のオブジェクトのクラスが含まれるJavaパッケージまたはRL Languageルールセットです。ツリー内のすべてのオブジェクトが同じパッケージまたはルールセット内に存在する必要があります。

要素および選択した子をアサートする以外に、親オブジェクトと子オブジェクトをリンクするXLinkファクトがアサートされます。ツリー内のすべてのオブジェクトのクラスで、RLクラス(rl-class-definition)またはfact-class宣言のsupports xpath(supports)句を使用する必要があります。

フォーマット

function assertXPath(String pkg, Object 要素, String xpath);

関連項目

assertidobjectretract


clearRule

名前付きのルールをルール・セッションから消去します。ルールのアクティブ化はすべてアジェンダから削除されます。

フォーマット

function clearRule(String 名前);

関連項目

getRuleSession


clearRulesetStack

ルールセット・スタックを空にします。

フォーマット

function clearRulesetStack();

関連項目

getRulesetStackgetStrategypopRulesetpushRulesetrunsetStrategy


clearWatchRules、clearWatchActivations、clearWatchFacts、clearWatchFocus、clearWatchCompilations、clearWatchAll

clearWatch関数は、デバッグ情報の出力を停止します。

フォーマット

function clearWatchRules();

function clearWatchActivations();

function clearWatchFacts();

function clearWatchFocus();

function clearWatchCompilations();

function clearWatchAll();

関連項目

watchRules、watchActivations、watchFacts、watchFocus、watchCompilations


contains

contains()関数はJava Collectioncontains()メソッドに似ていますが、コレクション内のJAXBElementの存在を処理する機能を持っています。

フォーマット

contains(Collection c, Object o) returns boolean

使用方法

contains()は、コレクションc内でJAXBElementを検出すると、そのJAXBElementから値クラスを取得して、オブジェクトoと比較します。

関連項目

assertTree


getCurrentDate

getCurrentDate関数では、CurrentDateファクトに関連付けられている日付が戻されます。

フォーマット

getCurrentDate() returns Calendar

使用方法

有効日と現在の日付は、直交する2つのアイテムです。有効日は、有効開始日および有効終了日のプロパティに従って有効になっているルールを判別するのに使用します。CurrentDateファクトでは、ルール・エンジンが管理している現在の日付を表すファクトを推論の対象にできます。

現在の日付を設定しても、有効日のセマンティクスには影響を与えません。

日付を推論の対象にするためのルールをルール内に明示的に作成する場合は、CurrentDateファクトを使用します。有効開始日または有効終了日、あるいはその両方をルールに割り当て、データ内の日付から判別されるルールを有効にする場合は、setEffectiveDate()を使用します。

関連項目

setCurrentDategetEffectiveDatesetEffectiveDate


getDecisionTrace

現在のトレースを戻し、新しいトレースを開始します。

フォーマット

getDecisionTrace() returns DecisionTrace

使用方法

関連項目

getDecisionTraceLevelgetDecisionTraceLevelwatchRules、watchActivations、watchFacts、watchFocus、watchCompilations


getDecisionTraceLevel

現在のデシジョン・トレース・レベルを取得します。

フォーマット

getDecisionTraceLevel() returns int

使用方法

サポートされているデシジョン・トレース・レベルには、次のレベルが含まれます。

関連項目

getDecisionTracegetDecisionTraceLimitwatchRules、watchActivations、watchFacts、watchFocus、watchCompilations


getDecisionTraceLimit

トレース内のイベント数に対する現在の制限値を戻します。

フォーマット

getDecisionTraceLimit() returns int

使用方法

関連項目

getDecisionTracegetDecisionTraceLevel


getEffectiveDate

getEffectiveDate関数では、有効日の現在値が戻されます。

フォーマット

getEffectiveDate() returns Calendar

使用方法

有効日と現在の日付は、直交する2つのアイテムです。有効日は、有効開始日および有効終了日のプロパティに従って有効になっているルールを判別するのに使用します。CurrentDateファクトでは、エンジンが管理している現在の日付を表すファクトを推論の対象にできます。どちらも明示的に設定できます。

現在の日付を設定しても、有効日のセマンティクスには影響を与えません。有効日を設定しても、CurrentDateファクトには影響を与えません。

日付を推論の対象にするためのルールをルール内に明示的に作成する場合は、CurrentDate (setCurrentDate())を使用します。有効開始日または有効終了日、あるいはその両方をルールに割り当て、データ内の日付から判別されるルールを有効にする場合は、setEffectiveDate()を使用します。

関連項目

setEffectiveDategetCurrentDatesetCurrentDate


getFactByType

この関数では、作業メモリー内にインスタンスが1つのみ存在するときに、classNameで識別されるファクト・タイプが戻されます。存在しない場合は、nullが戻されます。作業メモリー内にそのファクト・タイプの複数のインスタンスが存在する場合、例外がスローされます。

フォーマット

function getFactByType(String className) returns Object

関連項目

showFacts


getFactsByType

指定したクラスのインスタンスである、作業メモリー内のすべてのファクトのリストが戻されます。

フォーマット

function getFactsByType(String className) returns List

関連項目

showFacts


getRulesetStack

ルールセット・スタックをルールセット名の配列として戻します。

フォーマット

function getRulesetStack() returns String[];

使用方法

戻り値: ルールセット名の配列としてのルールセット・スタック

スタックの最上位であるエントリ0(ゼロ)はフォーカス・ルールセットです。フォーカス・ルールセットは、後続のrunrunUntilHaltまたはstep関数の実行によってアクティブ化が最初に起動されるルールセットです。

関連項目

clearRulesetStackgetStrategypopRulesetpushRulesetsetRulesetStacksetStrategy


getRuleSession

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 && … { … } }");
  }
}

関連項目

clearRule


getStrategy

現在の戦略を戻します。表2-7に、使用可能な戦略の値が示されています。

フォーマット

function getStrategy() returns String;

関連項目

clearRulesetStackgetRulesetStackpopRulesetpushRulesetsetStrategy


halt

halt関数では、現在起動中のルールの実行が停止され、停止されたルールの実行元であるrunrunUntilHaltまたはstep関数に制御が戻されます。アジェンダはそのままであるため、後続のrunrunUntilHaltまたはstepを実行するとルールの起動を再開できます。

halt関数は、runrunUntilHaltまたはstep関数のコンテキスト外で起動された場合は効果がありません。

フォーマット

function halt();

関連項目

resetrunrunUntilHaltstep


id

オブジェクトobjに関連付けられているファクトIDを戻します。objがファクトに関連付けられていない場合は、-1が戻されます。

フォーマット

function id(Object obj) returns int;

関連項目

assertobjectretract


isErrorInRuleConditionSuppressed

エラーの抑制は、ルール条件の各テストで発生します。各テストは個別に評価されます。評価中にエラーが発生したときにエラーの抑制を有効にした場合は、エラーが抑制されます。テストの評価中にエラーが発生したということは、テストの結果が不明であることを意味します。内部的には、この状態(true/false/unknown、http://en.wikipedia.org/wiki/Three-valued_logicを参照)を表すために、ルール・エンジンで3値ロジックが使用されます。true/falseの値が必要な場合、unknown値がfalseにマッピングされます。

テスト中のエラーは、RLドメイン(エンジンで検出される)またはJavaドメイン(テストで呼び出したJavaメソッドによってスローされる)のいずれかで発生します。RLドメインでは、RL式でnullオブジェクト参照を逆参照しようとすることにより発生する、RLNullPointerExceptionが最も一般的なエラーです。RLArithmeticException (整数のゼロによる除算)とRLIllegalArgumentExceptionは、ほとんど発生しません。RLArrayIndexOutOfBoundsException、RLClassCastExceptionおよびRLCloneNotSupportedExceptionは、ごくまれに発生します。

Javaドメインの例外は、ルール条件から呼び出したJavaメソッドによってスローされる例外です。これらの例外は、RL例外JavaExceptionでラップされ、getCause()で取得できるメソッドでスローされます。Javaメソッドによってスローされた例外は、エンジンでさらに判別できません。たとえば、null値が渡されたことにより、メソッドで例外がスローされた可能性がある場合でも、ルール・エンジンには、nullが原因であるかどうかを知る方法がありません。

エラーの抑制は、組込み関数を呼び出すことで制御できます。一般的な呼出し元は、デシジョン関数の初期アクションです。

フォーマット

isErrorInRuleConditionSuppressed() returns boolean

使用方法

RLのシグネチャ: isErrorInRuleConditionSuppressed() returns boolean

関連項目

setErrorInRuleConditionSuppressed


object

特定のファクトIDに関連付けられているオブジェクトを戻します。ファクトIDがない場合は、nullが戻されます。

フォーマット

function object(int factId) returns Object;

関連項目

assertidretract


println

特定の値をRuleSession出力ライターに出力します。

フォーマット

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

スタックが空の場合、popRulesetではRLRuntimeExceptionがスローされます。スタックが空でない場合、popRulesetではスタックからフォーカスが削除され、戻されます。

すべてのエントリの位置が1つずつ下に移動します。新しいフォーカスは、スタックの新しい最上位であるエントリ0(ゼロ)です。

スタックの最上位であるエントリ0(ゼロ)はフォーカス・ルールセットです。フォーカス・ルールセットは、後続のrunrunUntilHaltまたはstep関数の実行によってアクティブ化が最初に起動されるルールセットです。

フォーマット

function popRuleset() returns String;

例2-50 popRulesetの使用とRLRuntimeExceptionのスロー

clearRulesetStack();
popRuleset();        // RLRuntimeException

関連項目

clearRulesetStackgetRulesetStackgetStrategypushRulesetsetStrategy


pushRuleset

特定のルールセットをスタックに追加し、そのルールセットをフォーカスにします。すでにフォーカスであるルールセットを追加するとエラーが発生します(このエラーについてはRLIllegalArgumentExceptionがスローされます)。

スタックの最上位であるエントリ0(ゼロ)はフォーカス・ルールセットです。フォーカス・ルールセットは、後続のrunrunUntilHaltまたは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

関連項目

clearRulesetStackgetRulesetStackgetStrategypopRulesetsetStrategy


retract

オブジェクトobjに関連付けられているファクトを作業メモリーから削除します。

フォーマット

function retract(Object obj);

使用方法

取消しはアジェンダに影響を与える可能性があります。取り消されたファクトに依存するアクティブ化はアジェンダから削除されます。

(!を使用して)ファクトが存在しないことをテストする条件があるルールによって、アジェンダに新しいアクティブ化が配置される可能性があります。

関連項目

assertidobject


reset

作業メモリーからすべてのファクトを消去し、アジェンダからすべてのアクティブ化を消去して、非ファイナル・グローバル変数の初期化式を再評価します。

フォーマット

function reset();

関連項目

haltrunrunUntilHaltstep


run

アジェンダに存在するルール・アクティブ化を、次の条件に該当するまで起動します。

フォーマット

function run() returns int;

function run(String rulesetName) returns int;

使用方法

引数rulesetNameが指定された場合は、ルールの起動前に、名前付きルールセットがルールセット・スタックの最上位に追加されます。

nullのrulesetNameが指定された場合、ルールセット・スタックはルールの起動前に変更されません。

rulesetNameが指定されず、デフォルトのmainルールセットがルールセット・スタック上に存在しない場合は、ルールの起動前に、mainがルールセット・スタックの最下位に配置されます。

戻り値: int。起動されたルールの数。

関連項目

haltresetrunUntilHaltstep


runUntilHalt

この関数では、haltがコールされるまでルール・アクティブ化が起動されます。runおよびstepとは異なり、runUntilHaltは、アジェンダが空になっても戻りません。また、runUntilHaltでは、ルールセット・スタックから最下位のルールセット名は削除されません。かわりに、アジェンダにアクティブ化が格納されるのを待機します。

フォーマット

function runUntilHalt() returns int;

使用方法

メインのRuleSessionスレッドがビジーであるときにアクティブ化をアジェンダに追加する唯一の方法であるrunUntilHaltの実行は、2番目のスレッドに対して行われ、次のいずれかが実行されます。

  1. PropertyChangeListenersを使用したJava Beanファクトの変更

  2. assertまたはretract関数の実行

runUntilHaltの使用時はルールを注意して設計する必要があります。たとえば、プロパティが最小値のファクトを検出しようとするルールは、ファクトの最初のインスタンスがアサートされたときに起動され、その後は、それより小さい値のプロパティが設定された別のインスタンスがアサートされるたびに起動されます。

関連項目

haltresetrunstep


setCurrentDate

setCurrentDate関数では、エンジンが管理している現在の日付を表すファクトを推論の対象にするための日付が設定されます(CurrentDateファクトを使用)。

フォーマット

setCurrentDate(Calendar newDate)

使用方法

RLIllegalArgumentException例外は、newDate引数がnullの場合にスローされます。

ルール内で日付を明示的に推論の対象にする必要がある場合は、CurrentDateファクトを使用します。有効開始日および有効終了日をルールに割り当て、データ内の日付から判別されるルールを有効にする場合は、setEffectiveDateを使用する必要があります。setEffectiveDate関数は、CurrentDateファクトに影響を与えません。

デフォルトでは、現在の日付の値はルール・エンジンが暗黙的に管理します。CurrentDateファクトの値は現在のシステム日付に更新され、組込み関数のrunファミリが起動されると、内部的に(再)アサートされます。これは、新しい現在の日付がルール条件で評価されるように、ルールが起動される前に行われます。runUntilHaltの場合は、アジェンダにあるルールが0個から1個以上に遷移するたびに、この更新が実行されます。

一度setCurrentDate関数を呼び出すと、現在の日付を必要に応じて更新する作業はユーザーの役割になります。ルール・エンジンでは、有効日が暗黙的に管理されなくなります。この状態は、reset関数を起動するまで存続します。setCurrentDateを使用して現在の日付を明示的に設定した場合、時間を逆戻りさせる(前の時点に設定される)ことになるsetCurrentDate関数を起動すると、必ずエラーが発生し、RLIllegalArgumentExceptionがスローされます。reset関数を起動すると、現在の日付が任意の値に設定される場合があります。

関連項目

getCurrentDategetEffectiveDatesetEffectiveDate


setDecisionTraceLevel

デシジョン・トレース・レベルを指定したレベルに設定します。

フォーマット

setDecisionTraceLevel(int level)

使用方法

サポートされているデシジョン・トレース・レベルには、次のレベルが含まれます。

関連項目

getDecisionTracegetDecisionTraceLevelgetDecisionTraceLevelsetDecisionTraceLimitwatchRules、watchActivations、watchFacts、watchFocus、watchCompilations


setDecisionTraceLimit

トレース内のイベント数の制限値を設定します。

フォーマット

setDecisionTraceLimit(int count)

使用方法

デフォルト値は10000です。

関連項目

getDecisionTracegetDecisionTraceLevelgetDecisionTraceLevelsetDecisionTraceLevel


setEffectiveDate

setEffectiveDate関数では、ルール・エンジンの有効日が更新されます。

デフォルトでは、有効日の値は、ルール・エンジンによって暗黙的に管理されます。この場合、組込み関数のrunファミリが起動されると、有効日が現在のシステム日付に更新されます。これは、任意のルールが起動される前に実行されます。そのため、新しい有効日は、ルールの起動が開始される前に適用されます。runUntilHaltの場合は、アジェンダにあるルールのアクティブ化が0個から1個以上に遷移するたびに、この更新が実行されます。

フォーマット

setEffectiveDate(Calendar newDate)

使用方法

有効日を変更する唯一の方法は、setEffectiveDateを起動することです。reset関数を起動すると、有効日は任意の値に設定される場合があります。

RLIllegalArgumentException例外は、newDate引数がnullの場合にスローされます。

一度setEffectiveDate関数を呼び出すと、有効日を必要に応じて更新する作業がアプリケーションの役割になります。ルール・エンジンでは、有効日が暗黙的に管理されなくなります。

この状態は、reset関数を起動するまで存続します。

これは、デバッグや特定時点でのルール評価の実行、または有効日をアプリケーションで制御する必要があるその他のユースケースで役立ちます。

関連項目

getEffectiveDategetCurrentDatesetCurrentDate


setErrorInRuleConditionSuppressed

エラーの抑制は、ルール条件の各テストで発生します。各テストは個別に評価されます。評価中にエラーが発生したときにエラーの抑制を有効にした場合は、エラーが抑制されます。テストの評価中にエラーが発生したということは、テストの結果が不明であることを意味します。内部的には、この状態(true/false/unknown、http://en.wikipedia.org/wiki/Three-valued_logicを参照)を表すために、ルール・エンジンで3値ロジックが使用されます。true/falseの値が必要な場合、unknown値がfalseにマッピングされます。

テスト中のエラーは、RLドメイン(エンジンで検出される)またはJavaドメイン(テストで呼び出したJavaメソッドによってスローされる)のいずれかで発生します。RLドメインでは、RL式でnullオブジェクト参照を逆参照しようとすることにより発生する、RLNullPointerExceptionが最も一般的なエラーです。RLArithmeticException (整数のゼロによる除算)とRLIllegalArgumentExceptionは、ほとんど発生しません。RLArrayIndexOutOfBoundsException、RLClassCastExceptionおよびRLCloneNotSupportedExceptionは、ごくまれに発生します。

Javaドメインの例外は、ルール条件から呼び出したJavaメソッドによってスローされる例外です。これらの例外は、RL例外JavaExceptionでラップされ、getCause()で取得できるメソッドでスローされます。Javaメソッドによってスローされた例外は、エンジンでさらに判別できません。たとえば、null値が渡されたことにより、メソッドで例外がスローされた可能性がある場合でも、ルール・エンジンには、nullが原因であるかどうかを知る方法がありません。

エラーの抑制は、組込み関数を呼び出すことで制御できます。一般的な呼出し元は、デシジョン関数の初期アクションです。

フォーマット

setErrorInRuleConditionSuppressed(boolean bv) returns boolean

使用方法

RLのシグネチャ: setErrorInRuleConditionSuppressed(boolean bv) returns boolean

true値を渡すと、エラーの抑制が有効になります。戻り値は以前の設定です。

現在の設定は、isErrorInRuleConditionSuppressed組込み関数で問合せ可能です。

関連項目

isErrorInRuleConditionSuppressed


setRulesetStack

ルールセット・スタックをルールセット名の特定の配列に設定します。

スタックの最上位であるエントリ0(ゼロ)はフォーカス・ルールセットです。フォーカス・ルールセットは、後続のrunrunUntilHaltまたはstep関数の実行によってアクティブ化が最初に起動されるルールセットです。

フォーマット

function setRulesetStack(String[] rulesetStack

関連項目

clearRulesetStackgetRulesetStackgetStrategypopRulesetpushRulesetsetStrategy


setStrategy

戦略では、同じルールセット内の優先度が同じアクティブ化の実行順序が指定されます。表2-7は、有効な戦略の値を示しています。

表2-7 setStrategyおよびgetStrategy関数の戦略の値

戦略 説明

queue

アクティブ化は、古い方から順に起動されます。

stack

アクティブ化は、新しい方から順に起動されます。


フォーマット

function setStrategy(String strategy);

関連項目

clearRulesetStackgetRulesetStackgetStrategypopRulesetpushRuleset


showActivations

show関数では、ルール・セッションの状態が出力ライターに出力されます。表示可能な状態は、アジェンダ上のすべてのアクティブ化です。

フォーマット

function showActivations();

関連項目

clearWatchRules、clearWatchActivations、clearWatchFacts、clearWatchFocus、clearWatchCompilations、clearWatchAllshowFactswatchRules、watchActivations、watchFacts、watchFocus、watchCompilations


showFacts

show関数では、ルール・セッションの状態が出力ライターに出力されます。表示可能な状態は、作業メモリー内のすべてのファクトです。

フォーマット

function showFacts();

関連項目

clearWatchRules、clearWatchActivations、clearWatchFacts、clearWatchFocus、clearWatchCompilations、clearWatchAllshowActivationswatchRules、watchActivations、watchFacts、watchFocus、watchCompilations


step

アジェンダに存在するルール・アクティブ化を、次の条件に該当するまで起動します。

フォーマット

function step(int numRulesToFire) returns int;

function step(int numRulesToFire, String rulesetName) returns int;

function step(int numRulesToFire, boolean errorIfLimitHit) returns int;

function step(int numRulesToFire, String rulesetName, boolean errorIfLimitHit) returns int;

使用方法

ルールセット名が指定されず、mainルールセットがルールセット・スタック上に存在しない場合は、ルールの起動前に、mainルールセットがルールセット・スタックの最下位に配置されます。

rulesetNameというルールセットが指定された場合は、ルールの起動前に、指定されたルールセットがルールセット・スタックの最上位に追加されます。nullのルールセット名が指定された場合、ルールセット・スタックはルールの起動前に変更されません。

戻り値: 起動されたルールの数。

コール元は最後の2つのシグネチャを使用することにより、起動の制限(numRulesToFire)に達したことをエラー条件として扱うかどうかを指定できます。デフォルトはfalseです。つまり、この制限に達することはエラー条件に適合しません。

errorIfLimitHit引数をtrue値に設定したstep関数の呼出しを使用することにより、記述したルールの不具合が原因で発生する可能性のある、ルール起動の無限ループを捕捉できます。

関連項目

haltresetrunrunUntilHalt


watchRules、watchActivations、watchFacts、watchFocus、watchCompilations

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、clearWatchAllshowActivationsshowFacts