【正文】
. 怎樣工作 當(dāng)規(guī)則被解析后, DSL 被除去。因此在本范例中,使用上面的映射后的效果等于 DRL 的如下描述: Cheese(age42, type==39。{country}39。{type}39。但問題是 Cheese 中可能有許多屬性以 及在約束時(shí)會(huì)有許多種組合方式。如果你的 DSL表達(dá)式使用“ ”開始 ,它會(huì)被假設(shè)為字段約束,并被自動(dòng)加入在上面提供的聲明中(每行是一個(gè)字段約束)。 . 增加 facts的約束條件 當(dāng)編寫規(guī)則表達(dá)式時(shí),通常要對(duì) fact聲明增加許多約束。 expander 一般會(huì)將 DSL 文件放在與規(guī)則文件相同的目錄下,但是使用上面的代碼可以從不同目錄讀取 DSL,只需要提供對(duì)應(yīng)的讀取器即可。 為了使用 DSL 編譯和運(yùn)行規(guī)則,你需要將 DSL配置源碼與規(guī)則源碼一起傳入。注意,一旦你使用了 expander 關(guān)鍵字,如果解析器不能識(shí)別表達(dá)式,將會(huì)拋出錯(cuò)誤,你必須將所有東西都移到 DSL 中。 [when]And = and 上面定義的翻譯規(guī)則,將下面的輸入翻譯成指定的結(jié)果 例 . Some examples as processed There is a Person with name of kitty Person(name=kitty) Person is at least 42 years old and lives in atlanta Person(age 42, location=atlanta) Log boo (boo)。 { 和 } 只能用在表達(dá)式的左邊以用來標(biāo)記 tokens。 [譯者注:這里的內(nèi)容直譯不易理解,最好參看后面的例子 理解; ] 作為一個(gè)慣例,對(duì)文本數(shù)據(jù)使用引號(hào)是規(guī)則編輯器所默認(rèn)的。這樣的效果可能不是當(dāng)你想將不同的 DSL 擴(kuò)展鏈接在一起產(chǎn)生一個(gè)目標(biāo)表達(dá)式時(shí)想要的。 分解器將獲得你指定的表達(dá)式,然后取出輸入中的 {something}(稱為 Tokens)值進(jìn)行匹配。如果你使用 IDE,你可以獲得一個(gè)友好的圖形編輯器(以及一些校驗(yàn)),但保存文件的格式十分簡(jiǎn)單。 DSL 不關(guān)注規(guī)則的運(yùn)行時(shí),它們僅僅是分解和編譯時(shí)需 要的特性。 . 何時(shí)使用 DSL DSL 可以用作分離規(guī)則編輯(規(guī)則的作者)和在規(guī)則引擎中操作的對(duì)象的一個(gè)中間層。 Person person = ( Person ) ( person )。 ( These people are are over 30: )。 例 . Query People over the age of 30 query people over the age of 30 person : Person( age 30 ) end 通過在返回的查詢結(jié)果 (QueryResults)上進(jìn)行標(biāo)準(zhǔn)的 for 循環(huán)遍歷,每一行將返回一個(gè) QueryResult,該對(duì)象可以用來存取組元中的每一個(gè) Column。它提供了查詢working memory 中符合約束條件的對(duì)象的一個(gè)簡(jiǎn)單辦法。另一個(gè)要注意的是返回值約束,返回值片斷必須返回一個(gè)對(duì)象而不是原型。被查閱的 Field 會(huì)自動(dòng)封箱到對(duì)應(yīng)的對(duì)象類型(如 intInteger) ,如果本身已經(jīng)是對(duì)象則不會(huì)改變。 end . 對(duì)原型數(shù)據(jù)自動(dòng)封箱的提醒 Java 5 支持對(duì)原型進(jìn)行類型適當(dāng)?shù)淖詣?dòng)封箱和拆箱。group39。如果只是要求 Column,則意味著對(duì)每一個(gè)符 合的 Column。exists39。當(dāng)前只有 Column 可以在 not 中嵌套,以后將可以支持 and 和 or 進(jìn)行嵌套(已在 中實(shí)現(xiàn))。not39。但是當(dāng)函數(shù)的返回值不斷改變時(shí)(這樣的函數(shù)不能用在值約束中),使用 eval 非常合適。它可以用來查閱在規(guī)則的 LHS 中綁定的變量。如果你這樣想,很明顯對(duì)于一個(gè)規(guī)則能有多個(gè)行為,如果 Or 條件元素的兩邊都滿足的話。 圖 . or 有效的子條件元素 : and, or, not, exists, column 例 . or Person( sex == f, age 60 ) || Person( sex == m, age 65 ) Person( sex == f, age 60 ) or Person( sex == m, age 65 ) 圖 . or 例 . or with binding pensioner : ( Person( sex == f, age 60 ) or Person( sex == m, age 65 ) ) Or條件元素在多個(gè)規(guī)則(稱為子規(guī)則)中對(duì)每一個(gè)可能的邏輯輸出產(chǎn)生結(jié)果。 圖 . and 有效的子條件元素 (用括號(hào)進(jìn)行組合 ): and, or, not, exists, column 例 . Column Cheese( cheeseType : type ) amp。注意在‘ and’前面不能有一個(gè)如‘ or’這樣的聲明綁定,想一下你很容易明白。 例 . Return Value operator Person( girlAge : age, sex == F ) Person( age == ( new Integer(() + 2) ), sex == 39。所有的綁定原型聲明被封箱,當(dāng)前沒有自動(dòng)拆箱功能。M39。在斷言約束中使用的函數(shù)必須返回時(shí)間常量結(jié)果 [譯者注:這句的翻譯準(zhǔn)確,但不理解要表達(dá)的含義,提供英文原本‘ Functions used in a Predicate Constraint must return time constant results.’ ]。 例 . Bound Fact using 39。==39。聲明不能被用來 進(jìn)行匹配 (matchs)操作,雖然它與約束一起工作。excludes39。 例 . 正則表達(dá)式約束 Cheese( type matches (Buffulo)?\\S*Mozerella ) Contains Operator 包含操作 39。如果需要更多的控制,使用斷言約束。 Null 注意:你可以使用 ==和 !=將字段與 null 關(guān)鍵字進(jìn)行比較,象Cheese(type!=null)。那些操作可用依賴于字段的類型。 . JavaBeans as facts 作為 facts 的 javabean JavaBeans 注意: JavaBean 約定被遵循,但是從上面所示,你可以使用非 getter方法,而通過使用其它方法的全名 。 注意,如果原類型被用于一個(gè)字段, Drools 將自動(dòng)對(duì)它們封箱成相應(yīng)的對(duì)象類型(甚至于你使用 ),在 中的代碼表達(dá)式或代碼段中是沒有自動(dòng)解封功能的。 示例,查閱前面的 Cheese 類,這個(gè): Cheese( type==?)使用了實(shí)例的 getType()方法。 這里 field 的意義不是指類的公共或私有成員的字段。 圖 . Column 例 . Bound Column cheapStilton : Cheese( type == stilton, price 10 ) 這個(gè)與前面例子類似,但是在這里我們將一個(gè)變量綁定到規(guī)則引擎匹配到的Chesse 實(shí)例上。如果我們要對(duì)三個(gè)對(duì)象 Person、 Person 和 Pet進(jìn)行匹配,我們將有一個(gè)三個(gè)元素的數(shù)組;在 Drools 中我們稱這樣的一個(gè) facts列表為組元( tuple),在數(shù)組中的每一個(gè)元素成為一個(gè) Column[譯者注:很難準(zhǔn)確表達(dá),保留原英文 ]。Activationgroup 屬性可以是任何字符,只要所有你需要放在同一個(gè)組中的規(guī)則中的 activationgroup 屬性是相同的即可。只有在具有焦點(diǎn)的 agenda group 中的規(guī)則才能夠執(zhí)行。設(shè)置 noloop 為 true 可以阻止該規(guī)則被再次激活。 將對(duì)象從 working memory 中刪除 這些有用的方法是對(duì) KnowledgeHelper 接口實(shí)例所提供的方法的一個(gè)基本縮影 (查閱 KnowledgeHelper 接口獲得更多高級(jí)的操作 )。將你建立的新對(duì)象放到 working memory 中。 實(shí)際上 RHS 是一個(gè)當(dāng)規(guī)則執(zhí)行時(shí)的代碼塊。規(guī)則不能進(jìn)行嵌套。 規(guī)則必須有一個(gè)名稱,并且在一個(gè)包中是唯一的。在規(guī)則的推論中調(diào)用一個(gè)函數(shù),簡(jiǎn)單的使用函數(shù)名稱,并且傳入?yún)?shù)即可,就像方法調(diào)用一樣。 典型的函數(shù)聲明如下所示: function String calcSomething(String arg) { return hola !。 . Function 函數(shù) 圖 . function 相對(duì)于正常的 java 類,函數(shù)是在你的規(guī)則代碼中放置語言代 碼的方法。 可能的一個(gè)例子是 Email服務(wù)。 Global 不會(huì)設(shè)置到 Working Memory中,因此當(dāng)全局變量發(fā)生改變時(shí),引擎不會(huì)得知;因?yàn)檫@個(gè)原因,全局變量不能用在條件約束上,除非這個(gè)值不會(huì)發(fā)生改變。這為解析器提供了如何理解你自定義的規(guī)則語言。 . no spaces, unlike rule names which allow spaces. In terms of the order of elements, they can appear in any order in the rule file, with the exception of the package and expander statements being at the top of the file, before any rules appear. In all cases, the semi colons are optional. 圖 . package . import 導(dǎo)入 圖 . import Import 標(biāo)記就像 java 中的含義一樣。注意,包必須有一個(gè)名稱空間,并且使用標(biāo)準(zhǔn)的 java 約定進(jìn)行命名;例如包名不允許空格,不像規(guī)則名稱可以有空格。包名也就是名稱空間名,與文件或目錄名稱無關(guān)。引擎在遇到這些注釋時(shí)會(huì)迅速排除它們。避免在你的領(lǐng)域?qū)ο螅瑢傩?,方法,函?shù)以及規(guī)則的其它部分中使用保留字是明智的。相信 DSL 對(duì)你的應(yīng)用是有用的,它事實(shí)上可以讓規(guī)則看起來非常易懂。你可以認(rèn)為這些 dsl 文件也是對(duì)你的域模型的映射(它為你提供了一點(diǎn)的隔絕性)。 特別注意的是,空白是不重要的,除非在 DSL 中使用,在 DSL 中每一行會(huì)先于下一行處理(空白在這里可能有很重要的作用)。 LHS 是規(guī)則的條件部分,它遵循下面將提到的語法。但是你也可以將規(guī)則分開到多個(gè)規(guī)則文件中(在這種情況下建議采用 .rule擴(kuò)展名,但不是必需的),分散規(guī)則利于管理巨量規(guī)則的情況。對(duì)該技術(shù)非常有興趣的話,你可以查閱“ ” ,那是 Antlr3 為規(guī)則語言提供的語法分析。第三章 . 規(guī)則語言 . 概述 Drools 3 自帶一種非 XML 格式的規(guī)則語言。其中所用的圖稱為線路圖,是對(duì)語言中術(shù)語解釋的基本流圖表。在一個(gè) drl 文件中可以包含多個(gè)規(guī)則,函數(shù)等等。 ATTRIBUTES(通常是可選項(xiàng))指出規(guī)則的行為表現(xiàn)。任何在 LHS 中綁定的變量可以在 RHS 中使用。這個(gè)擴(kuò)展機(jī)制是一個(gè)可擴(kuò)展的 API,但是它默認(rèn)與 dsl擴(kuò)展名的文件工作,dsl 文件中包含了如何將域語言或自然語言映射為規(guī)則語言以及域?qū)ο蟆?DSL擴(kuò)展機(jī)制可以為不同的領(lǐng)域進(jìn)行預(yù)定義,并提供其它自然語言的格式進(jìn)行分析。 . Reserved words 在規(guī)則語言中使用了一些保留字。 when then rule end contains matches and or modify retract assert salience function query exists eval agendagro