【正文】
結(jié)構(gòu)(不用指定 when 或 then)。 要獲得查詢結(jié)果,使用 (name),” name”就是指 query 的名稱。 下例為所有 30 歲以上的人建立了一個(gè)簡(jiǎn)單的查詢。這些 Column可以通過(guò)聲明的名稱或索引位置存取。 ( we have + () + people over the age of 30 )。 for ( Iterator it = 。 ) { QueryResult result = ( QueryResult ) ()。 ( () + \n )。 DSL 將規(guī)則語(yǔ)言制于你的控制之下,并且可以使用所有規(guī)則語(yǔ)言和引擎的 特性。 DSL 也可以作為條件或行為的模板,使你可以在規(guī)則中重復(fù)使用,有時(shí)候可能僅僅是用來(lái)改變參數(shù)。如果你的規(guī)則的條件或推論遵循相似的模式,可以用模板的方式表達(dá);當(dāng)你希望隱藏實(shí)現(xiàn)的細(xì)節(jié),而將焦點(diǎn)放在商業(yè)規(guī)則上時(shí);或者你希望通過(guò)提供預(yù)定義的模版來(lái)控制規(guī)則的修改;這些都適合使用 DSL。 注意 Drools3 的 DSL 與 Drools 2 基于 XML 的 DSL 很不相同。 . 修改與管理 DSL DSL 配置是保存在無(wú)格式文本文件中。 例 . Example mapping [when]This is {something}=Something(something=={something}) 參考上面的示例, [when]指明了表達(dá)式所使用的范圍,是屬于 LHS或 RHS。在‘ =’符號(hào)右邊的部分是將要映射到的規(guī)則語(yǔ)言(當(dāng)然這個(gè)結(jié)構(gòu)依賴于你要用在LHS 還是 RHS上,如果是 LHS,則它是 LSH 的語(yǔ)法,如果是 RHS,則它是 java 代碼的片斷)。與 tokens 匹配的 值獲得后將替換等式右邊的同名處,所得到的目標(biāo)表達(dá)式是規(guī)則引擎實(shí)際使用的。這意味著在上面的例子中,所有在”There is”后面直到行未的文本將會(huì)被認(rèn)為是 {something}的值,作為替換目標(biāo)的實(shí)際值。作為繞過(guò)這個(gè)規(guī)則的最好方法是確認(rèn) [tokens]使用字符或標(biāo)點(diǎn)括上。注意圍繞的字符(雙引號(hào))在進(jìn)行內(nèi)部替代時(shí)不會(huì)被包含進(jìn) 去,只有中間的內(nèi)容被使用(而隨后到行尾的內(nèi)容,將被視為 Case 中的其它情況)。你也可以在 {tokens}外加上引號(hào)以確認(rèn)你想捕捉的數(shù)據(jù)。當(dāng)你剛開(kāi)始定義規(guī)則時(shí),使用 DSL 可能導(dǎo)致調(diào)式困難,但是它可以使維護(hù)變得簡(jiǎn)單,當(dāng)然可讀性也提高了。在表達(dá)式右邊需要的情況下 { 和 }可以代表本來(lái)的意思,不作為標(biāo)記看待,如: if (foo) { doSomething()。 例 . Some more examples This is a ment to be ignored. [when]There is a Person with name of {name}=Person(name=={name}) [when]Person is at least {age} years old and lives in {location}=Person(age {age}, location=={location}) [then]Log {message}=({message})。 There is a Person with name of bob and Person is at least 30 years old and lives in atlanta Person(name=kitty) and Person(age 30, location=atlanta) . 在規(guī)則中使用 DSL 當(dāng)你剛開(kāi)始學(xué)習(xí)規(guī)則時(shí),最好是按照標(biāo)準(zhǔn)的規(guī)則語(yǔ)言編寫(xiě)適合對(duì)象模型的規(guī)則。一旦你感覺(jué)習(xí)慣了,你可以提取領(lǐng)域語(yǔ)言來(lái)表達(dá)你在規(guī)則中所做的事情。作為繞過(guò)這個(gè)限制的一個(gè)方法,你可以在每一行前面加上“ ” ,它將告訴解析器按照字面意思原樣保留內(nèi)容,不會(huì)對(duì) 該行進(jìn)行擴(kuò)展(這在你需要調(diào)試規(guī)則問(wèn)題的時(shí)候特別有用)。這使得事情變得非常流暢。 PackageBuilder builder = new PackageBuilder()。 //source 代表規(guī)則源碼讀取器, dsl是 DSL 配置讀取器 你也 需要在規(guī)則源文件中使用 expander 關(guān)鍵字指定 dsl 定義的文件名。 你可以將 DSL 表達(dá)式合在一行上,只要解析器能夠清晰的了解 {tokens},否則你可能會(huì)將直到行尾的信息都讀進(jìn)來(lái)。你也可以獲得跨行的規(guī)則表達(dá)式,這意味著你可以如下例所示: Example . There is a person called Bob who is happy Or There is a person called Mike who is sad 當(dāng)然這里假設(shè)“ Or”被映射為“ or”條件元素。 Fact可能有許多 Field,所有這些 Field 可能在不同的時(shí)候被使用。 DSL工具使用一種簡(jiǎn)單的約定幫你實(shí)現(xiàn)上面的需求。 這很容易用一個(gè)例子來(lái)解釋。我們可以在普通的 DRL 的 LHS 條件中向下面這樣表達(dá): Cheese(age 5, price == 20, type==stilton, country==ch) 如果你之前確認(rèn)你在任何時(shí)候都需要用到上面所有的屬性,那很容易使用 DSL對(duì)上面的規(guī)則 LHS 進(jìn)行編碼。如果在這一案例中,你可以如下映射: [when]There is a Cheese with=Cheese() [when] age is less than {age}=age{age} [when] type is 39。=type==39。 [when] country equal to 39。=country==39。 重要提示 : 在 和約束映射之間必須有一個(gè)空格 接下來(lái)你可以如下描述規(guī)則: There is a Cheese with age is less than 42 type is 39。 解析器將挑出帶有“ ”的行(它們必須在自己行上),并且將它們作為一個(gè)約束加入上面的聲明中。stilton39。)。 DSL 配置被解析器讀取,因此解析器可以擴(kuò)展 DSL表達(dá)式到真正的規(guī)則語(yǔ)言表達(dá)式。如果規(guī)則文件 中有表達(dá)式不能被翻譯,一個(gè)錯(cuò)誤會(huì)被加入結(jié)果中,以及錯(cuò)誤的行號(hào)記錄(該行號(hào)是使用 DSL 編輯規(guī)則時(shí)的行號(hào))。 對(duì)規(guī)則的擴(kuò)展工作本身就是為每一行在 DSL 配置表達(dá)式中找到匹配的項(xiàng)。這個(gè)匹配 token 占位符的值或者通過(guò)搜索直到行尾,或者在 token 占位符后面的字符被匹配。 如果需要了解更深入的信息,查閱 ExpanderResolver, Expander 和DefaultExpander 類。 . 從頭開(kāi)始建立 DSL 如果規(guī)則是眾所周知的, DSL 可以幫助捕捉規(guī)則,而不用使用任何技術(shù)格式。 規(guī)則引擎需要在對(duì)象或數(shù)據(jù)模型上操作,在許多情況下你可以預(yù)先知道這些。在任何情況下,規(guī)則可以很好的與扁平對(duì)象模型一起工作。對(duì)象模型中通常有復(fù)雜的關(guān)聯(lián)和繼承關(guān)系,對(duì)于規(guī)則你會(huì)希望模型盡可能簡(jiǎn)單和扁平化,并且讓規(guī)則引擎推斷關(guān)聯(lián)性(這提供了未來(lái)的靈活性)。 技術(shù)人員和領(lǐng)域?qū)<彝ㄟ^(guò)使用 DSL 能夠達(dá)到相互溝通的 目的。經(jīng)過(guò)一段時(shí)間,你的 DSL 應(yīng)該可以穩(wěn)定下來(lái),這意味著所有對(duì)規(guī)則的改變都通過(guò) DSL 進(jìn)行。也同時(shí)尋找規(guī)則對(duì)象 /字段(將它們匹配到已經(jīng)知道的對(duì)象模型)。提供“ holes(洞)”給數(shù)據(jù)進(jìn)行修改(因?yàn)?許多聲明是類似的,只是一些數(shù)據(jù)發(fā)生改變)。反復(fù)這一過(guò)程,直到模式清晰并且穩(wěn)定下來(lái)。 ? 在這個(gè)階段你將要檢查被規(guī)則需要的對(duì)象和字段,使它們與數(shù)據(jù)模型更協(xié)調(diào)。并重復(fù)這個(gè)過(guò)程。 在 DSL 中一項(xiàng)具有挑戰(zhàn)性的內(nèi)容是表達(dá)綁定變量。然后你就可以在 DSL 中的任何地方使用這個(gè)變量了,包括在規(guī)則的行為部分。就像非 XML 格式的 DRL, XML 格式也被解析為內(nèi)部的“ AST”表現(xiàn)方式(為了更快的解析效率,使用 SAX 解析器)。 . 何時(shí)使用 XML 有幾種情況下, XML 是合適的。 如果你想手工修改 XML,使用一個(gè)好的支持 Schema 的編輯器將提供對(duì) XML更好的分級(jí)型視圖,更利于觀察( XMLSpy 和 Oxygen 是很好的工具,但是要付費(fèi)。 其它你希望使用 XML 的情況有: 有一個(gè)工具從某些輸入產(chǎn)生規(guī)則(程序化產(chǎn)生規(guī)則); 從另一種規(guī)則語(yǔ)言變換過(guò)來(lái); 從另一個(gè)發(fā)行 XML 的工具(使用 XSLT,你可以很容易的對(duì) XML 進(jìn)行變換); 注意,對(duì)上面情況你一樣也可以產(chǎn)生普通的規(guī)則。你可以直接建立 XML 格式的規(guī)則,但注意的是你也可以從 AST 對(duì)象直接產(chǎn)生 XML格式的規(guī)則。 . XML格式 一個(gè)完整的用語(yǔ)取代 XSD 的 WSC標(biāo)準(zhǔn)( XMLSchema)已經(jīng)提供,它也使用 XML 語(yǔ)言進(jìn)行描述,在這里不再重復(fù)說(shuō)明該規(guī)范。 /body /function rule name=my rule ruleattribute name=salience value=10 / lhs column objecttype=Foo / /lhs rhs ( hello )。 RHS 是簡(jiǎn)單的,它僅僅是一個(gè)代碼塊,當(dāng)規(guī)則激發(fā)時(shí)執(zhí)行。 LHS 的一個(gè)關(guān)鍵元素是 Column 元素。在 Column 對(duì)象下嵌套的是必須符合的約束。 在條件元素的葉節(jié)點(diǎn)上有 not, exists, and, or等等。被嵌套在 and 下的元素將被邏輯的與在一起。 Exists 和 Not 圍繞 Column 工作,檢查一個(gè)帶有約束條件的 Fact 的存在性。在代碼片斷中可以包含函數(shù)調(diào)用。 ] . 遺留的 Drools XML 規(guī)則格式 從上面看, Drools 遺留的 XML 格式與 有所不同?;旧?imports,globals(在 中它們替代應(yīng)用程序數(shù)據(jù) )工作一致。 However, there are some similarities. Basically the imports, globals (which replace applicationdata in drools ) work the same. Functions are also similar, except that they are specified one at a time (in Drools 2 they where specified in a single block). Example . Drools xml rule name=Goodbye Cruel World parameter identifier=goodbye classString/class /parameter java:condition(Goodbye)/java:condition java:consequence goodbyeWorld( goodbye )。這可以通過(guò)一個(gè)表格來(lái)完成。你最好根據(jù) 的新的 DSL 特性重新編寫(xiě)。 Example . Drools 3 XML equivalent rule name=Goodbye Cruel World lhs column identifier=39。 objecttype=39。 eval(Goodbye)/eval /lhs rhs goodbyeWorld( goodbye )。這個(gè)工作首先通過(guò)將規(guī)則從源碼狀態(tài)轉(zhuǎn)換到 AST 狀態(tài),然后倒出到需要的目標(biāo)格式。 完成所需工作的類如下: XmlDumper for exporting XML. DrlDumper for exporting DRL. DrlParser reading DRL. XmlPackageReader reading XML. 使用上面的組合,你可以在格式之間任意轉(zhuǎn)換,包括轉(zhuǎn)換回來(lái)。 通過(guò)使用 XSLT 為 XML 提供各種排序的可能, XSLT 和它的家族讓 XML 更