一個典型的DRL檔案:
①package com.sample
包名,不可以與關鍵字沖突。一個包通過名稱空間描繪,這樣很好的保持了一組規則的獨立性。
②import
标記就像java中的含義一樣。對于任何要用在規則中的對象,你需要指定完整的路徑和類型名。Drools從同名的java包中自動導入類。
③global
如果多個包定義了同樣名稱的全局變量,它們必須使用同樣的類型,并且全部指向同一個全局值。全部變量通常用來傳回資料,獲得提供資料或服務給規則使用。為了使用全局變量,你必須:
在規則檔案中聲明全局變量并使用它,如:
global java.util.List myGlobalList;
rule "Using a global"
when
eval( true )
then
myGlobalList.add( "Hello World" );
end
在working memory上設定全局變量的值。最好是在将fact插入working memory之前設定完所有全局變量,如:
List list = new ArrayList();
WorkingMemory wm = rulebase.newStatefulSession();
wm.setGlobal( "myGlobalList", list );
④function
相對于正常的java類,函數是在你的規則代碼中放置語言代碼的方法。它們不可能做任何超過你可以在幫助類(在java中定義,被設定入規則的Working Memory中的類)中做到的事情。使用函數的優點是可以将邏輯儲存在一個地方,并且你可以在需要的時候改變函數(這樣做各有優缺點)。函數最大的用處是被規則的推論(then)部分中的行為所調用,特别是當一個行為操作需要反複被調用時(将公用代碼抽取出來成為一個函數)。
⑤rule 名稱可以在“”下取任何名字。
屬性清單:
屬性 類型 預設值 功能描述
no-loop Boolean false 設定no-loop為true可以阻止該規則被再次激活。
salience integer 0 優先級數字高的規則會比優先級低的規則先執行。
agenda-group String MAIN 隻有在具有焦點的agenda group中的規則才能夠激發。
auto-focus Boolean false 如果該規則符合激活條件,則該規則所在agenda-group自動獲得焦點,允許規則激發。
activation-group String N/A 在同名activation-group中的規則将以互斥的方式激發
dialect String "java" or "mvel" 指定在LHS代碼表達式或RHS代碼塊中使用的語言。
date-effective String, 包含日期/時間定義 N/A 規則隻能在date-effective指定的日期和時間之後激活。
date-exptires String, 包含日期/時間定義 N/A 如果目前時間在date-expires指定的時間之後,規則不能激活。
duration long N/A 指出規則将在指定的一段時間後激發,如果那個時候規則的激活條件還是處于true的情況下。
⑥ LHS (when) 條件元素
為了能夠引用比對的對象,使用一個模式綁定變量如‘$c’。變量的字首使用的$是可選的,但是在複雜的規則中它會很友善用來差別變量與字段的不同。
$c : Cheese( type == "stilton", price < 10, age == "mature" )
&& 和|| 限制連接配接符
Cheese( type == "stilton" && price < 10, age == "mature" )
Cheese( type == "stilton" || price < 10, age == "mature" )
第一個有兩個限制而第二個組有一個限制,可以通過圓括号來改變求值的順序。
單值限制
Matches 操作
Cheese( type matches "(Buffalo)?\S*Mozerella" )
Cheese( type not matches "(Buffulo)?\S*Mozerella" )
Contains 操作
CheeseCounter( cheeses contains "stilton" )
CheeseCounter( cheeses not contains "cheddar" )
memberof操作
CheeseCounter( cheese memberof $matureCheeses )
CheeseCounter( cheese not memberof $matureCheeses )
字元串限制
字元串限制是最簡單的限制格式,将字段與指定的字元串求值:數值,日期,string或者boolean。
Cheese( quantity == 5 )
Cheese( bestBefore < "27-Oct-2007" )
Cheese( type == "stilton" )
Cheese( smelly == true )
綁定變量限制
變量可以綁定到Fact和它們的字段,然後在後面的字段限制中使用。綁定變量被稱為聲明。有效的操作符由被限制的字段類型決定;在那裡會進行強制轉換。綁定變量限制使用'=='操作符,因為能夠使用hash索引,是以提供非常快的執行速度。
Person( likes : favouriteCheese )
Cheese( type == likes )
傳回值限制
傳回值限制可以使用任何有效的Java中繼資料類型或對象。要避免使用任何Drools關鍵字作為聲明辨別。在傳回值限制中使用的函數必須傳回靜态常量(time constant)結果。之前聲明的綁定可以用在表達式中。
Person( girlAge : age, sex == "F" )
Person( age == ( girlAge + 2) ), sex == 'M' )
複合值限制
複合值限制用在可能有多個允許值的時候,目前隻支援'in' 和'not in'兩個操作。這些操作使用圓括号包含用逗号分開的值的清單,它可以是變量,字元串,傳回值或限定辨別符。'in' 和'not in'運算式實際上被文法分析器重寫成多個!= and ==組成的多重限制。
Person( $cheese : favouriteCheese )
Cheese( type in ( "stilton", "cheddar", $cheese )
多重限制
多重限制允許你對一個字段通過使用'&&' 或者'||'限制連接配接符進行多個限制條件的判斷。允許使用圓括号分組,它會讓這種限制看起來更自然。
Person( age ( (> 30 && < 40) || (> 20 && < 25) ) )
Person( age > 30 && < 40 || location == "london" )
内聯的Eval限制
eval限制可以使用任何有效的語言表達式,隻要它最終能被求值為boolean中繼資料類型。表達式必須是靜态常量(time constant)。任何在目前模式之前定義的變量都可以使用,自動代入(autovivification)機制用來自動建立字段綁定變量。當建構器發現辨別不是目前定義的變量名是,它将嘗試将它作為對象的字段來通路,這種情況下,建構器自動在inline-eval中建立該字段的同名變量。
Person( girlAge : age, sex = "F" )
Person( eval( girlAge == boyAge + 2 ), sex = 'M' )
⑦RHS (then) 執行操作
這部分應當包含一系列需要執行的操作。規則的RHS部分應該保持簡短的,這保持它是聲明性和可讀性的。如果你發現你需要在RHS中使用指令式或and/or條件代碼,那你可能需要将規則拆分為多個規則。RHS的主要目的是插入,删除修改working memory資料。
"update(object, handle);" 将告訴引擎對象已經改變(已經被綁定到LHS中的那一個),并且規則需要重新檢查。
"insert(new Something());" 将在working memory中放置一個你建立的對象。
"insertLogical(new Something());" 與insert類似,但是當沒有更多的fact支援目前激發規則的真值狀态時,對象自動删除。
"retract(handle);" removes an object from working memory.
⑧ Query
查詢中僅僅包含規則LHS部分的結構(不用指定when或then)。它提供了查詢working memory 中符合限制條件的對象的一個簡單辦法。
query "people over the age of 30"
person : Person( age > 30 )
通過在傳回的查詢結果(QueryResults)上進行标準的for循環周遊,每一行将傳回一個QueryResult,該對象可以用來存取組元中的每一個Column。這些Column可以通過聲明的名稱或索引位置存取。
QueryResults results = workingMemory.getQueryResults( "people over the age of 30" );
for ( Iterator it = results.iterator; it.hasNext(); ) {
QueryResult result = ( QueryResult ) it.next();
Person person = ( Person ) result.get( "person" );
}