From: <jbo...@li...> - 2006-04-24 04:51:26
|
Author: mic...@jb... Date: 2006-04-24 00:51:20 -0400 (Mon, 24 Apr 2006) New Revision: 3934 Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Rule_Language/Section-XML.xml Log: first cut Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Rule_Language/Section-XML.xml =================================================================== --- labs/jbossrules/trunk/documentation/manual/en/Chapter-Rule_Language/Section-XML.xml 2006-04-24 02:49:04 UTC (rev 3933) +++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Rule_Language/Section-XML.xml 2006-04-24 04:51:20 UTC (rev 3934) @@ -0,0 +1,269 @@ +<?xml version="1.0" encoding="UTF-8"?> +<section> + <title>XML Rule Language</title> + + <para>Drools also supports a "native" <indexterm> + <primary>XML</primary> + </indexterm> rule language as an alternative to DRL. This allows you to + capture and manage your rules as XML data. Just like the non-XML DRL format, + the XML format is parsed into the internal "AST" representation - as fast as + possible (using a SAX parser). There is no external transformation step + required. All the features are available with XML that are available to + DRL.</para> + + <section> + <title>When to use XML</title> + + <para>There are several scenarios that XML is desirable. However, we + recommend that it is not a default choice, as XML is not readily human + readable (unless you like headaches) and can create visually bloated + rules.</para> + + <para>If you do want to edit XML by hand, use a good schema aware editor + that provides nice heirarchical views of the XML, ideally visually + (commercial tools like XMLSpy, Oxygen etc are good, but cost money, but + then so do headache tablets).</para> + + <para>Other scenarious where you may want to use the XML format are if you + have a tool that generates rules from some input (programmatically + generated rules), or perhaps interchange from another rule language, or + from another tool that emits XML (using XSLT you can easily transform + between XML formats). Note you can always generate normal DRL as + well.</para> + + <para>Alternatively you may be embedding drools in a product that already + uses XML for configuration, so you would like the rules to be in an XML + format. You may be creating your own rule language on XML - note that you + can always use the AST objects directly to create your own rule language + as well (the options are many, due to the open architecture).</para> + </section> + + <section> + <title>The XML format</title> + + <para>A full W3C standards (XMLSchema) compliant XSD is provided that + describes the XML language, which will not be repeated here verbatim. A + summary of the language follows.</para> + + <example> + <title>Example <indexterm> + <primary>XML Rule</primary> + </indexterm></title> + + <programlisting><?xml version="1.0" encoding="UTF-8"?> +<package name="com.sample" + xmlns="http://drools.org/drools-3.0" + xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" + xs:schemaLocation="http://drools.org/drools-3.0 drools-3.0.xsd"> + +<import name="java.util.HashMap" /> +<import name="org.drools.*" /> + +<global identifier="x" type="com.sample.X" /> +<global identifier="yada" type="com.sample.Yada" /> + +<function return-type="void" name="myFunc"> + <parameter identifier="foo" type="Bar" /> + <parameter identifier="bada" type="Bing" /> + + <body> + System.out.println("hello world"); + </body> +</function> + +<rule name="my rule"> + <rule-attribute name="salience" value="10" /> + + <lhs> + <column object-type="Foo" /> + </lhs> + + <rhs> + System.out.println( "hello" ); +</rhs> +</rule> +</package> +</programlisting> + </example> + + <para>Referring to the above example: Notice the key parts, the + declaration for the Drools 3, schema, imports, globals (application-data + in drools 2), functions, and the rules. Most of the elements are self + explanatory if you have some understanding of the Drools 3 + features.</para> + + <para>Imports: import the types you wish to use in the rule.</para> + + <para>Globals: These are global objects that can be referred to in the + rules.</para> + + <para>Functions: this is a declaration of functions to be used in the + rules. You have to specify return types, a unique name and parameters, in + the body goes a snippet of code.</para> + + <para>Rule: see below.</para> + + <example> + <title>Detail of rule element</title> + + <programlisting><rule name="my rule"> + <lhs> + + <column object-type="Foo" /> + <column identifier="bar" object-type="Bar" /> + + <column object-type="Foo"> + <literal field-name="field1" evaluator="==" value="value1" /> + <predicate field-name="field1" identifier="var1" expression="1==1" /> + <return-value field-name="field1" evaluator="==" expression="1==1" /> + <field-binding field-name="field1" identifier="var1" /> + <bound-variable field-name="field1" evaluator="==" identifier="var1" /> + </column> + + <not> + <column object-type="Bar" /> + </not> + + <exists> + <column object-type="Bar" /> + </exists> + + <and> + <or> + <column object-type="Bar" /> + </or> + <column object-type="Yada" /> + </and> + + <or> + <and> + <column object-type="Foo" /> + </and> + <column object-type="Zaa" /> + </or> + + <eval expression="1==1" /> + </lhs> + + <rhs> + /* semantic actions here */ + </rhs> +</rule> +</programlisting> + </example> + + <para>Referring to the above rule detail:</para> + + <para>The rule has a LHS and RHS (conditions and consequence) sections. + The RHS is simple, it is just a block of semantic code that will be + executed when the rule is activated. The LHS is slightly more complicated, + </para> + + <example> + <title>Some more examples</title> + + <programlisting>#This is a comment 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}"=System.out.println("{message}"); +[when]And = and</programlisting> + </example> + + <para>Referring to the above examples, this would render the following + input as shown below: <example> + <title>Some examples as processed</title> + + <programlisting>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" ---> System.out.println("boo"); +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")</programlisting> + </example></para> + </section> + + <section> + <title>Legacy Drools 2.x XML rule format</title> + + <para>A good way to get started if you are new to Rules (and DSLs) is just + write the rules as you normally would against your object model. You can + unit test as you go (like a good agile citizen!). Once you feel + comfortable, you can look at extracting a domain language to express what + you are doing in the rules. Note that once you have started using the + "expander" keyword, you will get errors if the parser does not recognise + expressions you have in there - you need to move everything to the DSL. As + a way around this, you can prefix each line with ">" and it will tell + the parser to take that line literally, and not try and expand it (this is + handy also if you are debugging why something isn't working).</para> + + <para>As you work through building up your DSL, you will find that the DSL + configuration stabilises pretty quickly, and that as you add new rules and + edit rules you are reusing the same DSL expressions over and over. The aim + is to make things as fluent as possible.</para> + + <programlisting>#This is a comment 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}"=System.out.println("{message}"); +[when]And = and</programlisting> + + <para>To use the DSL when you want to compile and run the rules, you will + need to pass the DSL configuration source along with the rule source. + <programlisting>PackageBuilder builder = new PackageBuilder(); +builder.addPackageFromDrl( source, dsl ); +//source is a reader for the rule source, dsl is a reader for the DSL configuration +</programlisting> You will also need to specify the expander by name in the + rule source file: <programlisting>expander your-expander.dsl +</programlisting>Typically you keep the DSL in the same directory as the rule, + but this is not required if you are using the above API (you only need to + pass a reader). Otherwise everything is just the same.</para> + + <para>You can chain DSL expressions together on one line, as long as it is + clear to the parser what the {tokens} are (otherwise you risk reading in + too much text until the end of the line). The DSL expressions are + processed according to the mapping file, top to bottom in order. You can + also have the resulting rule expressions span lines - this means that you + can do things like:</para> + + <example> + <programlisting>There is a person called Bob who is happy + Or +There is a person called Mike who is sad +</programlisting> + </example> + + <para>Of course this assumes that "Or" is mapped to the "or" conditional + element (which is a sensible thing to do).</para> + </section> + + <section> + <title>How it works</title> + + <para>DSLs kick in when the rule is parsed. The DSL configuration is read + and supplied to the parser, so the parser can "expand" the DSL expressions + into the real rule language expressions.</para> + + <para>When the parser is processing the rules, it will check if an + "expander" representing a DSL is enabled, if it is, it will try to expand + the expression based on the context of where it is the rule. If an + expression can not be expanded, then an error will be added to the + results, and the line number recorded (this insures against typos when + editing the rules with a DSL). At present, the DSL expander is fairly + space sensitive, but this will be made more tolerant in future releases + (including tolerance for a wide range of punctuation).</para> + + <para>The expansion itself works by trying to match a line against the + expression in the DSL configuration. The values that correspond to the + token place holders are stored in a map based on the name of the token, + and then interpolated to the target mapping. The values that match the + token placeholders are extracted by either searching until the end of the + line, or until a character or word after the token place holder is + matched. The "{" and "}" are not included in the values that are + extracted, they are only used to demarcate the tokens - you should not use + these characters in the DSL expression (but you can in the target).</para> + + <para>Refer to the ExpanderResolver, Expander and DefaultExpander classes + for more indepth information if required. As the parser works off the + Expander and ExpanderResolver interfaces, it is possible to plug in your + own advanced expanders if required.</para> + </section> +</section> \ No newline at end of file |