diff --git a/drools-docs/doc-authoring-guideline-and-cheatsheet.txt b/drools-docs/doc-authoring-guideline-and-cheatsheet.txt
deleted file mode 100644
index 8e8cd40361..0000000000
--- a/drools-docs/doc-authoring-guideline-and-cheatsheet.txt
+++ /dev/null
@@ -1,200 +0,0 @@
-Drools Documentation Authoring Guideline and Cheat Sheet
-========================================================
-
-External documentation
-----------------------
-
-JBoss Documentation Guide: http://jboss.org/pressgang/jdg.html (a must read from chapter 6: Structure guidelines)
-JDocBook plugin: http://docs.jboss.org/docbook/userguide/html_single/index.html
-DocBook: http://www.sagehill.net/docbookxsl/
- http://www.docbook.org/tdg5/en/html/docbook.html
-
-Marking words in a paragraph
-----------------------------
-
-* Use for package names, class names, method names, ...:
- the class JavaDialectConfiguration
- the package drools.dialect.java.compiler
- the method toString()
-
-* Use for directories and files:
- the directory drools-docs/target/
- the file pom.xml
-
-* Use for commands:
- run the command mvn clean install
-
-* Use for literals and keywords:
- the value null
- the keyword not
-
-* Use to emphasis something (turns bold).
- Note that you can use on , etc:
- null
-
-Marking paragraphs
-------------------
-
-* You can encapsulate a paragraph or more in note, warning, etc:
-
-
-
- Always use one or more 's (or other elements) inside it,
- never write text directly (which gives visual bugs).
- Note: the JBoss Documentation Guide disallow the use of and
-
-* Use for longer code, commands or log listings:
-
- Do not use inside as it is a paragraph style
- (which gives code coloring bugs).
-
-* Use for java code to get color highlighting.
-
-* Use for XML code to get color highlighting.
-
-* Use with for example code:
-
- Configuring the JavaDialectConfiguration to use JANINO via a setter
-
-
-
-Images
-------
-
-* Please link svg image files instead of png bitmaps in the text whenever
- possible.
-
-* Please avoid using .bmp bitmaps, since it will bloat size of the end
- doc. To convert your bmp to a png images, use the GIMP, paint or the command "ffmpeg -i x.bmp x.png".
- Better yet, use a vector graphic program such as InkScape to make a true svg image.
- But this approach may take time and effort, recommended for processing diagrams but not for screenshots.
-
-* At the head of a docbook file, the xml:base property should be set to
- the relative path to the translation base directory ("en-US").
- For example: a file under "en-US/Chapter-Introduction/" has xml:base="../"
- while a file under "en-US/Chapter-Introduction/Section-WhatIs/" has xml:base="../../"
- If it is not set correctly, the images won't show up in a visual docbook editor like XmlMind.
- There is one exception: any file that use xinclude to include other files usually have a xml:base="./"
- and it should not contain images.
-
-* Use with to show an image.
-
-* Use for diagrams with a title:
-
- High-level View of a Rule Engine
-
-
-
-
-
-
-
-* For HTML, width="100%" ensures that imagedata is scaled down to the
- current width of the browser's window.
-
-Linking syntax in DocBook 5.0+:
--------------------------------
-http://www.sagehill.net/docbookxsl/Db5Tools.html#Db5UnivLinking
-
-Note: The jboss docbook xsl does not support docbook 5.0 syntax yet,
-so please use the docbook 4.5 linking syntax for the links.
-
-Lists
------
-
-* unnumbered list (bullets):
-
-
- Linear
- ...
-
-
-* numbered list:
-
- Initialize the ....
- ...
-
-
-* Inside a , always use a (or another element)
-
-Indexed terms:
--------------
-
- Drools implements and extends the
- Rete Rete algorithm,
- Leaps ...
-
-
-Citations:
----------
-To quote a Drools mailing list regular:
-
- Dave Hamu
- It seems to me
- that in the excitement of working with rules engines, that people forget
- that a rules engine is only one piece of a complex application or
- solution. Rules engines are not really intended to handle workflow or
- process executions nor are workflow engines or process management tools
- designed to do rules. Use the right tool for the job. Sure, a pair of
- pliers can be used as a hammering tool in a pinch, but that's not what
- it's designed for.
-
-
-
-You can see the effect of the above example code here:
-https://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/docs/drools-expert/html/ch01.html#d0e231
-
-
-Show source of reference:
--------------------------
-The term "Production Rule" originates from formal grammar - where it
- is described as "an abstract structure that describes a formal language
- precisely, i.e., a set of rules that mathematically delineates a (usually
- infinite) set of finite-length strings over a (usually finite) alphabet"
- (Wikipedia).
-
-
-You can see the the effect of the above example code here:
-https://hudson.jboss.org/hudson/job/drools/lastSuccessfulBuild/artifact/trunk/target/docs/drools-expert/html/ch01.html#d0e41
-
-You can of course combine the
, and together.
-
-
-Footnotes:
-----------
-TODO
-
-
-Callouts:
----------
-TODO
-
- ======================================
-
-I guess the "reference section" would be somehow like a bibliography
-section in a book or paper. Here is the information I found for
-bibliography markup:
-
-http://www.docbook.org/tdg5/en/html/bibliography.html
-
-But I'm not sure whether it is working with the JBoss customized XSLT
-and CSS. If it looks too complex for you, just don't waste your time
-and I'll try it out later and add the relevant information to the
-cheatsheet.
-
-For the "Definition/Concept", I found the tag that might be
-what you want:
-
-http://www.docbook.org/tdg5/en/html/termdef.html
-
-The example in the page looks not that complex. You can give it a try.
-Be warned I've not tested it yet (have much to do in the office for
-now), if this markup breaks the build, please let me know. (If it does
-not break the build, but you do not see any obvious visual effect,
-that means this tag is not defined the css. This is small problem and
-you can keep using the markup. I'm into CSS these days and will sooner
-or later update the Drools css for documentation.)
diff --git a/drools-docs/drools-expert-docs/pom.xml b/drools-docs/drools-expert-docs/pom.xml
index 94e2e3d3dc..7b275c0e59 100755
--- a/drools-docs/drools-expert-docs/pom.xml
+++ b/drools-docs/drools-expert-docs/pom.xml
@@ -6,7 +6,7 @@
org.droolsdrools-docs
- 5.2.0-SNAPSHOT
+ 5.5.0-SNAPSHOTdrools-expert-docs
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Chapter-User_Guide.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Chapter-ApiReference.xml
similarity index 95%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Chapter-User_Guide.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Chapter-ApiReference.xml
index 3a82b4b6a5..f71510483e 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Chapter-User_Guide.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Chapter-ApiReference.xml
@@ -4,7 +4,7 @@
xml:base="./" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
- User Guide
+ Api Reference
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Section-Building.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Section-Building.xml
similarity index 53%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Section-Building.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Section-Building.xml
index 6f98b456ca..c25c93a05d 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Section-Building.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Section-Building.xml
@@ -1,9 +1,12 @@
+ xml:base="../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
Building
@@ -11,7 +14,8 @@
-
+
+
@@ -22,26 +26,26 @@
The KnowledgeBuilder is responsible for taking source files, such as
a DRL file or an Excel file, and turning them into a Knowledge Package of
rule and process definitions which a Knowledge Base can consume. An object
- of the class ResourceType indicates the type of resource it is being
- asked to build.
+ of the class ResourceType indicates the type of resource it
+ is being asked to build.
- The ResourceFactory provides capabilities to load resources from a
- number of sources, such as Reader, ClassPath, URL, File, or ByteArray.
- Binaries, such as decision tables (Excel .xls files), should not use a Reader based
- resource handler, which is only suitable for text based resources.
+ The ResourceFactory provides capabilities to load
+ resources from a number of sources, such as Reader, ClassPath, URL, File,
+ or ByteArray. Binaries, such as decision tables (Excel .xls files), should
+ not use a Reader based resource handler, which is only suitable for text
+ based resources.KnowledgeBuilder
-
+
- The KnowlegeBuilder is created using the
+ The KnowledgeBuilder is created using the
KnowledgeBuilderFactory.
@@ -49,8 +53,7 @@
-
+
@@ -64,13 +67,15 @@
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
- A configuration can be created using the KnowledgeBuilderFactory.
- This allows the behavior of the Knowledge Builder to be modified. The most
- common usage is to provide a custom class loader so that the KnowledgeBuilder
- object can resolve classes that are not in the default classpath. The first parameter
- is for properties and is optional, i.e., it may be left null, in which case the
- default options will be used. The options parameter can be used for things
- like changing the dialect or registering new accumulator functions.
+ A configuration can be created using the
+ KnowledgeBuilderFactory. This allows the behavior of the
+ Knowledge Builder to be modified. The most common usage is to provide a
+ custom class loader so that the KnowledgeBuilder object can
+ resolve classes that are not in the default classpath. The first parameter
+ is for properties and is optional, i.e., it may be left null, in which
+ case the default options will be used. The options parameter can be used
+ for things like changing the dialect or registering new accumulator
+ functions.Creating a new KnowledgeBuilder with a custom ClassLoader
@@ -93,10 +98,45 @@ KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(kbuilder
- It is best practice to always check the hasErrors() method after an
- addition. You should not add more resources or retrieve the Knowledge Packages
- if there are errors. getKnowledgePackages() returns an empty list if
- there are errors.
+ It is a best practice to always check the compilation results after
+ a change an addition. The KnowledgeBuilder can report compilation results
+ of 3 different severities: ERROR, WARNING and INFO.
+
+ An ERROR indicates that the compilation of the resources failed and
+ you should not add more resources or retrieve the Knowledge Packages if
+ there are errors. getKnowledgePackages() returns an empty
+ list if there are errors.
+
+ WARNING and INFO results can be ignored, but are available for
+ inspection nonetheless. hasErrors() method after an
+ addition.
+
+ To check and retrieve the building results for a list of severities,
+ the KnowledgeBuilder interface offers a couple methods:
+
+
+ KnowledgeBuilder result inspection methods
+
+ /**
+ * Return the knowledge builder results for the listed severities.
+ *
+ * @param severities
+ * @return
+ */
+ KnowledgeBuilderResults getResults(ResultSeverity...severities );
+
+
+ /**
+ * Checks if the builder generated any results of the listed severities
+ * @param severities
+ * @return
+ */
+ boolean hasResults(ResultSeverity...severities );
+
+
+ The KnowledgeBuilder interface also has two helper methods to
+ inspect for errors only: hasErrors() and
+ getErrors():Validating
@@ -109,8 +149,8 @@ KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(kbuilder
When all the resources have been added and there are no errors the
- collection of Knowledge Packages can be retrieved. It is a Collection because
- there is one Knowledge Package per package namespace. These
+ collection of Knowledge Packages can be retrieved. It is a Collection
+ because there is one Knowledge Package per package namespace. These
Knowledge Packages are serializable and often used as a unit of
deployment.
@@ -146,6 +186,38 @@ if( kbuilder.hasErrors() ) {
Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
+ The KnowledgeBuilder also has a batch mode, with a fluent interface, that
+ allows to build multiple DRLs at once as in the following example:
+
+
+ Using KnowledgeBuilder in batch mode
+
+ KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+kbuilder.batch()
+ .add( ResourceFactory.newFileResource( "/project/myrules1.drl" ), ResourceType.DRL )
+ .add( ResourceFactory.newFileResource( "/project/myrules2.drl" ), ResourceType.DRL )
+ .add( ResourceFactory.newFileResource( "/project/mytypes1.drl" ), ResourceType.DRL )
+ .build();
+
+
+
+ In this way it is no longer necessary to build the DRLs files in the right order (e.g. first the DRLs
+ containing the type declarations and then the ones with the rules using them) and it will also be possible to have
+ circular references among them.
+
+ In the end the KnowledgeBuilder (regardless if you are using the batch mode or not) also allows to discard
+ what has been added with the last DRL(s) building. This can be useful to recover from having added a wrong DRL to
+ the KnowledgeBuilder as it follows:
+
+
+ Discard the building of the last added DRL
+
+ kbuilder.add( ResourceFactory.newFileResource( "/project/wrong.drl" ), ResourceType.DRL );
+if ( kbuilder.hasErrors() ) {
+ kbuilder.undo();
+}
+
+
@@ -153,11 +225,11 @@ Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
Instead of adding the resources to create definitions
programmatically it is also possible to do it by configuration, via the
- ChangeSet XML. The simple XML file supports
- three elements: add, remove, and modify, each of which has a sequence
- of <resource> subelements defining a configuration entity. The
- following XML schema is not normative and
- intended for illustration only.
+ ChangeSet XML. The simple XML file supports three elements: add, remove,
+ and modify, each of which has a sequence of <resource> subelements
+ defining a configuration entity. The following XML schema is
+ not normative and intended for illustration
+ only.XML Schema for ChangeSet XML (not normative)
@@ -225,9 +297,10 @@ Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
</xs:schema>
-
- Currently only the add element is supported, but the others will be implemented to
- support iterative changes. The following example loads a single DRL file.
+
+ Currently only the add element is supported, but the others will be
+ implemented to support iterative changes. The following example loads a
+ single DRL file.Simple ChangeSet XML
@@ -242,22 +315,23 @@ Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
- Notice the file: prefix, which signifies the protocol for the
- resource. The Change Set supports all the protocols provided by
+ Notice the file: prefix, which signifies the protocol
+ for the resource. The Change Set supports all the protocols provided by
java.net.URL, such as "file" and "http", as well as an additional
"classpath". Currently the type attribute must always be specified for a
resource, as it is not inferred from the file name extension. Using the
- ClassPath resource loader in Java allows you to specify the Class Loader to
- be used to locate the resource but this is not possible from XML. Instead,
- the Class Loader will default to the one used by the Knowledge Builder
- unless the ChangeSet XML is itself loaded by the ClassPath resource, in
- which case it will use the Class Loader specified for that resource.
+ ClassPath resource loader in Java allows you to specify the Class Loader
+ to be used to locate the resource but this is not possible from XML.
+ Instead, the Class Loader will default to the one used by the Knowledge
+ Builder unless the ChangeSet XML is itself loaded by the ClassPath
+ resource, in which case it will use the Class Loader specified for that
+ resource.Currently you still need to use the API to load that ChangeSet, but
- we will add support for containers such as Spring in the future, so that the
- process of creating a Knowledge Base can be done completely by XML configuration.
- Loading resources using an XML file couldn't be simpler, as it's just another
- resource type.
+ we will add support for containers such as Spring in the future, so that
+ the process of creating a Knowledge Base can be done completely by XML
+ configuration. Loading resources using an XML file couldn't be simpler, as
+ it's just another resource type.Loading the ChangeSet XML
@@ -266,10 +340,11 @@ Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
- ChangeSets can include any number of resources, and they even support
- additional configuration information, which currently is only needed for
- decision tables. Below, the example is expanded to load rules from a
- http URL location, and an Excel decision table from the classpath.
+ ChangeSets can include any number of resources, and they even
+ support additional configuration information, which currently is only
+ needed for decision tables. Below, the example is expanded to load rules
+ from a http URL location, and an Excel decision table from the
+ classpath.ChangeSet XML with resource configuration
@@ -287,17 +362,17 @@ Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
- The ChangeSet is especially useful when working with a Knowledge Agent,
- as it allows for change notification and automatic rebuilding of the
- Knowledge Base, which is covered in more detail in the section on the
+ The ChangeSet is especially useful when working with a Knowledge
+ Agent, as it allows for change notification and automatic rebuilding of
+ the Knowledge Base, which is covered in more detail in the section on the
Knowledge Agent, under Deploying.
- Directories can also be specified, to add all resources
- in that folder. Currently it is expected that all resources in
- that folder are of the same type. If you use the Knowledge Agent it will
- provide a continous scanning for added, modified or removed resources and
- rebuild the cached Knowledge Base. The KnowledgeAgent provides more
- information on this.
+ Directories can also be specified, to add all resources in that
+ folder. Currently it is expected that all resources in that folder are of
+ the same type. If you use the Knowledge Agent it will provide a continous
+ scanning for added, modified or removed resources and rebuild the cached
+ Knowledge Base. The KnowledgeAgent provides more information on
+ this.ChangeSet XML which adds a directory's contents
@@ -312,4 +387,50 @@ Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
+
+
+ Changing default building result severity
+
+ In some cases, it is possible to change the default severity of a
+ type of building result. For instance, when a new rule with the same name
+ of an existing rule is added to a package, the default behavior is to
+ replace the old rule by the new rule and report it as an INFO. This is
+ probably ideal for most use cases, but in some deployements, the user
+ might want to prevent the rule update and report it as an error.
+
+ Changing the default severity for a result type is the same as
+ configuring any other option in Drools and can be done either by API
+ calls, system properties or configuration files. As of this version,
+ Drools supports configurable result severity for rule updates and function
+ updates. To configure it using system properties or configuration files,
+ the user has to use the following properties:
+
+
+ Setting the severity using properties
+
+ // sets the severity of rule updates
+drools.kbuilder.severity.duplicateRule = <INFO|WARNING|ERROR>
+// sets the severity of function updates
+drools.kbuilder.severity.duplicateFunction = <INFO|WARNING|ERROR>
+
+
+
+ To configure it through the API:
+
+
+ Setting the severity using the API
+
+ KnowledgeBuilderConfiguration kbconf = ...
+
+// sets the severity of rule updates to error
+kbconf.setOption( KBuilderSeverityOption.get( "drools.kbuilder.severity.duplicateRule", ResultSeverity.ERROR ) );
+// sets the severity of function updates to error
+kbconf.setOption( KBuilderSeverityOption.get( "drools.kbuilder.severity.duplicateFunction", ResultSeverity.ERROR ) );
+
+
+
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Section-Deploying.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Section-Deploying.xml
similarity index 60%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Section-Deploying.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Section-Deploying.xml
index bec57e51c4..02153ea672 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Section-Deploying.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Section-Deploying.xml
@@ -1,9 +1,12 @@
+ xml:base="../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
Deploying
@@ -11,15 +14,16 @@
A Knowledge Package is a collection of Knowledge Definitions, such
as rules and processes. It is created by the Knowledge Builder, as
- described in the chapter "Building". Knowledge Packages are self-contained and
- serializable, and they currently form the basic deployment unit.
+ described in the chapter "Building". Knowledge Packages are self-contained
+ and serializable, and they currently form the basic deployment
+ unit.KnowledgePackage
-
+
@@ -34,40 +38,38 @@
KnowledgeBase
- The Knowlege Base is a repository of all the application's knowledge
- definitions. It may contain rules, processes, functions, and type models.
- The Knowledge Base itself does not contain instance data, known as facts;
- instead, sessions are created from the Knowledge Base into which data can be
- inserted and where process instances may be started. Creating the
- Knowlege Base can be
- heavy, whereas session creation is very light, so it is recommended that
- Knowledge Bases be cached where possible to allow for repeated session
- creation.
+ The Knowledge Base is a repository of all the application's
+ knowledge definitions. It may contain rules, processes, functions, and
+ type models. The Knowledge Base itself does not contain instance data,
+ known as facts; instead, sessions are created from the Knowledge Base into
+ which data can be inserted and where process instances may be started.
+ Creating the Knowledge Base can be heavy, whereas session creation is very
+ light, so it is recommended that Knowledge Bases be cached where possible
+ to allow for repeated session creation.KnowledgeBase
-
+
- A KnowledgeBase object is also serializable, and some people
- may prefer to build and then store a KnowledgeBase, treating it also
- as a unit of deployment, instead of the Knowledge Packages.
+ A KnowledgeBase object is also serializable, and some
+ people may prefer to build and then store a KnowledgeBase,
+ treating it also as a unit of deployment, instead of the Knowledge
+ Packages.
- The KnowlegeBase is created using the KnowledgeBaseFactory.
+ The KnowledgeBase is created using the KnowledgeBaseFactory.KnowledgeBaseFactory
-
+
@@ -81,9 +83,10 @@
KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
- If a custom class loader was used with the KnowledgeBuilder to
- resolve types not in the default class loader, then that must also be set
- on the KnowledgeBase. The technique for this is the same as with the
+ If a custom class loader was used with the
+ KnowledgeBuilder to resolve types not in the default class
+ loader, then that must also be set on the KnowledgeBase. The
+ technique for this is the same as with the
KnowledgeBuilder.
@@ -98,10 +101,10 @@ KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase( kbaseConf );
In-Process Building and Deployment
- This is the simplest form of deployment. It compiles the
- knowledge definitions and adds them to the Knowledge Base in the same JVM.
- This approach requires drools-core.jar and drools-compiler.jar to be on
- the classpath.
+ This is the simplest form of deployment. It compiles the knowledge
+ definitions and adds them to the Knowledge Base in the same JVM. This
+ approach requires drools-core.jar and drools-compiler.jar to be on the
+ classpath.Add KnowledgePackages to a KnowledgeBase
@@ -112,22 +115,22 @@ KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kpkgs );
- Note that the addKnowledgePackages(kpkgs) method can be called
- iteratively to add additional knowledge.
+ Note that the addKnowledgePackages(kpkgs) method can be
+ called iteratively to add additional knowledge.Building and Deployment in Separate Processes
- Both the KnowledgeBase and the KnowledgePackage
- are units of
- deployment and serializable. This means you can have one machine do any
- necessary building, requiring drools-compiler.jar, and
- have another machine deploy and execute everything, needing only
+ Both the KnowledgeBase and the
+ KnowledgePackage are units of deployment and serializable.
+ This means you can have one machine do any necessary building, requiring
+ drools-compiler.jar, and have another machine deploy
+ and execute everything, needing only
drools-core.jar.Although serialization is standard Java, we present an example of
- how one machine might write out the deployment unit and how another
+ how one machine might write out the deployment unit and how another
machine might read in and use that deployment unit.
@@ -155,14 +158,14 @@ kbase.addKnowledgePackages( kpkgs );
- The KnowledgeBase is also serializable and some people may prefer
- to build and then store the KnowledgeBase itself, instead of the
- Knowledge Packages.
+ The KnowledgeBase is also serializable and some people
+ may prefer to build and then store the KnowledgeBase itself,
+ instead of the Knowledge Packages.
- Drools Guvnor, our server side management system, uses this
- deployment approach. After Guvnor has compiled and published serialized
- Knowledge Packages on a URL, Drools can use the URL resource type
- to load them.
+ Drools Guvnor, our server side management system, uses this
+ deployment approach. After Guvnor has compiled and published serialized
+ Knowledge Packages on a URL, Drools can use the URL resource type to load
+ them.
@@ -170,42 +173,41 @@ kbase.addKnowledgePackages( kpkgs );
Stateful Knowledge Sessions will be discussed in more detail in
section "Running". The KnowledgeBase creates and returns
- StatefulKnowledgeSession objects, and it may optionally
- keep references to those.
- When KnowledgeBase modifications occur those modifications are applied
- against the data in the sessions. This reference is a weak reference and it
- is also optional, which is controlled by a boolean flag.
+ StatefulKnowledgeSession objects, and it may optionally keep
+ references to those. When KnowledgeBase modifications occur
+ those modifications are applied against the data in the sessions. This
+ reference is a weak reference and it is also optional, which is controlled
+ by a boolean flag.
KnowledgeAgent
- The KnowlegeAgent provides automatic loading, caching and
- re-loading of resources and is configured from a properties files. The
- Knowledge Agent can update or rebuild this Knowlege Base as the
- resources it uses are changed. The strategy for this is determined by the configuration
- given to the factory, but it is typically pull-based using regular
- polling. We hope to add push-based updates and rebuilds in future
+ The KnowlegeAgent provides automatic loading, caching
+ and re-loading of resources and is configured from a properties files. The
+ Knowledge Agent can update or rebuild this Knowlege Base as the resources
+ it uses are changed. The strategy for this is determined by the
+ configuration given to the factory, but it is typically pull-based using
+ regular polling. We hope to add push-based updates and rebuilds in future
versions. The Knowledge Agent will continuously scan all the added
- resources, using a default polling interval of 60 seconds. If their
- date of the last modification is updated it will rebuild the cached
- Knowledge Base using the new resources.
+ resources, using a default polling interval of 60 seconds. If their date
+ of the last modification is updated it will rebuild the cached Knowledge
+ Base using the new resources.KnowledgeAgent
-
+ The KnowlegeBuilder is created using a
- KnowledgeBuilderFactory object.
- The agent must specify a name, which is used in the log files to associate
- a log entry with the corresponding agent.
+ KnowledgeBuilderFactory object. The agent must specify a
+ name, which is used in the log files to associate a log entry with the
+ corresponding agent.
Creating the KnowledgeAgent
@@ -219,8 +221,7 @@ kbase.addKnowledgePackages( kpkgs );
-
+
@@ -228,14 +229,13 @@ kbase.addKnowledgePackages( kpkgs );
The following example constructs an agent that will build a new
KnowledgeBase from the specified ChangeSet. (See section "Building" for
more details on the ChangeSet format.) Note that the method can be called
- iteratively to add new resources over time.
- The Knowledge Agent polls the resources added from the ChangeSet
- every 60 seconds, the default interval, to see if they are updated.
- Whenever changes are found it will construct a new Knowledge Base or apply
- the modifications to the existing Knowledge Base according to its
- configuration.
- If the change set specifies a resource that
- is a directory its contents will be scanned for changes, too.
+ iteratively to add new resources over time. The Knowledge Agent polls the
+ resources added from the ChangeSet every 60 seconds, the default interval,
+ to see if they are updated. Whenever changes are found it will construct a
+ new Knowledge Base or apply the modifications to the existing Knowledge
+ Base according to its configuration. If the change set specifies a
+ resource that is a directory its contents will be scanned for changes,
+ too.
Writing the KnowledgePackage to an OutputStream
@@ -259,10 +259,10 @@ ResourceFactory.getResourceChangeScannerService().start();
The default resource scanning period may be changed via the
- ResourceChangeScannerService. A suitably updated
- ResourceChangeScannerConfiguration object is passed to the service's
- configure() method, which allows for the service to be reconfigured on
- demand.
+ ResourceChangeScannerService. A suitably updated
+ ResourceChangeScannerConfiguration object is passed to the
+ service's configure() method, which allows for the service to
+ be reconfigured on demand.
Changing the Scanning Intervals
@@ -275,19 +275,20 @@ ResourceFactory.getResourceChangeScannerService().configure( sconf );
- Knowledge Agents can take an empty Knowledge Base or a populated one.
- If a populated Knowledge Base is provided, the Knowledge Agent will
- run an iterator from Knowledge Base and subscribe to the resources that
- it finds. While it is
- possible for the Knowledge Builder to build all resources found in a
- directory, that information is lost by the Knowledge Builder so that those
- directories will not be continuously scanned. Only directories specified
- as part of the applyChangeSet(Resource) method are monitored.
-
- One of the advantages of providing KnowledgeBase as the starting
- point is that you can provide it with a KnowledgeBaseConfiguration. When
- resource changes are detected and a new KnowledgeBase object is
- instantiated, it will use the KnowledgeBaseConfiguration of the previous
+ Knowledge Agents can take an empty Knowledge Base or a populated
+ one. If a populated Knowledge Base is provided, the Knowledge Agent will
+ run an iterator from Knowledge Base and subscribe to the resources that it
+ finds. While it is possible for the Knowledge Builder to build all
+ resources found in a directory, that information is lost by the Knowledge
+ Builder so that those directories will not be continuously scanned. Only
+ directories specified as part of the applyChangeSet(Resource)
+ method are monitored.
+
+ One of the advantages of providing KnowledgeBase as the
+ starting point is that you can provide it with a
+ KnowledgeBaseConfiguration. When resource changes are
+ detected and a new KnowledgeBase object is instantiated, it
+ will use the KnowledgeBaseConfiguration of the previous
KnowledgeBase object.
@@ -304,19 +305,19 @@ KnowledgeBase kbase = kagent.getKnowledgeBase();
- In the above example getKnowledgeBase() will return the same
- provided kbase instance until resource changes are detected and a new
+ In the above example getKnowledgeBase() will return the
+ same provided kbase instance until resource changes are detected and a new
Knowledge Base is built. When the new Knowledge Base is built, it will be
- done with the KnowledgeBaseConfiguration that was provided to
+ done with the KnowledgeBaseConfiguration that was provided to
the previous KnowledgeBase.As mentioned previously, a ChangeSet XML can specify a directory and
all of its contents will be added. If this ChangeSet XML is used with the
- applyChangeSet() method it will also add any directories to the scanning
- process. When the directory scan detects an additional file, it will be
- added to the Knowledge Base; any removed file is removed from the
- Knowledge Base, and modified files will be removed from the Knowledge Base.
-
+ applyChangeSet() method it will also add any directories to
+ the scanning process. When the directory scan detects an additional file,
+ it will be added to the Knowledge Base; any removed file is removed from
+ the Knowledge Base, and modified files will be removed from the Knowledge
+ Base.ChangeSet XML which adds a directories contents
@@ -331,14 +332,14 @@ KnowledgeBase kbase = kagent.getKnowledgeBase();
- Note that for the resource type PKG the drools-compiler dependency is
- not needed as the Knowledge Agent is able to handle those with just
+ Note that for the resource type PKG the drools-compiler dependency
+ is not needed as the Knowledge Agent is able to handle those with just
drools-core.The KnowledgeAgentConfiguration can be used to modify a
- Knowledge Agent's default behavior. You could use this to load
- the resources from a directory, while inhibiting the continuous scan
- for changes of that directory.
+ Knowledge Agent's default behavior. You could use this to load the
+ resources from a directory, while inhibiting the continuous scan for
+ changes of that directory.Change the Scanning Behavior
@@ -355,8 +356,8 @@ KnowledgeAgent kagent =
Previously we mentioned Drools Guvnor and how it can build and
- publish serialized Knowledge Packages on a URL, and that the
- ChangeSet XML can handle URLs and Packages. Taken together, this forms
- an importanty deployment scenario for the Knowledge Agent.
+ publish serialized Knowledge Packages on a URL, and that the ChangeSet XML
+ can handle URLs and Packages. Taken together, this forms an importanty
+ deployment scenario for the Knowledge Agent.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Section-Running.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Section-Running.xml
similarity index 95%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Section-Running.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Section-Running.xml
index 45a3940dc5..9c6869c10c 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-User_Guide/Section-Running.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-ApiReference/Section-Running.xml
@@ -9,19 +9,19 @@
xmlns:ns="http://docbook.org/ns/docbook">
Running
-
+ KnowledgeBase
- The KnowlegeBase is a repository of all the
+ The KnowledgeBase is a repository of all the
application's knowledge definitions. It will contain rules, processes,
functions, and type models. The Knowledge Base itself does not contain
data; instead, sessions are created from the KnowledgeBase
into which data can be inserted and from which process instances may be
- started. Creating the KnowlegeBase can be heavy, whereas
- session creation is very light, so it is recommended that Knowle Bases be
- cached where possible to allow for repeated session creation.
+ started. Creating the KnowledgeBase can be heavy, whereas
+ session creation is very light, so it is recommended that KnowledgeBases
+ be cached where possible to allow for repeated session creation.Creating a new KnowledgeBase
@@ -42,7 +42,7 @@
+ format=""/>
@@ -86,7 +86,7 @@
-
+
@@ -163,19 +163,17 @@ ksession.retract( stiltonHandle );
UpdateThe Rule Engine must be notified of modified facts, so that they
- can be reprocessed. Internally, modification is actually a retract
- followed by an insert; the Rule Engine removes the fact from the
- WorkingMemory and inserts it again. You must use the
- update() method to notify the WorkingMemory
- of changed objects for those objects that are not able to notify the
- WorkingMemory themselves. Notice that
- update() always takes the modified object as a second
- parameter, which allows you to specify new instances for immutable
- objects. The update() method can only be used with
- objects that have shadow proxies turned on. The update method is only
- available within Java code. On the right hand side of a rule, also the
- modify statement is supported, providing simplified
- calls to the object's setters.
+ can be reprocessed. You must use the update() method to
+ notify the WorkingMemory of changed objects for those
+ objects that are not able to notify the WorkingMemory
+ themselves. Notice that update() always takes the
+ modified object as a second parameter, which allows you to specify new
+ instances for immutable objects. On the right hand side of a rule the
+ modify statement is recommended, as it makes the
+ changes and notifies the engine in a single statement. After a fact's
+ field values have changed you must call update before changing another
+ fact, or you will cause problems with the indexing within the rule
+ engine. The modify keyword avoids this problem.
Cheese stilton = new Cheese("stilton");
FactHandle stiltonHandle = workingMemory.insert( stilton );
@@ -189,7 +187,7 @@ workingMemory.update( stiltonHandle, stilton ); WorkingMemoryThe WorkingMemory provides access to the Agenda, permits query
- executions, and lets you access named Enty Points.
+ executions, and lets you access named Entry Points.
WorkingMemory
@@ -197,7 +195,7 @@ workingMemory.update( stiltonHandle, stilton );
+ format=""/>
@@ -207,7 +205,7 @@ workingMemory.update( stiltonHandle, stilton );
Queries are used to retrieve fact sets based on patterns, as
they are used in rules. Patterns may make use of optional parameters.
- Queries can be defined in the Knowlege Base, from where they are
+ Queries can be defined in the Knowledge Base, from where they are
called up to return the matching results. While iterating over the
result collection, any bound identifier in the query can be accessed
using the get(String identifier) method and any FactHandle for that
@@ -220,7 +218,7 @@ workingMemory.update( stiltonHandle, stilton );
+ format=""/>
@@ -231,7 +229,7 @@ workingMemory.update( stiltonHandle, stilton );
+ format=""/>
@@ -303,7 +301,7 @@ query.dispose() // make sure you call dispose when you want the query to close
The KnowledgeRuntime provides further methods that
are applicable to both rules and processes, such as setting globals and
- registering Channels (previously exit points, some
+ registering Channels (previously exit points, some
references may remain in docs for a while).
@@ -312,7 +310,7 @@ query.dispose() // make sure you call dispose when you want the query to close
+ format=""/>
@@ -358,7 +356,7 @@ ksession.setGlobal("list", list);
+ format=""/>
@@ -373,7 +371,7 @@ ksession.setGlobal("list", list);
+ format="PNG"/>
@@ -382,7 +380,7 @@ ksession.setGlobal("list", list);
of the filter interface which are used to allow or deny the firing of
an activation. What you filter on is entirely up to the
implementation. Drools 4.0 used to supply some out of the box filters,
- which have not be exposed in drools 5.0 drools-api, but they are
+ which have not be exposed in drools 5.0 knowledge-api, but they are
simple to implement and the Drools 4.0 code base can be referred
to.
@@ -432,7 +430,7 @@ ksession.setGlobal("list", list);
+ format="PNG"/>
@@ -446,7 +444,7 @@ ksession.setGlobal("list", list);
-
+
@@ -474,11 +472,14 @@ ksession.setGlobal("list", list);
As a general rule, it is a good idea not to count on rules firing
in any particular order, and to author the rules without worrying about
- a "flow".
+ a "flow". However when a flow is needed a number of possibilities exist,
+ including but not limited to: agenda groups, rule flow groups,
+ activation groups, control/semaphore facts. These are discussed in later
+ sections.
Drools 4.0 supported custom conflict resolution strategies; while
this capability still exists in Drools it has not yet been exposed to
- the end user via drools-api in Drools 5.0.
+ the end user via knowledge-api in Drools 5.0.
@@ -490,7 +491,7 @@ ksession.setGlobal("list", list);
+ format=""/>
@@ -501,12 +502,13 @@ ksession.setGlobal("list", list);
also have rules with "auto focus" which means that the focus is taken
for its agenda group when that rule's conditions are true.
- Agenda groups are known as "modules" in CLIPS terminology. They
- provide a handy way to create a "flow" between grouped rules. You can
- switch the group which has focus either from within the rule engine, or
- via the API. If your rules have a clear need for multiple "phases" or
- "sequences" of processing, consider using agenda-groups for this
- purpose.
+ Agenda groups are known as "modules" in CLIPS terminology. While
+ it best to design rules that do not need control flow, this is not
+ always possible. Agenda groups provide a handy way to create a "flow"
+ between grouped rules. You can switch the group which has focus either
+ from within the rule engine, or via the API. If your rules have a clear
+ need for multiple "phases" or "sequences" of processing, consider using
+ agenda-groups for this purpose.Each time setFocus() is called it pushes that Agenda
Group onto a stack. When the focus group is empty it is popped from the
@@ -528,7 +530,7 @@ ksession.setGlobal("list", list);
+ format=""/>
@@ -552,7 +554,7 @@ ksession.setGlobal("list", list);
+ format=""/>
@@ -588,7 +590,7 @@ ksession.setGlobal("list", list);
+ format=""/>
@@ -603,7 +605,7 @@ ksession.setGlobal("list", list);
+ format=""/>
@@ -644,7 +646,7 @@ ksession.setGlobal("list", list);
+ format=""/>
@@ -720,7 +722,7 @@ ksession.setGlobal("list", list);
+ format=""/>
@@ -760,7 +762,7 @@ logger.close();
+ format=""/>
@@ -1008,7 +1010,7 @@ results.getValue( "Get People" );
+ format=""/>
@@ -1019,7 +1021,7 @@ results.getValue( "Get People" );
+ format=""/>
@@ -1242,11 +1244,10 @@ QueryResults qresults = ( QueryResults ) bresults.getValue( "cheeses" );
when services are involved.There is currently no XML schema to support schema validation. The
- basic format is outlined here, and the drools-pipeline module
- has an illustrative unit test in the
- XStreamBatchExecutionTest unit test. The root element is
- <batch-execution> and it can contain zero or more commands
- elements.
+ basic format is outlined here, and the drools-pipeline module has an
+ illustrative unit test in the XStreamBatchExecutionTest unit
+ test. The root element is <batch-execution> and it can contain zero
+ or more commands elements.
Root XML element
@@ -1454,7 +1455,7 @@ QueryResults qresults = ( QueryResults ) bresults.getValue( "cheeses" );
+ format=""/>
@@ -1650,12 +1651,13 @@ ds.init();
Drools ClipsDrools Clips is an alpha level research project to provide a Clips
- like front end ot Drools.
+ like front end ot Drools. As of Drools 5.2 this module as stopped working,
+ we will try and fix for 5.3.
Deftemplates are working, the knowledge base handles multiple name
spaces and you can attach the knoweldge base to the session for interative
- building, to provide a more "shell" like environment suitable for Clips.
-
+ building, to provide a more "shell" like environment suitable for
+ Clips.
@@ -1682,7 +1684,7 @@ ds.init();
-
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Authoring/Chapter-Authoring.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Authoring/Chapter-Authoring.xml
deleted file mode 100644
index 2b485837ac..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Authoring/Chapter-Authoring.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- Authoring
-
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Chapter-Examples.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Chapter-Examples.xml
index 555dbb67e7..08732d1154 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Chapter-Examples.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Chapter-Examples.xml
@@ -18,6 +18,7 @@
the examples in another project (or another IDE) then you will need
to set up the dependencies by hand, of course. Many, but not all of the
examples are documented below, enjoy!
+ Some examples require Java 1.6 to run.
@@ -29,7 +30,10 @@
-
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-BankingExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-BankingExample.xml
index 60f20da476..256c64f160 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-BankingExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-BankingExample.xml
@@ -7,7 +7,8 @@
Banking TutorialName: BankingTutorial
-Main class: org.drools.tutorials.banking.Example*.java
+Main class: org.drools.tutorials.banking.BankingExamplesApp.java
+Module: drools-examples
Type: Java application
Rules file: org.drools.tutorials.banking.*.drl
Objective: Demonstrate pattern matching, basic sorting and calculation rules.
@@ -78,7 +79,7 @@
The first simple rule to execute has a single eval
- condition that will alway be true, so that this rule will match and
+ condition that will always be true, so that this rule will match and
fire, once, after the start.
@@ -89,7 +90,7 @@
eval( 1==1 )
then
System.out.println( "Rule 01 Works" );
-endh
+end
The output for the rule is below, showing that the rule matches
@@ -121,7 +122,7 @@ Rule 01 Works
}
- This doesn’t use any specific facts but instead asserts a set
+ This doesn't use any specific facts but instead asserts a set
of java.lang.Integer objects. This is not considered
"best practice" as a number is not a useful fact, but we use it here
to demonstrate basic techniques before more complexity is added.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-ConwaysGameOfLifeExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-ConwaysGameOfLifeExample.xml
index aad321bd70..4f25dcb926 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-ConwaysGameOfLifeExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-ConwaysGameOfLifeExample.xml
@@ -9,6 +9,7 @@
Name: Conway's Game Of Life
Main class: org.drools.examples.conway.ConwayAgendaGroupRun
org.drools.examples.conway.ConwayRuleFlowGroupRun
+Module: droolsjbpm-integration-examples (Note: this is in a different download, the droolsjbpm-integration download.)
Type: Java application
Rules file: conway-ruleflow.drl conway-agendagroup.drl
Objective: Demonstrates 'accumulate', 'collect' and 'from'
@@ -30,7 +31,7 @@
discuss the Drools parts of the implementation.We'll first introduce the grid view, shown below, designed for the
- visualisation of the game, showing the "arena" where the life simuation
+ visualisation of the game, showing the "arena" where the life simulation
takes place. Initially the grid is empty, meaning that there are no live
cells in the system. Each cell is either alive or dead, with live cells
showing a green ball. Preselected patterns of live cells can be
@@ -209,7 +210,7 @@ end
ruleflow-group "evaluate"
no-loop
when
-# A live cell has fewer than 2 live neighbors
+// A live cell has fewer than 2 live neighbors
theCell: Cell( liveNeighbors < 2, cellState == CellState.LIVE,
phase == Phase.EVALUATE )
then
@@ -222,7 +223,7 @@ rule "Kill The Overcrowded"
ruleflow-group "evaluate"
no-loop
when
-# A live cell has more than 3 live neighbors
+// A live cell has more than 3 live neighbors
theCell: Cell( liveNeighbors > 3, cellState == CellState.LIVE,
phase == Phase.EVALUATE )
then
@@ -235,7 +236,7 @@ rule "Give Birth"
ruleflow-group "evaluate"
no-loop
when
-# A dead cell has 3 live neighbors
+// A dead cell has 3 live neighbors
theCell: Cell( liveNeighbors == 3, cellState == CellState.DEAD,
phase == Phase.EVALUATE )
then
@@ -247,7 +248,7 @@ end
Once all Cell objects in the grid have been evaluated,
- we first clear any calculation activations that occured from any previous
+ we first clear any calculation activations that occurred from any previous
data changes. This is done via the "reset calculate" rule, which clears
any activations in the "calculate" group. We then enter a split in the
rule flow which allows any activations in both the "kill" and the "birth"
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-FibonacciExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-FibonacciExample.xml
index 832d1059cb..6eb5990d40 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-FibonacciExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-FibonacciExample.xml
@@ -7,7 +7,8 @@
Fibonacci ExampleName: Fibonacci
-Main class: org.drools.examples.FibonacciExample
+Main class: org.drools.examples.fibonacci.FibonacciExample
+Module: drools-examples
Type: Java application
Rules file: Fibonacci.drl
Objective: Demonstrates Recursion,
@@ -48,7 +49,7 @@
- Open the class org.drools.examples.FibonacciExample in your Eclipse IDE.
+ Open the class org.drools.examples.fibonacci.FibonacciExample in your Eclipse IDE.
@@ -228,7 +229,7 @@ end
// Bind f3 and s3; alternative reference of f2.sequence
f3 : Fibonacci( s3 : sequence == (f2.sequence + 1 ), value == -1 )
then
- // Note the various referencing rechniques.
+ // Note the various referencing techniques.
modify ( f3 ) { value = f1.value + v2 };
System.out.println( s3 + " == " + f3.value );
end
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-GolfingExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-GolfingExample.xml
index 0ed511bf8c..677cd1012c 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-GolfingExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-GolfingExample.xml
@@ -7,13 +7,14 @@
Golfing ExampleName: Golfing
-Main class: org.drools.examples.GolfingExample
+Main class: org.drools.examples.golfing.GolfingExample
+Module: drools-examples
Type: java application
Rules file: golf.drl
Objective: Configuration example that finds the solution from a large number of available cross products
- The golf example solves a "riddle" style problem that is simple enough to state in sentences, but for which a conventional algorithmic solition is not obvious. It does this by searching for a suitable combination from a "space" of possible solutions.
+ The golf example solves a "riddle" style problem that is simple enough to state in sentences, but for which a conventional algorithmic solution is not obvious. It does this by searching for a suitable combination from a "space" of possible solutions.The riddle
@@ -30,7 +31,7 @@
- The golfer to Fred�s immediate right is wearing blue pants.
+ The golfer to Fred's immediate right is wearing blue pants.
@@ -46,7 +47,7 @@
- The immediate thing about this riddle, is that a solution is not obvious (of course ! it wouldn't be a riddle otherwise !). It also isn't obvious how to write an algorithm to solve it (if it is for you - then you can take a break now, go have a coffee or someting to reward your uber intellect).
+ The immediate thing about this riddle, is that a solution is not obvious (of course ! it wouldn't be a riddle otherwise !). It also isn't obvious how to write an algorithm to solve it (if it is for you - then you can take a break now, go have a coffee or something to reward your uber intellect).Instead of thinking about how to solve it, we can be lazy and use rules instead. So we don't attempt to solve it, we just state the problem in rules, and let the engine derive the solution.
@@ -105,7 +106,7 @@ Tom 3 red
color != $fred.color,
color != $joe.color )
- Refering to the above, we also know there is a golfer called Bob, who wears plaid pants - once again that all we know about him. but of course, we add in the constraints that he must be in a different position to fred, joe, and also have different colored pants.
+ Referring to the above, we also know there is a golfer called Bob, who wears plaid pants - once again that all we know about him. but of course, we add in the constraints that he must be in a different position to fred, joe, and also have different colored pants.$tom : Golfer( name == "Tom",
position != 1,
@@ -144,6 +145,7 @@ Tom 3 red Name: TroubleTicket
Main class: org.drools.examples.TroubleTicketExample, org.drools.examples.TroubleTicketExampleWithDSL
+Module: drools-examples
Type: java application
Rules file: TroubleTicket.drl, TroubleTicketWithDSL.dslr
Objective: Show temporal rules in action
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-HelloWorldExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-HelloWorldExample.xml
index 2b965ab4bb..1adf46fb0d 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-HelloWorldExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-HelloWorldExample.xml
@@ -7,7 +7,8 @@
Hello WorldName: Hello World
-Main class: org.drools.examples.HelloWorldExample
+Main class: org.drools.examples.helloworld.HelloWorldExample
+Module: drools-examples
Type: Java application
Rules file: HelloWorld.drl
Objective: demonstrate basic rules in use
@@ -16,7 +17,7 @@
both the MVEL and Java dialects.This example demonstrates how to build Knowledge Bases and Sessions.
- Also, audit logging and debug outputs are shown, which is ommitted
+ Also, audit logging and debug outputs are shown, which is omitted
from other examples as it's all very similar. A KnowledgeBuilder
is used to turn a DRL source file into Package objects which
the Knowledge Base can consume. The add method takes a Resource
@@ -55,7 +56,7 @@ if (kbuilder.hasErrors()) {
// get the compiled packages (which are serializable)
final Collection<KnowledgePackage> pkgs = kbuilder.getKnowledgePackages();
-// add the packages to a knowledgebase (deploy the knowledge packages).
+// add the packages to a KnowledgeBase (deploy the knowledge packages).
final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages(pkgs);
@@ -133,7 +134,7 @@ ksession.dispose();
- Open the class org.drools.examples.HelloWorldExample in your
+ Open the class org.drools.examples.helloworld.HelloWorldExample in your
Eclipse IDE
@@ -173,19 +174,19 @@ Goodbye cruel world
HelloWorld: System.err in the Console window==>[ActivationCreated(0): rule=Hello World;
- tuple=[fid:1:1:org.drools.examples.HelloWorldExample$Message@17cec96]]
-[ObjectInserted: handle=[fid:1:1:org.drools.examples.HelloWorldExample$Message@17cec96];
- object=org.drools.examples.HelloWorldExample$Message@17cec96]
+ tuple=[fid:1:1:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]]
+[ObjectInserted: handle=[fid:1:1:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96];
+ object=org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]
[BeforeActivationFired: rule=Hello World;
- tuple=[fid:1:1:org.drools.examples.HelloWorldExample$Message@17cec96]]
+ tuple=[fid:1:1:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]]
==>[ActivationCreated(4): rule=Good Bye;
- tuple=[fid:1:2:org.drools.examples.HelloWorldExample$Message@17cec96]]
-[ObjectUpdated: handle=[fid:1:2:org.drools.examples.HelloWorldExample$Message@17cec96];
- old_object=org.drools.examples.HelloWorldExample$Message@17cec96;
- new_object=org.drools.examples.HelloWorldExample$Message@17cec96]
+ tuple=[fid:1:2:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]]
+[ObjectUpdated: handle=[fid:1:2:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96];
+ old_object=org.drools.examples.helloworld.HelloWorldExample$Message@17cec96;
+ new_object=org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]
[AfterActivationFired(0): rule=Hello World]
[BeforeActivationFired: rule=Good Bye;
- tuple=[fid:1:2:org.drools.examples.HelloWorldExample$Message@17cec96]]
+ tuple=[fid:1:2:org.drools.examples.helloworld.HelloWorldExample$Message@17cec96]]
[AfterActivationFired(4): rule=Good Bye]
@@ -216,7 +217,7 @@ Goodbye cruel world
m : Message( status == Message.HELLO, message : message )
then
System.out.println( message );
- modify ( m ) { message = "Goodbyte cruel world",
+ modify ( m ) { message = "Goodbye cruel world",
status = Message.GOODBYE };
end
@@ -272,7 +273,7 @@ end
to create a KnowledgeRuntimeLogger and called
logger.close() at the end. This created an audit log file that
can be shown in the Audit view. We use the Audit view in many of the
- examples to demostrate the example execution flow. In the view screen shot
+ examples to demonstrate the example execution flow. In the view screen shot
below we can see that the object is inserted, which creates an activation
for the "Hello World" rule; the activation is then executed which updates
the Message object causing the "Good Bye" rule to
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-HonestPoliticianExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-HonestPoliticianExample.xml
index 2f4eb1b646..f4fa6ff057 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-HonestPoliticianExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-HonestPoliticianExample.xml
@@ -7,7 +7,8 @@
Honest Politician ExampleName: Honest Politician
-Main class: org.drools.examples.HonestPoliticianExample
+Main class: org.drools.examples.honestpolitician.HonestPoliticianExample
+Module: drools-examples
Type: Java application
Rules file: HonestPoliticianExample.drl
Objective: Illustrate the concept of "truth maintenance" based on the logical insertion of facts
@@ -161,7 +162,7 @@ endHope object. (That action is highlighted green.) The
insertion of the Hope object activates "Hope Lives" and
de-activates "Hope is Dead"; it also activates "Corrupt the Honest"
- for each inserted honested politician. Rule "Hope Lives" executes,
+ for each inserted honest politician. Rule "Hope Lives" executes,
printing "Hurrah!!! Democracy Lives". Then, for each politician, rule
"Corrupt the Honest" fires, printing "I'm an evil corporation and I
have corrupted X", where X is the name of the politician, and modifies
@@ -173,4 +174,4 @@ end
dead" activates and fires printing "We are all Doomed!!! Democracy is
Dead".
-
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-InsuranceExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-InsuranceExample.xml
index a495593109..0a16fac8e2 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-InsuranceExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-InsuranceExample.xml
@@ -21,7 +21,7 @@
-
+
@@ -33,7 +33,7 @@
-
+
@@ -105,7 +105,7 @@ then
-
+
@@ -158,7 +158,7 @@ then
- You should see the RuleAgent downloadomg the pre-compiled package from brms, if something goes wrong and all tests fails, check if the BRMS is up and running and try rebuild the package snapshot.
+ You should see the RuleAgent downloading the pre-compiled package from brms, if something goes wrong and all tests fails, check if the BRMS is up and running and try rebuild the package snapshot.Running org.acme.insurance.test.DriverTest
RuleAgent(insuranceconfig) INFO (Wed Sep 18 14:11:44 BRT 2007): Configuring with newInstance=true, secondsToRefresh=30
@@ -175,19 +175,19 @@ Insurance calculate
Insurance Calcule: 0.0
Driver wants non related expenses coverage: 1.05
Driver wants glass coverage: 1.1025
-Driver wants extra assistence: 1.1576250000000001Driver wants an extra Car: 1.2155062500000002
+Driver wants extra assistance: 1.1576250000000001Driver wants an extra Car: 1.2155062500000002
Driver Single Young Male Driver factor: 1.9448100000000004
New Licenced driver 2.333772
approve: 0.0
-Policy aproved focusing insurance calcule agenda-group
+Policy approved focusing insurance calcule agenda-group
Insurance calculate
Insurance Calcule: 0.0
Night Vehicle Place: 1.44
Day Vehicle Place: 1.656
approve: 0.0
-Policy aproved focusing insurance calcule agenda-group
+Policy approved focusing insurance calcule agenda-group
Insurance calculate
-Insurance extra itens percent: 545.0
+Insurance extra items percent: 545.0
Insurance Calcule: 545.0
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.028 sec
@@ -208,7 +208,7 @@ Tests run: 16, Failures: 0, Errors: 0, Skipped: 0
-
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-MannersExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-MannersExample.xml
index aaada00777..ad51813ba1 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-MannersExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-MannersExample.xml
@@ -8,6 +8,7 @@
Name: Miss Manners
Main class: org.drools.benchmark.manners.MannersBenchmark
+Module: drools-examples
Type: Java application
Rules file: manners.drl
Objective: Advanced walkthrough on the Manners benchmark, covers Depth conflict resolution in depth.
@@ -154,7 +155,7 @@
- Indepth Discussion
+ In depth DiscussionCheating
@@ -359,7 +360,7 @@ end
pid cross product be chosen. How can this be possible
if we have activations, of the same time tag, for nearly all
existing Seating and Guest objects? For
- example, on the third iteration of findDeating the
+ example, on the third iteration of findSeating the
produced activations will be as shown below. Remember, this is from
a very small data set, and with larger data sets there would be many
more possible activated Seating solutions, with multiple
@@ -430,8 +431,7 @@ end
-
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-NumberGuessExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-NumberGuessExample.xml
index 90796eac00..f2dd382775 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-NumberGuessExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-NumberGuessExample.xml
@@ -6,22 +6,21 @@
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
Number Guess
- Name: Number Guess
-Main class: org.drools.examples.NumberGuessExample
+ Name: Number Guess
+Main class: org.drools.examples.numberguess.NumberGuessExample
+Module: droolsjbpm-integration-examples (Note: this is in a different download, the droolsjbpm-integration download.)
Type: Java application
Rules file: NumberGuess.drl
Objective: Demonstrate use of Rule Flow to organise Rules
- The "Number Guess" example shows the use of Rule Flow, a way of
- controlling the order in which rules are fired. It uses widely
- understood workflow diagrams for defining the order in which groups
- of rules will be executed.
+ The "Number Guess" example shows the use of Rule Flow, a way of controlling the order in which rules are fired.
+ It uses widely understood workflow diagrams for defining the order in which groups of rules will be executed.Creating the Number Guess RuleBase: NumberGuessExample.main() - part 1
- final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+ final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newClassPathResource( "NumberGuess.drl",
ShoppingExample.class ),
ResourceType.DRL );
@@ -33,12 +32,10 @@ final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
- The creation of the package and the loading of the rules (using
- the add() method) is the same as the previous examples.
- There is an additional line to add the Rule Flow
- (NumberGuess.rf), which provides the option of
- specifying different rule flows for the same Knowledge Base.
- Otherwise, the Knowledge Base is created in the same manner as before.
+ The creation of the package and the loading of the rules (using the add() method) is the same as
+ the previous examples. There is an additional line to add the Rule Flow (NumberGuess.rf), which
+ provides the option of specifying different rule flows for the same Knowledge Base. Otherwise, the Knowledge Base is
+ created in the same manner as before.Starting the RuleFlow: NumberGuessExample.main() - part 2
@@ -60,55 +57,42 @@ logger.close();
ksession.dispose();
- Once we have a Knowledge Base, we can use it to obtain a Stateful
- Session. Into our session we insert our facts, i.e., standard Java objects.
- (For simplicity, in this sample, these classes are all contained within
- our NumberGuessExample.java file. Class
- GameRules provides the maximum range and the number of guesses
- allowed. Class RandomNumber automatically generates a number
- between 0 and 100 and makes it available to our rules, by insertion via
- the getValue() method. Class Game keeps track
- of the guesses we have made before, and their number.
-
- Note that before we call the standard fireAllRules()
- method, we also start the process that we loaded earlier, via the
- startProcess() method. We'll learn where to obtain the
- parameter we pass ("Number Guess", i.e., the identifier of the rule flow)
- when we talk about the rule flow file and the graphical Rule Flow Editor
- below.
-
- Before we finish the discussion of our Java code, we note that in
- some real-life application we would examine the final state of the objects.
- (Here, we could retrieve the number of guesses, to add it to a high score
- table.) For this example we are content to ensure that the Working Memory
- session is cleared by calling the dispose() method.
+ Once we have a Knowledge Base, we can use it to obtain a Stateful Session. Into our session we insert our facts,
+ i.e., standard Java objects. (For simplicity, in this sample, these classes are all contained within our
+ NumberGuessExample.java file. Class GameRules provides the maximum range and the
+ number of guesses allowed. Class RandomNumber automatically generates a number between 0 and 100 and
+ makes it available to our rules, by insertion via the getValue() method. Class Game keeps
+ track of the guesses we have made before, and their number.
+
+ Note that before we call the standard fireAllRules() method, we also start the process that we
+ loaded earlier, via the startProcess() method. We'll learn where to obtain the parameter we pass ("Number
+ Guess", i.e., the identifier of the rule flow) when we talk about the rule flow file and the graphical Rule Flow
+ Editor below.
+
+ Before we finish the discussion of our Java code, we note that in some real-life application we would examine
+ the final state of the objects. (Here, we could retrieve the number of guesses, to add it to a high score table.) For
+ this example we are content to ensure that the Working Memory session is cleared by calling the dispose()
+ method.RuleFlow for the NumberGuess Example
-
+
- If you open the NumberGuess.rf file in the
- Drools IDE (provided you have the JBoss Rules extensions installed
- correctly in Eclipse) you should see the above diagram, similar to a
- standard flowchart. Its icons are similar (but not exactly the same)
- as in the JBoss jBPM workflow product. Should you wish to edit the
- diagram, a menu of available components should be available to the
- left of the diagram in the IDE, which is called the
- palette. This diagram is saved in XML, an
- (almost) human readable format, using XStream.
-
- If it is not already open, ensure that the Properties View is
- visible in the IDE. It can be opened by clicking "Window", then
- "Show View" and "Other", where you can select the "Properties" view.
- If you do this before you select any item on
- the rule flow (or click on the blank space in the rule flow) you
+ If you open the NumberGuess.rf file in the Drools IDE (provided you have the JBoss Rules
+ extensions installed correctly in Eclipse) you should see the above diagram, similar to a standard flowchart. Its
+ icons are similar (but not exactly the same) as in the JBoss jBPM workflow product. Should you wish to edit the
+ diagram, a menu of available components should be available to the left of the diagram in the IDE, which is called the
+ palette. This diagram is saved in XML, an (almost) human readable format, using XStream.
+
+ If it is not already open, ensure that the Properties View is visible in the IDE. It can be opened by clicking
+ "Window", then "Show View" and "Other", where you can select the "Properties" view. If you do this
+ before you select any item on the rule flow (or click on the blank space in the rule flow) you
should be presented with the following set of properties.
@@ -116,65 +100,53 @@ ksession.dispose();
-
+
- Keep an eye on the Properties View as we progress through the
- example's rule flow, as it presents valuable information. In this case, it
- provides us with the identification of the Rule Flow Process that
- we used in our earlier code snippet, when we called
- session.startProcess().
+ Keep an eye on the Properties View as we progress through the example's rule flow, as it presents valuable
+ information. In this case, it provides us with the identification of the Rule Flow Process that we used in our earlier
+ code snippet, when we called session.startProcess().
- In the "Number Guess" Rule Flow we encounter several node
- types, many of them identified by an icon.
+ In the "Number Guess" Rule Flow we encounter several node types, many of them identified by an icon.
-
-
+
- The Start node (white arrow in a green circle) and the End
- node (red box) mark beginning and end of the rule flow.
+ The Start node (white arrow in a green circle) and the End node (red box) mark beginning and end of the
+ rule flow.
- A Rule Flow Group box (yellow, without an icon) represents
- a Rule Flow Groups defined in our rules (DRL) file that we will
- look at later. For example, when the flow reaches the Rule Flow Group
- "Too High", only those rules marked with an attribute of
- ruleflow-group"Too High" can potentially fire.
+ A Rule Flow Group box (yellow, without an icon) represents a Rule Flow Groups defined in our rules (DRL)
+ file that we will look at later. For example, when the flow reaches the Rule Flow Group "Too High", only those
+ rules marked with an attribute of ruleflow-group"Too High" can potentially
+ fire.
- Action nodes (yellow, cog-shaped icon) perform standard Java
- method calls. Most action nodes in this example call
- System.out.println(), indicating the program's progress
- to the user.
+ Action nodes (yellow, cog-shaped icon) perform standard Java method calls. Most action nodes in this
+ example call System.out.println(), indicating the program's progress to the user.
- Split and Join Nodes (blue ovals, no icon) such as "Guess Correct?"
- and "More guesses Join" mark places where the flow of control can
- split, according to various conditions, and rejoin, respectively
+ Split and Join Nodes (blue ovals, no icon) such as "Guess Correct?" and "More guesses Join" mark places
+ where the flow of control can split, according to various conditions, and rejoin, respectively
- Arrows indicate the flow between the various nodes.
+ Arrows indicate the flow between the various nodes.
-
-
+
- The various nodes in combination with the rules make the
- Number Guess game work. For example, the "Guess" Rule Flow Group
- allows only the rule "Get user Guess" to fire, because only that rule
- has a matching attribute of ruleflow-group"Guess".
+ The various nodes in combination with the rules make the Number Guess game work. For example, the "Guess" Rule
+ Flow Group allows only the rule "Get user Guess" to fire, because only that rule has a matching attribute of
+ ruleflow-group"Guess".
- A Rule firing only at a specific point in the Rule Flow:
- NumberGuess.drl
+ A Rule firing only at a specific point in the Rule Flow: NumberGuess.drl
- rule "Get user Guess"
+ rule "Get user Guess"
ruleflow-group "Guess"
no-loop
when
@@ -192,100 +164,84 @@ ksession.dispose();
modify ( game ) { guessCount = game.guessCount + 1 }
insert( new Guess( i ) );
end
-
-
- The rest of this rule is fairly standard. The LHS section
- (after when) of the rule states that it will be activated
- for each RandomNumber object inserted into the Working
- Memory where guessCount is less than
- allowedGuesses from the GameRules object
- and where the user has not guessed the correct number.
-
- The RHS section (or consequence, after then) prints a
- message to the user and then awaits user input from
- System.in. After obtaining this input (the
- readLine() method call blocks until the return key is
- pressed) it modifies the guess count and inserts the new
- guess, making both available to the Working Memory.
-
- The rest of the rules file is fairly standard: the package
- declares the dialect as MVEL, and various Java classes are imported.
- In total, there are five rules in this file:
-
-
-
- Get User Guess, the Rule we examined above.
-
-
-
- A Rule to record the highest guess.
-
-
-
- A Rule to record the lowest guess.
-
-
-
- A Rule to inspect the guess and retract it from memory if
- incorrect.
-
-
-
- A Rule that notifies the user that all guesses have been
- used up.
-
-
-
- One point of integration between the standard Rules and
- the RuleFlow is via the ruleflow-group attribute on the
- rules, as dicussed above. A
- second point of integration between the rules (.drl) file
- and the Rules Flow .rf files is
- that the Split Nodes (the blue ovals) can use values in the Working Memory
- (as updated by the rules) to decide which flow of action to take. To see
- how this works, click on the "Guess Correct Node"; then within the
- Properties View, open the Constraints Editor by clicking the button at
- the right that appears once you click on the "Constraints" property line.
- You should see something similar to the diagram below.
-
-
- Edit Constraints for the "Guess Correct" Node
-
-
-
-
-
-
-
-
- Click on the "Edit" button beside "To node Too High" and you'll
- see a dialog like the one below. The values in the "Textual Editor"
- window follow the standard rule format for the LHS and can refer to
- objects in Working Memory.
- The consequence (RHS) is that the flow of control follows this node
- (i.e., "To node Too High") if the LHS expression evaluates to true.
-
-
- Constraint Editor for the "Guess Correct" Node: value too high
-
-
-
-
-
-
-
-
- Since the file NumberGuess.java contains a
- main() method, it
- can be run as a standard Java application, either from the command line
- or via the IDE. A typical game might result in the interaction below.
- The numbers in bold are typed in by the user.
-
-
- Example Console output where the Number Guess Example beat the
- human!
-
- You have 5 out of 5 guesses left.
+
+
+ The rest of this rule is fairly standard. The LHS section (after when) of the rule states
+ that it will be activated for each RandomNumber object inserted into the Working Memory where
+ guessCount is less than allowedGuesses from the GameRules object and where the
+ user has not guessed the correct number.
+
+ The RHS section (or consequence, after then) prints a message to the user and then awaits
+ user input from System.in. After obtaining this input (the readLine() method call blocks
+ until the return key is pressed) it modifies the guess count and inserts the new guess, making both available to the
+ Working Memory.
+
+ The rest of the rules file is fairly standard: the package declares the dialect as MVEL, and various Java
+ classes are imported. In total, there are five rules in this file:
+
+
+
+ Get User Guess, the Rule we examined above.
+
+
+
+ A Rule to record the highest guess.
+
+
+
+ A Rule to record the lowest guess.
+
+
+
+ A Rule to inspect the guess and retract it from memory if incorrect.
+
+
+
+ A Rule that notifies the user that all guesses have been used up.
+
+
+
+ One point of integration between the standard Rules and the RuleFlow is via the
+ ruleflow-group attribute on the rules, as discussed above. A second point of integration
+ between the rules (.drl) file and the Rules Flow .rf files is that the Split Nodes (the blue ovals) can use
+ values in the Working Memory (as updated by the rules) to decide which flow of action to take. To see how this works,
+ click on the "Guess Correct Node"; then within the Properties View, open the Constraints Editor by clicking the button
+ at the right that appears once you click on the "Constraints" property line. You should see something similar to the
+ diagram below.
+
+
+ Edit Constraints for the "Guess Correct" Node
+
+
+
+
+
+
+
+
+ Click on the "Edit" button beside "To node Too High" and you'll see a dialog like the one below. The values in
+ the "Textual Editor" window follow the standard rule format for the LHS and can refer to objects in Working Memory.
+ The consequence (RHS) is that the flow of control follows this node (i.e., "To node Too High") if the LHS expression
+ evaluates to true.
+
+
+ Constraint Editor for the "Guess Correct" Node: value too high
+
+
+
+
+
+
+
+
+ Since the file NumberGuess.java contains a main() method, it can be run as a
+ standard Java application, either from the command line or via the IDE. A typical game might result in the interaction
+ below. The numbers in bold are typed in by the user.
+
+
+ Example Console output where the Number Guess Example beat the human!
+
+ You have 5 out of 5 guesses left.
Please enter your guess from 0 to 100
50
Your guess was too high
@@ -309,77 +265,59 @@ You have no more guesses
The correct guess was 48
-
-
- A summary of what is happening in this sample is:
-
-
-
-
- The main() method of
- NumberGuessExample.java loads a Rule Base,
- creates a Stateful Session and inserts Game,
- GameRules and RandomNumber
- (containing the target number) objects into it. The
- method also sets the process flow we are going to use, and fires all
- rules. Control passes to the Rule Flow.
-
-
-
- File NumberGuess.rf, the Rule Flow,
- begins at the "Start" node.
-
-
-
- Control passes (via the "More guesses" join node) to the
- Guess node.
-
-
-
- At the Guess node, the appropriate Rule Flow Group
- ("Get user Guess") is enabled. In this case the Rule "Guess" (in the
- NumberGuess.drl file) is triggered. This rule
- displays a message to the user, takes the response, and puts it into
- Working Memory. Flow passes to the next Rule Flow Node.
-
-
-
- At the next node, "Guess Correct", constraints inspect the
- current session and decide which path to take.
-
- If the guess in step 4 was too high or too low, flow proceeds
- along a path which has an action node with normal Java code
- printing a suitable message and a Rule Flow Group causing a
- highest guess or lowest guess rule to be triggered. Flow passes
- from these nodes to step 6.
-
- If the guess in step 4 was right, we proceed along the path
- towards the end of the Rule Flow. Before we get there, an action
- node with normal Java code prints a statement "you guessed
- correctly". There is a join node here (just before the Rule Flow
- end) so that our no-more-guesses path (step 7) can also terminate
- the Rule Flow.
-
-
-
- Control passes as per the Rule Flow via a join node, a guess
- incorrect Rule Flow Group (triggering a rule to retract a guess from
- Working Memory) onto the "More guesses" decision node.
-
-
-
- The "More guesses" decision node (on the right hand side of the
- rule flow) uses constraints, again looking at values that the rules
- have put into the working memory, to decide if we have more
- guesses and if so, goto step 3. If not, we proceed to the end of
- the rule flow, via a Rule Flow Group that triggers a rule stating
- "you have no more guesses".
-
-
-
- The loop over steps 3 to 7 continues until the number is guessed
- correctly, or we run out of guesses.
-
-
-
-
+
+
+ A summary of what is happening in this sample is:
+
+
+
+ The main() method of NumberGuessExample.java loads a Rule Base, creates a
+ Stateful Session and inserts Game, GameRules and RandomNumber (containing
+ the target number) objects into it. The method also sets the process flow we are going to use, and fires all
+ rules. Control passes to the Rule Flow.
+
+
+
+ File NumberGuess.rf, the Rule Flow, begins at the "Start" node.
+
+
+
+ Control passes (via the "More guesses" join node) to the Guess node.
+
+
+
+ At the Guess node, the appropriate Rule Flow Group ("Get user Guess") is enabled. In this case the Rule
+ "Guess" (in the NumberGuess.drl file) is triggered. This rule displays a message to the user,
+ takes the response, and puts it into Working Memory. Flow passes to the next Rule Flow Node.
+
+
+
+ At the next node, "Guess Correct", constraints inspect the current session and decide which path to
+ take.
+
+ If the guess in step 4 was too high or too low, flow proceeds along a path which has an action node with
+ normal Java code printing a suitable message and a Rule Flow Group causing a highest guess or lowest guess rule to
+ be triggered. Flow passes from these nodes to step 6.
+
+ If the guess in step 4 was right, we proceed along the path towards the end of the Rule Flow. Before we get
+ there, an action node with normal Java code prints a statement "you guessed correctly". There is a join node here
+ (just before the Rule Flow end) so that our no-more-guesses path (step 7) can also terminate the Rule Flow.
+
+
+
+ Control passes as per the Rule Flow via a join node, a guess incorrect Rule Flow Group (triggering a rule to
+ retract a guess from Working Memory) onto the "More guesses" decision node.
+
+
+
+ The "More guesses" decision node (on the right hand side of the rule flow) uses constraints, again looking
+ at values that the rules have put into the working memory, to decide if we have more guesses and if so, goto step
+ 3. If not, we proceed to the end of the rule flow, via a Rule Flow Group that triggers a rule stating "you have no
+ more guesses".
+
+
+
+ The loop over steps 3 to 7 continues until the number is guessed correctly, or we run out of guesses.
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PetStoreExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PetStoreExample.xml
index 3c62c298d0..4fca8260ca 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PetStoreExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PetStoreExample.xml
@@ -7,7 +7,8 @@
Pet Store ExampleName: Pet Store
-Main class: org.drools.examples.PetStore
+Main class: org.drools.examples.petstore.PetStoreExample
+Module: drools-examples
Type: Java application
Rules file: PetStore.drl
Objective: Demonstrate use of Agenda Groups, Global Variables and integration with a GUI,
@@ -70,9 +71,8 @@ including callbacks from within the rules
Only a few Swing-related points will be discussed in this section,
but a good tutorial about Swing components can be found at Sun's
Swing website, in
-
- http://java.sun.com/docs/books/tutorial/uiswing/
- .
+ http://java.sun.com/docs/books/tutorial/uiswing/.The pieces of Java code in Petstore.java
that relate to rules and facts are shown below.
@@ -187,9 +187,9 @@ ui.createAndShowGUI();
package org.drools.examples
import org.drools.WorkingMemory
-import org.drools.examples.PetStore.Order
-import org.drools.examples.PetStore.Purchase
-import org.drools.examples.PetStore.Product
+import org.drools.examples.petstore.PetStoreExample.Order
+import org.drools.examples.petstore.PetStoreExample.Purchase
+import org.drools.examples.petstore.PetStoreExample.Product
import java.util.ArrayList
import javax.swing.JOptionPane;
@@ -469,7 +469,7 @@ endThe rule "do checkout" has no
agenda group set and no auto-focus attribute. As such, is is
deemed part of the default (MAIN) agenda group. This group gets focus by
- default when all the rules in agenda-groups that explicity had focus set
+ default when all the rules in agenda-groups that explicitly had focus set
to them have run their course.There is no LHS to the rule, so the RHS will always call the
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PongExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PongExample.xml
new file mode 100644
index 0000000000..9fb1979990
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PongExample.xml
@@ -0,0 +1,27 @@
+
+
+ Pong
+
+ A Conversion for the classic game Pong. Use the keys A, Z and K, M.
+ The ball should get faster after each bounce.
+
+ Name: Example Pong
+Main class: org.drools.games.pong.PongMain
+
+
+ Pong Screenshot
+
+
+
+
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PricingExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PricingExample.xml
index 801daa2e1a..c9b0901025 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PricingExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-PricingExample.xml
@@ -17,7 +17,8 @@
percentage.Name: Example Policy Pricing
-Main class: org.drools.examples.PricingRuleDTExample
+Main class: org.drools.examples.decisiontable.PricingRuleDTExample
+Module: drools-examples
Type: Java application
Rules file: ExamplePolicyPricing.xls
Objective: demonstrate spreadsheet-based decision tables.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-QuickStart.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-QuickStart.xml
deleted file mode 100755
index fe185ed8b9..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-QuickStart.xml
+++ /dev/null
@@ -1,767 +0,0 @@
-
-
- Introduction
-
-
- The IDE provides developers (and very technical users) with an environment to edit and test rules in various formats, and integrate it deeply with their applications. In cases where you prefer business rules and web tooling, you will want to look at the BRMS (but using the BRMS and the IDE together is not uncommon).
-
- The Drools IDE is delivered as an eclipse plugin, which
- allows you to author and manage rules from within Eclipse, as well as
- integrate rules with your application. This is an optional tool, and not all
- components are required to be used, you can use what components are relevant
- to you. The Drools IDE is also a part of the Red Hat Developer Studio (formerly known as JBoss IDE).
-
- This guide will cover some of the features of JBoss Drools, in as far
- as the IDE touches on them (it is assumed that the reader has some
- familiarity with rule engines, and Drools in particular. It is important to
- note that none of the underlying features of the rule engine are dependent
- on Eclipse, and integrators are free to use their tools of choice, as always
- ! Plenty of people use IntelliJ with rules, for instance.
-
- Note you can get the plug in either as a zip to download, or from an
- update site (refer to the chapter on installation).
-
-
- Overview
-
-
-
-
-
-
-
-
-
- Features outline
-
- The rules IDE has the following features
-
-
-
- Textual/graphical rule editor
-
-
-
- An editor that is aware of DRL syntax, and provides content
- assistance (including an outline view)
-
-
- An editor that is aware of DSL (domain specific langauge) extensions, and provides content assistance.
-
-
-
-
-
- RuleFlow graphical editor
- You can edit visual graphs which represent a process (a rule flow). The RuleFlow can then be applied to your rule package to have imperative control.
-
-
-
- Wizards to accelerate and ...
-
-
-
- Help you quickly create a new "rules" project
-
-
-
- Create a new rule resource
-
-
-
- Create a new Domain Specific language
-
-
-
- Create a new decision table, guided editor, ruleflow
-
-
-
-
-
-
-
- A domain specific language editor
-
-
-
- Create and manage mappings from your users language to the
- rule language
-
-
-
-
-
- Rule validation
-
-
-
- As rules are entered, the rule is "built" in the background
- and errors reported via the problem "view" where possible
-
-
-
-
-
- You can see the above features make use of Eclipse infrastructure
- and features. All of the power of eclipse is available.
-
-
-
- Creating a Rule project
-
- The aim of the new project wizard is to setup an executable scaffold
- project to start using rules immediately. This will setup a basic
- structure, classpath and sample rules and test case to get you
- started.
-
-
- New rule project scaffolding
-
-
-
-
-
-
-
- When you choose to create a new "rule project" - you will get a choice to add some default artifacts to it (like rules, decision tables, ruleflows etc). These can serve as a starting point, and will give you something executable to play with (which you can then modify and mould to your needs). The simplest case (a hello world rule) is shown below. Feel free to experiment with the plugin at this point.
-
-
- New rule project result
-
-
-
-
-
-
-
-
- The newly created project contains an example rule file (Sample.drl)
- in the src/rules dir and an example java file (DroolsTest.java) that can
- be used to execute the rules in a Drools engine in the folder src/java, in
- the com.sample package. All the others jars that are necessary during
- execution are also added to the classpath in a custom classpath container
- called Drools Library. Rules do not have to be kept in "java"
- projects at all, this is just a convenience for people who are already
- using eclipse as their Java IDE.
-
- Important note: The Drools plug in adds a "Drools Builder"
- capability to your eclipse instance. This means you can enable a builder
- on any project that will build and validate your rules when resources
- change. This happens automatically with the Rule Project Wizard, but you
- can also enable it manually on any project. One downside of this is if you
- have rule files that have a large number of rules (>500 rules per file)
- it means that the background builder may be doing a lot of work to
- build the rules on each change. An option here is to turn off the builder,
- or put the large rules into .rule files, where you can still use the rule
- editor, but it won't build them in the background - to fully validate the
- rules you will need to run them in a unit test of course.
-
-
-
- Creating a new rule and wizards
-
- You can create a rule simple as an empty text ".drl" file, or use
- the wizard to do so. The wizard menu can be invoked by Control+N, or
- choosing it from the toolbar (there will be a menu with the JBoss Drools
- icon).
-
-
- The wizard menu
-
-
-
-
-
-
-
-
- The wizard will ask for some basic options for generating a rule
- resource. These are just hints, you can change your mind later !. In terms
- of location, typically you would create a top level /rules directory to
- store your rules if you are creating a rule project, and store it in a
- suitably named subdirectory. The package name is mandatory, and is similar
- to a package name in java (ie. its a namespace that groups like rules
- together).
-
-
- New rule wizard
-
-
-
-
-
-
-
-
- This result of this wizard is to generate a rule skeleton to work
- from. As with all wizards, they are candy: you don't have to use them if
- you don't want !
-
-
-
- Textual rule editor
-
- The rule editor is where rule managers and developers will be
- spending most of their time. The rule editor follows the pattern of a
- normal text editor in eclipse, with all the normal features of a text
- editor. On top of this, the rule editor provides pop up content
- assistance. You invoke popup content assistance the "normal" way by
- pressing Control + Space at the same time.
-
-
- The rule editor in action
-
-
-
-
-
-
-
-
- The rule editor works on files that have a .drl (or .rule)
- extension. Rules are generally grouped together as a "package" of rules
- (like the old ruleset construct). It will also be possible to have rules
- in individual files (grouped by being in the same package "namespace" if
- you like). These DRL files are plain text files.
-
- You can see from the example above that the package is using a
- domain specific language (note the expander keyword, which tells the rule
- compiler to look for a dsl file of that name, to resolve the rule
- language). Even with the domain specific language (DSL) the rules are
- still stored as plain text as you see on screen, which allows simpler
- management of rules and versions (comparing versions of rules for
- instance).
-
- The editor has an outline view that is kept in sync with the
- structure of the rules (updated on save). This provides a quick way of
- navigating around rules by name, in a file which may have hundreds of
- rules. The items are sorted alphabetically by default.
-
-
- The rule outline view
-
-
-
-
-
-
-
-
-
-
- Guided editor (rule GUI)
-
- A new feature of the Drools IDE (since version 4) is the guided editor for rules. This is similar to the web based editor that is available in the BRMS. This allows you to build rules in a GUI driven fashion, based on your object model.
-
-
-
- The guided editor
-
-
-
-
-
-
-
-
-
- To create a rule this way, use the wizard menu. It will create a instance of a .brl file and open an editor. The guided editor works based on a .package file in the same directory as the .brl file. In this "package" file - you have the package name and import statements - just like you would in the top of a normal DRL file. So the first time you create a brl rule - you will need to ppulate the package file with the fact classes you are interested in. Once you have this the guided editor will be able to prompt you with facts/fields and build rules graphically.
-
-
-
- The guided editor works off the model classes (fact classes) that you configure. It then is able to "render" to DRL the rule that you have entered graphically. You can do this visually - and use it as a basis for learning DRL, or you can use it and build rules of the brl directly. To do this, you can either use the drools-ant module (it is an ant task that will build up all the rule assets in a folder as a rule package - so you can then deploy it as a binary file), OR you can use the following snippet of code to convert the brl to a drl rule:
-
-
-
- BRXMLPersitence read = BRXMLPersitence.getInstance();
-BRDRLPersistence write = BRDRLPersistence.getInstance();
-String brl = ... read from the .brl file as needed...
-String outputDRL = write.marshall(read.unmarshal(brl));
-//then pass the outputDRL to the PackageBuilder as normal
-
-
-
- Views
-
- When debugging an application using a Drools engine, these views
- can be used to check the state of the Drools engine itself: the Working
- Memory View, the Agenda View the Global Data View. To be able to use
- these views, create breakpoints in your code invoking the working memory.
- For example, the line where you call workingMemory.fireAllRules() is a
- good candidate. If the debugger halts at that joinpoint, you should select
- the working memory variable in the debug variables view. The following
- rules can then be used to show the details of the selected working
- memory:
-
-
-
- The Working Memory shows all elements in the working memory of
- the Drools working memory.
-
-
-
- The Agenda View shows all elements on the agenda. For each rule
- on the agenda, the rule name and bound variables are shown.
-
-
-
- The Global Data View shows all global data currently defined in
- the Drools working memory.
-
-
-
- The Audit view can be used to show audit logs that contain events
- that were logged during the execution of a rules engine in a tree
- view.
-
-
- The Working Memory View
-
-
-
-
-
-
-
- The Working Memory shows all elements in the working memory of the
- Drools engine.
-
- An action is added to the right of the view, to customize what is
- shown:
-
-
-
- The Show Logical Structure toggles showing the logical
- structure of the elements in the working memory, or all their
- details. Logical structures allow for example visualizing sets of
- elements in a more obvious way.
-
-
-
-
-
- The Agenda View
-
-
-
-
-
-
-
- The Agenda View shows all elements on the agenda. For each rule on
- the agenda, the rule name and bound variables are shown.
-
- An action is added to the right of the view, to customize what is
- shown:
-
-
-
- The Show Logical Structure toggles showing the logical
- structure of the agenda item, or all their details. Logical
- structures allow for example visualizing sets of elements in a more
- obvious way. The logical structure of AgendaItems shows the rule
- that is represented by the AgendaItem, and the values of all the
- parameters used in the rule.
-
-
-
-
-
- The Global Data View
-
-
-
-
-
-
-
- The Global Data View shows all global data currently defined in
- the Drools engine.
-
- An action is added to the right of the view, to customize what is
- shown:
-
-
-
- The Show Logical Structure toggles showing the logical
- structure of the elements in the working memory, or all their
- details. Logical structures allow for example visualizing sets of
- elements in a more obvious way.
-
-
-
-
-
- The Audit View
-
-
-
-
-
-
-
- The audit view can be used to visualize an audit log that can be
- created when executing the rules engine. To create an audit log, use the
- following code:
-
- WorkingMemory workingMemory = ruleBase.newWorkingMemory();
- // create a new Working Memory Logger, that logs to file.
- WorkingMemoryFileLogger logger = new WorkingMemoryFileLogger(workingMemory);
- // an event.log file is created in the log dir (which must exist)
- // in the working directory
- logger.setFileName("log/event");
-
- workingMemory.assertObject( ... );
- workingMemory.fireAllRules();
-
- // stop logging
- logger.writeToDisk();
-
- Open the log by clicking the Open Log action (first action in the
- Audit View) and select the file. The Audit view now shows all events
- that where logged during the executing of the rules. There are different
- types of events (each with a different icon):
-
-
-
- Object inserted (green square)
-
-
-
- Object updated (yellow square)
-
-
-
- Object removed (red square)
-
-
-
- Activation created (arrow to the right)
-
-
-
- Activation cancelled (arrow to the left)
-
-
-
- Activation executed (blue diamond)
-
-
-
- Ruleflow started / ended (process icon)
-
-
-
- Ruleflow-group activated / deactivated (process icon)
-
-
-
- Rule package added / removed (Drools icon)
-
-
-
- Rule added / removed (Drools icon)
-
-
-
- All these events show extra information concerning the event, like
- the id and toString representation of the object in case of working
- memory events (assert, modify and retract), the name of the rule and all
- the variables bound in the activation in case of an activation event
- (created, cancelled or executed). If an event occurs when executing an
- activation, it is shown as a child of the activation executed event. For
- some events, you can retrieve the "cause":
-
-
-
- The cause of an object modified or retracted event is the last
- object event for that object. This is either the object asserted
- event, or the last object modified event for that object.
-
-
-
- The cause of an activation cancelled or executed event is the
- corresponding activation created event.
-
-
-
- When selecting an event, the cause of that event is shown in green
- in the audit view (if visible of course). You can also right click the
- action and select the "Show Cause" menu item. This will scroll you to
- the cause of the selected event.
-
-
-
-
- Domain Specific Languages
-
- Domain Specific Languages (dsl) allow you to create a language that
- allows your rules to look like, rules ! Most often the domain specific
- language reads like natural language. Typically you would look at how a
- business analyst would describe the rule, in their own words, and then map
- this to your object model via rule constructs. A side benefit of this is
- that it can provide an insulation layer between your domain objects, and
- the rules themselves (as we know you like to refactor !). A domain
- specific language will grow as the rules grow, and works best when there
- are common terms used over an over, with different parameters.
-
- To aid with this, the rule workbench provides an editor for domain
- specific languages (they are stored in a plain text format, so you can
- use any editor of your choice - it uses a slightly enhanced version of the
- "Properties" file format, simply). The editor will be invoked on any files
- with a .dsl extension (there is also a wizard to create a sample
- DSL).
-
-
- Editing languages
-
-
- The Domain Specific Language editor
-
-
-
-
-
-
-
-
- The DSL editor provides a table view of Language Expression to
- Rule Expression mapping. The Language expression is what is used in the
- rules. This also feeds the content assistance for the rule editor, so
- that it can suggest Language Expressions from the DSL configuration (the
- rule editor loads up the DSL configuration when the rule resource is
- loaded for editing). The Rule language mapping is the "code" for the
- rules - which the language expression will be compiled to by the rule
- engine compiler. For form of this Rule language depends if it is for a
- condition or action part of a rule (it may be a snippet of java, for
- instance). The "scope" item indicates where the expression is targeted:
- is it for the "when" part of the rule (LHS)? the "then" part (RHS)? Or
- anywhere?
-
- By selecting a mapping item (a row in the table) you can see the
- expression and mapping in the greyed out fields below. Double clicking
- or pressing the edit button will open the edit dialog. You can remove
- items, and add new ones (you should generally only remove when you know
- that expression is no longer in use).
-
-
- Language Mapping editor dialog
-
-
-
-
-
-
-
-
- How it works: the "Language expression" is used to parse the rule
- language, depending on what the "scope" is set to. When it is found in a
- rule, the values that are market by the curly braces {value} are
- extracted from the rule source. These values are then interpolated with
- the "Rule mapping" expression, based on the names between the curly
- braces. So in the example above, the natural language expression maps
- to 2 constraints on a fact of type Person (ie the person object has the
- age field as less than {age}, and the location value is the string of
- {value}, where {age} and {value} are pulled out of the original rule
- source. The Rule mapping may be a java expression (such as if the scope
- was "then"). If you did not wish to use a language mapping for a
- particular rule in a drl, prefix the expression with > and the
- compiler will not try to translate it according to the language
- definition. Also note that domain specific languages are optional. When
- the rule is compiled, the .dsl file will also need to be
- available.
-
-
-
-
- The Rete View
-
- The Rete Tree View shows you the current Rete Network for your drl
- file. Just click on the tab "Rete Tree" below on the DRL Editor.
- Afterwards you can generate the current Rete Network visualization. You
- can push and pull the nodes to arrange your optimal network overview. If
- you got hundreds of nodes, select some of them with a frame. Then you can
- pull groups of them. You can zoom in and out, in case not all nodes are
- shown in the current view. For this press the button "+" oder "-".
-
- There is no export function, which creates a gif or jpeg picture, in
- the current release. Please use ctrl + alt + print to create a copy of
- your current eclipse window and cut it off.
-
-
-
-
-
-
-
- The graph is created with the Java Universal Network/Graph Framework
- (JUNG). The Rete View is
- an advanced feature which takes full advantage of the Eclipse Graphical Editing Framework (GEF).
-
- The Rete view works only in Drools Rule Projects, where the Drools
- Builder is set in the project´s properties.
-
- If you are using Drools in an other type of project, where you are
- not having a Drools Rule Project with the appropriate Drools Builder, you
- can create a little workaround:
-
- Set up a little Drools Rule Project next to it, putting needed
- libraries into it and the drls you want to inspect with the Rete View.
- Just click on the right tab below in the DRL Editor, followed by a click
- on "Generate Rete View".
-
-
-
- Large drl files
-
- Depending on the JDK you use, it may be necessary to increase the
- permanent generation max size. Both SUN and IBM jdk have a permanent
- generation, whereas BEA JRockit does not.
-
- To increase the permanent generation, start eclipse with
- -XX:MaxPermSize=###m
-
- Example: c:\eclipse\eclipse.exe -XX:MaxPermSize=128m
-
- Rulesets of 4,000 rules or greater should set the permanent
- generation to atleast 128Mb.
-
- (note that this may also apply to compiling large numbers of rules
- in general - as there is generally one or more classes per rule).
-
- As an alternative to the above, you may put rules in a file with the
- ".rule" extension, and the background builder will not try to compile them
- with each change, which may provide performance improvements if your IDE
- becomes sluggish with very large numbers of rules.
-
-
-
-
-
- Debugging rules
-
-
- Debugging
-
-
-
-
-
-
-
- You can debug rules during the execution of your Drools application.
- You can add breakpoints in the consequences of your rules, and whenever
- such a breakpoint is uncounted during the execution of the rules, the execution
- is halted. You can then inspect the variables known at that point and use any
- of the default debugging actions to decide what should happen next (step over,
- continue, etc.). You can also use the debug views to inspect the content of the
- working memory and agenda.
-
-
- Creating breakpoints
- You can add/remove rule breakpoints in drl files in two ways, similar to adding
- breakpoints to Java files:
-
-
- Double-click the ruler of the DRL editor at the line where you want to
- add a breakpoint. Note that rule breakpoints can only be created in the
- consequence of a rule. Double-clicking on a line where no breakpoint is allowed
- will do nothing. A breakpoint can be removed by double-clicking the ruler once more.
-
-
-
- If you right-click the ruler, a popup menu will show up, containing the
- "Toggle breakpoint" action. Note that rule breakpoints can only be created in the
- consequence of a rule. The action is automatically disabled if no rule
- breakpoint is allowed at that line. Clicking the action will add a breakpoint at the
- selected line, or remove it if there was one already.
-
-
- The Debug Perspective contains a Breakpoints view which can be used to see
- all defined breakpoints, get their properties, enable/disable or remove them, etc.
-
-
- Debugging rules
- Drools breakpoints are only enabled if you debug your application as
- a Drools Application. You can do this like this:
-
-
- Debug as Drools Application
-
-
-
-
-
-
-
-
-
- Select the main class of your application. Right click it and select the
- "Debug As >" sub-menu and select Drools Application. Alternatively, you can also select
- the "Debug ..." menu item to open a
- new dialog for creating, managing and running debug configurations (see
- screenshot below)
-
-
- Select the "Drools Application" item in the left tree and click the "New
- launch configuration" button (leftmost icon in the toolbar above the tree). This
- will create a new configuration and already fill in some of the properties
- (like the project and main class) based on main class you selected in the beginning.
- All properties shown here are the same as any standard Java program.
-
-
- Change the name of your debug configuration to something meaningful.
- You can just accept the defaults for all other properties. For more information
- about these properties, please check the eclipse jdt documentation.
-
-
- Click the "Debug" button on the bottom to start debugging your application. You only have to define your debug configuration once. The next time you try to run your Drools application, you don't have to create a new one but select the one you defined previously by selecting it in the tree on the left, as a sub-element of the "Drools Application"
- tree node, and then click the Debug button. The eclipse toolbar also contains shortcut
- buttons to quickly re-execute the one of your previous configurations (at least when the
- Java, Java Debug, or Drools perspective has been selected).
-
-
-
-
-
-
-
- Debug as Drools Application Configuration
-
-
-
-
-
-
-
- After clicking the "Debug" button, the application starts executing and will halt if any
- breakpoint is encountered. This can be a Drools rule breakpoint, or any other standard
- Java breakpoint. Whenever a Drools rule breakpoint is encountered, the corresponding drl
- file is opened and the active line is highlighted. The Variables view also contains all rule
- parameters and their value. You can then use the default Java debug actions
- to decide what to do next (resume, terminate, step over, etc.). The debug views can also
- be used to determine the contents of the working memory and agenda at that time as well
- (you don't have to select a working memory now, the current executing working memory
- is automatically shown).
-
-
-
- Debugging
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-ShoppingExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-ShoppingExample.xml
index a4ddec7a33..a193f1c99b 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-ShoppingExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-ShoppingExample.xml
@@ -7,7 +7,8 @@
Shopping ExampleName:Shopping Example
-Main class: org.drools.examples.ShoppingExample
+Main class: org.drools.examples.shopping.ShoppingExample
+Module: drools-examples
Type: java application
Rules file: Shopping.drl
Objective: demonstrate truth maintenance, accumulate
@@ -38,7 +39,7 @@ session.retract( hatPurchaseHandle );
System.out.println( "Customer mark has returned the hat" );
session.fireAllRules();
- Refering the the above listing, we can see there is a Customer ("mark"), and there are 2 Products ("shoes" and "hat") which are available for Purchase. In this case, a Purchase combines a customer with a product (and a product has a price attribute).
+ Referring the the above listing, we can see there is a Customer ("mark"), and there are 2 Products ("shoes" and "hat") which are available for Purchase. In this case, a Purchase combines a customer with a product (and a product has a price attribute).Note that after we fireAllRules(), we then retract the purchase of a hat (but leave the purchase of shoes in). Running the example as a java application should see the following output:
@@ -91,7 +92,7 @@ end
Calculating the discount is done with a single rule, using the higher order logic of "accumulate".
- rule "Apply 10% discount if total purcahses is over 100"
+ rule "Apply 10% discount if total purchases is over 100"
no-loop true
dialect "java"
when
@@ -106,6 +107,6 @@ end An interesting part of this rule is the "accumulate": this is saying to accumulate a total (sum) of the $price of a product (product.price) for all Purchase facts that belong to the customer ($c). The result of this is a Double. The rule then checks to see if this total is greater then 100. If it is, it applies the discount (of 10), and then inserts a logical fact of the Discount object.
- The purpose of the logical insertion of the Discount, is to automatically retract the Discount object should the total of the purchases not add up to > 100 (when the LHS is no longer satisified, restract the resulting logical assertions - this is what is meant by "truth maintenance"). The act of inserting the Discount, causes the "Discount awarded notification" rule to activate. However, should the discount fact be retracted, the "Discount removed notification" will activate, resulting in the customers discount being wiped out. In the example you can see this happen, as after the first fireAllRules(), a purchase is retracted, causing the total to fall below 100, which means the conditions that satisfied the "Apply 10% discount..." rule no longer apply, hence the logical fact of "Discount" is automatically retracted.
+ The purpose of the logical insertion of the Discount, is to automatically retract the Discount object should the total of the purchases not add up to > 100 (when the LHS is no longer satisfied, retract the resulting logical assertions - this is what is meant by "truth maintenance"). The act of inserting the Discount, causes the "Discount awarded notification" rule to activate. However, should the discount fact be retracted, the "Discount removed notification" will activate, resulting in the customers discount being wiped out. In the example you can see this happen, as after the first fireAllRules(), a purchase is retracted, causing the total to fall below 100, which means the conditions that satisfied the "Apply 10% discount..." rule no longer apply, hence the logical fact of "Discount" is automatically retracted.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-StateExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-StateExample.xml
index 2f827f5143..a43447d5d4 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-StateExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-StateExample.xml
@@ -16,14 +16,15 @@
Understanding the State ExampleName: State Example
-Main class: org.drools.examples.StateExampleUsingSalience
+Main class: org.drools.examples.state.StateExampleUsingSalience
+Module: drools-examples
Type: Java application
Rules file: StateExampleUsingSalience.drl
Objective: Demonstrates basic rule use
and Conflict Resolution for rule firing priority.Each State class has fields for its name and its
- current state (see the class org.drools.examples.State).
+ current state (see the class org.drools.examples.state.State).
The two possible states for each objects are:
@@ -85,7 +86,7 @@ session.dispose(); // Stateful rule session must always be disposed when finishe
- Open the class org.drools.examples.StateExampleUsingSalience in your Eclipse IDE.
+ Open the class org.drools.examples.state.StateExampleUsingSalience in your Eclipse IDE.
@@ -127,7 +128,7 @@ D finished
In the "Audit View" click the "Open Log" button and select
- the file "<drools-examples-drl-dir>/log/state.log".
+ the file "<drools-examples-dir>/log/state.log".
@@ -285,9 +286,9 @@ session.insert( fact, dynamic );
There are two other classes in this example:
- StateExampleUsingAgendGroup and
+ StateExampleUsingAgendaGroup and
StateExampleWithDynamicRules. Both execute from A to B
- to C to D, as just shown. The StateExampleUsingAgendGroup
+ to C to D, as just shown. The StateExampleUsingAgendaGroup
uses agenda-groups to control the rule conflict and which one fires
first. StateExampleWithDynamicRules shows how an
additional rule can be added to an already running Working Memory
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-SudokuExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-SudokuExample.xml
index 798d945cc1..c216440204 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-SudokuExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-SudokuExample.xml
@@ -7,9 +7,9 @@
Sudoku ExampleName: Sudoku
-Main class: org.drools.examples.sudoku.Main
+Main class: org.drools.examples.sudoku.SudokuExample
Type: Java application
-Rules file: sudokuSolver.drl, sudokuValidator.drl
+Rules file: sudoku.drl, validate.drl
Objective: Demonstrates the solving of logic problems, and complex pattern matching.
@@ -44,12 +44,15 @@
Running the ExampleDownload and install drools-examples as described above and then
- execute java org.drools.examples.sudoku.Main. This
- example requires Java 5.
+ execute java org.drools.examples.DroolsExamplesApp and
+ click on "SudokuExample".
- A window will be displayed with a relatively simple partially
- filled grid.
- New remote site
+ The window contains an empty grid, but the program comes
+ with a number of grids stored internally which can be loaded
+ and solved. Click on "File", then "Samples" and select "Simple"
+ to load one of the examples. Note that all buttons are disabled
+ until a grid is loaded.
+ Initial screen
@@ -58,28 +61,9 @@
- Click on the "Solve" button and the Drools-based engine will fill
- out the remaining values. The Console window will display detailed
- information about the rules which are executing to solve the puzzle
- in a human readable form.
-
- Rule #3 determined the value at (4,1) could not be 4 as this value already exists in the same column at (8,1)
-Rule #3 determined the value at (5,5) could not be 2 as this value already exists in the same row at (5,6)
-Rule #7 determined (3,5) is 2 as this is the only possible cell in the column that can have this value
-Rule #1 cleared the other PossibleCellValues for (3,5) as a ResolvedCellValue of 2 exists for this cell.
-Rule #1 cleared the other PossibleCellValues for (3,5) as a ResolvedCellValue of 2 exists for this cell.
-...
-Rule #3 determined the value at (1,1) could not be 1 as this value already exists in the same zone at (2,1)
-Rule #6 determined (1,7) is 1 as this is the only possible cell in the row that can have this value
-Rule #1 cleared the other PossibleCellValues for (1,7) as a ResolvedCellValue of 1 exists for this cell.
-Rule #6 determined (1,1) is 8 as this is the only possible cell in the row that can have this value
-
- Once all of the activated rules for the solving logic have
- executed, the engine executes a second rule base to check that the
- solution is complete and valid. In this case it is, and the "Solve"
- button is disabled and displays a text like
- "Solved (1052ms)".
- New remote site
+ Loading the "Simple" example fills the grid according to the
+ puzzle's initial state.
+ After loading "Simple"
@@ -88,12 +72,10 @@ Rule #6 determined (1,1) is 8 as this is the only possible cell in the row that
- The example comes with a number of grids which can be loaded and
- solved. Click on "File", then "Samples" and "Medium" to load a more
- challenging grid. Note that the solve button is enabled when the new
- grid is loaded.
-
- New remote site
+ Click on the "Solve" button and the Drools-based engine will fill
+ out the remaining values, and the buttons are inactive once
+ more.
+ "Simple" Solved
@@ -102,93 +84,90 @@ Rule #6 determined (1,1) is 8 as this is the only possible cell in the row that
- Click on the "Solve" button again to solve this new grid.
-
- New remote site
-
-
-
-
-
-
-
+ Alternatively, you may click on the "Step" button to see the next
+ digit found by the rule set. The Console window will display detailed
+ information about the rules which are executing to solve the step
+ in a human readable form. Some examples of these messages are
+ presented below.
+
+single 8 at [0,1]
+column elimination due to [1,2]: remove 9 from [4,2]
+hidden single 9 at [1,2]
+row elimination due to [2,8]: remove 7 from [2,4]
+remove 6 from [3,8] due to naked pair at [3,2] and [3,7]
+hidden pair in row at [4,6] and [4,4]
+
+
+ Click on the "Dump" button to see the state of the grid, with
+ cells showing either the established value or the remaining
+ possibilitiescandidates.
+
+ Col: 0 Col: 1 Col: 2 Col: 3 Col: 4 Col: 5 Col: 6 Col: 7 Col: 8
+Row 0: 2 4 7 9 2 456 4567 9 23 56 9 --- 5 --- --- 1 --- 3 67 9 --- 8 --- 4 67
+Row 1: 12 7 9 --- 8 --- 1 67 9 23 6 9 --- 4 --- 23 67 1 3 67 9 3 67 9 --- 5 ---
+Row 2: 1 4 7 9 1 456 --- 3 --- 56 89 5 78 5678 --- 2 --- 4 67 9 1 4 67
+Row 3: 1234 12345 1 45 12 5 8 --- 6 --- 2 5 78 5 78 45 7 --- 9 ---
+Row 4: --- 6 --- --- 7 --- 5 --- 4 --- 2 5 8 --- 9 --- 5 8 --- 1 --- --- 3 ---
+Row 5: --- 8 --- 12 45 1 45 9 12 5 --- 3 --- 2 5 7 567 4567 2 4 67
+Row 6: 1 3 7 1 3 6 --- 2 --- 3 56 8 5 8 3 56 8 --- 4 --- 3 567 9 1 678
+Row 7: --- 5 --- 1 34 6 1 4 678 3 6 8 --- 9 --- 34 6 8 1 3 678 --- 2 --- 1 678
+Row 8: 34 --- 9 --- 4 6 8 --- 7 --- --- 1 --- 23456 8 3 56 8 3 56 6 8
+Now, let us load a Sudoku grid that is deliberately invalid. Click
on "File", "Samples" and "!DELIBERATELY BROKEN!". Note that this grid
starts with some issues, for example the value 5 appears twice in the
first row.
- New remote site
+ Broken initial state
-
+
- Nevertheless, click on the "Solve" button to apply the solving
- rules to this invalid grid. Note that the "Solve" button is relabelled
- to indicate that the resulting solution is invalid.
- New remote site
-
-
-
-
-
-
-
+ A few simple rules perform a sanity check, right after loading
+ a grid. In this case, the following messages are printed on
+ standard output:
+
+cell [0,8]: 5 has a duplicate in row 0
+cell [0,0]: 5 has a duplicate in row 0
+cell [6,0]: 8 has a duplicate in col 0
+cell [4,0]: 8 has a duplicate in col 0
+Validation complete.
+
- In addition, the validation rule set outputs all of the issues
- which are discovered to the console.
-
-There are two cells on the same column with the same value at (6,0) and (4,0)
-There are two cells on the same column with the same value at (4,0) and (6,0)
-There are two cells on the same row with the same value at (2,4) and (2,2)
-There are two cells on the same row with the same value at (2,2) and (2,4)
-There are two cells on the same row with the same value at (6,3) and (6,8)
-There are two cells on the same row with the same value at (6,8) and (6,3)
-There are two cells on the same column with the same value at (7,4) and (0,4)
-There are two cells on the same column with the same value at (0,4) and (7,4)
-There are two cells on the same row with the same value at (0,8) and (0,0)
-There are two cells on the same row with the same value at (0,0) and (0,8)
-There are two cells on the same column with the same value at (1,2) and (3,2)
-There are two cells on the same column with the same value at (3,2) and (1,2)
-There are two cells in the same zone with the same value at (6,3) and (7,3)
-There are two cells in the same zone with the same value at (7,3) and (6,3)
-There are two cells on the same column with the same value at (7,3) and (6,3)
-There are two cells on the same column with the same value at (6,3) and (7,3)
-
- We will look at the solving rule set later in this section, but
- for the moment we should note that some theoretically solvable solutions
- can not be solved by the engine as it stands. Click on
- "File", "Samples" and then "Hard 3" to load a sparsely populated grid.
-
- New remote site
+ Nevertheless, click on the "Solve" button to apply the solving
+ rules to this invalid grid. This will not complete; some cells
+ remain empty.
+ Broken "solved" state
-
+
- Now click on the "Solve" button and note that the current rules
- are unable to complete the grid, even though (if you are a Sudoku
- aficionado) you may be able to see a way forward with the solution.
-
- New remote site
-
-
-
-
-
-
-
- At the present time, the solving functionality has been achieved
- by the use of ten rules. This rule set could be extended to enable the
- engine to tackle more complex logic for filling grids such as
- this.
+ The solving functionality has been achieved by the use of
+ rules that implement standard solving techniques. They are based
+ on the sets of values that are still candidates for a cell. If,
+ for instance, such a set contains a single value, then this is
+ the value for the cell. A little less obvious is the single
+ occurrence of a value in one of the groups of nine cells. The
+ rules detecting these situations insert a fact of type Setting
+ with the solution value for some specific cell. This fact causes the
+ elimination of this value from all other cells in any of the
+ groups the cell belongs to. Finally, it is retracted.
+
+ Other rules merely reduce the permissible values for some
+ cells. Rules "naked pair", "hidden pair in row", "hidden pair in column"
+ and "hidden pair in square" merely eliminate possibilities but
+ do not establish solutions. More sophisticated eliminations are done by
+ "X-wings in rows", "X-wings in columns", "intersection removal row" and
+ "intersection removal column".
@@ -202,11 +181,9 @@ There are two cells on the same column with the same value at (6,3) and (7,3)
The package org.drools.examples.sudoku.swing
contains a set of classes which implement a framework for Sudoku
puzzles. Note that this package does not have any dependencies on
- the Drools libraries. SudokuGridModel
- defines an interface which can be implemented to store a Sudoku puzzle
- as a 9x9 grid of Integer values, some of which may be null,
- indicating that the value for the cell has not yet been resolved.
- SudokuGridView is
+ the Drools libraries. SudokuGridModel defines an
+ interface which can be implemented to store a Sudoku puzzle as a 9x9
+ grid of Cell objects. SudokuGridView is
a Swing component which can visualize any implementation of
SudokuGridModel. SudokuGridEvent and
SudokuGridListener are used to
@@ -217,266 +194,132 @@ There are two cells on the same column with the same value at (6,3) and (7,3)SudokuGridSamples provides a number of partially filled
Sudoku puzzles for demonstration purposes.
- Package org.drools.examples.sudoku.rules contains an
- implementation of SudokuGridModel which is based on Drools.
- Two Java objects are used, both of which extend
- AbstractCellValue and represent a value for a specific cell
- in the grid, including the row and column location of the cell, an index
- of the 3x3 zone the cell is contained in, and the value of the cell.
- PossibleCellValue indicates that we do not currently know
- for sure what the value in a cell is. There can be from 2 to 9 possible
- cell values for a given cell. ResolvedCellValue indicates
- that we have determined what the value
- for a cell must be. There can only be one resolved cell value for a
- given cell. DroolsSudokuGridModel implements
- SudokuGridModel and is responsible for converting an
- initial two dimensional array of partially specified cells into a set
- of CellValue Java object, creating a Working Memory
- based on solverSudoku.drl and inserting the
- CellValue objects into the Working Memory. When the
- solve() method is called it calls in turn
- fireAllRules() on this Working Memory to try to solve
- the puzzle. DroolsSudokuGridModel attaches a
- WorkingMemoryListener to the Working Memory, which
- allows it to be called back on insert and retract events as the
- puzzle is solved. When a new ResolvedCellValue is inserted
- into the Working Memory, this callback allows the implementation to
- fire a SudokuGridEvent to its
- SudokuGridListener clientele, which can then update
- themselves in realtime. Once all the rules fired by the solver Working
- Memory have executed, DroolsSudokuGridModel runs a
- second set of rules, based on validatorSudoku.drl
- which works with the same set of Java objects to determine whether the
- resulting grid is a valid and a full solution.
-
- The class org.drools.examples.sudoku.Main implements
- a Java application combining the components desribed.
-
- The packae org.drools.examples.sudoku contains two
- DRL files. solverSudoku.drl defines the rules
- which attempt to solve a Sudoku puzzle, and
- validator.drl defines the rules which determin
- whether the current state of the Working Memory represents a valid
- solution. Both use PossibleCellValue and
- ResolvedCellValue objects as their facts and
- both output information to the Console window as their rules fire. In a
- real-world situation we would insert logging information and use the
- WorkingMemoryListener to display this information to a
- user, rather than use the console in this fashion.
+ Package org.drools.examples.sudoku.rules contains a
+ utility class with a method for compiling DRL files.
+
+ The package org.drools.examples.sudoku contains a
+ set of classes implementing the elementary Cell object
+ and its various aggregations: the CellFile subtypes
+ CellRow and CellCol as well as
+ CellSqr, all of which are subtypes of
+ CellGroup. It's interesting to note that Cell
+ and CellGroup are subclasses of SetOfNine,
+ which provides a property free with the
+ type Set<Integer>. For a Cell it
+ represents the individual candidate set; for a CellGroup
+ the set is the union of all candidate sets of its cells, or, simply,
+ the set of digits that still need to be allocated.
+
+
+ With 81 Cell and 27 CellGroup objects and
+ the linkage provided by the Cell properties
+ cellRow, cellCol and cellSqr
+ and the CellGroup property cells, a list of
+ Cell objects, it is possible to write rules that
+ detect the specific situations that permit the allocation of a
+ value to a cell or the elimination of a value from some candidate
+ set.
+
+ An object of class Setting is used for triggering
+ the operations that accompany the allocation of a value: its removal
+ from the candidate sets of sibling cells and associated cell groups.
+ Moreover, the presence of a Setting fact is used in
+ all rules that should detect a new situation; this is to avoid
+ reactions to inconsistent intermediary states.
+
+ An object of class Stepping is used in a
+ low priority rule to execute an emergency halt when a "Step"
+ does not terminate regularly. This indicates that the puzzle
+ cannot be solved by the program.
+
+
+ The class org.drools.examples.sudoku.SudokuExample
+ implements a Java application combining the components described.
- Sudoku Validator Rules (validatorSudoku.drl)
-
- We start with the validator rules as this rule set is shorter and
- simpler than the solver rule set.
-
- The first rule simply checks that no PossibleCellValue
- objects remain in the Working Memory. Once the puzzle is solved, only
- ResolvedCellValue objects should be present, one for
- each cell.
-
- The other three rules each match all of the
- ResolvedCellValue objects and bind them to the
- variable $resolved1. They then look for
- ResolvedCellValues that
- contain the same value and are located, respectively, in the same row,
- column, or 3x3 zone. If these rules are fired they add a message to a
- global list of strings describing the reason the solution is invalid.
- DroolsSudokoGridModel injects this list before it runs
- the rule set and checks whether it is empty or not after having called
- fireAllRules(). If it is not empty then it prints all the
- strings in the list and sets a flag to indicate that the grid is not
- solved.
-
+ Sudoku Validator Rules (validate.drl)
-
- Sudoku Solving Rules (solverSudoku.drl)
-
- Now let us look at the more complex rule set used to solve Sudoku
- puzzles.
-
- Rule #1 is basically a book-keeping rule. Several of the other
- rules insert ResolvedCellValues into the working memory
- at specific rows and columns after they have determined that a given
- cell must have a
- certain value. At this point, it is important to clear the Working
- Memory of any inserted PossibleCellValues at the same
- row and column
- with invalid values. This rule is therefore given a higher salience than
- the remaining rules to ensure that as soon as the LHS is true,
- activations for the rule move to the top of the Agenda and are fired. In
- turn, this prevents the spurious firing of other rules due to the
- combination of a ResolvedCellValue and one or more
- PossibleCellValues being present in the same cell.
- This rule also calls update() on the
- ResolvedCellValue, even though its value has not in
- fact been modified to ensure that Drools fires an event to any
- WorkingMemoryListeners attached to the Working Memory
- so that they can update themselves - in
- this case so that the GUI can display the new state of the grid.
-
- Rule #2 identifies cells in the grid which have only one possible
- value. The first line of the when clause matches all of the
- PossibleCellValue objects in the Working Memory. The
- second line demonstrates a use of the not keyword. This rule
- will only fire if no other PossibleCellValue objects
- exist in the Working Memory at the same
- row and column but with a different value. When the rule fires, the
- single PossibleCellValue at the row and column is
- retracted from the Working Memory and is replaced by a new
- ResolvedCellValue at the same
- row and column with the same value.
-
- Rule #3 removes PossibleCellValues with a given
- value from a row when they have the same value as a
- ResolvedCellValue. In other words, when a cell is filled
- with a resolved value, we need to remove the
- possibility of any other cell on the same row having this value. The
- first line of the when clause matches all ResolvedCellValue
- objects in the Working Memory. The second line matches
- PossibleCellValues which have both the same row and the
- same value as these ResolvedCellValue
- objects. If any are found, the rule activates and, when fired retracts
- the PossibleCellValue which can no longer be a solution
- for that cell.
-
- Rules #4 and #5 act in the same way as Rule #3 but check for
- redundant PossibleCellValues in a given column and a
- given zone of the grid as a ResolvedCellValue
- respectively.
-
- Rule #6 checks for the scenario where a possible cell value only
- appears once in a given row. The first line of the LHS matches against
- all PossibleCellValue facts in the Working Memory, storing
- the result in a number of local variables. The second line checks that
- no other PossibleCellValue objects with the same value
- exist on this row. The third to fifth lines check that there is not
- a ResolvedCellValue with the same value in the same zone,
- row or column so that this rule does not fire prematurely.
- It is interesting to note that we could remove lines 3 to 5 and give
- rules #3, #4 and #5 a higher salience to make sure they always fire
- before rules #6,#7 and #8. When the rule fires, we know that
- $possible must represent the value for the cell;
- so, as in Rule #2, we retract $possible and replace it
- with the equivalent, new ResolvedCellValue.
-
- Rules #7 and #8 act in the same way as Rule #2 but check for
- single PossibleCellValues in a given column and a given
- zone of the grid, respectively.
-
- Rule #9 represents the most complex currently implemented rule.
- This rule implements the logic that, if we know that a pair of given
- values can only occur in two cells on a specific row, (for example we
- have determined the values of 4 and 6 can only appear in the first row
- in cells [0,3] and [0,5]) and this pair of cells can not hold other
- values, then, although we do not know which of the pair contains a
- four and which contains a six, we do know that these two values must be
- in these two cells, and hence we can remove the possibility of them
- occuring anywhere else in the same row.
-
-
-
- Rules #10 and #11 act in the same way as rule #9 but check for the
- existance of only two possible values in a given column and zone,
- respectively.
-
- To solve harder grids, the rule set would need to be extended
- further with more complex rules that encapsulate more complex
- reasoning.
+ Validation rules detect duplicate numbers in cell groups.
+ They are combined in an agenda group which enables us to activate
+ them, explicitly, after loading a puzzle.
+
+ The three rules "duplicate in cell..." are very similar.
+ The first pattern locates a cell with an allocated value. The second
+ pattern pulls in any of the three cell groups the cell belongs to.
+ The final pattern would find a cell (other than the first one) with
+ the same value as the first cell and in the same row, column or
+ square, respectively.
+
+ Rule "terminate group" fires last. It prints a message and
+ calls halt.
- Suggestions for Future Developments
-
- There are a number of ways in which this example could be
- developed. The reader is encouraged to consider these as
- excercises.
-
-
-
- Agenda groups are a great declarative tool for
- phased execution. In this example, it is easy to see we have two
- phases: "resolution" and "validation". Right now, they are executed
- by creating two separate rule bases, each for one "job".
- Presumably it would be better to define agenda groups for all the
- rules, spliting them in "resolution" rules and "validation" rules,
- all loaded in a single rule base. The engine executes resolution and
- right after that, executes validation.
-
-
-
- Auto-focus is a great way of handling exceptions
- to the regular rules execution. In our case, if we detect an
- inconsistency, either in the input data or in the resolution rules,
- why should we spend time continuing the execution if it will be
- invalid anyway? It is better to simply (and immediately)
- report the inconsistency as soon as it is found. To do that, since
- we now have a single rulebase with all rules, we simply need to
- define the auto-focus attribute for all rules validating puzzle
- consistency.
-
-
-
- Logical insert: an inconsistency only exists while wrong data
- is in the working memory. As so, we could state that the
- validation rules logically insert inconsistencies and as soon as the
- offending data is retracted, the inconsistency no longer
- exists.
-
-
-
- session.iterateObjects(): although a valid
- use case having a global list to add the found problems, I think
- it would be more
- interesting to ask the Stateful Session by the desired list of
- problems, using session.iterateObjects( new ClassObjectFilter(
- Inconsistency.class ) ). Having the inconsistency class
- can also allow us to paint in red the offending cells in the
- GUI.
-
-
-
- kcontext.getKnowledgeRuntime().halt(): even
- reporting the error as soon as it is found, we need a way to tell
- the engine to stop evaluating rules. We
- can do that creating a rule that, in the presence of inconsistencies,
- calls halt() to stop evaluation.
-
-
-
- Queries: looking at the method
- getPossibleCellValues(int row, int col) in
- DroolsSudokuGridModel, we see it iterating over all
- CellValue objects, looking for the few it wants. That
- is a great opportunity to demonstrate Drools queries. We just
- define a query to
- return the objects we want and iterate over it, cleanly and nicely.
- Other queries may be defined as needed.
-
-
-
- Globals as services: the main objective of this change is to
- attend the next proposed change , but it is nice by its own.
- In order to teach the use of globals as services, it
- would be nice to set up a callback, so that each rule that finds the
- ResolvedCellValue for a given cell can call, to
- notify and update the corresponding cell in the GUI, providing
- immediate feedback for
- the user. Also, the last found cell could have its number painted in
- a different color to facilitate the identification of the rules'
- conclusions.
-
-
-
- Step by step execution: now that we have immediate user
- feedback, we can make use of the restricted run feature in Drools,
- i.e., we could add a button in the GUI, that, when activated,
- causes the execution of a single rule, by calling
- fireAllRules( 1 ). This way, the user would see,
- step by step, what the engine is doing.
-
-
+ Sudoku Solving Rules (sudoku.drl)
+
+ There are three types of rules in this file: one group
+ handles the allocation of a number to a cell, another group
+ detects feasible allocations, and the third group eliminates
+ values from candidate sets.
+
+ Rules "set a value", "eliminate a value from Cell" and
+ "retract setting" depend on the presence of a Setting
+ object. The first rule handles the assignment to the cell and the
+ operations for removing the value from the "free" sets of the
+ cell's three groups. Also, it decrements a counter that, when
+ zero, returns control to the Java application that has called
+ fireUntilHalt(). The purpose of rule
+ "eliminate a value from Cell" is to reduce the candidate lists
+ of all cells that are related to the newly assigned cell. Finally,
+ when all eliminations have been made, rule "retract setting"
+ retracts the triggering Setting fact.
+
+ There are just two rules that detect a situation where an
+ allocation of a number to a cell is possible. Rule "single" fires
+ for a Cell with a candidate set containing a single
+ number. Rule "hidden single" fires when there is no cell with a
+ single candidate but when there is a cell containing a candidate but
+ this candidate is absent from all other cells in one of the three
+ groups the cell belongs to. Both rules create and insert a
+ Setting fact.
+
+ Rules from the largest group of rules implement, singly or
+ in groups of two or three, various solving techniques, as they are
+ employed when solving Sudoku puzzles manually.
+
+ Rule "naked pair" detects identical candidate sets of size 2
+ in two cells of a group; these two values may be removed from all
+ other candidate sets of that group.
+
+ A similar idea motivates the three rules "hidden pair in...";
+ here, the rules look for a subset of two numbers in exactly two cells
+ of a group, with neither value occurring in any of the other cells of
+ this group. This, then, means that all other candidates can be
+ eliminated from the two cells harbouring the hidden pair.
+
+ A pair of rules deals with "X-wings" in rows and columns.
+ When there are only two possible cells for a value in each of
+ two different rows (or columns) and these candidates lie also
+ in the same columns (or rows), then all other candidates for
+ this value in the columns (or rows) can be eliminated. If you
+ follow the pattern sequence in one of these rules, you will see
+ how the conditions that are conveniently expressed by words such as
+ "same" or "only" result in patterns with suitable constraints
+ or prefixed with "not".
+
+ The rule pair "intersection removal..." is based on the
+ restricted occurrence of some number within one square, either
+ in a single row or in a single column. This means that this number
+ must be in one of those two or three cells of the row or column;
+ hence it can be removed from the candidate sets of all other cells
+ of the group. The pattern establishes the restricted occurrence
+ and then fires for each cell outside the square and within the
+ same cell file.
+
+ These rules are sufficient for many but certainly not for all
+ Sudoku puzzles. To solve very difficult grids, the rule set would
+ need to be extended with more complex rules. (Ultimately, there
+ are puzzles that cannot be solved except by trial and error.)
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-TextAdventureExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-TextAdventureExample.xml
new file mode 100644
index 0000000000..d2bffec534
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-TextAdventureExample.xml
@@ -0,0 +1,35 @@
+
+
+ Adventures with Drools
+
+ Based on the Adventure in Prolog, over at the Amzi website, http://www.amzi.com/AdventureInProlog/,
+ we started to work on a text adventure game for Drools. They are ideal as
+ they can start off simple and build in complexity and size over time, they
+ also demonstrate key aspects of declarative relational programming.
+
+ Name: Example Text Adventure
+Main class: org.drools.games.adventure.TextAdventure
+
+ You can view the 8 minute demonstration and introduction for the
+ example at http://downloads.jboss.org/drools/videos/text-adventures.swf
+
+
+ Pong Screenshot
+
+
+
+
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-TroubleTicketExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-TroubleTicketExample.xml
index 44a45f9b0b..5238671fa8 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-TroubleTicketExample.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-TroubleTicketExample.xml
@@ -67,7 +67,7 @@ end
Referring to the above audit log, we can see each customer asserted, but nothing happens. As soon as the first ticket gets asserted, it joins it with the customer, and creates some activations: one is the "new ticket" rule, the other is for the appropriate priority (which we will show below). Note that items in the above view do not mean the rule fired at that point.
- Also, don't forget to use "fireAllRules()" - a common mistake ! (In this case we are using a statefull session, so this is necessary).
+ Also, don't forget to use "fireAllRules()" - a common mistake ! (In this case we are using a stateful session, so this is necessary).If we run the rules, we should expect that the "New Ticket" rule will be activated for all tickets, so looking at the audit log view (by opening the file which was saved automatically when the rules were run):
@@ -185,7 +185,7 @@ Email : [Ticket [Customer D : Silver] : Escalate]
session.update( ft3,
t3 );
- in the code (outside of rules) - this simulates a customer service officer maarking a ticket as done (and of course, uses the fact handle we kept from before). This results in a cancelled activation (as we no longer have a New Silvert customer ticket - it is done) and a new activation to log the fact it was done.
+ in the code (outside of rules) - this simulates a customer service officer marking a ticket as done (and of course, uses the fact handle we kept from before). This results in a cancelled activation (as we no longer have a New Silver customer ticket - it is done) and a new activation to log the fact it was done.In all the excitement, in parallel the engine has been watching the time pass, and it happens that the Gold tickets start to escalate, and then silver (as expected).
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-WumpusWorldExample.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-WumpusWorldExample.xml
new file mode 100644
index 0000000000..c79a0d0ffe
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Examples/Section-WumpusWorldExample.xml
@@ -0,0 +1,76 @@
+
+
+ Wumpus World
+
+ Name: Example Wumpus World
+Main class: org.drools.games.wumpus.WumpusWorldMain
+
+ Wumpus World is an AI example covered in the book "Artificial
+ Intelligence : A Modern Approach". When the game first starts all the cells
+ are greyed out. As you walk around they become visible. The cave has pits, a
+ wumpus and gold. When you are next to a pit you will feel a breeze, when you
+ are next to the wumpus you will smell a stench and see glitter when next to
+ gold. The sensor icons are shown above the move buttons. If you walk into a
+ pit or the wumpus, you die. A more detailed overview of Wumpus World can be
+ found at http://www.cis.temple.edu/~giorgio/cis587/readings/wumpus.shtml.
+ A 20 minute video showing how the game is created and works is at http://www.youtube.com/watch?v=4CvjKqUOEzM.
+
+
+ Wumpus World
+
+
+
+
+
+
+
+
+
+ Cave Screenshot
+
+
+
+
+
+
+
+
+
+ Signals Screenshot
+
+
+
+
+
+
+
+
+
+ Smell Stench
+
+
+
+
+
+
+
+
+
+ Move Up, Wumpus Collision
+
+
+
+
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-IDE/Chapter-IDE.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-IDE/Chapter-IDE.xml
new file mode 100644
index 0000000000..c6eb7f9ef1
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-IDE/Chapter-IDE.xml
@@ -0,0 +1,1024 @@
+
+
+ The Rule IDE (Eclipse)
+
+ The Eclipse based IDE provides developers (and very technical users)
+ with an environment to edit and test rules in various formats, and integrate
+ it deeply with their applications. In cases where you prefer business rules
+ and web tooling, you will want to look at the BRMS (but using the BRMS and
+ the IDE together is not uncommon).
+
+ The Drools IDE is delivered as an Eclipse plug-in, which allows you to
+ author and manage rules from within Eclipse, as well as integrate rules with
+ your application. This is an optional tool, and not all components are
+ required to be used, you can use what components are relevant to you. The
+ Drools IDE is also a part of the Red Hat Developer Studio (formerly known as
+ JBoss IDE).
+
+ This guide will cover some of the features of JBoss Drools, in as far
+ as the IDE touches on them (it is assumed that the reader has some
+ familiarity with rule engines, and Drools in particular. It is important to
+ note that none of the underlying features of the rule engine are dependent
+ on Eclipse, and integrators are free to use their tools of choice, as always
+ ! Plenty of people use IntelliJ with rules, for instance.
+
+
+ You can get the plug-in either as a zip to download, or from an
+ update site. Refer to the chapter on installation.
+
+
+
+ Overview
+
+
+
+
+
+
+
+
+
+ Features Outline
+
+ The rules IDE has the following features
+
+
+
+ Textual/graphical rule editor
+
+
+
+ An editor that is aware of DRL syntax, and provides content
+ assistance (including an outline view)
+
+
+
+ An editor that is aware of DSL (domain specific language)
+ extensions, and provides content assistance.
+
+
+
+
+
+ RuleFlow graphical editor
+
+ You can edit visual graphs which represent a process (a rule
+ flow). The RuleFlow can then be applied to your rule package to have
+ imperative control.
+
+
+
+ Wizards for fast creation of
+
+
+
+ a "rules" project
+
+
+
+ a rule resource, either as a DRL file or a "guided rule
+ editor" file (.brl)
+
+
+
+ a Domain Specific language
+
+
+
+ a decision table
+
+
+
+ a ruleflow
+
+
+
+
+
+ A domain specific language editor
+
+
+
+ Create and manage mappings from your user's language to the
+ rule language
+
+
+
+
+
+ Rule validation
+
+
+
+ As rules are entered, the rule is "built" in the background
+ and errors reported via the problem view where possible
+
+
+
+
+
+ The above features make use of Eclipse infrastructure and features,
+ with all of the power of Eclipse being available.
+
+
+
+ Drools Runtimes
+
+ A Drools runtime is a collection of jar files that represent one
+ specific release of the Drools project jars. To create a runtime, you must
+ point the IDE to the release of your choice. If you want to create a new
+ runtime based on the latest Drools project jars included in the plugin
+ itself, you can also easily do that. You are required to specify a default
+ Drools runtime for your Eclipse workspace, but each individual project can
+ override the default and select the appropriate runtime for that project
+ specifically.
+
+
+ Defining a Drools Runtime
+
+ To define one or more Drools runtimes using the Eclipse
+ preferences view you open up your Preferences, by selecting the
+ "Preferences" menu item in the menu "Window". A "Preferences" dialog
+ should show all your settings. On the left side of this dialog, under
+ the Drools category, select "Installed Drools runtimes". The panel on
+ the right should then show the currently defined Drools runtimes. If you
+ have not yet defined any runtimes, it should look like the figure
+ below.
+
+
+
+
+
+
+
+ To define a new Drools runtime, click on the add button. A dialog
+ such as the one shown below should pop up, asking for the name of your
+ runtime and the location on your file system where it can be
+ found.
+
+
+
+
+
+
+
+ In general, you have two options:
+
+
+
+ If you simply want to use the default jar files as included in
+ the Drools Eclipse plugin, you can create a new Drools runtime
+ automatically by clicking the "Create a new Drools 5 runtime ..."
+ button. A file browser will show up, asking you to select the folder
+ on your file system where you want this runtime to be created. The
+ plugin will then automatically copy all required dependencies to the
+ specified folder. After selecting this folder, the dialog should
+ look like the figure shown below.
+
+
+
+ If you want to use one specific release of the Drools project,
+ you should create a folder on your file system that contains all the
+ necessary Drools libraries and dependencies. Instead of creating a
+ new Drools runtime as explained above, give your runtime a name and
+ select the location of this folder containing all the required
+ jars.
+
+
+
+
+
+
+
+
+
+ After clicking the OK button, the runtime should show up in your
+ table of installed Drools runtimes, as shown below. Click on checkbox in
+ front of the newly created runtime to make it the default Drools
+ runtime. The default Drools runtime will be used as the runtime of all
+ your Drools project that have not selected a project-specific
+ runtime.
+
+
+
+
+
+
+
+ You can add as many Drools runtimes as you need. For example, the
+ screenshot below shows a configuration where two runtimes have been
+ defined: a Drools 5.1.1 runtime and a Drools 5.2.0.M2 runtime. The
+ Drools 5.1.1 runtime is selected as the default one.
+
+
+
+
+
+
+
+ Note that you will need to restart Eclipse if you changed the
+ default runtime and you want to make sure that all the projects that are
+ using the default runtime update their classpath accordingly.
+
+
+
+ Selecting a runtime for your Drools project
+
+ Whenever you create a Drools project (using the New Drools Project
+ wizard or by converting an existing Java project to a Drools project
+ using the action "Convert to Drools Project" that is shown when you are
+ in the Drools perspective and you right-click an existing Java project),
+ the plugin will automatically add all the required jars to the classpath
+ of your project.
+
+ When creating a new Drools project, the plugin will automatically
+ use the default Drools runtime for that project, unless you specify a
+ project-specific one. You can do this in the final step of the New
+ Drools Project wizard, as shown below, by deselecting the "Use default
+ Drools runtime" checkbox and selecting the appropriate runtime in the
+ drop-down box. If you click the "Configure workspace settings ..." link,
+ the workspace preferences showing the currently installed Drools
+ runtimes will be opened, so you can add new runtimes there.
+
+
+
+
+
+
+
+ You can change the runtime of a Drools project at any time by
+ opening the project properties and selecting the Drools category, as
+ shown below. Mark the "Enable project specific settings" checkbox and
+ select the appropriate runtime from the drop-down box. If you click the
+ "Configure workspace settings ..." link, the workspace preferences
+ showing the currently installed Drools runtimes will be opened, so you
+ can add new runtimes there. If you deselect the "Enable project specific
+ settings" checkbox, it will use the default runtime as defined in your
+ global preferences.
+
+
+
+
+
+
+
+
+
+
+ Creating a Rule Project
+
+ The aim of the new project wizard is to set up an executable
+ scaffold project to start using rules immediately. This will set up a
+ basic structure, the classpath, sample rules and a test case to get you
+ started.
+
+
+ New rule project scaffolding
+
+
+
+
+
+
+
+
+ When you choose to create a new "rule project" you will get a choice
+ to add some default artifacts to it, like rules, decision tables,
+ ruleflows, etc. These can serve as a starting point, and will give you
+ something executable almost immediately, which you can then modify and
+ mould to your needs. The simplest case (a hello world rule) is shown
+ below. Feel free to experiment with the plug-in at this point.
+
+
+ New rule project result
+
+
+
+
+
+
+
+
+ The newly created project contains an example rule file (Sample.drl)
+ in the src/rules directory and an example Java file (DroolsTest.java) that
+ can be used to execute the rules in a Drools engine. You'll find this in
+ the folder src/java, in the com.sample package. All the other jars that
+ are necessary during execution are also added to the classpath in a custom
+ classpath container called Drools Library. Rules do not have to be kept in
+ "Java" projects at all, this is just a convenience for people who are
+ already using Eclipse as their Java IDE.
+
+ Important note: The Drools plug-in adds a "Drools Builder"
+ capability to your Eclipse instance. This means you can enable a builder
+ on any project that will build and validate your rules when resources
+ change. This happens automatically with the Rule Project Wizard, but you
+ can also enable it manually on any project. One downside of this is that
+ if you have rule files with a large number of rules (more than 500 rules
+ per file), it means that the background builder may be doing a lot of work
+ to build the rules on each change. An option here is to turn off the
+ builder, or put the large rules into .rule files, where you can still use
+ the rule editor, but it won't build them in the background. To fully
+ validate the rules you will need to run them in a unit test of
+ course.
+
+
+
+ Creating a New Rule and Wizards
+
+ You can create a rule simple as an empty text ".drl" file, or use
+ the wizard to do so. The wizard menu can be invoked with Control+N, or by
+ choosing it from the toolbar, where there is a menu with the JBoss Drools
+ icon.
+
+
+ The wizard menu
+
+
+
+
+
+
+
+
+ The wizard will ask for some basic options for generating a rule
+ resource. These are just hints - you can change your mind later. For
+ storing rule files you would typically create a directory src/rules and
+ create suitably named subdirectories. The package name is mandatory, and
+ is similar to a package name in Java; i.e., it establishes a namespace for
+ grouping related rules.
+
+
+ New rule wizard
+
+
+
+
+
+
+
+
+ The result of this wizard is a rule skeleton, for you to expand. As
+ with all wizards, they are an optional help - you don't have to use them
+ if you don't want to.
+
+
+
+ Textual Rule Editor
+
+ The rule editor is where rule managers and developers will be
+ spending most of their time. The rule editor follows the pattern of a
+ normal text editor in Eclipse, with all the customary features of a text
+ editor. On top of this, the rule editor provides pop-up content
+ assistance. You invoke pop-up content assistance the "normal" way by
+ pressing Control+Space.
+
+
+ The rule editor in action
+
+
+
+
+
+
+
+
+ The rule editor works on files that have a .drl (or .rule)
+ extension. Usually these contain related rules, but it would also be
+ possible to have rules in individual files, grouped by being in the same
+ package "namespace", if you so prefer. These DRL files are plain text
+ files.
+
+ You can see from the example above that the rule group is using a
+ domain specific language. Note the expander keyword, which tells the rule
+ compiler to look for a dsl file of that name, to resolve the rule
+ language. Even with the domain specific language (DSL) the rules are still
+ stored as plain text as you see it onscreen, which allows simpler
+ management of rules and versions, e.g., comparing versions of
+ rules.
+
+ The editor has an outline view that is kept in sync with the
+ structure of the rules; it is updated on save. This provides a quick way
+ of navigating around rules by name, even in a file which may have hundreds
+ of rules. The items are sorted alphabetically by default.
+
+
+ The rule outline view
+
+
+
+
+
+
+
+
+
+
+ Drools Views
+
+ When debugging an application using a Drools engine, these views can
+ be used to check the state of the Drools engine itself: the Working Memory
+ View, the Agenda View, and the Global Data View. To be able to use these
+ views, create breakpoints in your code invoking the working memory. For
+ example, the line where you call workingMemory.fireAllRules() is a good
+ candidate. If the debugger halts at that joinpoint, you should select the
+ working memory variable in the debug variables view. The available views
+ can then be used to show the details of the selected working
+ memory:
+
+
+
+ The Working Memory View shows all elements of the Drools working
+ memory.
+
+
+
+ The Agenda View shows all elements on the agenda. For each rule
+ on the agenda, the rule name and bound variables are shown.
+
+
+
+ The Global Data View shows all global data currently defined in
+ the Drools working memory.
+
+
+
+ The Audit view can be used to display audit logs containing events
+ that were logged during the execution of a rules engine, in tree
+ form.
+
+
+ The Working Memory View
+
+
+
+
+
+
+
+ The Working Memory View shows all elements in the working memory
+ of the Drools engine.
+
+ An action is added to the right of the view, to customize what is
+ shown:
+
+
+
+ The Show Logical Structure toggles showing the logical
+ structure of the elements in the working memory, or all their
+ details. Logical structures allow for visualizing sets of elements
+ in a more obvious way.
+
+
+
+
+
+ The Agenda View
+
+
+
+
+
+
+
+ The Agenda View shows all elements on the agenda. For each rule on
+ the agenda, the rule name and bound variables are shown.
+
+ An action is added to the right of the view, to customize what is
+ shown:
+
+
+
+ The Show Logical Structure toggles showing the logical
+ structure of the agenda item, or all their details. Logical
+ structures allow for example visualizing sets of elements in a more
+ obvious way. The logical structure of AgendaItems shows the rule
+ that is represented by the AgendaItem, and the values of all the
+ parameters used in the rule.
+
+
+
+
+
+ The Global Data View
+
+
+
+
+
+
+
+ The Global Data View shows all global data currently defined in
+ the Drools engine.
+
+ An action is added to the right of the view, to customize what is
+ shown:
+
+
+
+ The Show Logical Structure toggles showing the logical
+ structure of the elements in the working memory, or all their
+ details. Logical structures allow for example visualizing sets of
+ elements in a more obvious way.
+
+
+
+
+
+ The Audit View
+
+
+
+
+
+
+
+ The audit view visualizes an audit log, that is optionally created
+ when executing the rules engine. To create an audit log, use the
+ following code:
+
+ StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+// Create a new Knowledge Runtime Logger, that logs to file.
+// An event.log file is created in the subdirectory log dir (which must exist) of the working directory
+KnowledgeRuntimeLogger logger = KnowledgeRuntimeLoggerFactory.newFileLogger( ksession, "log/event");
+
+ksession.insert(...);
+ksession.fireAllRules();
+
+// stop logging
+logger.close();
+
+ Open the log by clicking the Open Log action, the first icon in
+ the Audit View, and select the file. The Audit View now shows all events
+ that where logged during the executing of the rules. There are different
+ types of events, each with a different icon:
+
+
+
+ Object inserted, a green square:
+
+
+
+
+
+
+
+ Object updated, a yellow square:
+
+
+
+
+
+
+
+ Object removed, a red square:
+
+
+
+
+
+
+
+ Activation created, a right arrow:
+
+
+
+
+
+
+
+ Activation cancelled, a left arrow:
+
+
+
+
+
+
+
+ Activation executed, a blue diamond:
+
+
+
+
+
+
+
+ Ruleflow start or end, the "process" icon:
+
+
+
+
+
+
+
+ Ruleflow-group activation or deactivation, the "activity"
+ icon:
+
+
+
+
+
+
+
+ Rule package addition or removal, the Drools icon:
+
+
+
+
+
+
+
+
+ Rule addition or removal, the Drools icon:
+
+
+
+
+
+
+
+ All these events show extra information concerning the event, like
+ the id and toString representation of the object in case of working
+ memory events (insert, modify and retract), the name of the rule and all
+ the variables bound in the activation in case of an activation event
+ (created, cancelled or executed). If an event occurs when executing an
+ activation, it is shown as a child of the activation's execution event.
+ For some events, you can retrieve the "cause":
+
+
+
+ The cause of an object modified or retracted event is the last
+ object event for that object. This is either the object asserted
+ event, or the last object modified event for that object.
+
+
+
+ The cause of an activation cancelled or executed event is the
+ corresponding activation created event.
+
+
+
+ When selecting an event, the cause of that event is shown in green
+ in the audit view (if visible of course). You can also right click the
+ action and select the "Show Cause" menu item. This will scroll you to
+ the cause of the selected event.
+
+
+
+
+ Domain Specific Languages
+
+ Domain Specific Languages (DSL) enable you to create a language that
+ allows your rules to look like - rules! Most often the domain specific
+ language reads like natural language. Typically you would look at how a
+ business analyst would describe the rule, in their own words, and then map
+ this to your object model, via rule constructs. A side benefit of this is
+ that it can provide an insulation layer between your domain objects and
+ the rules themselves (as we know you like to refactor). A domain specific
+ language will grow as the rules grow, and works best when there are common
+ terms used over an over, with different parameters.
+
+ To aid with this, the rule workbench provides an editor for Domain
+ Specific Languages. They are stored in a plain text format, so you can use
+ any editor of your choice; this format is simply a slightly enhanced
+ version of the "Properties" file format. The editor will be invoked on any
+ files with a .dsl extension. There is also a wizard to create a sample
+ DSL.
+
+
+ Editing languages
+
+
+ The Domain Specific Language editor
+
+
+
+
+
+
+
+
+ The DSL editor provides a tabular view of the mapping of Language
+ to Rule Expressions. The Language Expression is what is used in the
+ rules. This also feeds the content assistance for the rule editor, so
+ that it can suggest Language Expressions from the DSL configuration.
+ (The rule editor loads the DSL configuration when the rule resource is
+ loaded for editing.) The Rule language mapping defines the "code" for
+ the rules into which the language expression will be compiled by the
+ rule engine compiler. The form of this Rule language expression depends
+ on it being intended for the condition or the action part of a rule.
+ (For the RHS it may be a snippet of Java, for instance). The "scope"
+ item indicates where the expression belongs, "when" indicating the LHS,
+ "then" the RHS, and "*" meaning anywhere. It's also possible to create
+ aliases for keywords.
+
+ By selecting a mapping item (a row in the table) you can see the
+ expression and mapping in the text fields below the table. Double
+ clicking or pressing the edit button will open the edit dialog. Other
+ buttons let you remove and add mappings. Don't remove mappings while
+ they are still in use.
+
+
+ Language Mapping editor dialog
+
+
+
+
+
+
+
+
+ Here is a short description of the DSL translation process. The
+ parser reads the rule text in a DSL, line by line, and tries to match
+ some "Language Expression", depending on the scope. After a match, the
+ values that correspond to a placeholder between curly braces (e.g.,
+ {age}) are extracted from the rule source. The placeholders in the
+ corresponding "Rule Expression" are replaced by their corresponding
+ value. In the example above, the natural language expression maps to two
+ constraints on a fact of type Person, based on the fields age and
+ location, and the {age} and {location} values are extracted from the
+ original rule text.
+
+ If you do not wish to use a language mapping for a particular rule
+ in a drl, prefix the expression with > and the compiler will not try
+ to translate it according to the language definition. Also note that
+ Domain Specific Languages are optional. When the rule is compiled, the
+ .dsl file will also need to be available.
+
+
+
+
+ The Rete View
+
+ The Rete Tree View shows you the current Rete Network for your DRL
+ file. You display it by clicking on the tab "Rete Tree" at the bottom of
+ the DRL Editor window. With the Rete Network visualization being open, you
+ can use drag-and-drop on individual nodes to arrange optimal network
+ overview. You may also select multiple nodes by dragging a rectangle over
+ them; then the entire group can be moved around. The Eclips toolbar icons
+ for zooming in and out can be used in the customary manner.
+
+ In the current release there is no export function to creates a gif
+ or jpg file. Meanwhile, please use ctrl + alt + print to create a copy of
+ your current Eclipse window, and cut it off.
+
+
+
+
+
+
+
+ The Rete View is an advanced feature which takes full advantage of
+ the Eclipse Graphical Editing Framework (GEF).
+
+ The Rete view works only in Drools Rule Projects, where the Drools
+ Builder is set in the project´s properties.
+
+ If you are using Drools in another type of project where you are not
+ having a Drools Rule Project with the appropriate Drools Builder, you can
+ use a workaround: Set up a little Drools Rule Project next to it, putting
+ needed libraries into it, and the DRLs you want to inspect with the Rete
+ View. Just click on the right tab below in the DRL Editor, followed by a
+ click on "Generate Rete View".
+
+
+
+ Large DRL Files
+
+ Depending on the JDK you use, it may be necessary to increase the
+ permanent generation max size. Both the SUN and the IBM JDK have a
+ permanent generation, whereas BEA JRockit does not.
+
+ To increase the permanent generation, start Eclipse with
+ -XX:MaxPermSize=###m
+
+ Example: c:\Eclipse\Eclipse.exe -XX:MaxPermSize=128m
+
+ Rulesets of 4,000 rules or greater should set the permanent
+ generation to at least 128Mb.
+
+
+ This may also apply to compiling large numbers of rules in
+ general, as there is generally one or more classes per rule.
+
+
+ As an alternative to the above, you may put rules in a file with the
+ ".rule" extension, and the background builder will not try to compile them
+ with each change, which may provide performance improvements if your IDE
+ becomes sluggish with very large numbers of rules.
+
+
+
+ Debugging Rules
+
+
+ Debugging
+
+
+
+
+
+
+
+
+ You can debug rules during the execution of your Drools application.
+ You can add breakpoints in the consequences of your rules, and whenever
+ such a breakpoint is encountered during the execution of the rules,
+ execution is halted. You can then inspect the variables known at that
+ point and use any of the default debugging actions to decide what should
+ happen next: step over, continue, etc. You can also use the debug views to
+ inspect the content of the working memory and the Agenda.
+
+
+ Creating Breakpoints
+
+ You can add and remove rule breakpoints in DRL files in two ways,
+ similar to adding breakpoints to Java files:
+
+
+
+ Double-click the ruler of the DRL editor at the line where you
+ want to add a breakpoint. Note that rule breakpoints can only be
+ created in the consequence of a rule. Double-clicking on a line
+ where no breakpoint is allowed will do nothing. A breakpoint can be
+ removed by double-clicking the ruler once more.
+
+
+
+ If you right-click the ruler, a popup menu will show up,
+ containing the "Toggle breakpoint" action. Note that rule
+ breakpoints can only be created in the consequence of a rule. The
+ action is automatically disabled if no rule breakpoint is allowed at
+ that line. Clicking the action will add a breakpoint at the selected
+ line, or remove it if there was one already.
+
+
+
+ The Debug Perspective contains a Breakpoints view which can be
+ used to see all defined breakpoints, get their properties,
+ enable/disable or remove them, etc.
+
+
+
+ Debugging Rules
+
+ Drools breakpoints are only enabled if you debug your application
+ as a Drools Application. You can do this like this:
+
+
+ Debug as Drools Application
+
+
+
+
+
+
+
+
+
+
+ Select the main class of your application. Right click it and
+ select the "Debug As >" sub-menu and select Drools Application.
+ Alternatively, you can also select the "Debug ..." menu item to open
+ a new dialog for creating, managing and running debug configurations
+ (see the screenshot below).
+
+
+
+ Select the "Drools Application" item in the left tree and
+ click the "New launch configuration" button (leftmost icon in the
+ toolbar above the tree). This will create a new configuration with
+ some of the properties (like project and main class)already filled
+ in, based on the main class you selected in the beginning. All
+ properties shown here are the same as for any standard Java
+ program.
+
+
+
+ Change the name of your debug configuration to something
+ meaningful. You can just accept the defaults for all other
+ properties. For more information about these properties, please
+ check the Eclipse JDT documentation.
+
+
+
+ Click the "Debug" button on the bottom to start debugging your
+ application. You only have to define your debug configuration once.
+ The next time you run your Drools application, you don't have to
+ create a new one but select the previously defined one in the tree
+ on the left, as a sub-element of the "Drools Application" tree node,
+ and then click the Debug button. The Eclipse toolbar also contains
+ shortcut buttons to quickly re-execute one of your previous
+ configurations (at least when one of the Java, Java Debug, or Drools
+ perspectives has been selected).
+
+
+
+
+ Debug as Drools Application Configuration
+
+
+
+
+
+
+
+
+ After clicking the "Debug" button, the application starts
+ executing and will halt if any breakpoint is encountered. This can be a
+ Drools rule breakpoint, or any other standard Java breakpoint. Whenever
+ a Drools rule breakpoint is encountered, the corresponding DRL file is
+ opened and the active line is highlighted. The Variables view also
+ contains all rule parameters and their value. You can then use the
+ default Java debug actions to decide what to do next: resume, terminate,
+ step over, etc. The debug view can also be used to inspect the contents
+ of the Working Memory and the Agenda at that time as well. You don't
+ have to select a Working Memory now, as the current executing working
+ memory is automatically shown.
+
+
+ Debugging
+
+
+
+
+
+
+
+
+
+
+
+ Preferences
+
+ The rules IDE also comes with a set of customizable preferences.
+
+
+
+
+
+
+
+ In particular they allow to configure the following options:
+
+
+
+ Automatically reparse all rules if a Java resource is changed:
+ triggers a rebuilding of all the rules when a Java class is modified
+
+
+
+ Allow cross reference in DRL files:
+ makes it possible to have a resource in a DRL file referencing another resource defined
+ in a different file. For example you could have a rule in a file using a type declared in
+ another file. Note that by enabling this option it will no longer possible to declare
+ the same resource (i.e. two rule with the same name in the same package) in two different DRL files.
+
+
+
+ Internal Drools classes use:
+ allows, disallows or discourages (generating warning) the use of Drools classes not exposed in
+ the public API
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-IDE/Chapter-QuickStart.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-IDE/Chapter-QuickStart.xml
deleted file mode 100755
index 67acc3b594..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-IDE/Chapter-QuickStart.xml
+++ /dev/null
@@ -1,807 +0,0 @@
-
-
- The Rule IDE (Eclipse)
-
-
- The Eclipse based IDE provides developers (and very technical users) with
- an environment to edit and test rules in various formats, and integrate it
- deeply with their applications. In cases where you prefer business rules and
- web tooling, you will want to look at the BRMS (but using the BRMS and the
- IDE together is not uncommon).
-
- The Drools IDE is delivered as an Eclipse plug-in, which
- allows you to author and manage rules from within Eclipse, as well as
- integrate rules with your application. This is an optional tool, and not all
- components are required to be used, you can use what components are relevant
- to you. The Drools IDE is also a part of the Red Hat Developer Studio
- (formerly known as JBoss IDE).
-
- This guide will cover some of the features of JBoss Drools, in as far
- as the IDE touches on them (it is assumed that the reader has some
- familiarity with rule engines, and Drools in particular. It is important to
- note that none of the underlying features of the rule engine are dependent
- on Eclipse, and integrators are free to use their tools of choice, as always
- ! Plenty of people use IntelliJ with rules, for instance.
-
- You can get the plug-in either as a zip to download, or from an
- update site. Refer to the chapter on installation.
-
-
- Overview
-
-
-
-
-
-
-
-
-
- Features Outline
-
- The rules IDE has the following features
-
-
-
- Textual/graphical rule editor
-
-
-
- An editor that is aware of DRL syntax, and provides content
- assistance (including an outline view)
-
-
- An editor that is aware of DSL (domain specific langauge) extensions, and provides content assistance.
-
-
-
-
-
- RuleFlow graphical editor
- You can edit visual graphs which represent a process (a rule flow). The RuleFlow can then be applied to your rule package to have imperative control.
-
-
-
- Wizards for fast creation of
-
-
-
- a "rules" project
-
-
-
- a rule resource, either as a DRL file or a "guided rule editor" file (.brl)
-
-
-
- a Domain Specific language
-
-
-
- a decision table
-
-
- a ruleflow
-
-
-
-
-
-
-
- A domain specific language editor
-
-
-
- Create and manage mappings from your user's language to the
- rule language
-
-
-
-
-
- Rule validation
-
-
-
- As rules are entered, the rule is "built" in the background
- and errors reported via the problem view where possible
-
-
-
-
-
- The above features make use of Eclipse infrastructure
- and features, with all of the power of Eclipse being available.
-
-
-
- Creating a Rule Project
-
- The aim of the new project wizard is to set up an executable scaffold
- project to start using rules immediately. This will set up a basic
- structure, the classpath, sample rules and a test case to get you
- started.
-
-
- New rule project scaffolding
-
-
-
-
-
-
-
- When you choose to create a new "rule project" you will get a choice to
- add some default artifacts to it, like rules, decision tables, ruleflows, etc.
- These can serve as a starting point, and will give you something executable
- almost immediately, which you can then modify and mould to your needs. The
- simplest case (a hello world rule) is shown below. Feel free to experiment
- with the plug-in at this point.
-
-
- New rule project result
-
-
-
-
-
-
-
-
- The newly created project contains an example rule file (Sample.drl)
- in the src/rules directory and an example Java file (DroolsTest.java) that can
- be used to execute the rules in a Drools engine. You'll find this in the
- folder src/java, in the com.sample package. All the other jars that are
- necessary during
- execution are also added to the classpath in a custom classpath container
- called Drools Library. Rules do not have to be kept in "Java"
- projects at all, this is just a convenience for people who are already
- using Eclipse as their Java IDE.
-
- Important note: The Drools plug-in adds a "Drools Builder"
- capability to your Eclipse instance. This means you can enable a builder
- on any project that will build and validate your rules when resources
- change. This happens automatically with the Rule Project Wizard, but you
- can also enable it manually on any project. One downside of this is that
- if you have rule files with a large number of rules (more than 500 rules
- per file), it means that the background builder may be doing a lot of work to
- build the rules on each change. An option here is to turn off the builder,
- or put the large rules into .rule files, where you can still use the rule
- editor, but it won't build them in the background. To fully validate the
- rules you will need to run them in a unit test of course.
-
-
-
- Creating a New Rule and Wizards
-
- You can create a rule simple as an empty text ".drl" file, or use
- the wizard to do so. The wizard menu can be invoked with Control+N, or by
- choosing it from the toolbar, where there is a menu with the JBoss Drools
- icon.
-
-
- The wizard menu
-
-
-
-
-
-
-
-
- The wizard will ask for some basic options for generating a rule
- resource. These are just hints - you can change your mind later. For
- storing rule files you would typically create a directory src/rules and
- create suitably named subdirectories. The package name is mandatory, and
- is similar to a package name in Java; i.e., it establishes a namespace for
- grouping related rules.
-
-
- New rule wizard
-
-
-
-
-
-
-
-
- The result of this wizard is a rule skeleton, for you to expand.
- As with all wizards, they are an optional help - you don't have to use
- them if you don't want to.
-
-
-
- Textual Rule Editor
-
- The rule editor is where rule managers and developers will be
- spending most of their time. The rule editor follows the pattern of a
- normal text editor in Eclipse, with all the customary features of a text
- editor. On top of this, the rule editor provides pop-up content
- assistance. You invoke pop-up content assistance the "normal" way by
- pressing Control+Space.
-
-
- The rule editor in action
-
-
-
-
-
-
-
-
- The rule editor works on files that have a .drl (or .rule)
- extension. Usually these contain related rules, but it would also be
- possible to have rules in individual files, grouped by being in the
- same package "namespace", if you so prefer. These DRL files are plain
- text files.
-
- You can see from the example above that the rule group is using a
- domain specific language. Note the expander keyword, which tells the rule
- compiler to look for a dsl file of that name, to resolve the rule
- language. Even with the domain specific language (DSL) the rules are
- still stored as plain text as you see it onscreen, which allows simpler
- management of rules and versions, e.g., comparing versions of rules.
-
- The editor has an outline view that is kept in sync with the
- structure of the rules; it is updated on save. This provides a quick way of
- navigating around rules by name, even in a file which may have hundreds of
- rules. The items are sorted alphabetically by default.
-
-
- The rule outline view
-
-
-
-
-
-
-
-
-
-
- The Guided Editor (Rule GUI)
-
- A new feature of the Drools IDE (since version 4) is the guided editor for rules.
- This is similar to the web based editor that is available in the BRMS. It
- allows you to build rules in a GUI-driven fashion, based on your object
- model.
-
-
- The guided editor
-
-
-
-
-
-
-
-
-
- To create a rule this way, use the wizard menu. It will create an instance
- of a .brl file and open it in the guided editor. This editor works
- based on a .package file in the same directory as the .brl file. In
- this "package" file you have the package name and import statements - just
- like you would at the top of a normal DRL file. First time you create
- a brl rule you will need to populate the package file with the fact
- classes you are interested in. Once you have this, the guided editor
- will be able to prompt you with facts and their fields so that you can
- build rules graphically.
-
-
- The guided editor works off the model classes (or fact classes) that you
- configure. It then is able to "render" to DRL the rule that you have
- entered graphically. You can do this visually - and use it as a basis
- for learning DRL, or you can use it and build rules of the brl directly.
- One way to do this is by using the drools-ant module, which is an ant task
- that creates all the rule assets in a folder, as a rule package, so that
- you can then deploy it as a binary file. Alternatively, you can use the
- following snippet of code to convert the brl to a drl rule.
-
- BRXMLPersistence read = BRXMLPersistence.getInstance();
-BRDRLPersistence write = BRDRLPersistence.getInstance();
-String brl = ... // read from the .brl file as needed...
-String outputDRL = write.marshall(read.unmarshal(brl));
-// Pass the outputDRL to the PackageBuilder, as usual
-
-
-
- Drools Views
-
- When debugging an application using a Drools engine, these views
- can be used to check the state of the Drools engine itself: the Working
- Memory View, the Agenda View, and the Global Data View. To be able to use
- these views, create breakpoints in your code invoking the working memory.
- For example, the line where you call workingMemory.fireAllRules() is a
- good candidate. If the debugger halts at that joinpoint, you should select
- the working memory variable in the debug variables view. The available
- views can then be used to show the details of the selected working
- memory:
-
-
-
- The Working Memory View shows all elements of the Drools
- working memory.
-
-
-
- The Agenda View shows all elements on the agenda. For each rule
- on the agenda, the rule name and bound variables are shown.
-
-
-
- The Global Data View shows all global data currently defined in
- the Drools working memory.
-
-
-
- The Audit view can be used to display audit logs containing events
- that were logged during the execution of a rules engine, in tree form.
-
-
- The Working Memory View
-
-
-
-
-
-
-
- The Working Memory View shows all elements in the working memory of the
- Drools engine.
-
- An action is added to the right of the view, to customize what is
- shown:
-
-
-
- The Show Logical Structure toggles showing the logical
- structure of the elements in the working memory, or all their
- details. Logical structures allow for visualizing sets of
- elements in a more obvious way.
-
-
-
-
-
- The Agenda View
-
-
-
-
-
-
-
- The Agenda View shows all elements on the agenda. For each rule on
- the agenda, the rule name and bound variables are shown.
-
- An action is added to the right of the view, to customize what is
- shown:
-
-
-
- The Show Logical Structure toggles showing the logical
- structure of the agenda item, or all their details. Logical
- structures allow for example visualizing sets of elements in a more
- obvious way. The logical structure of AgendaItems shows the rule
- that is represented by the AgendaItem, and the values of all the
- parameters used in the rule.
-
-
-
-
-
- The Global Data View
-
-
-
-
-
-
-
- The Global Data View shows all global data currently defined in
- the Drools engine.
-
- An action is added to the right of the view, to customize what is
- shown:
-
-
-
- The Show Logical Structure toggles showing the logical
- structure of the elements in the working memory, or all their
- details. Logical structures allow for example visualizing sets of
- elements in a more obvious way.
-
-
-
-
-
- The Audit View
-
-
-
-
-
-
-
- The audit view visualizes an audit log, that is optionally
- created when executing the rules engine. To create an audit log, use the
- following code:
-
- WorkingMemory workingMemory = ruleBase.newWorkingMemory();
-// Create a new Working Memory Logger, that logs to file.
-WorkingMemoryFileLogger logger = new WorkingMemoryFileLogger(workingMemory);
-// An event.log file is created in the subdirectory log (which must exist)
-// of the working directory.
-logger.setFileName( "log/event" );
-
-workingMemory.assertObject(...);
-workingMemory.fireAllRules();
-
-// stop logging
-logger.writeToDisk();
-
- Open the log by clicking the Open Log action, the first icon in the
- Audit View, and select the file. The Audit View now shows all events
- that where logged during the executing of the rules. There are different
- types of events, each with a different icon:
-
-
-
- Object inserted, a green square:
-
-
-
- Object updated, a yellow square:
-
-
-
- Object removed, a red square:
-
-
-
- Activation created, a right arrow:
-
-
-
- Activation cancelled, a left arrow:
-
-
-
- Activation executed, a blue diamond:
-
-
-
- Ruleflow start or end, the "process" icon:
-
-
-
- Ruleflow-group activation or deactivation, the "activity" icon:
-
-
-
- Rule package addition or removal, the Drools icon:
-
-
-
- Rule addition or removal, the Drools icon:
-
-
-
- All these events show extra information concerning the event, like
- the id and toString representation of the object in case of working
- memory events (insert, modify and retract), the name of the rule and all
- the variables bound in the activation in case of an activation event
- (created, cancelled or executed). If an event occurs when executing an
- activation, it is shown as a child of the activation's execution event. For
- some events, you can retrieve the "cause":
-
-
-
- The cause of an object modified or retracted event is the last
- object event for that object. This is either the object asserted
- event, or the last object modified event for that object.
-
-
-
- The cause of an activation cancelled or executed event is the
- corresponding activation created event.
-
-
-
- When selecting an event, the cause of that event is shown in green
- in the audit view (if visible of course). You can also right click the
- action and select the "Show Cause" menu item. This will scroll you to
- the cause of the selected event.
-
-
-
-
- Domain Specific Languages
-
- Domain Specific Languages (DSL) enable you to create a language that
- allows your rules to look like - rules! Most often the domain specific
- language reads like natural language. Typically you would look at how a
- business analyst would describe the rule, in their own words, and then map
- this to your object model, via rule constructs. A side benefit of this is
- that it can provide an insulation layer between your domain objects and
- the rules themselves (as we know you like to refactor). A domain
- specific language will grow as the rules grow, and works best when there
- are common terms used over an over, with different parameters.
-
- To aid with this, the rule workbench provides an editor for Domain
- Specific Languages. They are stored in a plain text format, so you can
- use any editor of your choice; this format is simply a slightly enhanced
- version of the "Properties" file format. The editor will be invoked on
- any files with a .dsl extension. There is also a wizard to create a sample
- DSL.
-
-
- Editing languages
-
-
- The Domain Specific Language editor
-
-
-
-
-
-
-
-
- The DSL editor provides a tabular view of the mapping of
- Language to Rule Expressions. The Language Expression is what is used in the
- rules. This also feeds the content assistance for the rule editor, so
- that it can suggest Language Expressions from the DSL configuration. (The
- rule editor loads the DSL configuration when the rule resource is
- loaded for editing.) The Rule language mapping defines the "code" for the
- rules into which the language expression will be compiled by the rule
- engine compiler. The form of this Rule language expression depends on it
- being intended for the condition or the action part of a rule. (For the
- RHS it may be a snippet of Java, for instance). The "scope" item indicates
- where the expression belongs, "when" indicating the LHS, "then" the RHS,
- and "*" meaning anywhere. It's also possible to create aliases for
- keywords.
-
- By selecting a mapping item (a row in the table) you can see the
- expression and mapping in the text fields below the table. Double clicking
- or pressing the edit button will open the edit dialog. Other buttons let you
- remove and add mappings. Don't remove mappings while they are still in
- use.
-
-
- Language Mapping editor dialog
-
-
-
-
-
-
-
-
- Here is a short description of the DSL translation process.
- The parser reads the rule text in a DSL, line by line, and tries to
- match some "Language Expression", depending on the scope. After a
- match, the values that correspond to a placeholder between curly
- braces (e.g., {age}) are extracted from the rule source. The
- placeholders in the corresponding "Rule Expression" are replaced by
- their corresponding value. In the example above, the natural
- language expression maps to two constraints on a fact of type
- Person, based on the fields age and location, and the {age} and {location}
- values are extracted from the original rule text.
-
- If you do not wish to use a language mapping for a
- particular rule in a drl, prefix the expression with > and the
- compiler will not try to translate it according to the language
- definition. Also note that Domain Specific Languages are optional. When
- the rule is compiled, the .dsl file will also need to be
- available.
-
-
-
-
- The Rete View
-
- The Rete Tree View shows you the current Rete Network for your DRL
- file. You display it by clicking on the tab "Rete Tree" at the bottom
- of the DRL Editor window. With the Rete Network visualization being open,
- you can use drag-and-drop on individual nodes to arrange optimal network
- overview. You may also select multiple nodes by dragging a rectangle
- over them; then the entire group can be moved around. The Eclips toolbar
- icons for zooming in and out can be used in the customary manner.
-
- In the current release there is no export function to creates a gif
- or jpeg file. Meanwhile, please use ctrl + alt + print to create a copy of
- your current Eclipse window, and cut it off.
-
-
-
-
-
-
-
- The Rete View is an advanced feature which takes full advantage of
- the Eclipse Graphical Editing Framework (GEF).
-
- The Rete view works only in Drools Rule Projects, where the Drools
- Builder is set in the project´s properties.
-
- If you are using Drools in another type of project where you are
- not having a Drools Rule Project with the appropriate Drools Builder, you
- can use a workaround: Set up a little Drools Rule Project next
- to it, putting needed libraries into it, and the DRLs you want to inspect
- with the Rete View.
- Just click on the right tab below in the DRL Editor, followed by a click
- on "Generate Rete View".
-
-
-
- Large DRL Files
-
- Depending on the JDK you use, it may be necessary to increase the
- permanent generation max size. Both the SUN and the IBM JDK have a permanent
- generation, whereas BEA JRockit does not.
-
- To increase the permanent generation, start Eclipse with
- -XX:MaxPermSize=###m
-
- Example: c:\Eclipse\Eclipse.exe -XX:MaxPermSize=128m
-
- Rulesets of 4,000 rules or greater should set the permanent
- generation to at least 128Mb.
-
- This may also apply to compiling large numbers of rules
- in general, as there is generally one or more classes per rule.
-
- As an alternative to the above, you may put rules in a file with the
- ".rule" extension, and the background builder will not try to compile them
- with each change, which may provide performance improvements if your IDE
- becomes sluggish with very large numbers of rules.
-
-
-
-
-
- Debugging Rules
-
-
- Debugging
-
-
-
-
-
-
-
- You can debug rules during the execution of your Drools application.
- You can add breakpoints in the consequences of your rules, and whenever
- such a breakpoint is encountered during the execution of the rules,
- execution is halted. You can then inspect the variables known at that
- point and use any
- of the default debugging actions to decide what should happen next: step over,
- continue, etc. You can also use the debug views to inspect the content of the
- working memory and the Agenda.
-
-
- Creating Breakpoints
- You can add and remove rule breakpoints in DRL files in two ways,
- similar to adding breakpoints to Java files:
-
-
- Double-click the ruler of the DRL editor at the line where you want to
- add a breakpoint. Note that rule breakpoints can only be created in the
- consequence of a rule. Double-clicking on a line where no breakpoint is allowed
- will do nothing. A breakpoint can be removed by double-clicking the ruler once more.
-
-
-
- If you right-click the ruler, a popup menu will show up, containing the
- "Toggle breakpoint" action. Note that rule breakpoints can only be created in the
- consequence of a rule. The action is automatically disabled if no rule
- breakpoint is allowed at that line. Clicking the action will add a breakpoint at the
- selected line, or remove it if there was one already.
-
-
- The Debug Perspective contains a Breakpoints view which can be used to see
- all defined breakpoints, get their properties, enable/disable or remove them, etc.
-
-
- Debugging Rules
- Drools breakpoints are only enabled if you debug your application as
- a Drools Application. You can do this like this:
-
-
- Debug as Drools Application
-
-
-
-
-
-
-
-
-
- Select the main class of your application. Right click it and select
- the "Debug As >" sub-menu and select Drools Application. Alternatively,
- you can also select the "Debug ..." menu item to open a new dialog
- for creating, managing and running debug configurations (see the
- screenshot below).
-
-
-
- Select the "Drools Application" item in the left tree and click
- the "New launch configuration" button (leftmost icon in the toolbar
- above the tree). This will create a new configuration with some of
- the properties (like project and main class)already filled in,
- based on the main class you selected in the beginning. All properties
- shown here are the same as for any standard Java program.
-
-
-
- Change the name of your debug configuration to something meaningful.
- You can just accept the defaults for all other properties. For more
- information about these properties, please check the Eclipse JDT
- documentation.
-
-
-
- Click the "Debug" button on the bottom to start debugging your
- application. You only have to define your debug configuration once.
- The next time you run your Drools application, you don't have
- to create a new one but select the previously defined one
- in the tree on the left, as a sub-element of the "Drools Application"
- tree node, and then click the Debug button. The Eclipse toolbar also
- contains shortcut buttons to quickly re-execute one of your
- previous configurations (at least when one of the Java, Java Debug,
- or Drools perspectives has been selected).
-
-
-
-
- Debug as Drools Application Configuration
-
-
-
-
-
-
-
- After clicking the "Debug" button, the application starts executing
- and will halt if any breakpoint is encountered. This can be a Drools rule
- breakpoint, or any other standard Java breakpoint. Whenever a Drools rule
- breakpoint is encountered, the corresponding DRL file is opened and the
- active line is highlighted. The Variables view also contains all rule
- parameters and their value. You can then use the default Java debug actions
- to decide what to do next: resume, terminate, step over, etc. The debug
- view can also be used to inspect the contents of the Working Memory and the
- Agenda at that time as well. You don't have to select a Working Memory now,
- as the current executing working memory is automatically shown.
-
-
- Debugging
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Chapter-Introduction.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Chapter-Introduction.xml
index a8fb1fbb2d..45517350d7 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Chapter-Introduction.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Chapter-Introduction.xml
@@ -4,9 +4,12 @@
xml:base="./" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
- The Rule Engine
+ Introduction
-
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-AIKnowledgeRepresentation.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-AIKnowledgeRepresentation.xml
new file mode 100644
index 0000000000..b6db53970e
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-AIKnowledgeRepresentation.xml
@@ -0,0 +1,547 @@
+
+
+ Artificial Intelligence
+
+
+ A Little History
+
+ Over the last few decades artificial
+ intelligence (AI) became an unpopular term, with the well-known
+ "AI
+ Winter". There were large boasts from scientists and engineers
+ looking for funding, which never lived up to expectations, resulting in many
+ failed projects. Thinking
+ Machines Corporation and the 5th
+ Generation Computer (5GP) project probably exemplify best the
+ problems at the time.
+
+ Thinking Machines Corporation was one of the leading AI firms in
+ 1990, it had sales of nearly $65 million. Here is a quote from its
+ brochure:
+
+ Some day we will build a thinking machine. It will be a truly
+ intelligent machine. One that can see and hear and speak. A machine that
+ will be proud of us.
+
+ Yet 5 years later it filed for bankruptcy protection under Chapter 11.
+ The site inc.com has a fascinating article titled "The Rise and
+ Fall of Thinking Machines". The article covers the growth of the
+ industry and how a cosy relationship with Thinking Machines and DARPA over-heated
+ the market, to the point of collapse. It explains how and why commerce
+ moved away from AI and towards more practical number-crunching super
+ computers.
+
+ The 5th Generation Computer project was a USD 400 million project in
+ Japan to build a next generation computer. Valves (or Tubes) was the first generation, transistors
+ the second, integrated circuits the third and finally microprocessors was
+ the fourth. The fifth was intended to be a machine capable of effective Artificial Intelligence.
+ This project spurred an "arms" race with the UK and USA, that
+ caused much of the AI bubble. The 5GP would provide massive multi-cpu
+ parallel processing hardware along with powerful knowledge representation
+ and reasoning software via Prolog; a type of
+ expert system. By 1992 the project was considered
+ a failure and cancelled. It was the largest and most visible commercial
+ venture for Prolog, and many of the failures are pinned on the problems
+ of trying to run a logic based programming language concurrently on multi CPU
+ hardware with effective results. Some believe that the failure of the 5GP
+ project tainted Prolog and resigned it academia, see "Whatever
+ Happened to Prolog" by John C. Dvorak.
+
+ However while research funding dried up and the term AI became less
+ used, many green shoots where planted and continued more quietly under
+ discipline specific names: cognitive systems,
+ machine learning, intelligent
+ systems, knowledge representation and
+ reasoning. Offshoots of these then made their way into
+ commercial systems, such as expert systems in the Business
+ Rules Management System (BRMS) market.
+
+ Imperative, system based languages, languages
+ such as C, C++, Java and C#/.Net have dominated the last 20 years, enabled by
+ the practicality of the languages and ability to run with good performance
+ on commodity hardware. However many believe there is renaissance
+ underway in the field of AI, spurred by advances in hardware
+ capabilities and AI research. In 2005 Heather Havenstein authored "Spring
+ comes to AI winter" which outlines a case for this resurgence,
+ which she refers to as a spring. Norvig and Russel
+ dedicate several pages to what factors allowed the industry to over come
+ it's problems and the research that came about as a result:
+
+ Recent years have seen a revolution in both the content and
+ the methodology of work in artificial intelligence. It is now more common
+ to build on existing theories than to propose brand-new ones, to base
+ claims on rigorous theorems or hard experimental evidence rather than on
+ intuition, and to show relevance to real-world applications rather than
+ toy examples. (Artificial Intelligence: A Modern
+ Approach.)
+
+ Computer vision, neural
+ networks, machine learning and
+ knowledge representation and reasoning (KRR) have
+ made great strides towards becoming practical in commercial environments. For
+ example, vision-based systems can now fully map out and navigate their
+ environments with strong recognition skills. As a result we now have self-driving
+ cars about to enter the commercial market.
+ Ontological research, based around description
+ logic, has provided very rich semantics to represent our world. Algorithms
+ such as the tableaux algorithm have made it possible to effectively use
+ those rich semantics in large complex ontologies. Early KRR systems, like
+ Prolog in 5GP, were dogged by the limited semantic capabilities and memory
+ restrictions on the size of those ontologies.
+
+
+
+ Knowledge Representation and Reasoning
+
+ In A Little History talks about AI as a broader subject and touches
+ on Knowledge Representation and Reasoning (KRR) and also Expert Systems,
+ I'll come back to Expert Systems later.
+
+ KRR is about how we represent our knowledge in symbolic form, i.e.
+ how we describe something. Reasoning is about how we go about the act of
+ thinking using this knowledge. System based/Object-Oriented languages, like C++/Java/C#,
+ have classification systems, called Classes, to be able to describe
+ things. In Java we calls exemplars of these things beans or instances. However those
+ classification systems are limited to ensure computational efficiency.
+ Over the years researchers have developed increasingly sophisticated ways
+ to represent our world. Many of you may already have heard of OWL (Web
+ Ontology Language). There is always a gap between what we can be
+ theoretically represented and what can be used computationally in
+ practically timely manner, which is why OWL has different sub-languages
+ from Lite to Full. It is not believed that any reasoning system can
+ support OWL Full. Although each year algorithmic advances try to narrow
+ that gap and improve the expressiveness available to reasoning engines.
+
+ There are also many approaches to how these systems go about
+ thinking. You may have heard discussions comparing the merits of
+ forward chaining, which is reactive and data driven, with backward chaining,
+ which is passive and query driven. Many other types of reasoning
+ techniques exist, each of which enlarges the scope of the problems we can
+ tackle declaratively. To list just a few: imperfect reasoning (fuzzy
+ logic, certainty factors), defeasible logic, belief systems, temporal
+ reasoning and correlation. You don't need to understand all these terms
+ to understand and use Drools. They are just there to give
+ an idea of the range of scope of research topics, which is actually far
+ more extensive, and continues to grow as researchers
+ push new boundaries.
+
+ KRR is often referred to as the core of Artificial Intelligence. Even
+ when using biological approaches like neural networks, which model the
+ brain and are more about pattern recognition than thinking, they still
+ build on KRR theory. My first endeavours with Drools were engineering
+ oriented, as I had no formal training or understanding of KRR. Learning
+ KRR has allowed me to get a much wider theoretical background. Allowing me
+ to better understand both what I've done and where I'm going, as it
+ underpins nearly all of the theoretical side to our Drools R&D. It
+ really is a vast and fascinating subject that will pay dividends for those
+ who take the time to learn. I know it did and still does for me. Bracham and
+ Levesque have written a seminal piece of work, called "Knowledge
+ Representation and Reasoning" that is a must read for anyone wanting to build strong
+ foundations. I would also recommend the Russel and Norvig
+ book "Artificial Intelligence, a modern approach" which also covers
+ KRR.
+
+
+
+ Rule Engines and Production Rule Systems (PRS)
+
+ We've now covered a brief history of AI and learnt that the core of
+ AI is formed around KRR. We've shown than KRR is vast and fascinating
+ subject which forms the bulk of the theory driving Drools R&D.
+
+ The rule engine is the computer program that delivers KRR
+ functionality to the developer. At a high level it has three
+ components:
+
+
+
+ Ontology
+
+
+
+ Rules
+
+
+
+ Data
+
+
+
+ As previous mentioned the ontology is the representation model we
+ use for our "things". It could be simple records or Java classes or full
+ blown OWL based ontologies. The Rules do the reasoning and facilitate
+ thinking. The distinction between rules and ontologies blurs a little with
+ OWL based ontologies, whose richness is rule based.
+
+ The term "rules engine" is quite ambiguous in that it can be any system
+ that uses rules, in any form, that can be applied to data to produce
+ outcomes. This includes simple systems like form validation and dynamic
+ expression engines. The book "How to Build a Business Rules Engine (2004)"
+ by Malcolm Chisholm exemplifies this ambiguity. The book is actually about
+ how to build and alter a database schema to hold validation rules. The
+ book then shows how to generate VB code from those validation rules to
+ validate data entry. While perfectly valid, this is very different to what
+ we are talking about.
+
+ Drools started life as a specific type of rule engine called a
+ production rule system (PRS) and was based around the Rete algorithm
+ (usually pronounced as two syllables, e.g., REH-te or RAY-tay). The
+ Rete algorithm, developed by Charles Forgey in 1979, forms the brain of a
+ Production Rules System and is able to scale to a large number of rules
+ and facts. A Production Rule is a two-part structure: the engine matches
+ facts and data against Production Rules - also called Productions or just
+ Rules - to infer conclusions which result in actions.
+
+ when
+ <conditions>
+then
+ <actions>;
+
+ The process of matching the new or existing facts against Production
+ Rules is called pattern matching
+ Pattern Matching
+ , which is performed by the inference
+ engine
+ Inference Engine
+ . Actions execute in response to changes in data, like a
+ database trigger; we say this is a data
+ driven
+ data driven
+ approach to reasoning. The actions themselves can change
+ data, which in turn could match against other rules causing them to fire;
+ this is referred to as
+ forward chaining
+ forward chaining
+
+ Drools implements and extends the
+ Rete
+ Rete algorithm;
+ Leaps
+ . The Drools
+ Rete
+ Rete implementation is called ReteOO, signifying that
+ Drools has an enhanced and optimized implementation of the Rete algorithm
+ for object oriented systems. Our more recent work goes well beyond Rete.
+ Other Rete based engines also have marketing terms for their proprietary
+ enhancements to Rete, like RetePlus and Rete III. Th e most common
+ enhancements are covered in "Production Matching for Large Learning
+ Systems (Rete/UL)" (1995) by Robert B. Doorenbos. "Leaps" used to be
+ provided, but was retired as it became unmaintained. The good news is that our
+ research is close to producing an algorithm that merges the benefits of
+ Leaps with Rete.
+
+ The Rules are stored in the
+ Production Memory
+ Production Memory and the facts that the Inference Engine
+ matches against are kept in the
+ WorkingMemory
+ Working Memory. Facts are asserted into the Working Memory
+ where they may then be modified or retracted. A system with a large number
+ of rules and facts may result in many rules being true for the same fact
+ assertion; these rules are said to be in conflict. The Agenda manages the
+ execution order of these conflicting rules using a Conflict Resolution
+ strategy.
+
+
+ High-level View of a Production Rule System
+
+
+
+
+
+
+
+
+
+
+ Hybrid Reasoning Systems (HRS)
+
+ You may have read discussions comparing the merits of forward
+ chaining (reactive and data driven) or backward chaining(passive query).
+ Here is a quick explanation of these two main types of reasoning.
+
+ Forward chaining is "data-driven" and thus reactionary, with facts
+ being asserted into working memory, which results in one or more rules
+ being concurrently true and scheduled for execution by the Agenda. In
+ short, we start with a fact, it propagates through the rules, and we end in a
+ conclusion.
+
+
+ Forward Chaining
+
+
+
+
+
+
+
+
+ Backward chaining is "goal-driven", meaning that we start with a
+ conclusion which the engine tries to satisfy. If it can't, then it searches
+ for conclusions that it can satisfy. These are known as subgoals, that
+ will help satisfy some unknown part of the current goal. It continues this
+ process until either the initial conclusion is proven or there are no more
+ subgoals. Prolog is an example of a Backward Chaining engine. Drools can
+ also do backward chaining, which we refer to as derivation queries.
+
+
+ Backward Chaining
+
+
+
+
+
+
+
+
+ Historically you would have to make a choice between systems like
+ OPS5 (forward) or Prolog (backward). Nowadays many modern systems provide both
+ types of reasoning capabilities. There are also many other types of
+ reasoning techniques, each of which enlarges the scope of the problems we
+ can tackle declaratively. To list just a few: imperfect reasoning (fuzzy
+ logic, certainty factors), defeasible logic, belief systems, temporal
+ reasoning and correlation. Modern systems are merging these capabilities,
+ and others not listed, to create hybrid reasoning
+ systems (HRS).
+
+ While Drools started out as a PRS, 5.x introduced Prolog style
+ backward chaining reasoning as well as some functional programming styles.
+ For this reason we now prefer the term Hybrid Reasoning System when describing Drools.
+
+
+ Drools current provides crisp reasoning, but imperfect reasoning is
+ almost ready. Initially this will be imperfect reasoning with fuzzy logic;
+ later we'll add support for other types of uncertainty. Work is also under
+ way to bring OWL based ontological reasoning, which will integrate with
+ our traits system. We also continue to improve our
+ functional programming capabilities.
+
+
+
+ Expert Systems
+
+ You will often hear the terms expert systems
+ used to refer to production rule systems or
+ Prolog-like systems. While this is normally
+ acceptable, it's technically incorrect as these are frameworks to build expert
+ systems with, rather than expert systems themselves. It becomes an
+ expert system once there is an ontological model to represent the domain
+ and there are facilities for knowledge acquisition and explanation.
+
+
+ Mycin is the most famous expert system, built
+ during the 70s. It is still heavily covered in academic literature, such
+ as the recommended book "Expert Systems" by Peter Jackson.
+
+
+ Early History of Expert Systems
+
+
+
+
+
+
+
+
+
+ Recommended Reading
+
+ General AI, KRR and Expert System
+ Books
+
+ For those wanting to get a strong theoretical background in KRR and
+ expert systems, I'd strongly recommend the following books. "Artificial
+ Intelligence: A Modern Approach" is a must have, for anyone's
+ bookshelf.
+
+
+
+ Introduction to Expert Systems
+
+
+
+ Peter Jackson
+
+
+
+
+
+
+
+ Expert Systems: Principles and Programming
+
+
+
+ Joseph C. Giarratano, Gary D. Riley
+
+
+
+
+
+
+
+ Knowledge Representation and Reasoning
+
+
+
+ Ronald J. Brachman, Hector J. Levesque
+
+
+
+
+
+
+
+ Artificial Intelligence : A Modern Approach.
+
+
+
+ Stuart Russell and Peter Norvig
+
+
+
+
+
+
+ Recommended Reading
+
+
+
+
+
+
+
+
+ Papers
+
+ Here are some recommended papers that cover interesting areas
+ in rule engine research:
+
+
+
+ Production Matching for Large Learning Systems : Rete/UL
+ (1993)
+
+
+
+ Robert B. Doorenbos
+
+
+
+
+
+ Advances In Rete Pattern Matching
+
+
+
+ Marshall Schor, Timothy P. Daly, Ho Soo Lee, Beth R.
+ Tibbitts (AAAI 1986)
+
+
+
+
+
+ Collection-Oriented Match
+
+
+
+ Anurag Acharya and Milind Tambe (1993)
+
+
+
+
+
+ The Leaps Algorithm (1990)
+
+
+
+ Don Battery
+
+
+
+
+
+ Gator: An Optimized Discrimination Network for Active Database
+ Rule Condition Testing (1993)
+
+
+
+ Eric Hanson , Mohammed S. Hasan
+
+
+
+
+
+ Drools Books
+
+ There are currently three Drools books, all from Packt
+ Publishing.
+
+
+
+ JBoss Drools Business Rules
+
+
+
+ Paul Brown
+
+
+
+
+
+ Drools JBoss Rules 5.0 Developers Guide
+
+
+
+ Michali Bali
+
+
+
+
+
+ Drools Developer's Cookbook
+
+
+
+ Lucas Amador
+
+
+
+
+
+
+ Recommended Reading
+
+
+
+
+
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-Rete.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-Rete.xml
new file mode 100644
index 0000000000..429876531f
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-Rete.xml
@@ -0,0 +1,176 @@
+
+
+ Rete Algorithm
+
+ The Rete algorithm was invented by Dr. Charles
+ Forgy and documented in his PhD thesis in 1978-79. A simplified version of
+ the paper was published in 1982 (http://citeseer.ist.psu.edu/context/505087/0).
+ The latin word "rete" means "net" or "network". The Rete algorithm can be
+ broken into 2 parts: rule compilation and runtime execution.
+
+ The compilation algorithm describes how the Rules in the Production
+ Memory are processed to generate an efficient discrimination network. In
+ non-technical terms, a discrimination network is used to filter data as it
+ propagates through the network. The nodes at the top of the network would
+ have many matches, and as we go down the network, there would be fewer
+ matches. At the very bottom of the network are the terminal nodes. In Dr.
+ Forgy's 1982 paper, he described 4 basic nodes: root, 1-input, 2-input and
+ terminal.
+
+
+ Rete Nodes
+
+
+
+
+
+
+
+
+ The root node is where all objects enter the network. From there, it
+ immediately goes to the ObjectTypeNode. The purpose of the ObjectTypeNode is
+ to make sure the engine doesn't do more work than it needs to. For example,
+ say we have 2 objects: Account and Order. If the rule engine tried to
+ evaluate every single node against every object, it would waste a lot of
+ cycles. To make things efficient, the engine should only pass the object to
+ the nodes that match the object type. The easiest way to do this is to
+ create an ObjectTypeNode and have all 1-input and 2-input nodes descend from
+ it. This way, if an application asserts a new Account, it won't propagate to
+ the nodes for the Order object. In Drools when an object is asserted it
+ retrieves a list of valid ObjectTypesNodes via a lookup in a HashMap from
+ the object's Class; if this list doesn't exist it scans all the
+ ObjectTypeNodes finding valid matches which it caches in the list. This
+ enables Drools to match against any Class type that matches with an
+ instanceof check.
+
+
+ ObjectTypeNodes
+
+
+
+
+
+
+
+
+ ObjectTypeNodes can propagate to AlphaNodes, LeftInputAdapterNodes and
+ BetaNodes. AlphaNodes are used to evaluate literal conditions. Although the
+ 1982 paper only covers equality conditions, many RETE implementations
+ support other operations. For example, Account.name == "Mr
+ Trout" is a literal condition. When a rule has multiple literal
+ conditions for a single object type, they are linked together. This means
+ that if an application asserts an Account object, it must first satisfy the
+ first literal condition before it can proceed to the next AlphaNode. In Dr.
+ Forgy's paper, he refers to these as IntraElement conditions. The following
+ diagram shows the AlphaNode combinations for Cheese( name == "cheddar",
+ strength == "strong" ):
+
+
+ AlphaNodes
+
+
+
+
+
+
+
+
+ Drools extends Rete by optimizing the propagation from ObjectTypeNode
+ to AlphaNode using hashing. Each time an AlphaNode is added to an
+ ObjectTypeNode it adds the literal value as a key to the HashMap with the
+ AlphaNode as the value. When a new instance enters the ObjectType node,
+ rather than propagating to each AlphaNode, it can instead retrieve the
+ correct AlphaNode from the HashMap,thereby avoiding unnecessary literal
+ checks.
+
+ There are two two-input nodes, JoinNode and NotNode, and both are
+ types of BetaNodes. BetaNodes are used to compare 2 objects, and their
+ fields, to each other. The objects may be the same or different types. By
+ convention we refer to the two inputs as left and right. The left input for
+ a BetaNode is generally a list of objects; in Drools this is a Tuple. The
+ right input is a single object. Two Nodes can be used to implement 'exists'
+ checks. BetaNodes also have memory. The left input is called the Beta Memory
+ and remembers all incoming tuples. The right input is called the Alpha
+ Memory and remembers all incoming objects. Drools extends Rete by performing
+ indexing on the BetaNodes. For instance, if we know that a BetaNode is
+ performing a check on a String field, as each object enters we can do a hash
+ lookup on that String value. This means when facts enter from the opposite
+ side, instead of iterating over all the facts to find valid joins, we do a
+ lookup returning potentially valid candidates. At any point a valid join is
+ found the Tuple is joined with the Object; which is referred to as a partial
+ match; and then propagated to the next node.
+
+
+ JoinNode
+
+
+
+
+
+
+
+
+ To enable the first Object, in the above case Cheese, to enter the
+ network we use a LeftInputNodeAdapter - this takes an Object as an input and
+ propagates a single Object Tuple.
+
+ Terminal nodes are used to indicate a single rule having matched all
+ its conditions; at this point we say the rule has a full match. A rule with
+ an 'or' conditional disjunctive connective results in subrule generation for
+ each possible logically branch; thus one rule can have multiple terminal
+ nodes.
+
+ Drools also performs node sharing. Many rules repeat the same
+ patterns, and node sharing allows us to collapse those patterns so that they
+ don't have to be re-evaluated for every single instance. The following two
+ rules share the first pattern, but not the last:
+
+ rule
+when
+ Cheese( $cheddar : name == "cheddar" )
+ $person : Person( favouriteCheese == $cheddar )
+then
+ System.out.println( $person.getName() + " likes cheddar" );
+end
+
+ rule
+when
+ Cheese( $cheddar : name == "cheddar" )
+ $person : Person( favouriteCheese != $cheddar )
+then
+ System.out.println( $person.getName() + " does not like cheddar" );
+end
+
+ As you can see below, the compiled Rete network shows that the alpha
+ node is shared, but the beta nodes are not. Each beta node has its own
+ TerminalNode. Had the second pattern been the same it would have also been
+ shared.
+
+
+ Node Sharing
+
+
+
+
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-What_is_a_Rule_Engine.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-What_is_a_Rule_Engine.xml
deleted file mode 100644
index f503f62e1b..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-What_is_a_Rule_Engine.xml
+++ /dev/null
@@ -1,182 +0,0 @@
-
-
- What is a Rule Engine?
-
-
- Introduction and Background
-
- Artificial Intelligence (A.I.) is a very broad research area that
- focuses on "Making computers think like people" and includes disciplines
- such as Neural Networks, Genetic Algorithms, Decision Trees, Frame Systems
- and Expert Systems. Knowledge representation is the area of A.I. concerned
- with how knowledge is represented and manipulated. Expert Systems use
- Knowledge representation to facilitate the codification of knowledge into
- a knowledge base which can be used for reasoning, i.e., we can process
- data with this knowledge base to infer conclusions. Expert Systems are
- also known as Knowledge-based Systems and Knowledge-based Expert Systems
- and are considered to be "applied artificial intelligence". The process of
- developing with an Expert System is Knowledge Engineering. EMYCIN was one
- of the first "shells" for an Expert System, which was created from the
- MYCIN medical diagnosis Expert System. Whereas early Expert Systems had
- their logic hard-coded, "shells" separated the logic from the system,
- providing an easy to use environment for user input. Drools is a Rule
- Engine that uses the rule-based approach to implement an Expert System and
- is more correctly classified as a Production Rule System.
-
- The term "Production Rule" originates from formal grammars where it
- is described as "an abstract structure that describes a formal language
- precisely, i.e., a set of rules that mathematically delineates a (usually
- infinite) set of finite-length strings over a (usually finite) alphabet"
- (Wikipedia).
-
- Business Rule Management Systems build additional value on top of a
- general purpose Rule Engine by providing business user focused systems for
- rule creation, management, deployment, collaboration, analysis and end
- user tools. Further adding to this value is the fast evolving and popular
- methodology "Business Rules Approach", which is a helping to formalize the
- role of Rule Engines in the enterprise.
-
- The term Rule Engine is quite ambiguous in that it can be any system
- that uses rules, in any form, that can be applied to data to produce
- outcomes. This includes simple systems like form validation and dynamic
- expression engines. The book "How to Build a Business Rules Engine (2004)"
- by Malcolm Chisholm exemplifies this ambiguity. The book is actually about
- how to build and alter a database schema to hold validation rules. The
- book then shows how to generate VB code from those validation rules to
- validate data entry. This, while a very valid and useful topic for some,
- caused quite a surprise to this author, unaware at the time in the
- subtleties of Rules Engines' differences, who was hoping to find some
- hidden secrets to help improve the Drools engine. JBoss jBPM uses
- expressions and delegates in its Decision nodes which control the
- transitions in a Workflow. At each node it evaluates ther is a rule set
- that dictates the transition to undertake, and so this is also a Rule
- Engine. While a Production Rule System is a kind of Rule Engine and also
- an Expert System, the validation and expression evaluation Rule Engines
- mentioned previously are not Expert Systems.
-
- A Production Rule System is Turing complete, with a focus on
- knowledge representation to express propositional and first order logic in
- a concise, non-ambiguous and declarative manner. The brain of a Production
- Rules System is an Inference Engine that is able to scale to a large
- number of rules and facts. The Inference Engine matches facts and data
- against Production Rules - also called Productions or just Rules - to
- infer conclusions which result in actions. A Production Rule is a two-part
- structure using First Order Logic for reasoning over knowledge
- representation.
-
- when
- <conditions>
-then
- <actions>;
-
- The process of matching the new or existing facts against Production
- Rules is called
- Pattern Matching
- Pattern Matching, which is performed by the
- Inference Engine
- Inference Engine. There are a number of algorithms used for
- Pattern Matching by Inference Engines including:
-
-
-
- Linear
-
-
-
- Rete
-
-
-
- Treat
-
-
-
- Leaps
-
-
-
- Drools implements and extends the
- Rete
- Rete algorithm;
- Leaps
- Leaps used to be provided but was retired as it became
- unmaintained. The Drools
- Rete
- Rete implementation is called ReteOO, signifying that
- Drools has an enhanced and optimized implementation of the Rete algorithm
- for object oriented systems. Other Rete based engines also have marketing
- terms for their proprietary enhancements to Rete, like RetePlus and Rete
- III. The most common enhancements are covered in "Production Matching for
- Large Learning Systems (Rete/UL)" (1995) by Robert B. Doorenbos.
-
- The Rules are stored in the
- Production Memory
- Production Memory and the facts that the Inference Engine
- matches against are kept in the
- WorkingMemory
- Working Memory. Facts are asserted into the Working Memory
- where they may then be modified or retracted. A system with a large number
- of rules and facts may result in many rules being true for the same fact
- assertion; these rules are said to be in conflict. The Agenda manages the
- execution order of these conflicting rules using a Conflict Resolution
- strategy.
-
-
- High-level View of a Rule Engine
-
-
-
-
-
-
-
-
- There are two methods of execution for a rule system: Forward
- Chaining and Backward Chaining; systems that implement both are called
- Hybrid Rule Systems. Understanding these two modes of operation is the key
- to understanding why a Production Rule System is different and how to get
- the best from it. Forward chaining is "data-driven" and thus reactionary,
- with facts being asserted into working memory, which results in one or
- more rules being concurrently true and scheduled for execution by the
- Agenda. In short, we start with a fact, it propagates and we end in a
- conclusion. Drools is a forward chaining engine.
-
-
- Forward Chaining
-
-
-
-
-
-
-
-
- Backward chaining is "goal-driven", meaning that we start with a
- conclusion which the engine tries to satisfy. If it can't it then searches
- for conclusions that it can satisfy; these are known as subgoals, that
- will help satisfy some unknown part of the current goal. It continues this
- process until either the initial conclusion is proven or there are no more
- subgoals. Prolog is an example of a Backward Chaining engine; Drools plans
- to provide support for Backward Chaining in a future release.
-
-
- Backward Chaining
-
-
-
-
-
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-Why_use_a_Rule_Engine.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-Why_use_a_Rule_Engine.xml
index b5eaf8b83a..009c8d4dfe 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-Why_use_a_Rule_Engine.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Introduction/Section-Why_use_a_Rule_Engine.xml
@@ -56,12 +56,12 @@
Your data is in your domain objects, the logic is in the rules.
This is fundamentally breaking the OO coupling of data and logic,
which can be an advantage or a disadvantage depending on your point of
- view. The upshot is that the logic can be much easier to maintain as
+ view. The upshot is that the logic can be much easier to maintain when
there are changes in the future, as the logic is all laid out in
rules. This can be especially true if the logic is cross-domain or
multi-domain logic. Instead of the logic being spread across many
domain objects or controllers, it can all be organized in one or more
- very distinct rules files.
+ discrete rules files.
@@ -71,8 +71,7 @@
Drools' ReteOO, provide very efficient ways of matching
rule patterns to your domain object data. These are especially
efficient when you have datasets that change in small portions as the
- rule engine can remember past matches. These algorithms are battle
- proven.
+ rule engine can remember past matches. These algorithms are battle-proven.
@@ -124,7 +123,7 @@
answer, some more explanation is required. The reason why there is no
"traditional" approach is possibly one of the following:
- The problem is just too fiddle for traditional code.
+ The problem is just too fiddly for traditional code.The problem may not be complex, but you can't see a
non-fragile way of building a solution for it.
@@ -158,8 +157,8 @@
very logical. Rules can allow them to express the logic in their own
terms. Of course, they still have to think critically and be capable
of logical thinking. Many people in nontechnical positions do
- not have training in formal logic, so be careful and work with them,
- as by codifying business knowledge in rules, you will often expose
+ not have training in formal logic, so be careful as you work with them:
+ by codifying business knowledge in rules, you will often expose
holes in the way the business rules and processes are currently
understood.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Chapter-JSR94.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Chapter-JSR94.xml
index 543abb8bcc..18b10be517 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Chapter-JSR94.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Chapter-JSR94.xml
@@ -4,12 +4,12 @@
xml:base="./" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
- The Java Rule Engine API
+ The Java Rule Engine API (JSR94)
-
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-How_To_Use.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-HowToUse.xml
old mode 100755
new mode 100644
similarity index 99%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-How_To_Use.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-HowToUse.xml
index deafa2e32d..449d6704fb
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-How_To_Use.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-HowToUse.xml
@@ -16,7 +16,7 @@
The RuleServiceProviderManager manages the registration and
retrieval of RuleServiceProviders. The Drools RuleServiceProvider
implementation is automatically registered via a static block when the
- class is loaded using Class.forNamem, in much the same way as JDBC
+ class is loaded using Class.forName, in much the same way as JDBC
drivers.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-Introduction.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-Introduction.xml
index 46b1db5e5c..6d44035c4a 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-Introduction.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-Introduction.xml
@@ -21,7 +21,7 @@
It should be remembered that the JSR94 standard represents the "least
common denominator" in features across rule engines. This means that
there is less functionality in the JSR94 API than in the standard
- Drools API. So, by using JSR94, you forfeit the advantage of using the
+ Knowledge (Drools and jBPM) API. So, by using JSR94, you forfeit the advantage of using the
full capabilities of the Drools Rule Engine. It is necessary to expose
further functionality, like globals and support for DRL, DSL and XML,
via property maps due to the very basic feature set of JSR94; this
@@ -29,5 +29,5 @@
provide a rule language, you are only solving a small fraction of the
complexity of switching rule engines with very little gain. So, while
we support JSR94, for those that insist on using it, we strongly
- recommend you program against the Drools API.
+ recommend you program against the Knowledge (Drools and jBPM) API.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-Specification.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-Specification.xml
index 4ce56cf69c..07d0b00617 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-Specification.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-JSR94/Section-Specification.xml
@@ -40,7 +40,7 @@
implementation of the Java Rule Engine API will be called the
modifyObject() and
retractObject() methods of the encapsulated
- Drools API.
+ Knowledge (Drools and jBPM) API.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Chapter-Language_Reference.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Chapter-LanguageReference.xml
similarity index 96%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Chapter-Language_Reference.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Chapter-LanguageReference.xml
index 700110129d..c4b4ec08da 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Chapter-Language_Reference.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Chapter-LanguageReference.xml
@@ -4,7 +4,7 @@
xml:base="./" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
- The Rule Language
+ Rule Language Reference
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Comments.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Comments.xml
similarity index 59%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Comments.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Comments.xml
index 7f9fb57bf1..47f6a49185 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Comments.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Comments.xml
@@ -1,9 +1,12 @@
+ xml:base="../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
CommentsComments are sections of text that are ignored by the rule engine.
@@ -13,32 +16,23 @@
Single line comment
-
- Single line comment
-
-
-
-
-
-
-
-
- To create single line comments, you can use either '#' or '//'. The
- parser will ignore anything in the line after the comment symbol.
- Example:
+ To create single line comments, you can use '//'. The parser will
+ ignore anything in the line after the comment symbol. Example:rule "Testing Comments"
when
- # this is a single line comment
- // this is also a single line comment
- eval( true ) # this is a comment in the same line of a pattern
+ // this is a single line comment
+ eval( true ) // this is a comment in the same line of a pattern
then
// this is a comment inside a semantic code block
- # this is another comment in a semantic code block
end
+
+
+ Drools also supports for backward compatibility the use of '#' for
+ single line comments, but this is deprecated and will be removed in
+ future releases.
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-DSL.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-DSL.xml
similarity index 99%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-DSL.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-DSL.xml
index 82045b392f..f06e8dc975 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-DSL.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-DSL.xml
@@ -33,7 +33,7 @@
proper. DSL sentences can also act as "templates" for conditional elements and
consequence actions that are used repeatedly in your rules, possibly with
minor variations. You may define DSL sentences as being mapped to these
- repeated phrases, with parameters providing a means for accomodating those
+ repeated phrases, with parameters providing a means for accommodating those
variations.DSLs have no impact on the rule engine at runtime, they are just a
@@ -327,7 +327,7 @@ There is a person with name of "Bob" and Person is at least 30 years old and liv
with any number of embedded variable definitions,
terminated by an equal sign ("="). A variable definition is enclosed
in braces ("{" and "}"). It
- consists of a variable name and two optional attachements, separated
+ consists of a variable name and two optional attachments, separated
by colons (":"). If there is one attachment, it is a regular expression
for matching text that is to be assigned to the variable; if there
are two attachments, the first one is a hint for the GUI
@@ -414,7 +414,7 @@ There is a person with name of "Bob" and Person is at least 30 years old and liv
# conditional element: "T" or "t", "a" or "an", convert matched word
[when][][Tt]here is an? {entity:\w+}=
- ${entity!lc}: ${entity!ucfirst} ()
+ ${entity!lc}: {entity!ucfirst} ()
# consequence statement: convert matched word, literal braces
[then][]update {entity:\w+}=modify( ${entity!lc} )\{ \}
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-ErrorMessages.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-ErrorMessages.xml
similarity index 83%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-ErrorMessages.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-ErrorMessages.xml
index 1daaff7d73..c706691ef2 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-ErrorMessages.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-ErrorMessages.xml
@@ -1,15 +1,14 @@
+ xml:base="../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
Error Messages
-
- (updated to Drools 5.0)
-
-
Drools 5 introduces standardized error messages. This standardization
aims to help users to find and resolve problems in a easier and faster way.
In this section you will learn how to identify and interpret those error
@@ -58,7 +57,7 @@
101: No viable alternativeIndicates the most common errors, where the parser came to a
- decision point but couldn't identify an alternative. Here are some
+ decision point but couldn't identify an alternative. Here are some
examples:
@@ -80,8 +79,8 @@
- At first glance this seems to be valid syntax, but it is not (exits
- != exists). Let's take a look at next example:
+ At first glance this seems to be valid syntax, but it is not
+ (exits != exists). Let's take a look at next example:1: package org.drools;
@@ -103,12 +102,12 @@
- This message means that the parser encountered the token
- WHEN, actually a hard keyword, but
- it's in the wrong place since the the rule name is missing.
+ This message means that the parser encountered the token WHEN, actually a hard keyword, but it's in the
+ wrong place since the the rule name is missing.
- The error "no viable alternative" also occurs when you make
- a simple lexical mistake. Here is a sample of a lexical problem:
+ The error "no viable alternative" also occurs when you make a
+ simple lexical mistake. Here is a sample of a lexical problem:1: rule simple_rule
@@ -117,7 +116,9 @@
4: then
5: end
-
+
+
+
The above code misses to close the quotes and because of this the
parser generates this error message:
@@ -132,8 +133,8 @@
Usually the Line and Column information are accurate, but in
some cases (like unclosed quotes), the parser generates a 0:-1
- position. In this case you should check whether you didn't forget to close
- quotes, apostrophes or parentheses.
+ position. In this case you should check whether you didn't forget to
+ close quotes, apostrophes or parentheses.
@@ -141,7 +142,7 @@
102: Mismatched inputThis error indicates that the parser was looking for a particular
- symbol that it didn’t find at the current input position. Here are some
+ symbol that it didn't find at the current input position. Here are some
samples:
@@ -205,8 +206,8 @@
just replace the commas (',') by AND operator ('&&').
- In some situations you can get more than one error message. Try to
- fix one by one, starting at the first one. Some error messages are
+ In some situations you can get more than one error message. Try
+ to fix one by one, starting at the first one. Some error messages are
generated merely as consequences of other errors.
@@ -247,7 +248,8 @@
The fdsfdsfds text is invalid and
- the parser couldn’t identify it as the soft keyword rule.
+ the parser couldn't identify it as the soft keyword
+ rule.
This error is very similar to 102: Mismatched input, but usually
@@ -258,9 +260,9 @@
104: Trailing semi-colon not allowed
- This error is associated with the eval clause, where its
- expression may not be terminated with a semicolon. Check this
- example:
+ This error is associated with the eval clause,
+ where its expression may not be terminated with a semicolon. Check this
+ example:1: rule simple_rule
@@ -281,8 +283,7 @@
- This problem is simple to fix: just remove the
- semi-colon.
+ This problem is simple to fix: just remove the semi-colon.
@@ -290,8 +291,8 @@
The recognizer came to a subrule in the grammar that must match an
alternative at least once, but the subrule did not match anything.
- Simply put: the parser has entered a branch from where there is no
- way out. This example illustrates it:
+ Simply put: the parser has entered a branch from where there is no way
+ out. This example illustrates it:1: template test_error
@@ -309,16 +310,16 @@
- To fix this problem it is necessary to remove the numeric value
- as it is neither a valid data type which might begin a new template
- slot nor a possible start for any other rule file construct.
+ To fix this problem it is necessary to remove the numeric value as
+ it is neither a valid data type which might begin a new template slot
+ nor a possible start for any other rule file construct.Other Messages
- Any other message means that something bad has happened, so
- please contact the development team.
+ Any other message means that something bad has happened, so please
+ contact the development team.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Function.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Function.xml
similarity index 100%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Function.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Function.xml
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Keywords.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Keywords.xml
new file mode 100644
index 0000000000..3632ef4d1d
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Keywords.xml
@@ -0,0 +1,218 @@
+
+
+ Keywords
+
+ Drools 5 introduces the concept of hard and
+ soft keywords.
+
+ Hard keywords are reserved, you cannot use any hard keyword when
+ naming your domain objects, properties, methods, functions and other
+ elements that are used in the rule text.
+
+ Here is the list of hard keywords that must be avoided as identifiers
+ when writing rules:
+
+
+
+ true
+
+
+
+ false
+
+
+
+ null
+
+
+
+ Soft keywords are just recognized in their context, enabling you to
+ use these words in any other place if you wish, although, it is still
+ recommended to avoid them, to avoid confusions, if possible. Here is a list
+ of the soft keywords:
+
+
+
+ lock-on-active
+
+
+
+ date-effective
+
+
+
+ date-expires
+
+
+
+ no-loop
+
+
+
+ auto-focus
+
+
+
+ activation-group
+
+
+
+ agenda-group
+
+
+
+ ruleflow-group
+
+
+
+ entry-point
+
+
+
+ duration
+
+
+
+ package
+
+
+
+ import
+
+
+
+ dialect
+
+
+
+ salience
+
+
+
+ enabled
+
+
+
+ attributes
+
+
+
+ rule
+
+
+
+ extend
+
+
+
+ when
+
+
+
+ then
+
+
+
+ template
+
+
+
+ query
+
+
+
+ declare
+
+
+
+ function
+
+
+
+ global
+
+
+
+ eval
+
+
+
+ not
+
+
+
+ in
+
+
+
+ or
+
+
+
+ and
+
+
+
+ exists
+
+
+
+ forall
+
+
+
+ accumulate
+
+
+
+ collect
+
+
+
+ from
+
+
+
+ action
+
+
+
+ reverse
+
+
+
+ result
+
+
+
+ end
+
+
+
+ over
+
+
+
+ init
+
+
+
+ Of course, you can have these (hard and soft) words as part of a
+ method name in camel case, like notSomething() or accumulateSomething() -
+ there are no issues with that scenario.
+
+ Although the 3 hard keywords above are unlikely to be used in your
+ existing domain models, if you absolutely need to use them as identifiers
+ instead of keywords, the DRL language provides the ability to escape hard
+ keywords on rule text. To escape a word, simply enclose it in grave accents,
+ like this:
+
+ Holiday( `true` == "yes" ) // please note that Drools will resolve that reference to the method Holiday.isTrue()
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Overview.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Overview.xml
similarity index 100%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Overview.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Overview.xml
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Package.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Package.xml
similarity index 98%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Package.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Package.xml
index d8e98a1ec8..159196ac33 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Package.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Package.xml
@@ -40,7 +40,7 @@
- Notice that any rule atttribute (as described the section Rule Attributes)
+ Notice that any rule attribute (as described the section Rule Attributes)
may also be written at package level, superseding the attribute's default value.
The modified default may still be replaced by an attribute setting within
a rule.
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Query.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Query.xml
new file mode 100644
index 0000000000..fd3e4779a8
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Query.xml
@@ -0,0 +1,173 @@
+
+
+ Query
+
+
+ query
+
+
+
+
+
+
+
+
+ A query is a simple way to search the working memory for facts that
+ match the stated conditions. Therefore, it contains only the structure of
+ the LHS of a rule, so that you specify neither "when" nor "then". A query
+ has an optional set of parameters, each of which can be optionally typed. If
+ the type is not given, the type Object is assumed. The engine will attempt
+ to coerce the values as needed. Query names are global to the KnowledgeBase;
+ so do not add queries of the same name to different packages for the same
+ RuleBase.
+
+ To return the results use
+ ksession.getQueryResults("name"), where "name" is the query's
+ name. This returns a list of query results, which allow you to retrieve the
+ objects that matched the query.
+
+ The first example presents a simple query for all the people over the
+ age of 30. The second one, using parameters, combines the age limit with a
+ location.
+
+
+ Query People over the age of 30
+
+ query "people over the age of 30"
+ person : Person( age > 30 )
+end
+
+
+
+ Query People over the age of x, and who live in y
+
+ query "people over the age of x" (int x, String y)
+ person : Person( age > x, location == y )
+end
+
+
+ We iterate over the returned QueryResults using a standard "for" loop.
+ Each element is a QueryResultsRow which we can use to access each of the
+ columns in the tuple. These columns can be accessed by bound declaration
+ name or index position.
+
+
+ Query People over the age of 30
+
+ QueryResults results = ksession.getQueryResults( "people over the age of 30" );
+System.out.println( "we have " + results.size() + " people over the age of 30" );
+
+System.out.println( "These people are are over 30:" );
+
+for ( QueryResultsRow row : results ) {
+ Person person = ( Person ) row.get( "person" );
+ System.out.println( person.getName() + "\n" );
+}
+
+
+ Support for positional syntax has been added for more compact code. By
+ default the declared type order in the type declaration matches the argument
+ position. But it possible to override these using the @position annotation.
+ This allows patterns to be used with positional arguments, instead of the
+ more verbose named arguments.
+
+ declare Cheese
+ name : String @position(1)
+ shop : String @position(2)
+ price : int @position(0)
+end
+
+
+ The @Position annotation, in the org.drools.definition.type package,
+ can be used to annotate original pojos on the classpath. Currently only
+ fields on classes can be annotated. Inheritance of classes is supported, but
+ not interfaces or methods. The isContainedIn query below demonstrates the
+ use of positional arguments in a pattern; Location(x, y;)
+ instead of Location( thing == x, location == y).
+
+ Queries can now call other queries, this combined with optional query
+ arguments provides derivation query style backward chaining. Positional and
+ named syntax is supported for arguments. It is also possible to mix both
+ positional and named, but positional must come first, separated by a semi
+ colon. Literal expressions can be passed as query arguments, but at this
+ stage you cannot mix expressions with variables. Here is an example of a
+ query that calls another query. Note that 'z' here will always be an 'out'
+ variable. The '?' symbol means the query is pull only, once the results are
+ returned you will not receive further results as the underlying data
+ changes.
+
+ declare Location
+ thing : String
+ location : String
+end
+
+query isContainedIn( String x, String y )
+ Location(x, y;)
+ or
+ ( Location(z, y;) and ?isContainedIn(x, z;) )
+end
+
+ As previously mentioned you can use live "open" queries to reactively
+ receive changes over time from the query results, as the underlying data it
+ queries against changes. Notice the "look" rule calls the query without
+ using '?'.
+
+ query isContainedIn( String x, String y )
+ Location(x, y;)
+ or
+ ( Location(z, y;) and isContainedIn(x, z;) )
+end
+
+rule look when
+ Person( $l : likes )
+ isContainedIn( $l, 'office'; )
+then
+ insertLogical( $l 'is in the office' );
+end
+
+
+ Drools supports unification for derivation queries, in short this
+ means that arguments are optional. It is possible to call queries from java
+ leaving arguments unspecified using the static field
+ org.drools.runtime.rule.Variable.v - note you must use 'v' and not an
+ alternative instance of Variable. These are referred to as 'out' arguments.
+ Note that the query itself does not declare at compile time whether an
+ argument is in or an out, this can be defined purely at runtime on each use.
+ The following example will return all objects contained in the
+ office.
+
+ results = ksession.getQueryResults( "isContainedIn", new Object[] { Variable.v, "office" } );
+l = new ArrayList<List<String>>();
+for ( QueryResultsRow r : results ) {
+ l.add( Arrays.asList( new String[] { (String) r.get( "x" ), (String) r.get( "y" ) } ) );
+}
+
+
+ The algorithm uses stacks to handle recursion, so the method stack
+ will not blow up.
+
+ The following is not yet supported:
+
+
+
+ List and Map unification
+
+
+
+ Variables for the fields of facts
+
+
+
+ Expression unification - pred( X, X + 1, X * Y / 7 )
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Rule.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Rule.xml
new file mode 100644
index 0000000000..62a5fabf18
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-Rule.xml
@@ -0,0 +1,3463 @@
+
+
+ Rule
+
+
+ rule
+
+
+
+
+
+
+
+
+ A rule specifies that when a particular set of
+ conditions occur, specified in the Left Hand Side (LHS),
+ then do what queryis specified as a list of actions in
+ the Right Hand Side (RHS). A common question from users is "Why use when
+ instead of if?" "When" was chosen over "if" because "if" is normally part of
+ a procedural execution flow, where, at a specific point in time, a condition
+ is to be checked. In contrast, "when" indicates that the condition
+ evaluation is not tied to a specific evaluation sequence or point in time,
+ but that it happens continually, at any time during the life time of the
+ engine; whenever the condition is met, the actions are executed.
+
+ A rule must have a name, unique within its rule package. If you define
+ a rule twice in the same DRL it produces an error while loading. If you add
+ a DRL that includes a rule name already in the package, it replaces the
+ previous rule. If a rule name is to have spaces, then it will need to be
+ enclosed in double quotes (it is best to always use double quotes).
+
+ Attributes - described below - are optional. They are best written one
+ per line.
+
+ The LHS of the rule follows the when keyword
+ (ideally on a new line), similarly the RHS follows the
+ then keyword (again, ideally on a newline). The rule is
+ terminated by the keyword end. Rules cannot be
+ nested.
+
+
+ Rule Syntax Overview
+
+ rule "<name>"
+ <attribute>*
+when
+ <conditional element>*
+then
+ <action>*
+end
+
+
+
+ A simple rule
+
+ rule "Approve if not rejected"
+ salience -100
+ agenda-group "approval"
+ when
+ not Rejection()
+ p : Policy(approved == false, policyState:status)
+ exists Driver(age > 25)
+ Process(status == policyState)
+ then
+ log("APPROVED: due to no objections.");
+ p.setApproved(true);
+end
+
+
+
+ Rule Attributes
+
+ Rule attributes provide a declarative way to influence the behavior
+ of the rule. Some are quite simple, while others are part of complex
+ subsystems such as ruleflow. To get the most from Drools you should make
+ sure you have a proper understanding of each attribute.
+
+
+ rule attributes
+
+
+
+
+
+
+
+
+
+
+ no-loop
+
+
+ default value: false
+
+ type: Boolean
+
+ When a rule's consequence modifies a fact it may cause the
+ rule to activate again, causing an infinite loop. Setting no-loop to
+ true will skip the creation of another Activation for the rule with
+ the current set of facts.
+
+
+
+
+ ruleflow-group
+
+
+ default value: N/A
+
+ type: String
+
+ Ruleflow is a Drools feature that lets you exercise control
+ over the firing of rules. Rules that are assembled by the same
+ ruleflow-group identifier fire only when their group is
+ active.
+
+
+
+
+ lock-on-active
+
+
+ default value: false
+
+ type: Boolean
+
+ Whenever a ruleflow-group becomes active or an agenda-group
+ receives the focus, any rule within that group that has
+ lock-on-active set to true will not be activated any more;
+ irrespective of the origin of the update, the activation of a
+ matching rule is discarded. This is a stronger version of no-loop,
+ because the change could now be caused not only by the rule itself.
+ It's ideal for calculation rules where you have a number of rules
+ that modify a fact and you don't want any rule re-matching and
+ firing again. Only when the ruleflow-group is no longer active or
+ the agenda-group loses the focus those rules with lock-on-active set
+ to true become eligible again for their activations to be placed
+ onto the agenda.
+
+
+
+
+ salience
+
+
+ default value: 0
+
+ type: integer
+
+ Each rule has an integer salience attribute which defaults to
+ zero and can be negative or positive. Salience is a form of priority
+ where rules with higher salience values are given higher priority
+ when ordered in the Activation queue.
+
+ Drools also supports dynamic salience where you can use an
+ expression involving bound variables.
+
+
+ Dynamic Salience
+
+ rule "Fire in rank order 1,2,.."
+ salience( -$rank )
+ when
+ Element( $rank : rank,... )
+ then
+ ...
+end
+
+
+
+
+
+ agenda-group
+
+
+ default value: MAIN
+
+ type: String
+
+ Agenda groups allow the user to partition the Agenda providing
+ more execution control. Only rules in the agenda group that has
+ acquired the focus are allowed to fire.
+
+
+
+
+ auto-focus
+
+
+ default value: false
+
+ type: Boolean
+
+ When a rule is activated where the auto-focus
+ value is true and the rule's agenda group does not have focus yet,
+ then it is given focus, allowing the rule to potentially
+ fire.
+
+
+
+
+ activation-group
+
+
+ default value: N/A
+
+ type: String
+
+ Rules that belong to the same activation-group, identified by
+ this attribute's string value, will only fire exclusively. In other
+ words, the first rule in an activation-group to fire will cancel the
+ other rules' activations, i.e., stop them from firing.
+
+ Note: This used to be called Xor group, but technically it's
+ not quite an Xor. You may still hear people mention Xor group; just
+ swap that term in your mind with activation-group.
+
+
+
+
+ dialect
+
+
+ default value: as specified by the package
+
+ type: String
+
+ possible values: "java" or "mvel"
+
+ The dialect species the language to be used for any code
+ expressions in the LHS or the RHS code block. Currently two dialects
+ are available, Java and MVEL. While the dialect can be specified at
+ the package level, this attribute allows the package definition to
+ be overridden for a rule.
+
+
+
+
+ date-effective
+
+
+ default value: N/A
+
+ type: String, containing a date and time definition
+
+ A rule can only activate if the current date and time is after
+ date-effective attribute.
+
+
+
+
+ date-expires
+
+
+ default value: N/A
+
+ type: String, containing a date and time definition
+
+ A rule cannot activate if the current date and time is after
+ the date-expires attribute.
+
+
+
+
+ duration
+
+
+ default value: no default value
+
+ type: long
+
+ The duration dictates that the rule will fire after a
+ specified duration, if it is still true.
+
+
+
+
+
+ Some attribute examples
+
+ rule "my rule"
+ salience 42
+ agenda-group "number 1"
+ when ...
+
+
+
+
+ Timers and Calendars
+
+ Rules now support both interval and cron based timers, which replace
+ the now deprecated duration attribute.
+
+
+ Sample timer attribute uses
+
+ timer ( int: <initial delay> <repeat interval>? )
+timer ( int: 30s )
+timer ( int: 30s 5m )
+
+timer ( cron: <cron expression> )
+timer ( cron:* 0/15 * * * ? )
+
+
+ Interval (indicated by "int:") timers follow the semantics of
+ java.util.Timer objects, with an initial delay and an optional repeat
+ interval. Cron (indicated by "cron:") timers follow standard Unix cron
+ expressions:
+
+
+ A Cron Example
+
+ rule "Send SMS every 15 minutes"
+ timer (cron:* 0/15 * * * ?)
+when
+ $a : Alarm( on == true )
+then
+ channels[ "sms" ].insert( new Sms( $a.mobileNumber, "The alarm is still on" );
+end
+
+
+ Calendars are used to control when rules can fire. The Calendar API
+ is modelled on Quartz:
+
+
+ Adapting a Quartz Calendar
+
+ Calendar weekDayCal = QuartzHelper.quartzCalendarAdapter(org.quartz.Calendar quartzCal)
+
+
+ Calendars are registered with the StatefulKnowledgeSession:
+
+
+ Registering a Calendar
+
+ ksession.getCalendars().set( "weekday", weekDayCal );
+
+
+ They can be used in conjunction with normal rules and rules
+ including timers. The rule attribute "calendars" may contain one or more
+ comma-separated calendar names written as string literals.
+
+
+ Using Calendars and Timers together
+
+ rule "weekdays are high priority"
+ calendars "weekday"
+ timer (int:0 1h)
+when
+ Alarm()
+then
+ send( "priority high - we have an alarm” );
+end
+
+rule "weekend are low priority"
+ calendars "weekend"
+ timer (int:0 4h)
+when
+ Alarm()
+then
+ send( "priority low - we have an alarm” );
+end
+
+
+
+
+ Left Hand Side (when) syntax
+
+
+ What is the Left Hand Side?
+
+ The Left Hand Side (LHS) is a common name for the conditional part
+ of the rule. It consists of zero or more Conditional Elements. If the
+ LHS is empty, it will be considered as a condition element that is
+ always true and it will be activated once, when a new WorkingMemory
+ session is created.
+
+
+ Left Hand Side
+
+
+
+
+
+
+
+
+
+ Rule without a Conditional Element
+
+ rule "no CEs"
+when
+ // empty
+then
+ ... // actions (executed once)
+end
+
+// The above rule is internally rewritten as:
+
+rule "eval(true)"
+when
+ eval( true )
+then
+ ... // actions (executed once)
+end
+
+
+ Conditional elements work on one or more
+ patterns (which are described below). The most
+ common conditional element is "and". Therefore it is
+ implicit when you have multiple patterns in the LHS of a rule that are
+ not connected in any way:
+
+
+ Implicit and
+
+ rule "2 unconnected patterns"
+when
+ Pattern1()
+ Pattern2()
+then
+ ... // actions
+end
+
+// The above rule is internally rewritten as:
+
+rule "2 and connected patterns"
+when
+ Pattern1()
+ and Pattern2()
+then
+ ... // actions
+end
+
+
+
+ An "and" cannot have a leading declaration
+ binding (unlike for example or). This is obvious,
+ since a declaration can only reference a single fact at a time, and
+ when the "and" is satisfied it matches both facts -
+ so which fact would the declaration bind to?
+
+ // Compile error
+$person : (Person( name == "Romeo" ) and Person( name == "Juliet"))
+
+
+
+
+ Pattern (conditional element)
+
+
+ What is a pattern?
+
+ A pattern element is the most important Conditional Element. It
+ can potentially match on each fact that is inserted in the working
+ memory.
+
+ A pattern contains of zero or more constraints and has an
+ optional pattern binding. The railroad diagram below shows the syntax
+ for this.
+
+
+ Pattern
+
+
+
+
+
+
+
+
+ In its simplest form, with no constraints, a pattern matches
+ against a fact of the given type. In the following case the type is
+ Cheese, which means that the pattern will match against
+ all Person objects in the Working Memory:
+
+ Person()
+
+ The type need not be the actual class of some fact object.
+ Patterns may refer to superclasses or even interfaces, thereby
+ potentially matching facts from many different classes.
+
+ Object() // matches all objects in the working memory
+
+ Inside of the pattern parenthesis is where all the action
+ happens: it defines the constraints for that pattern. For example,
+ with a age related constraint:
+
+ Person( age == 100 )
+
+
+ For backwards compatibility reasons it's allowed to suffix
+ patterns with the ; character. But it is not
+ recommended to do that.
+
+
+
+
+ Pattern binding
+
+ For referring to the matched object, use a pattern binding
+ variable such as $p.
+
+
+ Pattern with a binding variable
+
+ rule ...
+when
+ $p : Person()
+then
+ System.out.println( "Person " + $p );
+end
+
+
+ The prefixed dollar symbol ($) is just a
+ convention; it can be useful in complex rules where it helps to easily
+ differentiate between variables and fields, but it is not
+ mandatory.
+
+
+
+
+ Constraint (part of a pattern)
+
+
+ What is a constraint?
+
+ A constraint is an expression that returns
+ true or false. This example has
+ a constraint that states 5 is smaller than
+ 6:
+
+ Person( 5 < 6 ) // just an example, as constraints like this would be useless in a real pattern
+
+ In essence, it's a Java expression with some enhancements (such
+ as property access) and a few differences (such as
+ equals() semantics for ==).
+ Let's take a deeper look.
+
+
+
+ Property access on Java Beans (POJO's)
+
+ Any bean property can be used directly. A bean property is
+ exposed using a standard Java bean getter: a method
+ getMyProperty() (or
+ isMyProperty() for a primitive boolean) which takes
+ no arguments and return something. For example: the age property is
+ written as age in DRL instead of the getter
+ getAge():
+
+ Person( age == 50 )
+
+// this is the same as:
+Person( getAge() == 50 )
+
+ Drools uses the standard JDK Introspector
+ class to do this mapping, so it follows the standard Java bean
+ specification.
+
+
+ We recommend using property access (age)
+ over using getters explicitly (getAge()) because
+ of performance enhancements through field indexing.
+
+
+
+ Property accessors must not change the state of the object in
+ a way that may effect the rules. Remember that the rule engine
+ effectively caches the results of its matching in between
+ invocations to make it faster.
+
+ public int getAge() {
+ age++; // Do NOT do this
+ return age;
+}
+
+ public int getAge() {
+ Date now = DateUtil.now(); // Do NOT do this
+ return DateUtil.differenceInYears(now, birthday);
+}
+
+ To solve this latter case, insert a fact that wraps the
+ current date into working memory and update that fact between
+ fireAllRules as needed.
+
+
+
+ The following fallback applies: if the getter of a property
+ cannot be found, the compiler will resort to using the property name
+ as a method name and without arguments:
+
+ Person( age == 50 )
+
+// If Person.getAge() does not exists, this falls back to:
+Person( age() == 50 )
+
+
+ Nested property access is also supported:
+
+ Person( address.houseNumber == 50 )
+
+// this is the same as:
+Person( getAddress().getHouseNumber() == 50 )
+
+ Nested properties are also indexed.
+
+
+ In a stateful session, care should be taken when using nested
+ accessors as the Working Memory is not aware of any of the nested
+ values, and does not know when they change. Either consider them
+ immutable while any of their parent references are inserted into the
+ Working Memory. Or, instead, if you wish to modify a nested value
+ you should mark all of the outer facts as updated. In the above
+ example, when the houseNumber changes, any
+ Person with that Address must
+ be marked as updated.
+
+
+
+
+ Java expression
+
+ You can use any Java expression that returns a
+ boolean as a constraint inside the parentheses of a
+ pattern. Java expressions can be mixed with other expression
+ enhancements, such as property access:
+
+ Person( age == 50 )
+
+ It is possible to change the evaluation priority by using
+ parentheses, as in any logic or mathematical expression:
+
+ Person( age > 100 && ( age % 10 == 0 ) )
+
+ It is possible to reuse Java methods:
+
+ Person( Math.round( weight / ( height * height ) ) < 25.0 )
+
+
+ As for property accessors, methods must not change the state
+ of the object in a way that may affect the rules. Any method
+ executed on a fact in the LHS should be a read
+ only method.
+
+ Person( incrementAndGetAge() == 10 ) // Do NOT do this
+
+
+
+ The state of a fact should not change between rule invocations
+ (unless those facts are marked as updated to the working memory on
+ every change):
+
+ Person( System.currentTimeMillis() % 1000 == 0 ) // Do NOT do this
+
+
+ Normal Java operator precedence applies, see the operator
+ precedence list below.
+
+
+ All operators have normal Java semantics except for
+ == and !=.
+
+ The == operator has null-safe
+ equals() semantics:
+
+ // Similar to: java.util.Objects.equals(person.getFirstName(), "John")
+// so (because "John" is not null) similar to:
+// "John".equals(person.getFirstName())
+Person( firstName == "John" )
+
+ The != operator has null-safe
+ !equals() semantics:
+
+ // Similar to: !java.util.Objects.equals(person.getFirstName(), "John")
+Person( firstName != "John" )
+
+
+ Type coercion is always attempted if the field and the value are
+ of different types; exceptions will be thrown if a bad coercion is
+ attempted. For instance, if "ten" is provided as a string in a numeric
+ evaluator, an exception is thrown, whereas "10" would coerce to a
+ numeric 10. Coercion is always in favor of the field type and not the
+ value type:
+
+ Person( age == "10" ) // "10" is coerced to 10
+
+
+
+ Comma separated AND
+
+ The comma character (',') is used to separate
+ constraint groups. It has implicit AND connective
+ semantics.
+
+ // Person is at least 50 and weighs at least 80 kg
+Person( age > 50, weight > 80 )
+
+ // Person is at least 50, weighs at least 80 kg and is taller than 2 meter.
+Person( age > 50, weight > 80, height > 2 )
+
+
+ Although the && and
+ , operators have the same semantics, they are
+ resolved with different priorities: The
+ && operator precedes the
+ || operator. Both the
+ && and || operator
+ precede the , operator. See the operator
+ precedence list below.
+
+ The comma operator should be preferred at the top level
+ constraint, as it makes constraints easier to read and the engine
+ will often be able to optimize them better.
+
+
+ The comma (,) operator cannot be embedded in
+ a composite constraint expression, such as parentheses:
+
+ Person( ( age > 50, weight > 80 ) || height > 2 ) // Do NOT do this: compile error
+
+// Use this instead
+Person( ( age > 50 && weight > 80 ) || height > 2 )
+
+
+
+ Binding variables
+
+ A property can be bound to a variable:
+
+ // 2 persons of the same age
+Person( $firstAge : age ) // binding
+Person( age == $firstAge ) // constraint expression
+
+ The prefixed dollar symbol ($) is just a
+ convention; it can be useful in complex rules where it helps to easily
+ differentiate between variables and fields.
+
+
+ For backwards compatibility reasons, It's allowed (but not
+ recommended) to mix a constraint binding and constraint expressions
+ as such:
+
+ // Not recommended
+Person( $age : age * 2 < 100 )
+
+ // Recommended (separates bindings and constraint expressions)
+Person( age * 2 < 100, $age : age )
+
+
+ Bound variable restrictions using the operator
+ == provide for very fast execution as it use hash
+ indexing to improve performance.
+
+
+
+ Unification
+
+ Drools does not allow bindings to the same declaration. However
+ this is an important aspect to derivation query unification. While
+ positional arguments are always processed with unification a special
+ unification symbol, ':=', was introduced for named arguments named
+ arguments. The following "unifies" the age argument across two
+ people.
+
+ Person( $age := age )
+Person( $age := age)
+
+ In essence unification will declare a binding for the first
+ occurrence and constrain to the same value of the bound field for
+ sequence occurrences.
+
+
+
+ Special literal support
+
+ Besides normal Java literals (including Java 5 enums), this
+ literal is also supported:
+
+
+ Date literal
+
+ The date format dd-mmm-yyyy is supported by
+ default. You can customize this by providing an alternative date
+ format mask as the System property named
+ drools.dateformat. If more control is required, use a
+ restriction.
+
+
+ Date Literal Restriction
+
+ Cheese( bestBefore < "27-Oct-2009" )
+
+
+
+
+
+ List and Map access
+
+ It's possible to directly access a List value
+ by index:
+
+ // Same as childList(0).getAge() == 18
+Person( childList[0].age == 18 )
+
+ It's also possible to directly access a Map
+ value by key:
+
+ // Same as credentialMap.get("jsmith").isValid()
+Person( credentialMap["jsmith"].valid )
+
+
+
+ Abbreviated combined relation condition
+
+ This allows you to place more than one restriction on a field
+ using the restriction connectives && or
+ ||. Grouping via parentheses is permitted,
+ resulting in a recursive syntax pattern.
+
+
+ Abbreviated combined relation condition
+
+
+
+
+
+
+
+
+
+ Abbreviated combined relation condition with
+ parentheses
+
+
+
+
+
+
+
+
+ // Simple abbreviated combined relation condition using a single &&
+Person( age > 30 && < 40 )
+
+ // Complex abbreviated combined relation using groupings
+Person( age ( (> 30 && < 40) ||
+ (> 20 && < 25) ) )
+
+ // Mixing abbreviated combined relation with constraint connectives
+Person( age > 30 && < 40 || location == "london" )
+
+
+
+ Special DRL operators
+
+
+ Operators
+
+
+
+
+
+
+
+
+ Coercion to the correct value for the evaluator and the field
+ will be attempted.
+
+
+ The operators <
+ <=>
+ >=
+
+ These operators can be used on properties with natural
+ ordering. For example, for Date fields, <
+ means before, for String
+ fields, it means alphabetically lower.
+
+ Person( firstName < $otherFirstName )
+
+ Person( birthDate < $otherBirthDate )
+
+ Only applies on Comparable
+ properties.
+
+
+
+ The operator matches
+
+ Matches a field against any valid Java
+ regular expression
+ Regular Expression. Typically that regexp is a string
+ literal, but variables that resolve to a valid regexp are also
+ allowed.
+
+
+ Regular Expression Constraint
+
+ Cheese( type matches "(Buffalo)?\\S*Mozarella" )
+
+
+
+ Like in Java, regular expressions written as string literals
+ need to escape '\'.
+
+
+ Only applies on String properties.
+ Using matches against a null value
+ always evaluates to false.
+
+
+
+ The operator not matches
+
+ The operator returns true if the String does not match the
+ regular expression. The same rules apply as for the
+ matches operator. Example:
+
+
+ Regular Expression Constraint
+
+ Cheese( type not matches "(Buffulo)?\\S*Mozarella" )
+
+
+ Only applies on String properties.
+ Using not matches against a null value
+ always evaluates to true.
+
+
+
+ The operator contains
+
+ The operator contains is used to check
+ whether a field that is a
+ Collection
+ Collection or array contains the specified
+ value.
+
+
+ Contains with Collections
+
+ CheeseCounter( cheeses contains "stilton" ) // contains with a String literal
+CheeseCounter( cheeses contains $var ) // contains with a variable
+
+
+ Only applies on Collection
+ properties.
+
+
+
+ The operator not contains
+
+ The operator not contains is used to check
+ whether a field that is a
+ Collection
+ Collection or array does not
+ contain the specified value.
+
+
+ Literal Constraint with Collections
+
+ CheeseCounter( cheeses not contains "cheddar" ) // not contains with a String literal
+CheeseCounter( cheeses not contains $var ) // not contains with a variable
+
+
+ Only applies on Collection
+ properties.
+
+
+
+ For backward compatibility, the
+ excludes operator is supported as a synonym
+ for not contains.
+
+
+
+
+
+ The operator memberOf
+
+ The operator memberOf is used to check
+ whether a field is a member of a collection or array; that
+ collection must be a variable.
+
+
+ Literal Constraint with Collections
+
+ CheeseCounter( cheese memberOf $matureCheeses )
+
+
+
+
+ The operator not memberOf
+
+ The operator not memberOf is used to check
+ whether a field is not a member of a collection or array; that
+ collection must be a variable.
+
+
+ Literal Constraint with Collections
+
+ CheeseCounter( cheese not memberOf $matureCheeses )
+
+
+
+
+ The operator soundslike
+
+ This operator is similar to matches, but it
+ checks whether a word has almost the same sound (using English
+ pronunciation) as the given value. This is based on the Soundex
+ algorithm (see
+ http://en.wikipedia.org/wiki/Soundex).
+
+
+ Test with soundslike
+
+ // match cheese "fubar" or "foobar"
+Cheese( name soundslike 'foobar' )
+
+
+
+
+ The operator str
+
+ This operator str is used to check whether
+ a field that is a String starts with or ends with
+ a certain value. It can also be used to check the length of the
+ String.
+
+ Message( routingValue str[startsWith] "R1" )
+
+ Message( routingValue str[endsWith] "R2" )
+
+ Message( routingValue str[length] 17 )
+
+
+
+ The operators in and not
+ in (compound value restriction)
+
+ The compound value restriction is used where there is more
+ than one possible value to match. Currently only the
+ in and not in evaluators
+ support this. The second operand of this operator must be a
+ comma-separated list of values, enclosed in parentheses. Values may
+ be given as variables, literals, return values or qualified
+ identifiers. Both evaluators are actually syntactic
+ sugar, internally rewritten as a list of multiple
+ restrictions using the operators != and
+ ==.
+
+
+ compoundValueRestriction
+
+
+
+
+
+
+
+
+
+ Compound Restriction using "in"
+
+ Person( $cheese : favouriteCheese )
+Cheese( type in ( "stilton", "cheddar", $cheese ) )
+
+
+
+
+
+ Inline eval operator (deprecated)
+
+
+ Inline Eval Expression
+
+
+
+
+
+
+
+
+ An
+ Predicate
+ inline eval constraint can use any valid dialect
+ expression as long as it results to a primitive boolean. The
+ expression must be constant over time. Any previously bound variable,
+ from the current or previous pattern, can be used; autovivification is
+ also used to auto-create field binding variables. When an identifier
+ is found that is not a current variable, the builder looks to see if
+ the identifier is a field on the current object type, if it is, the
+ field binding is auto-created as a variable of the same name. This is
+ called autovivification of field variables inside of inline
+ eval's.
+
+ This example will find all male-female pairs where the male is 2
+ years older than the female; the variable age is
+ auto-created in the second pattern by the autovivification
+ process.
+
+
+ Return Value operator
+
+ Person( girlAge : age, sex = "F" )
+Person( eval( age == girlAge + 2 ), sex = 'M' ) // eval() is actually obsolete in this example
+
+
+
+ Inline eval's are effectively obsolete as their inner syntax
+ is now directly supported. It's recommended not to use them. Simply
+ write the expression without wrapping eval() around it.
+
+
+
+
+ Operator precedence
+
+ The operators are evaluated in this precedence:
+
+
+
+
+
+
+ Positional Arguments
+
+ Patterns now support positional arguments on type
+ declarations.
+
+ Positional arguments are ones where you don't need to specify the
+ field name, as the position maps to a known named field. i.e. Person(
+ name == "mark" ) can be rewritten as Person( "mark"; ). The semicolon
+ ';' is important so that the engine knows that everything before it is a
+ positional argument. Otherwise we might assume it was a boolean
+ expression, which is how it could be interpreted after the semicolon.
+ You can mix positional and named arguments on a pattern by using the
+ semicolon ';' to separate them. Any variables used in a positional that
+ have not yet been bound will be bound to the field that maps to that
+ position.
+
+ declare Cheese
+ name : String
+ shop : String
+ price : int
+end
+
+
+ Example patterns, with two constraints and a binding. Remember
+ semicolon ';' is used to differentiate the positional section from the
+ named argument section. Variables and literals and expressions using
+ just literals are supported in positional arguments, but not variables.
+ Positional arguments are always resolved using unification.
+
+ Cheese( "stilton", "Cheese Shop", p; )
+Cheese( "stilton", "Cheese Shop"; p : price )
+Cheese( "stilton"; shop == "Cheese Shop", p : price )
+Cheese( name == "stilton"; shop == "Cheese Shop", p : price )
+
+
+ Positional arguments that are given a previously declared binding
+ will constrain against that using unification; these are referred to as
+ input arguments. If the binding does not yet exist, it will create the
+ declaration binding it to the field represented by the position
+ argument; these are referred to as output arguments.
+
+
+
+ Fine grained property change listeners
+
+ When you call modify() (see the modify statement section) on a given object it will trigger a revaluation of all
+ patterns of the matching object type in the knowledge base. This can can lead to unwanted and useless evaluations
+ and in the worst cases to infinite recursions. The only workaround to avoid it was to split up your objects into
+ smaller ones having a 1 to 1 relationship with the original object.
+
+ This feature allows the pattern matching to only react to modification of properties actually
+ constrained or bound inside of a given pattern. That will help with performance and recursion and avoid artificial
+ object splitting.
+
+ By default this feature is off in order to make the behavior of the rule engine backward compatible with the
+ former releases. When you want to activate it on a specific bean you have to annotate it with @propertyReactive.
+ This annotation works both on drl type declarations:
+
+ declare Person
+ @propertyReactive
+ firstName : String
+ lastName : String
+ end
+
+ and on Java classes:
+
+ @PropertyReactive
+ public static class Person {
+ private String firstName;
+ private String lastName;
+ }
+
+ In this way, for instance, if you have a rule like the following:
+
+ rule "Every person named Mario is a male" when
+ $person : Person( firstName == "Mario" )
+ then
+ modify ( $person ) { setMale( true ) }
+ end
+
+ you won't have to add the no-loop attribute to it in order to avoid an infinite recursion because the engine
+ recognizes that the pattern matching is done on the 'firstName' property while the RHS of the rule modifies the
+ 'male' one. Note that this feature does not work for update(), and this is one of the reasons why we promote
+ modify() since it encapsulates the field changes within the statement. Moreover, on Java classes, you can also
+ annotate any method to say that its invocation actually modifies other properties. For instance in the former
+ Person class you could have a method like:
+
+ @Modifies( { "firstName", "lastName" } )
+ public void setName(String name) {
+ String[] names = name.split("\\s");
+ this.firstName = names[0];
+ this.lastName = names[1];
+ }
+
+ That means that if a rule has a RHS like the following:
+
+ modify($person) { setName("Mario Fusco") }
+
+ it will correctly recognize that the values of both properties 'firstName' and 'lastName' could have
+ potentially been modified and act accordingly, not missing of reevaluating the patterns constrained on them. At
+ the moment the usage of @Modifies is not allowed on fields but only on methods. This is coherent with the most
+ common scenario where the @Modifies will be used for methods that are not related with a class field as in the
+ Person.setName() in the former example. Also note that @Modifies is not transitive, meaning that if another method
+ internally invokes the Person.setName() one it won't be enough to annotate it with @Modifies( { "name" } ), but it
+ is necessary to use @Modifies( { "firstName", "lastName" } ) even on it. Very likely @Modifies transitivity will
+ be implemented in the next release.
+
+ For what regards nested accessors, the engine will be notified only for top level fields. In other words a
+ pattern matching like:
+
+ Person ( address.city.name == "London )
+
+ will be revaluated only for modification of the 'address' property of a Person object. In the same way the
+ constraints analysis is currently strictly limited to what there is inside a pattern. Another example could help
+ to clarify this. An LHS like the following:
+
+ $p : Person( )
+ Car( owner = $p.name )
+
+ will not listen on modifications of the person's name, while this one will do:
+
+ Person( $name : name )
+ Car( owner = $name )
+
+ To overcome this problem it is possible to annotate a pattern with @watch as it follows:
+
+ $p : Person( ) @watch ( name )
+ Car( owner = $p.name )
+
+ Indeed, annotating a pattern with @watch allows you to modify the inferred set of properties for which that
+ pattern will react. Note that the properties named in the @watch annotation are actually added to the ones
+ automatically inferred, but it is also possible to explicitly exclude one or more of them prepending their name
+ with a ! and to make the pattern to listen for all or none of the properties of the type used in the pattern
+ respectively with the wildcrds * and !*. So, for example, you can annotate a pattern in the LHS of a rule
+ like:
+
+ // listens for changes on both firstName (inferred) and lastName
+ Person( firstName == $expectedFirstName ) @watch( lastName )
+
+ // listens for all the properties of the Person bean
+ Person( firstName == $expectedFirstName ) @watch( * )
+
+ // listens for changes on lastName and explicitly exclude firstName
+ Person( firstName == $expectedFirstName ) @watch( lastName, !firstName )
+
+ // listens for changes on all the properties except the age one
+ Person( firstName == $expectedFirstName ) @watch( *, !age )
+
+ Since doesn't make sense to use this annotation on a pattern using a type not annotated with
+ @PropertyReactive the rule compiler will raise a compilation error if you try to do so. Also the duplicated usage
+ of the same property in @watch (for example like in: @watch( firstName, ! firstName ) ) will end up in a
+ compilation error. In a next release we will make the automatic detection of the properties to be listened smarter
+ by doing analysis even outside of the pattern.
+
+ It also possible to enable this feature by default on all the types of your model or to completely disallow
+ it by using on option of the KnowledgeBuilderConfiguration. In particular this new PropertySpecificOption can have
+ one of the following 3 values:
+
+ - DISABLED => the feature is turned off and all the other related annotations are just ignored
+ - ALLOWED => this is the default behavior: types are not property reactive unless they are not annotated with @PropertySpecific
+ - ALWAYS => all types are property reactive by default
+
+ So, for example, to have a KnowledgeBuilder generating property reactive types by default you could
+ do:
+
+ KnowledgeBuilderConfiguration config = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration();
+ config.setOption(PropertySpecificOption.ALWAYS);
+ KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(config);
+
+ In this last case it will be possible to disable the property reactivity feature on a specific type by
+ annotating it with @ClassReactive.
+
+
+
+ Basic conditional elements
+
+
+ Conditional Element and
+
+ The Conditional Element "and" is used to
+ group other Conditional Elements into a logical conjunction. Drools
+ supports both prefix and and infix
+ and.
+
+
+ infixAnd
+
+
+
+
+
+
+
+
+ Traditional infix and is supported:
+
+ //infixAnd
+Cheese( cheeseType : type ) and Person( favouriteCheese == cheeseType )
+
+ Explicit grouping with parentheses is also supported:
+
+ //infixAnd with grouping
+( Cheese( cheeseType : type ) and
+ ( Person( favouriteCheese == cheeseType ) or
+ Person( favouriteCheese == cheeseType ) )
+
+
+ The symbol && (as an alternative to
+ and) is deprecated. But it is still supported in
+ the syntax for backwards compatibility.
+
+
+
+ prefixAnd
+
+
+
+
+
+
+
+
+ Prefix and is also supported:
+
+ (and Cheese( cheeseType : type )
+ Person( favouriteCheese == cheeseType ) )
+
+ The root element of the LHS is an implicit prefix
+ and and doesn't need to be specified:
+
+
+ implicit root prefixAnd
+
+ when
+ Cheese( cheeseType : type )
+ Person( favouriteCheese == cheeseType )
+then
+ ...
+
+
+
+
+ Conditional Element or
+
+ The Conditional Element or is used to group
+ other Conditional Elements into a logical disjunction. Drools supports
+ both prefix or and infix
+ or.
+
+
+ infixOr
+
+
+
+
+
+
+
+
+ Traditional infix or is supported:
+
+ //infixOr
+Cheese( cheeseType : type ) or Person( favouriteCheese == cheeseType )
+
+ Explicit grouping with parentheses is also supported:
+
+ //infixOr with grouping
+( Cheese( cheeseType : type ) or
+ ( Person( favouriteCheese == cheeseType ) and
+ Person( favouriteCheese == cheeseType ) )
+
+
+ The symbol || (as an alternative to
+ or) is deprecated. But it is still supported in
+ the syntax for backwards compatibility.
+
+
+
+ prefixOr
+
+
+
+
+
+
+
+
+ Prefix or is also supported:
+
+ (or Person( sex == "f", age > 60 )
+ Person( sex == "m", age > 65 )
+
+
+ The behavior of the Conditional Element or
+ is different from the connective || for
+ constraints and restrictions in field constraints. The engine
+ actually has no understanding of the Conditional Element
+ or. Instead, via a number of different logic
+ transformations, a rule with or is rewritten as a
+ number of subrules. This process ultimately results in a rule that
+ has a single or as the root node and one subrule
+ for each of its CEs. Each subrule can activate and fire like any
+ normal rule; there is no special behavior or interaction between
+ these subrules. - This can be most confusing to new rule
+ authors.
+
+
+ The Conditional Element or also allows for
+ optional pattern binding. This means that each resulting subrule will
+ bind its pattern to the pattern binding. Each pattern must be bound
+ separately, using eponymous variables:
+
+ pensioner : ( Person( sex == "f", age > 60 ) or Person( sex == "m", age > 65 ) )
+
+ (or pensioner : Person( sex == "f", age > 60 )
+ pensioner : Person( sex == "m", age > 65 ) )
+
+ Since the conditional element or results in
+ multiple subrule generation, one for each possible logically outcome,
+ the example above would result in the internal generation of two
+ rules. These two rules work independently within the Working Memory,
+ which means both can match, activate and fire - there is no
+ shortcutting.
+
+ The best way to think of the conditional element
+ or is as a shortcut for generating two or more
+ similar rules. When you think of it that way, it's clear that for a
+ single rule there could be multiple activations if two or more terms
+ of the disjunction are true.
+
+
+
+ Conditional Element not
+
+
+ not
+
+
+
+
+
+
+
+
+ The CE not is first order logic's
+ non-existential quantifier and checks for the non-existence of
+ something in the Working Memory. Think of "not" as meaning "there must
+ be none of...".
+
+ The keyword not may be followed by
+ parentheses around the CEs that it applies to. In the simplest case of
+ a single pattern (like below) you may optionally omit the
+ parentheses.
+
+
+ No Busses
+
+ not Bus()
+
+
+
+ No red Busses
+
+ // Brackets are optional:
+not Bus(color == "red")
+// Brackets are optional:
+not ( Bus(color == "red", number == 42) )
+// "not" with nested infix and - two patterns,
+// brackets are requires:
+not ( Bus(color == "red") and
+ Bus(color == "blue") )
+
+
+
+
+ Conditional Element exists
+
+
+ exists
+
+
+
+
+
+
+
+
+ The CE exists is first order logic's
+ existential quantifier and checks for the existence of something in
+ the Working Memory. Think of "exists" as meaning "there is at least
+ one..". It is different from just having the pattern on its own, which
+ is more like saying "for each one of...". If you use
+ exists with a pattern, the rule will only activate
+ at most once, regardless of how much data there is in working memory
+ that matches the condition inside of the exists
+ pattern. Since only the existence matters, no bindings will be
+ established.
+
+ The keyword exists must be followed by
+ parentheses around the CEs that it applies to. In the simplest case of
+ a single pattern (like below) you may omit the parentheses.
+
+
+ At least one Bus
+
+ exists Bus()
+
+
+
+ At least one red Bus
+
+ exists Bus(color == "red")
+// brackets are optional:
+exists ( Bus(color == "red", number == 42) )
+// "exists" with nested infix and,
+// brackets are required:
+exists ( Bus(color == "red") and
+ Bus(color == "blue") )
+
+
+
+
+
+ Advanced conditional elements
+
+
+ Conditional Element forall
+
+
+ forall
+
+
+
+
+
+
+
+
+ The Conditional Element forall completes the
+ First Order Logic support in Drools. The Conditional Element
+ forall evaluates to true when all facts that match
+ the first pattern match all the remaining patterns. Example:
+
+ rule "All English buses are red"
+when
+ forall( $bus : Bus( type == 'english')
+ Bus( this == $bus, color = 'red' ) )
+then
+ // all English buses are red
+end
+
+ In the above rule, we "select" all Bus objects whose type is
+ "english". Then, for each fact that matches this pattern we evaluate
+ the following patterns and if they match, the forall CE will evaluate
+ to true.
+
+ To state that all facts of a given type in the working memory
+ must match a set of constraints, forall can be
+ written with a single pattern for simplicity. Example:
+
+
+ Single Pattern Forall
+
+ rule "All Buses are Red"
+when
+ forall( Bus( color == 'red' ) )
+then
+ // all Bus facts are red
+end
+
+
+ Another example shows multiple patterns inside the
+ forall:
+
+
+ Multi-Pattern Forall
+
+ rule "all employees have health and dental care programs"
+when
+ forall( $emp : Employee()
+ HealthCare( employee == $emp )
+ DentalCare( employee == $emp )
+ )
+then
+ // all employees have health and dental care
+end
+
+
+ Forall can be nested inside other CEs. For instance,
+ forall can be used inside a not
+ CE. Note that only single patterns have optional parentheses, so that
+ with a nested forall parentheses must be
+ used:
+
+
+ Combining Forall with Not CE
+
+ rule "not all employees have health and dental care"
+when
+ not ( forall( $emp : Employee()
+ HealthCare( employee == $emp )
+ DentalCare( employee == $emp ) )
+ )
+then
+ // not all employees have health and dental care
+end
+
+
+ As a side note, forall( p1 p2 p3...) is equivalent
+ to writing:
+
+ not(p1 and not(and p2 p3...))
+
+ Also, it is important to note that forall is
+ a scope delimiter. Therefore, it can use any
+ previously bound variable, but no variable bound inside it will be
+ available for use outside of it.
+
+
+
+ Conditional Element from
+
+
+ from
+
+
+
+
+
+
+
+
+ The Conditional Element from enables users to
+ specify an arbitrary source for data to be matched by LHS patterns.
+ This allows the engine to reason over data not in the Working Memory.
+ The data source could be a sub-field on a bound variable or the
+ results of a method call. It is a powerful construction that allows
+ out of the box integration with other application components and
+ frameworks. One common example is the integration with data retrieved
+ on-demand from databases using hibernate named queries.
+
+ The expression used to define the object source is any
+ expression that follows regular MVEL syntax. Therefore, it allows you
+ to easily use object property navigation, execute method calls and
+ access maps and collections elements.
+
+ Here is a simple example of reasoning and binding on another
+ pattern sub-field:
+
+ rule "validate zipcode"
+when
+ Person( $personAddress : address )
+ Address( zipcode == "23920W") from $personAddress
+then
+ // zip code is ok
+end
+
+ With all the flexibility from the new expressiveness in the
+ Drools engine you can slice and dice this problem many ways. This is
+ the same but shows how you can use a graph notation with the
+ 'from':
+
+ rule "validate zipcode"
+when
+ $p : Person( )
+ $a : Address( zipcode == "23920W") from $p.address
+then
+ // zip code is ok
+end
+
+ Previous examples were evaluations using a single pattern. The
+ CE from also support object sources that return a
+ collection of objects. In that case, from will
+ iterate over all objects in the collection and try to match each of
+ them individually. For instance, if we want a rule that applies 10%
+ discount to each item in an order, we could do:
+
+ rule "apply 10% discount to all items over US$ 100,00 in an order"
+when
+ $order : Order()
+ $item : OrderItem( value > 100 ) from $order.items
+then
+ // apply discount to $item
+end
+
+ The above example will cause the rule to fire once for each item
+ whose value is greater than 100 for each given order.
+
+ You must take caution, however, when using
+ from, especially in conjunction with the
+ lock-on-active rule attribute as it may produce
+ unexpected results. Consider the example provided earlier, but now
+ slightly modified as follows:
+
+ rule "Assign people in North Carolina (NC) to sales region 1"
+ruleflow-group "test"
+lock-on-active true
+when
+ $p : Person( )
+ $a : Address( state == "NC") from $p.address
+then
+ modify ($p) {} // Assign person to sales region 1 in a modify block
+end
+
+rule "Apply a discount to people in the city of Raleigh"
+ruleflow-group "test"
+lock-on-active true
+when
+ $p : Person( )
+ $a : Address( city == "Raleigh") from $p.address
+then
+ modify ($p) {} // Apply discount to person in a modify block
+end
+
+ In the above example, persons in Raleigh, NC should be assigned
+ to sales region 1 and receive a discount; i.e., you would expect both
+ rules to activate and fire. Instead you will find that only the second
+ rule fires.
+
+ If you were to turn on the audit log, you would also see that
+ when the second rule fires, it deactivates the first rule. Since the
+ rule attribute lock-on-active prevents a rule from
+ creating new activations when a set of facts change, the first rule
+ fails to reactivate. Though the set of facts have not changed, the use
+ of from returns a new fact for all intents and
+ purposes each time it is evaluated.
+
+ First, it's important to review why you would use the above
+ pattern. You may have many rules across different rule-flow groups.
+ When rules modify working memory and other rules downstream of your
+ RuleFlow (in different rule-flow groups) need to be reevaluated, the
+ use of modify is critical. You don't, however, want
+ other rules in the same rule-flow group to place activations on one
+ another recursively. In this case, the no-loop
+ attribute is ineffective, as it would only prevent a rule from
+ activating itself recursively. Hence, you resort to
+ lock-on-active.
+
+ There are several ways to address this issue:
+
+
+
+ Avoid the use of from when you can assert
+ all facts into working memory or use nested object references in
+ your constraint expressions (shown below).
+
+
+
+ Place the variable assigned used in the modify block as the
+ last sentence in your condition (LHS).
+
+
+
+ Avoid the use of lock-on-active when you
+ can explicitly manage how rules within the same rule-flow group
+ place activations on one another (explained below).
+
+
+
+ The preferred solution is to minimize use of
+ from when you can assert all your facts into
+ working memory directly. In the example above, both the Person and
+ Address instance can be asserted into working memory. In this case,
+ because the graph is fairly simple, an even easier solution is to
+ modify your rules as follows:
+
+ rule "Assign people in North Carolina (NC) to sales region 1"
+ruleflow-group "test"
+lock-on-active true
+when
+ $p : Person(address.state == "NC" )
+then
+ modify ($p) {} // Assign person to sales region 1 in a modify block
+end
+
+rule "Apply a discount to people in the city of Raleigh"
+ruleflow-group "test"
+lock-on-active true
+when
+ $p : Person(address.city == "Raleigh" )
+then
+ modify ($p) {} //Apply discount to person in a modify block
+end
+
+ Now, you will find that both rules fire as expected. However, it
+ is not always possible to access nested facts as above. Consider an
+ example where a Person holds one or more Addresses and you wish to use
+ an existential quantifier to match people with at least one address
+ that meets certain conditions. In this case, you would have to resort
+ to the use of from to reason over the
+ collection.
+
+ There are several ways to use from to achieve
+ this and not all of them exhibit an issue with the use of
+ lock-on-active. For example, the following use of
+ from causes both rules to fire as expected:
+
+ rule "Assign people in North Carolina (NC) to sales region 1"
+ruleflow-group "test"
+lock-on-active true
+when
+ $p : Person($addresses : addresses)
+ exists (Address(state == "NC") from $addresses)
+then
+ modify ($p) {} // Assign person to sales region 1 in a modify block
+end
+
+rule "Apply a discount to people in the city of Raleigh"
+ruleflow-group "test"
+lock-on-active true
+when
+ $p : Person($addresses : addresses)
+ exists (Address(city == "Raleigh") from $addresses)
+then
+ modify ($p) {} // Apply discount to person in a modify block
+end
+
+ However, the following slightly different approach does exhibit
+ the problem:
+
+ rule "Assign people in North Carolina (NC) to sales region 1"
+ruleflow-group "test"
+lock-on-active true
+when
+ $assessment : Assessment()
+ $p : Person()
+ $addresses : List() from $p.addresses
+ exists (Address( state == "NC") from $addresses)
+then
+ modify ($assessment) {} // Modify assessment in a modify block
+end
+
+rule "Apply a discount to people in the city of Raleigh"
+ruleflow-group "test"
+lock-on-active true
+when
+ $assessment : Assessment()
+ $p : Person()
+ $addresses : List() from $p.addresses
+ exists (Address( city == "Raleigh") from $addresses)
+then
+ modify ($assessment) {} // Modify assessment in a modify block
+end
+
+ In the above example, the $addresses variable is returned from
+ the use of from. The example also introduces a new
+ object, assessment, to highlight one possible solution in this case.
+ If the $assessment variable assigned in the condition (LHS) is moved
+ to the last condition in each rule, both rules fire as
+ expected.
+
+ Though the above examples demonstrate how to combine the use of
+ from with lock-on-active where
+ no loss of rule activations occurs, they carry the drawback of placing
+ a dependency on the order of conditions on the LHS. In addition, the
+ solutions present greater complexity for the rule author in terms of
+ keeping track of which conditions may create issues.
+
+ A better alternative is to assert more facts into working
+ memory. In this case, a person's addresses may be asserted into
+ working memory and the use of from would not be
+ necessary.
+
+ There are cases, however, where asserting all data into working
+ memory is not practical and we need to find other solutions. Another
+ option is to reevaluate the need for
+ lock-on-active. An alternative to
+ lock-on-active is to directly manage how rules
+ within the same rule-flow group activate one another by including
+ conditions in each rule that prevent rules from activating each other
+ recursively when working memory is modified. For example, in the case
+ above where a discount is applied to citizens of Raleigh, a condition
+ may be added to the rule that checks whether the discount has already
+ been applied. If so, the rule does not activate.
+
+
+
+ Conditional Element collect
+
+
+ collect
+
+
+
+
+
+
+
+
+ The Conditional Element collect allows rules
+ to reason over a collection of objects obtained from the given source
+ or from the working memory. In First Oder Logic terms this is the
+ cardinality quantifier. A simple example:
+
+ import java.util.ArrayList
+
+rule "Raise priority if system has more than 3 pending alarms"
+when
+ $system : System()
+ $alarms : ArrayList( size >= 3 )
+ from collect( Alarm( system == $system, status == 'pending' ) )
+then
+ // Raise priority, because system $system has
+ // 3 or more alarms pending. The pending alarms
+ // are $alarms.
+end
+
+ In the above example, the rule will look for all pending alarms
+ in the working memory for each given system and group them in
+ ArrayLists. If 3 or more alarms are found for a given system, the rule
+ will fire.
+
+ The result pattern of collect can be any
+ concrete class that implements the java.util.Collection
+ interface and provides a default no-arg public constructor. This means
+ that you can use Java collections like ArrayList, LinkedList, HashSet,
+ etc., or your own class, as long as it implements the
+ java.util.Collection interface and provide a default
+ no-arg public constructor.
+
+ Both source and result patterns can be constrained as any other
+ pattern.
+
+ Variables bound before the collect CE are in
+ the scope of both source and result patterns and therefore you can use
+ them to constrain both your source and result patterns. But note that
+ collect is a scope delimiter for bindings, so that
+ any binding made inside of it is not available for use outside of
+ it.
+
+ Collect accepts nested from CEs. The
+ following example is a valid use of "collect":
+
+ import java.util.LinkedList;
+
+rule "Send a message to all mothers"
+when
+ $town : Town( name == 'Paris' )
+ $mothers : LinkedList()
+ from collect( Person( gender == 'F', children > 0 )
+ from $town.getPeople()
+ )
+then
+ // send a message to all mothers
+end
+
+
+
+ Conditional Element accumulate
+
+
+ accumulate
+
+
+
+
+
+
+
+
+ The Conditional Element accumulate is a more
+ flexible and powerful form of collect, in the sense
+ that it can be used to do what collect does and
+ also achieve results that the CE collect is not
+ capable of doing. Basically, what it does is that it allows a rule to
+ iterate over a collection of objects, executing custom actions for
+ each of the elements, and at the end it returns a result
+ object.
+
+ Accumulate supports both the use of pre-defined accumulate
+ functions, or the use of inline custom code. Inline custom code should
+ be avoided though, as it is harder for rule authors to maintain, and
+ frequently leads to code duplication. Accumulate functions are easier
+ to test and reuse.
+
+ The Accumulate CE also supports multiple different syntaxes. The
+ preferred syntax is the top level accumulate, as noted bellow, but all
+ other syntaxes are supported for backward compatibility.
+
+
+ Accumulate CE (preferred syntax)
+
+ The top level accumulate syntax is the most compact and
+ flexible syntax. The simplified syntax is as follows:
+
+ accumulate( <source pattern>; <functions> [;<constraints>] )
+
+
+ For instance, a rule to calculate the minimum, maximum and
+ average temperature reading for a given sensor and that raises an
+ alarm if the minimum temperature is under 20C degrees and the
+ average is over 70C degrees could be written in the following way,
+ using Accumulate:
+
+ rule "Raise alarm"
+when
+ $s : Sensor()
+ accumulate( Reading( sensor == $s, $temp : temperature );
+ $min : min( $temp ),
+ $max : max( $temp ),
+ $avg : average( $temp );
+ $min < 20, $avg > 70 )
+then
+ // raise the alarm
+end
+
+ In the above example, min, max and average are Accumulate
+ Functions and will calculate the minimum, maximum and average
+ temperature values over all the readings for each sensor.
+
+ Drools ships with several built-in accumulate functions,
+ including:
+
+
+
+ average
+
+
+
+ min
+
+
+
+ max
+
+
+
+ count
+
+
+
+ sum
+
+
+
+ collectList
+
+
+
+ collectSet
+
+
+
+ These common functions accept any expression as input. For
+ instance, if someone wants to calculate the average profit on all
+ items of an order, a rule could be written using the average
+ function:
+
+ rule "Average profit"
+when
+ $order : Order()
+ accumulate( OrderItem( order == $order, $cost : cost, $price : price );
+ $avgProfit : average( 1 - $cost / $price ) )
+then
+ // average profit for $order is $avgProfit
+end
+
+ Accumulate Functions are all pluggable. That means that if
+ needed, custom, domain specific functions can easily be added to the
+ engine and rules can start to use them without any restrictions. To
+ implement a new Accumulate Function all one needs to do is to create
+ a Java class that implements the
+ org.drools.runtime.rule.TypedAccumulateFunction
+ interface and add a line to the configuration file or set a system
+ property to let the engine know about the new function. As an
+ example of an Accumulate Function implementation, the following is
+ the implementation of the average
+ function:
+
+ /**
+ * An implementation of an accumulator capable of calculating average values
+ */
+public class AverageAccumulateFunction implements org.drools.runtime.rule.TypedAccumulateFunction {
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+
+ }
+
+ public static class AverageData implements Externalizable {
+ public int count = 0;
+ public double total = 0;
+
+ public AverageData() {}
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ count = in.readInt();
+ total = in.readDouble();
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ out.writeInt(count);
+ out.writeDouble(total);
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.drools.base.accumulators.AccumulateFunction#createContext()
+ */
+ public Serializable createContext() {
+ return new AverageData();
+ }
+
+ /* (non-Javadoc)
+ * @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
+ */
+ public void init(Serializable context) throws Exception {
+ AverageData data = (AverageData) context;
+ data.count = 0;
+ data.total = 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object, java.lang.Object)
+ */
+ public void accumulate(Serializable context,
+ Object value) {
+ AverageData data = (AverageData) context;
+ data.count++;
+ data.total += ((Number) value).doubleValue();
+ }
+
+ /* (non-Javadoc)
+ * @see org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object, java.lang.Object)
+ */
+ public void reverse(Serializable context,
+ Object value) throws Exception {
+ AverageData data = (AverageData) context;
+ data.count--;
+ data.total -= ((Number) value).doubleValue();
+ }
+
+ /* (non-Javadoc)
+ * @see org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
+ */
+ public Object getResult(Serializable context) throws Exception {
+ AverageData data = (AverageData) context;
+ return new Double( data.count == 0 ? 0 : data.total / data.count );
+ }
+
+ /* (non-Javadoc)
+ * @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
+ */
+ public boolean supportsReverse() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class< ? > getResultType() {
+ return Number.class;
+ }
+
+}
+
+
+ The code for the function is very simple, as we could expect,
+ as all the "dirty" integration work is done by the engine. Finally,
+ to plug the function into the engine, we added it to the
+ configuration file:
+
+ drools.accumulate.function.average =
+ org.drools.base.accumulators.AverageAccumulateFunction
+
+ Here, "drools.accumulate.function." is a prefix that must
+ always be used, "average" is how the function will be used in the
+ rule file, and
+ "org.drools.base.accumulators.AverageAccumulateFunction" is the
+ fully qualified name of the class that implements the function
+ behavior.
+
+
+
+ Alternate Syntax: single function with return type
+
+ The accumulate syntax evolved over time with the goal of
+ becoming more compact and expressive. Nevertheless, Drools still
+ supports previous syntaxes for backward compatibility
+ purposes.
+
+ In case the rule is using a single accumulate function on a
+ given accumulate, the author may add a pattern for the result object
+ and use the "from" keyword to link it to the accumulate result.
+ Example: a rule to apply a 10% discount on orders over $100 could be
+ written in the following way:
+
+ rule "Apply 10% discount to orders over US$ 100,00"
+when
+ $order : Order()
+ $total : Number( doubleValue > 100 )
+ from accumulate( OrderItem( order == $order, $value : value ),
+ sum( $value ) )
+then
+ # apply discount to $order
+end
+
+ In the above example, the accumulate element is using only one
+ function (sum), and so, the rules author opted to explicitly write a
+ pattern for the result type of the accumulate function (Number) and
+ write the constraints inside it. There are no problems in using this
+ syntax over the compact syntax presented before, except that is is a
+ bit more verbose. Also note that it is not allowed to use both the
+ return type and the functions binding in the same accumulate statement.
+
+
+
+ Accumulate with inline custom code
+
+
+ The use of accumulate with inline custom code is not a good
+ practice for several reasons, including difficulties on maintaining
+ and testing rules that use them, as well as the inability of
+ reusing that code. Implementing your own accumulate functions is
+ very simple and straightforward, they are easy to unit test and to
+ use. This form of accumulate is supported for backward
+ compatibility only.
+
+
+ Another possible syntax for the accumulate is to define inline
+ custom code, instead of using accumulate functions. As noted on the
+ previous warned, this is discouraged though for the stated
+ reasons.
+
+ The general syntax of the accumulate CE
+ with inline custom code is:
+
+ <result pattern>from accumulate(<source pattern>,
+ init(<init code>),
+ action(<action code>),
+ reverse(<reverse code>),
+ result(<result expression>) )
+
+
+ The meaning of each of the elements is the following:
+
+
+
+ <source pattern>: the source
+ pattern is a regular pattern that the engine will try to match
+ against each of the source objects.
+
+
+
+ <init code>: this is a semantic
+ block of code in the selected dialect that will be executed once
+ for each tuple, before iterating over the source objects.
+
+
+
+ <action code>: this is a
+ semantic block of code in the selected dialect that will be
+ executed for each of the source objects.
+
+
+
+ <reverse code>: this is an
+ optional semantic block of code in the selected dialect that if
+ present will be executed for each source object that no longer
+ matches the source pattern. The objective of this code block is
+ to undo any calculation done in the <action
+ code> block, so that the engine can do decremental
+ calculation when a source object is modified or retracted,
+ hugely improving performance of these operations.
+
+
+
+ <result expression>: this is a
+ semantic expression in the selected dialect that is executed
+ after all source objects are iterated.
+
+
+
+ <result pattern>: this is a
+ regular pattern that the engine tries to match against the
+ object returned from the <result
+ expression>. If it matches, the
+ accumulate conditional element evaluates to
+ true and the engine proceeds with the
+ evaluation of the next CE in the rule. If it does not matches,
+ the accumulate CE evaluates to
+ false and the engine stops evaluating CEs
+ for that rule.
+
+
+
+ It is easier to understand if we look at an example:
+
+ rule "Apply 10% discount to orders over US$ 100,00"
+when
+ $order : Order()
+ $total : Number( doubleValue > 100 )
+ from accumulate( OrderItem( order == $order, $value : value ),
+ init( double total = 0; ),
+ action( total += $value; ),
+ reverse( total -= $value; ),
+ result( total ) )
+then
+ # apply discount to $order
+end
+
+ In the above example, for each Order in the
+ Working Memory, the engine will execute the init
+ code initializing the total variable to zero. Then it
+ will iterate over all OrderItem objects for that order,
+ executing the action for each one (in the
+ example, it will sum the value of all items into the total
+ variable). After iterating over all OrderItem objects,
+ it will return the value corresponding to the result
+ expression (in the above example, the value of variable
+ total). Finally, the engine will try to match the
+ result with the Number pattern, and if the double value
+ is greater than 100, the rule will fire.
+
+ The example used Java as the semantic dialect, and as such,
+ note that the usage of the semicolon as statement delimiter is
+ mandatory in the init, action and reverse code blocks. The result is
+ an expression and, as such, it does not admit ';'. If the user uses
+ any other dialect, he must comply to that dialect's specific
+ syntax.
+
+ As mentioned before, the reverse code is
+ optional, but it is strongly recommended that the user writes it in
+ order to benefit from the improved performance on update
+ and retract.
+
+ The accumulate CE can be used to execute
+ any action on source objects. The following example instantiates and
+ populates a custom object:
+
+ rule "Accumulate using custom objects"
+when
+ $person : Person( $likes : likes )
+ $cheesery : Cheesery( totalAmount > 100 )
+ from accumulate( $cheese : Cheese( type == $likes ),
+ init( Cheesery cheesery = new Cheesery(); ),
+ action( cheesery.addCheese( $cheese ); ),
+ reverse( cheesery.removeCheese( $cheese ); ),
+ result( cheesery ) );
+then
+ // do something
+end
+
+
+
+
+
+ Conditional Element eval
+
+
+ eval
+
+
+
+
+
+
+
+
+ The conditional element eval is essentially a
+ catch-all which allows any semantic code (that returns a primitive
+ boolean) to be executed. This code can refer to variables that were
+ bound in the LHS of the rule, and functions in the rule package. Overuse
+ of eval reduces the declarativeness of your rules and can result in a
+ poorly performing engine. While eval can be used
+ anywhere in the patterns, the best practice is to add it as the last
+ conditional element in the LHS of a rule.
+
+ Evals cannot be indexed and thus are not as efficient as Field
+ Constraints. However this makes them ideal for being used when functions
+ return values that change over time, which is not allowed within Field
+ Constraints.
+
+ For folks who are familiar with Drools 2.x lineage, the old Drools
+ parameter and condition tags are equivalent to binding a variable to an
+ appropriate type, and then using it in an eval node.
+
+ p1 : Parameter()
+p2 : Parameter()
+eval( p1.getList().containsKey( p2.getItem() ) )
+
+ p1 : Parameter()
+p2 : Parameter()
+// call function isValid in the LHS
+eval( isValid( p1, p2 ) )
+
+
+
+ Railroad diagrams
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The Right Hand Side (then)
+
+
+ Usage
+
+ The Right Hand Side (RHS) is a common name for the consequence or
+ action part of the rule; this part should contain a list of actions to
+ be executed. It is bad practice to use imperative or conditional code in
+ the RHS of a rule; as a rule should be atomic in nature - "when this,
+ then do this", not "when this, maybe do this". The RHS part of a rule
+ should also be kept small, thus keeping it declarative and readable. If
+ you find you need imperative and/or conditional code in the RHS, then
+ maybe you should be breaking that rule down into multiple rules. The
+ main purpose of the RHS is to insert, retractor modify working memory
+ data. To assist with that there are a few convenience methods you can
+ use to modify working memory; without having to first reference a
+ working memory instance.
+
+ update(object,
+ handle); will tell the engine that an
+ object has changed (one that has been bound to something on the LHS) and
+ rules may need to be reconsidered.
+
+ update(object);
+ can also be used; here the Knowledge Helper will look up the facthandle
+ for you, via an identity check, for the passed object. (Note that if you
+ provide Property Change Listeners to your Java beans that you are
+ inserting into the engine, you can avoid the need to call
+ update() when the object changes.). After a fact's field
+ values have changed you must call update before changing another fact,
+ or you will cause problems with the indexing within the rule engine. The
+ modify keyword avoids this problem.
+
+ insert(new
+ Something()); will place a new
+ object of your creation into the Working Memory.
+
+ insertLogical(new
+ Something()); is similar to
+ insert, but the object will be automatically retracted when there are no
+ more facts to support the truth of the currently firing rule.
+
+ retract(handle);
+ removes an object from Working Memory.
+
+ These convenience methods are basically macros that provide short
+ cuts to the KnowledgeHelper instance that lets you access
+ your Working Memory from rules files. The predefined variable
+ drools of type KnowledgeHelper lets you call
+ several other useful methods. (Refer to the KnowledgeHelper
+ interface documentation for more advanced operations).
+
+
+
+ The call drools.halt() terminates rule execution
+ immediately. This is required for returning control to the point
+ whence the current session was put to work with
+ fireUntilHalt().
+
+
+
+ Methods insert(Object o), update(Object
+ o) and retract(Object o) can be called on
+ drools as well, but due to their frequent use they can
+ be called without the object reference.
+
+
+
+ drools.getWorkingMemory() returns the
+ WorkingMemory object.
+
+
+
+ drools.setFocus( String s) sets the focus to the
+ specified agenda group.
+
+
+
+ drools.getRule().getName(), called from a rule's
+ RHS, returns the name of the rule.
+
+
+
+ drools.getTuple() returns the Tuple that matches
+ the currently executing rule, and
+ drools.getActivation() delivers the corresponding
+ Activation. (These calls are useful for logging and debugging
+ purposes.)
+
+
+
+ The full Knowledge Runtime API is exposed through another
+ predefined variable, kcontext, of type
+ KnowledgeContext. Its method
+ getKnowledgeRuntime() delivers an object of type
+ KnowledgeRuntime, which, in turn, provides access to a
+ wealth of methods, many of which are quite useful for coding RHS
+ logic.
+
+
+
+ The call kcontext.getKnowledgeRuntime().halt()
+ terminates rule execution immediately.
+
+
+
+ The accessor getAgenda() returns a reference to
+ this session's Agenda, which in turn provides access to
+ the various rule groups: activation groups, agenda groups, and rule
+ flow groups. A fairly common paradigm is the activation of some
+ agenda group, which could be done with the lengthy call:
+
+ // give focus to the agenda group CleanUp
+kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup( "CleanUp" ).setFocus();
+
+ (You can achieve the same using drools.setFocus(
+ "CleanUp" ).)
+
+
+
+ To run a query, you call getQueryResults(String
+ query), whereupon you may process the results, as explained
+ in section .
+
+
+
+ A set of methods dealing with event management lets you, among
+ other things, add and remove event listeners for the Working Memory
+ and the Agenda.
+
+
+
+ MethodgetKnowledgeBase() returns the
+ KnowledgeBase object, the backbone of all the Knowledge
+ in your system, and the originator of the current session.
+
+
+
+ You can manage globals with setGlobal(...),
+ getGlobal(...) and getGlobals().
+
+
+
+ Method getEnvironment() returns the runtime's
+ Environment which works much like what you know as your
+ operating system's environment.
+
+
+
+
+
+ The modify Statement
+
+ This language extension provides a structured approach to fact
+ updates. It combines the update operation with a number of setter calls
+ to change the object's fields. This is the syntax schema for the
+ modify statement:
+
+ modify ( <fact-expression> ) {
+ <expression> [ ,<expression> ]*
+}
+
+ The parenthesized <fact-expression>
+ must yield a fact object reference. The expression list in the block
+ should consist of setter calls for the given object, to be written
+ without the usual object reference, which is automatically prepended by
+ the compiler.
+
+ The example illustrates a simple fact modification.
+
+
+ A modify statement
+
+ rule "modify stilton"
+when
+ $stilton : Cheese(type == "stilton")
+then
+ modify( $stilton ){
+ setPrice( 20 ),
+ setAge( "overripe" )
+ }
+end
+
+
+ The advantages in using the modify statment are particularly clear when
+ used in conjuction with fine grained property change listeners.
+ See the corresponding section for more details.
+
+
+
+
+ A Note on Auto-boxing and Primitive Types
+
+ Drools attempts to preserve numbers in their primitive or object
+ wrapper form, so a variable bound to an int primitive when used in a code
+ block or expression will no longer need manual unboxing; unlike Drools 3.0
+ where all primitives were autoboxed, requiring manual unboxing. A variable
+ bound to an object wrapper will remain as an object; the existing JDK 1.5
+ and JDK 5 rules to handle auto-boxing and unboxing apply in this case.
+ When evaluating field constraints, the system attempts to coerce one of
+ the values into a comparable format; so a primitive is comparable to an
+ object wrapper.
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-TypeDeclaration.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-TypeDeclaration.xml
new file mode 100644
index 0000000000..c300aa4c30
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-TypeDeclaration.xml
@@ -0,0 +1,700 @@
+
+
+ Type Declaration
+
+
+ meta_data
+
+
+
+
+
+
+
+
+
+ type_declaration
+
+
+
+
+
+
+
+
+ Type declarations have two main goals in the rules engine: to allow
+ the declaration of new types, and to allow the declaration of metadata for
+ types.
+
+
+
+ Declaring new types: Drools works
+ out of the box with plain Java objects as facts. Sometimes, however,
+ users may want to define the model directly to the rules engine, without
+ worrying about creating models in a lower level language like Java. At
+ other times, there is a domain model already built, but eventually the
+ user wants or needs to complement this model with additional entities
+ that are used mainly during the reasoning process.
+
+
+
+ Declaring metadata: facts may
+ have meta information associated to them. Examples of meta information
+ include any kind of data that is not represented by the fact attributes
+ and is consistent among all instances of that fact type. This meta
+ information may be queried at runtime by the engine and used in the
+ reasoning process.
+
+
+
+
+ Declaring New Types
+
+ To declare a new type, all you need to do is use the keyword
+ declare, followed by the list of fields, and the
+ keyword end. A new fact must have a list of fields,
+ otherwise the engine will look for an existing fact class in the classpath
+ and raise an error if not found.
+
+
+ Declaring a new fact type: Address
+
+ declare Address
+ number : int
+ streetName : String
+ city : String
+end
+
+
+
+ The previous example declares a new fact type called
+ Address. This fact type will have three attributes:
+ number, streetName and city. Each
+ attribute has a type that can be any valid Java type, including any other
+ class created by the user or even other fact types previously
+ declared.
+
+ For instance, we may want to declare another fact type
+ Person:
+
+
+ declaring a new fact type: Person
+
+ declare Person
+ name : String
+ dateOfBirth : java.util.Date
+ address : Address
+end
+
+
+
+ As we can see on the previous example, dateOfBirth is
+ of type java.util.Date, from the Java API, while
+ address is of the previously defined fact type
+ Address.
+
+ You may avoid having to write the fully qualified name of a class
+ every time you write it by using the import clause, as
+ previously discussed.
+
+
+ Avoiding the need to use fully qualified class names by using
+ import
+
+ import java.util.Date
+
+declare Person
+ name : String
+ dateOfBirth : Date
+ address : Address
+end
+
+
+ When you declare a new fact type, Drools will, at compile time,
+ generate bytecode that implements a Java class representing the fact type.
+ The generated Java class will be a one-to-one Java Bean mapping of the
+ type definition. So, for the previous example, the generated Java class
+ would be:
+
+
+ generated Java class for the previous Person fact type
+ declaration
+
+ public class Person implements Serializable {
+ private String name;
+ private java.util.Date dateOfBirth;
+ private Address address;
+
+ // empty constructor
+ public Person() {...}
+
+ // constructor with all fields
+ public Person( String name, Date dateOfBirth, Address address ) {...}
+
+ // if keys are defined, constructor with keys
+ public Person( ...keys... ) {...}
+
+ // getters and setters
+ // equals/hashCode
+ // toString
+}
+
+
+
+ Since the generated class is a simple Java class, it can be used
+ transparently in the rules, like any other fact.
+
+
+ Using the declared types in rules
+
+ rule "Using a declared Type"
+when
+ $p : Person( name == "Bob" )
+then
+ // Insert Mark, who is Bob's mate.
+ Person mark = new Person();
+ mark.setName("Mark");
+ insert( mark );
+end
+
+
+
+
+
+ Declaring Metadata
+
+ Metadata may be assigned to several different constructions in
+ Drools: fact types, fact attributes and rules. Drools uses the at sign
+ ('@') to introduce metadata, and it always uses the form:
+
+ @metadata_key( metadata_value )
+
+ The parenthesized metadata_value is
+ optional.
+
+ For instance, if you want to declare a metadata attribute like
+ author, whose value is Bob, you could
+ simply write:
+
+
+ Declaring a metadata attribute
+
+ @author( Bob )
+
+
+ Drools allows the declaration of any arbitrary metadata attribute,
+ but some will have special meaning to the engine, while others are simply
+ available for querying at runtime. Drools allows the declaration of
+ metadata both for fact types and for fact attributes. Any metadata that is
+ declared before the attributes of a fact type are assigned to the fact
+ type, while metadata declared after an attribute are assigned to that
+ particular attribute.
+
+
+ Declaring metadata attributes for fact types and
+ attributes
+
+ import java.util.Date
+
+declare Person
+ @author( Bob )
+ @dateOfCreation( 01-Feb-2009 )
+
+ name : String @key @maxLength( 30 )
+ dateOfBirth : Date
+ address : Address
+end
+
+
+ In the previous example, there are two metadata items declared for
+ the fact type (@author and @dateOfCreation) and
+ two more defined for the name attribute (@key and
+ @maxLength). Please note that the @key metadata
+ has no required value, and so the parentheses and the value were
+ omitted.:
+
+ @position can be used to declare the position of a field, overriding
+ the default declared order. This is used for positional constraints in
+ patterns.
+
+ declare Cheese
+ name : String @position(1)
+ shop : String @position(2)
+ price : int @position(0)
+end
+
+
+
+ Predefined class level annotations
+
+ Some annotations have predefined semantics that are interpreted by
+ the engine. The following is a list of some of these predefined
+ annotations and their meaning.
+
+
+ @role( <fact | event> )
+
+ See Drools Fusion documentation for details.
+
+
+
+ @typesafe( <boolean> )
+
+ By default all type declarations are compiled with type safety
+ enabled; @typesafe( false ) provides a means to override this
+ behaviour by permitting a fall-back, to type unsafe evaluation where
+ all constraints are generated as MVEL constraints and executed
+ dynamically. This can be important when dealing with collections that
+ do not have any generics or mixed type collections.
+
+
+
+ @timestamp( <attribute name> )
+
+ See Drools Fusion documentation for details.
+
+
+
+ @duration( <attribute name> )
+
+ See Drools Fusion documentation for details.
+
+
+
+ @expires( <time interval> )
+
+ See Drools Fusion documentation for details.
+
+
+
+ @propertyChangeSupport
+
+ Facts that implement support for property changes as defined in
+ the Javabean(tm) spec, now can be annotated so that the engine
+ register itself to listen for changes on fact properties. The boolean
+ parameter that was used in the insert() method in the Drools 4 API is
+ deprecated and does not exist in the drools-api module.
+
+
+ @propertyChangeSupport
+
+ declare Person
+ @propertyChangeSupport
+end
+
+
+
+
+ @propertyReactive
+
+ Make this type property reactive. See Fine grained property
+ change listeners section for details.
+
+
+
+
+ Predefined attribute level annotations
+
+ As noted before, Drools also supports annotations in type
+ attributes. Here is a list of predefined attribute annotations.
+
+
+ @key
+
+ Declaring an attribute as a key attribute has 2 major effects on
+ generated types:
+
+
+
+ The attribute will be used as a key identifier for the
+ type, and as so, the generated class will implement the equals()
+ and hashCode() methods taking the attribute into account when
+ comparing instances of this type.
+
+
+
+ Drools will generate a constructor using all the key
+ attributes as parameters.
+
+ For instance:
+
+
+ example of @key declarations for a type
+
+ declare Person
+ firstName : String @key
+ lastName : String @key
+ age : int
+end
+
+
+
+ For the previous example, Drools will generate equals() and
+ hashCode() methods that will check the firstName and lastName
+ attributes to determine if two instances of Person are equal to each
+ other, but will not check the age attribute. It will also generate a
+ constructor taking firstName and lastName as parameters, allowing one
+ to create instances with a code like this:
+
+
+ creating an instance using the key constructor
+
+ Person person = new Person( "John", "Doe" );
+
+
+
+
+ @position
+
+ Patterns support positional arguments on type
+ declarations.
+
+ Positional arguments are ones where you don't need to specify
+ the field name, as the position maps to a known named field. i.e.
+ Person( name == "mark" ) can be rewritten as Person( "mark"; ). The
+ semicolon ';' is important so that the engine knows that everything
+ before it is a positional argument. Otherwise we might assume it was a
+ boolean expression, which is how it could be interpreted after the
+ semicolon. You can mix positional and named arguments on a pattern by
+ using the semicolon ';' to separate them. Any variables used in a
+ positional that have not yet been bound will be bound to the field
+ that maps to that position.
+
+ declare Cheese
+ name : String
+ shop : String
+ price : int
+end
+
+
+ The default order is the declared order, but this can be
+ overridden using @position
+
+ declare Cheese
+ name : String @position(1)
+ shop : String @position(2)
+ price : int @position(0)
+end
+
+
+ The @Position annotation, in the org.drools.definition.type
+ package, can be used to annotate original pojos on the classpath.
+ Currently only fields on classes can be annotated. Inheritance of
+ classes is supported, but not interfaces of methods yet.
+
+ Example patterns, with two constraints and a binding. Remember
+ semicolon ';' is used to differentiate the positional section from the
+ named argument section. Variables and literals and expressions using
+ just literals are supported in positional arguments, but not
+ variables.
+
+
+Cheese( "stilton", "Cheese Shop", p; )
+Cheese( "stilton", "Cheese Shop"; p : price )
+Cheese( "stilton"; shop == "Cheese Shop", p : price )
+Cheese( name == "stilton"; shop == "Cheese Shop", p : price )
+
+
+
+
+
+
+ Declaring Metadata for Existing Types
+
+ Drools allows the declaration of metadata attributes for existing
+ types in the same way as when declaring metadata attributes for new fact
+ types. The only difference is that there are no fields in that
+ declaration.
+
+ For instance, if there is a class org.drools.examples.Person, and
+ one wants to declare metadata for it, it's possible to write the following
+ code:
+
+
+ Declaring metadata for an existing type
+
+ import org.drools.examples.Person
+
+declare Person
+ @author( Bob )
+ @dateOfCreation( 01-Feb-2009 )
+end
+
+
+
+ Instead of using the import, it is also possible to reference the
+ class by its fully qualified name, but since the class will also be
+ referenced in the rules, it is usually shorter to add the import and use
+ the short class name everywhere.
+
+
+ Declaring metadata using the fully qualified class name
+
+ declare org.drools.examples.Person
+ @author( Bob )
+ @dateOfCreation( 01-Feb-2009 )
+end
+
+
+
+
+ Parametrized constructors for declared types
+
+ Generate constructors with parameters for declared types.
+
+ Example: for a declared type like the following:
+
+ declare Person
+ firstName : String @key
+ lastName : String @key
+ age : int
+end
+
+
+ The compiler will implicitly generate 3 constructors: one without
+ parameters, one with the @key fields, and one with all fields.
+
+ Person() // parameterless constructor
+Person( String firstName, String lastName )
+Person( String firstName, String lastName, int age )
+
+
+
+ Non Typesafe Classes
+
+ @typesafe( <boolean>) has been added to type declarations. By
+ default all type declarations are compiled with type safety enabled;
+ @typesafe( false ) provides a means to override this behaviour by
+ permitting a fall-back, to type unsafe evaluation where all constraints
+ are generated as MVEL constraints and executed dynamically. This can be
+ important when dealing with collections that do not have any generics or
+ mixed type collections.
+
+
+
+ Accessing Declared Types from the Application Code
+
+ Declared types are usually used inside rules files, while Java
+ models are used when sharing the model between rules and applications.
+ Although, sometimes, the application may need to access and handle facts
+ from the declared types, especially when the application is wrapping the
+ rules engine and providing higher level, domain specific user interfaces
+ for rules management.
+
+ In such cases, the generated classes can be handled as usual with
+ the Java Reflection API, but, as we know, that usually requires a lot of
+ work for small results. Therefore, Drools provides a simplified API for
+ the most common fact handling the application may want to do.
+
+ The first important thing to realize is that a declared fact will
+ belong to the package where it was declared. So, for instance, in the
+ example below, Person will belong to the
+ org.drools.examples package, and so the fully qualified name
+ of the generated class will be
+ org.drools.examples.Person.
+
+
+ Declaring a type in the org.drools.examples package
+
+ package org.drools.examples
+
+import java.util.Date
+
+declare Person
+ name : String
+ dateOfBirth : Date
+ address : Address
+end
+
+
+ Declared types, as discussed previously, are generated at knowledge
+ base compilation time, i.e., the application will only have access to them
+ at application run time. Therefore, these classes are not available for
+ direct reference from the application.
+
+ Drools then provides an interface through which users can handle
+ declared types from the application code:
+ org.drools.definition.type.FactType. Through this interface,
+ the user can instantiate, read and write fields in the declared fact
+ types.
+
+
+ Handling declared fact types through the API
+
+ // get a reference to a knowledge base with a declared type:
+KnowledgeBase kbase = ...
+
+// get the declared FactType
+FactType personType = kbase.getFactType( "org.drools.examples",
+ "Person" );
+
+// handle the type as necessary:
+// create instances:
+Object bob = personType.newInstance();
+
+// set attributes values
+personType.set( bob,
+ "name",
+ "Bob" );
+personType.set( bob,
+ "age",
+ 42 );
+
+// insert fact into a session
+StatefulKnowledgeSession ksession = ...
+ksession.insert( bob );
+ksession.fireAllRules();
+
+// read attributes
+String name = personType.get( bob, "name" );
+int age = personType.get( bob, "age" );
+
+
+
+
+ The API also includes other helpful methods, like setting all the
+ attributes at once, reading values from a Map, or reading all attributes
+ at once, into a Map.
+
+ Although the API is similar to Java reflection (yet much simpler to
+ use), it does not use reflection underneath, relying on much more
+ performant accessors implemented with generated bytecode.
+
+
+
+ Type Declaration 'extends'
+
+ Type declarations now support 'extends' keyword for
+ inheritance
+
+ In order to extend a type declared in Java by a DRL declared
+ subtype, repeat the supertype in a declare statement without any
+ fields.
+
+ import org.people.Person
+
+declare Person
+end
+
+declare Student extends Person
+ school : String
+end
+
+declare LongTermStudent extends Student
+ years : int
+ course : String
+end
+
+
+
+ Traits
+
+ The same fact may have multiple dynamic types which do not fit naturally in a class hierarchy.
+ Traits allow to model this very common scenario. A trait is an interface that can be applied (and eventually
+ removed) to an individual object at runtime. To create a trait out of an interface, one has to add a @format(trait)
+ annotation to its declaration in DRL as in the following example:
+
+ declare GoldenCustomer
+ @format(trait)
+ // fields will map to getters/setters
+ code : String
+ balance : long
+ discount : int
+ maxExpense : long
+end
+
+ In order to apply a trait to an object, we provide the new don keyword, which can be used as simply as this:
+
+ when
+ $c : Customer()
+then
+ GoldenCustomer gc = don( $c, Customer.class );
+end
+
+ when a core object dons a trait, a proxy class is created on the fly (one such class will be generated lazily for each
+ core/trait class combination). The proxy instance, which wraps the core object and implements the trait interface, is inserted
+ automatically and will possibly activate other rules. An immediate advantage of declaring and using interfaces, getting the
+ implementation proxy for free from the engine, is that multiple inheritance hierarchies can be exploited when writing rules.
+ The core classes, however, need not implement any of those interfaces statically, also facilitating the use of legacy classes as
+ cores. In fact, any object can don a trait. For efficiency reasons, however, one can add the @Traitable annotation to a declared
+ bean class to reduce the amount of glue code that the compiler will have to generate. This is optional and will not change the
+ behavior of the engine:
+
+ declare Customer
+ @Traitable
+ code : String
+ balance : long
+end
+
+ The only connection between core classes and trait interfaces is at the proxy level, a trait is not specifically tied to a
+ core class. This means that the same trait can be applied to totally different objects. For this reason, the trait does not
+ transparently expose the fields of its core object. So, when writing a rule using a trait interface, only the fields of the interface
+ will be available, as usual. However, any field in the interface that corresponds to a core object field, will be mapped by the proxy class:
+
+ when
+ $o: OrderItem( $p : price, $code : custCode )
+ $c: GoldenCustomer( code == $code, $a : balance, $d: discount )
+then
+ $c.setBalance( $a - $p*$d );
+end
+
+ In this case, the code and balance would be read from the underlying Customer object. Likewise, the setAccount will modify the
+ underlying object, preserving a strongly typed access to the data structures. Now, one might wonder what happens when a core class
+ does NOT provide the implementation for a field defined in an interface. We call hard fields those trait fields which are also core fields
+ and thus readily available, while we define soft those fields which are NOT provided by the core class. Hidden fields, instead, are fields
+ in the core class not exposed by the interface.
+
+ So, while hard field management is intuitive, there remains the problem of soft and hidden fields. The solution we have adopted
+ is to use a two-part proxy. Internally, proxies are formed by a proper proxy and a wrapper. The former implements the interface, while
+ the latter manages the core object fields, implementing a name/value map to supports soft fields. The proxy, then, uses both the core
+ object and the map wrapper to implement the interface, as needed. So, you can write:
+
+ when
+ $sc : GoldenCustomer( $c : code, // hard getter
+ $maxExpense : maxExpense > 1000 // soft getter
+ )
+then
+ $sc.setDiscount( ... ); // soft setter
+end
+
+ The wrapper, then, provides a looser form of typing when writing rules. However, it has also other uses. The wrapper is specific
+ to the object it wraps, regardless of how many traits have been attached to an object: all the proxies on the same object will share the
+ same wrapper. Secondly, the wrapper also contains a back-reference to all proxies attached to the wrapped object, effectively allowing
+ traits to see each other. To this end, we have provided the new isA operator:
+
+ $sc : GoldenCustomer( $maxExpense : maxExpense > 1000,
+ this isA "SeniorCustomer"
+)
+
+ Eventually, the business logic may require that a trait is removed from a wrapped object. To this end, we provide two options.
+ The first is a "logical don", which will result in a logical insertion of the proxy resulting from the traiting operation:
+
+ then
+ don( $x, // core object
+ Customer.class, // trait class
+ true // optional flag for logical insertion
+ )
+
+
+ The second is the use of the shed keyword, which causes the retraction of the proxy corresponding to the given argument type:
+
+ then
+ Thing t = shed( $x, GoldenCustomer.class )
+
+ This operation returns another proxy implementing the org.drools.factmodel.traits.Thing interface, where the getFields() and getCore()
+ methods are defined. Internally, in fact, all declared traits are generated to extend this interface (in addition to any others specified).
+ This allows to preserve the wrapper with the soft fields which would otherwise be lost.
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-XML.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-XML.xml
similarity index 96%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-XML.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-XML.xml
index 5f042bdc81..d878da6bf4 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-XML.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-LanguageReference/Section-XML.xml
@@ -5,15 +5,22 @@
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
XML Rule Language
-
+
+ The XML rule language has not been updated to support functionality
+ introduced in Drools 5.x and is consider a deprecated feature.
+ As an option, Drools also supports a "native" XML 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.
+ required.
+
+
+ Legacy Drools 2.x XML rule format
+ The Drools 2.x legacy XML format is no longer supported by Drools XML parser
+ When to use XML
@@ -57,9 +64,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<package name="com.sample"
- xmlns="http://drools.org/drools-4.0"
+ xmlns="http://drools.org/drools-5.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
- xs:schemaLocation="http://drools.org/drools-4.0 drools-4.0.xsd">
+ xs:schemaLocation="http://drools.org/drools-5.0 drools-5.0.xsd">
<import name="java.util.HashMap" />
<import name="org.drools.*" />
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Keywords.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Keywords.xml
deleted file mode 100644
index a18bcf794a..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Keywords.xml
+++ /dev/null
@@ -1,242 +0,0 @@
-
-
-
-
- (updated to Drools 5.0)
-
-
-
- Keywords
-
- Drools 5 introduces the concept of hard and
- soft keywords.
-
- Hard keywords are reserved, you cannot use any hard keyword when
- naming your domain objects, properties, methods, functions and other
- elements that are used in the rule text.
-
- Here is the list of hard keywords that must be avoided as identifiers
- when writing rules:
-
-
-
- true
-
-
-
- false
-
-
-
- accumulate
-
-
-
- collect
-
-
-
- from
-
-
-
- null
-
-
-
- over
-
-
-
- then
-
-
-
- when
-
-
-
- Soft keywords are just recognized in their context, enabling you to
- use these words in any other place you wish. Here is a list of the soft
- keywords:
-
-
-
- lock-on-active
-
-
-
- date-effective
-
-
-
- date-expires
-
-
-
- no-loop
-
-
-
- auto-focus
-
-
-
- activation-group
-
-
-
- agenda-group
-
-
-
- ruleflow-group
-
-
-
- entry-point
-
-
-
- duration
-
-
-
- package
-
-
-
- import
-
-
-
- dialect
-
-
-
- salience
-
-
-
- enabled
-
-
-
- attributes
-
-
-
- rule
-
-
-
- extend
-
-
-
- template
-
-
-
- query
-
-
-
- declare
-
-
-
- function
-
-
-
- global
-
-
-
- eval
-
-
-
- not
-
-
-
- in
-
-
-
- or
-
-
-
- and
-
-
-
- exists
-
-
-
- forall
-
-
-
- action
-
-
-
- reverse
-
-
-
- result
-
-
-
- end
-
-
-
- init
-
-
-
- Of course, you can have these (hard and soft) words as part of a
- method name in camel case, like notSomething() or accumulateSomething() -
- there are no issues with that scenario.
-
- Another improvement of the DRL language is the ability to escape hard
- keywords on rule text. This feature enables you to use your existing
- domain objects without worrying about keyword collision. To escape a word,
- simply enclose it in grave accents, like this:
-
- Holiday( `when` == "july" )
-
- The escape should be used everywehere in rule text, except within code
- expressions in the LHS or RHS code block. Here are examples of proper
- usage:
-
- rule "validate holiday by eval"
-dialect "mvel"
-when
- h1 : Holiday( )
- eval( h1.when == "july" )
-then
- System.out.println(h1.name + ":" + h1.when);
-end
-
-
- rule "validate holiday"
-dialect "mvel"
-when
- h1 : Holiday( `when` == "july" )
-then
- System.out.println(h1.name + ":" + h1.when);
-end
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Query.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Query.xml
deleted file mode 100644
index 538d82d7ac..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Query.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
- Query
-
-
- query
-
-
-
-
-
-
-
-
- A query is a simple way to search the working memory for facts that
- match the stated conditions. Therefore, it contains only the structure of
- the LHS of a rule, so that you specify neither "when" nor "then". A query
- has an optional set of parameters, each of which can be optionally typed. If
- the type is not given, the type Object is assumed. The engine will attempt
- to coerce the values as needed. Query names are global to the KnowledgeBase;
- so do not add queries of the same name to different packages for the same
- RuleBase.
-
- To return the results use
- ksession.getQueryResults("name"), where "name" is the query's
- name. This returns a list of query results, which allow you to retrieve the
- objects that matched the query.
-
- The first example presents a simple query for all the people over the
- age of 30. The second one, using parameters, combines the age limit with a
- location.
-
-
- Query People over the age of 30
-
- query "people over the age of 30"
- person : Person( age > 30 )
-end
-
-
-
- Query People over the age of x, and who live in y
-
- query "people over the age of x" (int x, String y)
- person : Person( age > x, location == y )
-end
-
-
- We iterate over the returned QueryResults using a standard "for" loop.
- Each element is a QueryResultsRow which we can use to access each of the
- columns in the tuple. These columns can be accessed by bound declaration
- name or index position.
-
-
- Query People over the age of 30
-
- QueryResults results = ksession.getQueryResults( "people over the age of 30" );
-System.out.println( "we have " + results.size() + " people over the age of 30" );
-
-System.out.println( "These people are are over 30:" );
-
-for ( QueryResultsRow row : results ) {
- Person person = ( Person ) row.get( "person" );
- System.out.println( person.getName() + "\n" );
-}
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Rule.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Rule.xml
deleted file mode 100644
index a161b20d0b..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-Rule.xml
+++ /dev/null
@@ -1,2525 +0,0 @@
-
-
- Rule
-
-
- rule
-
-
-
-
-
-
-
-
- A rule specifies that when a particular set of
- conditions occur, specified in the Left Hand Side (LHS),
- then do what is specified as a list of actions in the
- Right Hand Side (RHS). A common question from users is "Why use when instead
- of if?" "When" was chosen over "if" because "if" is normally part of a
- procedural execution flow, where, at a specific point in time, a condition
- is to be checked. In contrast, "when" indicates that the condition
- evaluation is not tied to a specific evaluation sequence or point in time,
- but that it happens continually, at any time during the life time of the
- engine; whenever the condition is met, the actions are executed.
-
- A rule must have a name, unique within its rule package. If you define
- a rule twice in the same DRL it produces an error while loading. If you add
- a DRL that includes a rule name already in the package, it replaces the
- previous rule. If a rule name is to have spaces, then it will need to be
- enclosd in double quotes (it is best to always use double quotes).
-
- Attributes - described below - are optional. They are best written one
- per line.
-
- The LHS of the rule follows the when keyword
- (ideally on a new line), similarly the RHS follows the
- then keyword (again, ideally on a newline). The rule is
- terminated by the keyword end. Rules cannot be
- nested.
-
-
- Rule Syntax Overview
-
- rule "<name>"
- <attribute>*
-when
- <conditional element>*
-then
- <action>*
-end
-
-
-
- A simple rule
-
- rule "Approve if not rejected"
- salience -100
- agenda-group "approval"
- when
- not Rejection()
- p : Policy(approved == false, policyState:status)
- exists Driver(age > 25)
- Process(status == policyState)
- then
- log("APPROVED: due to no objections.");
- p.setApproved(true);
-end
-
-
-
- Rule Attributes
-
- Rule attributes provide a declarative way to influence the behavior
- of the rule. Some are quite simple, while others are part of complex
- subsystems such as ruleflow. To get the most from Drools you should make
- sure you have a proper understanding of each attribute.
-
-
- rule attributes
-
-
-
-
-
-
-
-
-
-
- no-loop
-
-
- default value: false
-
- type: Boolean
-
- When the rule's consequence modifies a fact it may cause the
- Rule to activate again, causing recursion. Setting no-loop to true
- means the attempt to create the Activation for the current set of
- data will be ignored.
-
-
-
-
- ruleflow-group
-
-
- default value: N/A
-
- type: String
-
- Ruleflow is a Drools feature that lets you exercise control
- over the firing of rules. Rules that are assembled by the same
- ruleflow-group identifier fire only when their group is
- active.
-
-
-
-
- lock-on-active
-
-
- default value: false
-
- type: Boolean
-
- Whenever a ruleflow-group becomes active or an agenda-group
- receives the focus, any rule within that group that has
- lock-on-active set to true will not be activated any more;
- irrespective of the origin of the update, the activation of a
- matching rule is discarded. This is a stronger version of no-loop,
- because the change could now be caused not only by the rule itself.
- It's ideal for calculation rules where you have a number of rules
- that modify a fact and you don't want any rule re-matching and
- firing again. Only when the ruleflow-group is no longer active or
- the agenda-group loses the focus those rules with lock-on-active set
- to true become eligible again for their activations to be placed
- onto the agenda.
-
-
-
-
- salience
-
-
- default value: 0
-
- type: integer
-
- Each rule has a salience attribute that can be assigned an
- integer number, which defaults to zero and can be negative or
- positive. Salience is a form of priority where rules with higher
- salience values are given higher priority when ordered in the
- Activation queue.
- Drools also supports dynamic salience where you can use
- an expression involving bound variables.
-
-
- Dynamic Salience
- rule "Fire in rank order 1,2,.."
- salience( -$rank )
- when
- Element( $rank : rank,... )
- then
- ...
- end
-
-
-
-
-
- agenda-group
-
-
- default value: MAIN
-
- type: String
-
- Agenda groups allow the user to partition the Agenda providing
- more execution control. Only rules in the agenda group that has
- acquired the focus are allowed to fire.
-
-
-
-
- auto-focus
-
-
- default value: false
-
- type: Boolean
-
- When a rule is activated where the auto-focus
- value is true and the rule's agenda group does not have focus yet,
- then it is given focus, allowing the rule to potentially
- fire.
-
-
-
-
- activation-group
-
-
- default value: N/A
-
- type: String
-
- Rules that belong to the same activation-group, identified by
- this attribute's string value, will only fire exclusively. In other
- words, the first rule in an activation-group to fire will cancel the
- other rules' activations, i.e., stop them from firing.
-
- Note: This used to be called Xor group, but technically it's
- not quite an Xor. You may still hear people mention Xor group; just
- swap that term in your mind with activation-group.
-
-
-
-
- dialect
-
-
- default value: as specified by the package
-
- type: String
-
- possible values: "java" or "mvel"
-
- The dialect species the language to be used for any code
- expressions in the LHS or the RHS code block. Currently two dialects
- are available, Java and MVEL. While the dialect can be specified at
- the package level, this attribute allows the package definition to
- be overridden for a rule.
-
-
-
-
- date-effective
-
-
- default value: N/A
-
- type: String, containing a date and time definition
-
- A rule can only activate if the current date and time is after
- date-effective attribute.
-
-
-
-
- date-expires
-
-
- default value: N/A
-
- type: String, containing a date and time definition
-
- A rule cannot activate if the current date and time is after
- the date-expires attribute.
-
-
-
-
- duration
-
-
- default value: no default value
-
- type: long
-
- The duration dictates that the rule will fire after a
- specified duration, if it is still true.
-
-
-
-
-
- Some attribute examples
-
- rule "my rule"
- salience 42
- agenda-group "number 1"
- when ...
-
-
-
-
-
- Timers and Calendars
-
- Rule's now suport both interval and cron based timers, which replace
- the now deprecated duration attribute.
-
-
- Sample timer attribute uses
-
- timer ( int: <initial delay> <repeat interval>? )
-timer ( int: 30s )
-timer ( int: 30s 5m )
-
-timer ( cron: <cron expression> )
-timer ( cron:* 0/15 * * * ? )
-
-
- Interval "int:" timers follow the JDK semantics for initial delay
- optionally followed by a repeat interval. Cron "cron:" timers follow
- standard cron expressions:
-
-
- A Cron Example
-
- rule "Send SMS every 15 minutes"
- timer (cron:* 0/15 * * * ?)
-when
- $a : Alarm( on == true )
-then
- channels[ "sms" ].insert( new Sms( $a.mobileNumber, "The alarm is still on" );
-end
-
-
- Calendars may now be used to control when rules can fire. The Calendar API is
- modelled on Quartz
- http://www.quartz-scheduler.org/ :
-
-
- Adapting a Quartz Calendar
-
- Calendar weekDayCal = QuartzHelper.quartzCalendarAdapter(org.quartz.Calendar quartzCal)
-
-
- Calendars are registered with the StatefulKnowledgeSession:
-
-
- Registering a Calendar
-
- ksession.getCalendars().set( "week day", weekDayCal );
-
-
- They can be used in conjunction with normal rules and rules
- including timers. The rule calendar attribute can have one or more comma
- calendar names.
-
-
- Using Calendars and Timers together
-
- rule "weekdays are high priority"
- calendars "weekday"
- timer (int:0 1h)
-when
- Alarm()
-then
- send( "priority high - we have an alarm” );
-end
-
-rule "weekend are low priority"
- calendars "weekend"
- timer (int:0 4h)
-when
- Alarm()
-then
- send( "priority low - we have an alarm” );
-end
-
-
-
-
- Left Hand Side (when) Conditional Elements
-
- The Left Hand Side (LHS) is a common name for the conditional part
- of the rule. It consists of zero or more Conditional Elements. If the LHS
- is left empty, it is re-written as eval(true), which means
- that the rule's condition is always true. It will be activated, once, when
- a new Working Memory session is created.
-
-
- Left Hand Side
-
-
-
-
-
-
-
-
-
- Rule without a Conditional Element
-
- rule "no CEs"
-when
-then
- <action>*
-end
-
-# The above rule is internally rewritten as:
-
-rule "eval(true)"
-when
- eval( true )
-then
- <action>*
-end
-
-
- Conditional elements work on one or more
- patterns (which are described below). The most common
- one is and, which is implicit when you have multiple
- patterns in the LHS of a rule that are not connected in any way. Note that
- an and cannot have a leading declaration binding like
- or. This is obvious, since a declaration can only
- reference a single fact, and when the and is satisfied
- it matches more than one fact - so which fact would the declaration bind
- to?
-
-
- Pattern
-
- The pattern element is the most important Conditional Element. The
- entity relationship diagram below provides an overview of the various
- parts that make up the pattern's constraints and how they work together;
- each is then covered in more detail with railroad diagrams and
- examples.
-
-
- Pattern Entity Relationship Diagram
-
-
-
-
-
-
-
-
- At the top of the ER diagram you can see that the pattern consists
- of zero or more constraints and has an optional pattern binding. The
- railroad diagram below shows the syntax for this.
-
-
- Pattern
-
-
-
-
-
-
-
-
- In its simplest form, with no constraints, a pattern matches
- against a fact of the given type. In the following case the type is
- Cheese, which means that the pattern will match against all
- Cheese objects in the Working Memory.
-
- Notice that the type need not be the actual class of some fact
- object. Patterns may refer to superclasses or even interfaces, thereby
- potentially matching facts from many different classes.
-
-
- Simple Pattern
-
- Cheese()
-
-
- For referring to the matched object, use a pattern binding
- variable such as $c. The prefixed dollar symbol ('$') is
- optional; it can be useful in complex rules where it helps to more
- easily differentiate between variables and fields.
-
-
- Pattern with a binding variable
-
- $c : Cheese()
-
-
- Inside of the pattern parenthesis is where all the action happens.
- A constraint can be either a Field Constraint, Inline Eval, or a
- Constraint Group. Constraints can be separated by the following symbols:
- ',', '&&' or '||'.
-
-
- Constraints
-
-
-
-
-
-
-
-
-
- Constraint
-
-
-
-
-
-
-
-
-
- constraintGroup
-
-
-
-
-
-
-
-
- The comma character (',') is used to separate constraint groups.
- It has implicit and connective semantics.
- Constraint Group connective ','
-
- # Cheese type is stilton and price < 10 and age is mature.
-Cheese( type == "stilton", price < 10, age == "mature" )
- The above example has three constraint groups, each with a
- single constraint:
-
-
-
- Group 1 - type == "stilton" requires that the
- type is stilton.
-
-
-
- Group 2 - price < 10 demands a price less than
- 10.
-
-
-
- Group 3 - age == "mature" accepts only mature
- cheese.
-
-
-
- The '&&' (and) and '||' (or) constraint connectives allow
- constraint groups to have multiple constraints. Example:
-
-
- && and || Constraint Connectives
-
- // Cheese type is "stilton" and price < 10, and age is mature
-Cheese( type == "stilton" && price < 10, age == "mature" )
-// Cheese type is "stilton" or price < 10, and age is mature
-Cheese( type == "stilton" || price < 10, age == "mature" )
-
-
- The above example has two constraint groups. The first has two
- constraints and the second has one constraint.
-
- The connectives are evaluated in the following order, from first
- to last:
-
-
-
- &&
-
-
-
- ||
-
-
-
- ,
-
-
-
- It is possible to change the evaluation priority by using
- parentheses, as in any logic or mathematical expression. Example:
-
-
- Using parentheses to change evaluation priority
-
- # Cheese type is stilton and ( price is less than 20 or age is mature ).
-Cheese( type == "stilton" && ( price < 20 || age == "mature" ) )
-
-
- In the above example, the use of parentheses evaluates the
- connective '||' before the connective '&&'.
-
- Also, it is important to note that besides having the same
- semantics, the connectives '&&' and ',' are resolved with
- different priorities, and ',' cannot be embedded in a composite
- constraint expression.
-
-
- Not Equivalent connectives
-
- // invalid as ',' cannot be embedded in an expression:
-Cheese( ( type == "stilton", price < 10 ) || age == "mature" )
-// valid as '&&' can be embedded in an expression:
-Cheese( ( type == "stilton" && price < 10 ) || age == "mature")
-
-
-
- Field Constraints
-
- A Field constraint specifies a restriction to be used on a named
- field; the field name can have an optional variable binding.
-
-
- fieldConstraint
-
-
-
-
-
-
-
-
- There are three types of restrictions: Single Value Restriction,
- Compound Value Restriction, and Multi Restriction.
-
-
- restriction
-
-
-
-
-
-
-
-
-
- JavaBeans as facts
-
- A field is derived from an accessible method of the object. If
- your model objects follow the Java Bean pattern, then fields are
- exposed using "getXXX" or "isXXX" methods, where these methods take
- no arguments, and return something. Within patterns, fields can be
- accessed using the bean naming convention, so that "getType" would
- be accessed as "type". Drools uses the standard JDK Introspector
- class to do this mapping.
-
- For example, referring to our Cheese class, the pattern
- Cheese(type == "brie") applies the getType() method to
- a Cheese instance. If a field name cannot be found, the compiler
- will resort to using the name as a method without arguments. Thus,
- the method toString() is called due to a constraint
- Cheese(toString == "cheddar"). In this case, you use
- the full name of the method with correct capitalization, but still
- without parentheses. Do please make sure that you are accessing
- methods that take no parameters, and that are in fact
- accessors which don't change the state of the
- object in a way that may effect the rules. Remember that the rule
- engine effectively caches the results of its matching in between
- invocations to make it faster.
-
-
-
- Values
-
- The field constraints can take a number of values; including
- literal, qualifiedIdentifier (enum), variable and
- returnValue.
-
-
- literal
-
-
-
-
-
-
-
-
-
- qualifiedIdentifier
-
-
-
-
-
-
-
-
-
- variable
-
-
-
-
-
-
-
-
-
- returnValue
-
-
-
-
-
-
-
-
- You can do checks against fields that are or may be null,
- using '==' and '!=' as you would expect, and the literal
- null keyword, as in Cheese(type !=
- null), where the evaluator will not throw an exception and
- return true if the value is null. Type coercion is always attempted
- if the field and the value are of different types; exceptions will
- be thrown if a bad coercion is attempted. For instance, if "ten" is
- provided as a string in a numeric evaluator, an exception is thrown,
- whereas "10" would coerce to a numeric 10. Coercion is always in
- favor of the field type and not the value type.
-
-
-
- Single Value Restriction
-
-
- singleValueRestriction
-
-
-
-
-
-
-
-
- A Single Value Restriction is a binary relation, applying a
- binary operator to the field value and another value, which may be a
- literal, a variable, a parenthesized expression ("return value"), or
- a qualified identifier, i.e., an enum constant.
-
-
- Operators
-
-
- Operators
-
-
-
-
-
-
-
-
- The operators '==' and '!=' are valid for all types. Other
- relational operatory may be used whenever the type values are
- ordered; for date fields, '<' means "before". The pair
- matches and not matches is
- only applicable to string fields, contains and
- not contains require the field to be of some
- Collection type. Coercion to the correct value for the evaluator
- and the field will be attempted, as mentioned in the "Values"
- section.
-
-
- The Operator matches
-
- Matches a field against any valid Java
- regular expression
- Regular Expression. Typically that regexp is a
- string literal, but variables that resolve to a valid regexp are
- also allowed. It is important to note that, different
- from Java, within regular expressions written as
- string literals you don't need to escape
- '\'. Example:
-
-
- Regular Expression Constraint
-
- Cheese( type matches "(Buffalo)?\S*Mozarella" )
-
-
-
-
- The Operator not matches
-
- The operator returns true if the string does not match the
- regular expression. The same rules apply as for the
- matches operator. Example:
-
-
- Regular Expression Constraint
-
- Cheese( type not matches "(Buffulo)?\S*Mozarella" )
-
-
-
-
- The Operator contains
-
- The operator contains is used to check
- whether a field that is a
- Collection
- Collection or array contains the specified
- value.
-
-
- Contains with Collections
-
- CheeseCounter( cheeses contains "stilton" ) // contains with a String literal
-CheeseCounter( cheeses contains $var ) // contains with a variable
-
-
-
-
- The Operator not contains
-
- The operator not contains is used to
- check whether a field that is a
- Collection
- Collection or array does not
- contain the specified value.
-
-
- Literal Constraint with Collections
-
- CheeseCounter( cheeses not contains "cheddar" ) // not contains with a String literal
-CheeseCounter( cheeses not contains $var ) // not contains with a variable
-
-
-
-
- For backward compatibility, the
- excludes operator is supported as a
- synonym for not contains.
-
-
-
-
-
- The Operator memberOf
-
- The operator memberOf is used to check
- whether a field is a member of a collection or array; that
- collection must be a variable.
-
-
- Literal Constraint with Collections
-
- CheeseCounter( cheese memberOf $matureCheeses )
-
-
-
-
- The Operator not memberOf
-
- The operator not memberOf is used to
- check whether a field is not a member of a collection or array;
- that collection must be a variable.
-
-
- Literal Constraint with Collections
-
- CheeseCounter( cheese not memberOf $matureCheeses )
-
-
-
-
- The Operator soundslike
-
- This operator is similar to matches,
- but it checks whether a word has almost the same sound (using
- English pronounciation) as the given value. This is based on the
- Soundex algorithm (see
- http://en.wikipedia.org/wiki/Soundex).
-
-
- Test with soundslike
-
- // match cheese "fubar" or "foobar"
-Cheese( name soundslike 'foobar' )
-
-
-
-
- The Operator str
-
- This operator str is used to
- check whether a field that is a
- String
- String starts with or ends with with a certain value. It can also be used to check
- the length of the String.
-
- Test with str
-
- $m : Message( routingValue str[startsWith] "R1" )
- $m : Message( routingValue str[endsWith] "R2" )
- $m : Message( routingValue str[length] 17 )
-
-
-
-
-
-
-
- Literal Restrictions
-
- Literal restrictions are the simplest form of restrictions
- and evaluate a field against a specified literal, which may be
- numeric or a date, a string or a boolean.
-
-
- literalRestriction
-
-
-
-
-
-
-
-
- Literal Restrictions using the operator '==' provide for
- faster execution as we can index using hashing to improve
- performance.
-
-
- Numeric
-
- All standard Java numeric primitives are supported.
-
-
- Numeric Literal Restriction
-
- Cheese( quantity == 5 )
-
-
-
-
- Date
-
- The date format "dd-mmm-yyyy" is supported by default. You
- can customize this by providing an alternative date format mask
- as the System property named drools.dateformat. If
- more control is required, use the inline-eval constraint.
-
-
- Date Literal Restriction
-
- Cheese( bestBefore < "27-Oct-2009" )
-
-
-
-
- String
-
- Any valid Java String is allowed.
-
-
- String Literal Restriction
-
- Cheese( type == "stilton" )
-
-
-
-
- Boolean
-
- Only true or false can be used;
- 0 and 1 are not acceptable. A boolean field alone (as in
- Cheese( smelly ) is not permitted; you must compare
- this to a boolean literal.
-
-
- Boolean Literal Restriction
-
- Cheese( smelly == true )
-
-
-
-
- Qualified Identifier
-
- Enums can be used as well, both JDK 1.4 and 5 style enums
- are supported. For the latter you must be executing on a JDK 5
- environment.
-
-
- Boolean Literal Restriction
-
- Cheese( smelly == SomeClass.TRUE )
-
-
-
-
-
- Bound Variable Restriction
-
-
- variableRestriction
-
-
-
-
-
-
-
-
- Variables can be bound to facts and their fields and then
- used in subsequent Field Constraints. A bound variable is called a
-
- declaration
- Declaration. Valid operators are determined by the
- type of the field being constrained; coercion will be attempted
- where possible. Bound Variable Restrictions using the operator
- '==' provide for very fast execution as we can use hashing to
- improve performance.
-
-
- Bound Field using the operator '=='
-
- Person( likes : favouriteCheese )
-Cheese( type == likes )
-
-
- Here, likes is the variable that is bound in
- its declaration to the field favouriteCheese of any
- matching Person instance. It is then used to constrain the type of
- Cheese in the following pattern. Any valid Java variable name can
- be used, and it may be prefixed with a '$', which you will often
- see used to help differentiate declarations from fields. The
- example below shows a declaration for $stilton, bound
- to the object matching the first pattern and used with a
- contains operator. - Note the optional use of
- '$'.
-
-
- Bound Fact using 'contains' operator
-
- $stilton : Cheese( type == "stilton" )
-Cheesery( cheeses contains $stilton )
-
-
-
-
- Return Value Restriction
-
-
- returnValueRestriction
-
-
-
-
-
-
-
-
- A
- Return Value
- Return Value restriction is a parenthesized
- expression composed from literals, any valid Java primitive or
- object, previously bound variables, function calls, and operators.
- Functions used in a Return Value must return results that do not
- depend on time.
-
-
- Return Value Restriction
-
- Person( girlAge : age, sex == "F" )
-Person( age == ( girlAge + 2) ), sex == 'M' )
-
-
-
-
-
-
- Compound Value Restriction
-
- The compound value restriction is used where there is more
- than one possible value to match. Currently only the
- in and not in evaluators
- support this. The second operand of this operator must be a
- comma-separated list of values, enclosed in parentheses. Values may
- be given as variables, literals, return values or qualified
- identifiers. Both evaluators are actually "syntactic sugar",
- internally rewritten as a list of multiple restrictions using the
- operators '!=' and '=='.
-
-
- compoundValueRestriction
-
-
-
-
-
-
-
-
-
-
-
- Compound Restriction using "in"
-
- Person( $cheese : favouriteCheese )
-Cheese( type in ( "stilton", "cheddar", $cheese )
-
-
-
-
-
- Multi Restriction
-
- Multi restriction allows you to place more than one
- restriction on a field using the restriction connectives
- '&&' or '||'. Grouping via parentheses is permitted,
- resulting in a recursive syntax pattern.
-
-
- multiRestriction
-
-
-
-
-
-
-
-
-
- restrictionGroup
-
-
-
-
-
-
-
-
-
-
-
- Multi Restriction
-
- // Simple multi restriction using a single &&
-Person( age > 30 && < 40 )
-// Complex multi restriction using groupings of multi restrictions
-Person( age ( (> 30 && < 40) ||
- (> 20 && < 25) ) )
-// Mixing muti restrictions with constraint connectives
-Person( age > 30 && < 40 || location == "london" )
-
-
-
-
-
- Inline Eval Constraints
-
-
- Inline Eval Expression
-
-
-
-
-
-
-
-
- An
- Predicate
- inline eval constraint can use any valid dialect
- expression as long as it results to a primitive boolean. The
- expression must be constant over time. Any previously bound variable,
- from the current or previous pattern, can be used; autovivification is
- also used to auto-create field binding variables. When an identifier
- is found that is not a current variable, the builder looks to see if
- the identifier is a field on the current object type, if it is, the
- field binding is auto-created as a variable of the same name. This is
- called autovivification of field variables inside of inline
- evals.
-
- This example will find all male-female pairs where the male is 2
- years older than the female; the variable age is
- auto-created in the second pattern by the autovivification
- process.
-
-
- Return Value operator
-
- Person( girlAge : age, sex = "F" )
-Person( eval( age == girlAge + 2 ), sex = 'M' )
-
-
-
-
-
- Nested Accessors
-
- Drools permits nested accessors in in the
- field constraints using the MVEL accessor graph notation. Field
- constraints involving nested accessors are actually re-written as an
- MVEL dialect inline-eval. Care should be taken when using nested
- accessors as the Working Memory is not aware of any of the nested
- values, and does not know when they change; they should be considered
- immutable while any of their parent references are inserted into the
- Working Memory. If you wish to modify a nested value you should remove
- the parent objects first and re-assert afterwards. If you only have a
- single parent at the root of the graph, when in the MVEL dialect, you
- can use the modify construct and its block setters
- to write the nested accessor assignments while retracting and
- inserting the the root parent object as required. Nested accessors can
- be used on either side of the operator symbol.
-
-
- Nested Accessors
-
- // Find a pet older than its owners first-born child
-$p : Person( )
-Pet( owner == $p, age > $p.children[0].age )
-
- This is internally rewriten as an MVEL inline eval:
-
- // Find a pet older than its owners first-born child
-$p : Person( )
-Pet( owner == $p, eval( age > $p.children[0].age ) )
-
-
- Note: Nested accessors have a
- much greater performance cost than direct field accesses, so use them
- carefully.
-
-
-
-
- Conditional Element and
-
- The Conditional Element and is used to group
- other Conditional Elements into a logical conjunction. The root element
- of the LHS is an implicit prefix and and doesn't need
- to be specified. Drools supports both prefix and and
- infix and, but prefix is the preferred option as its
- implicit grouping avoids confusion.
-
-
- prefixAnd
-
-
-
-
-
-
-
-
-
-
-
- prefixAnd
-
- (and Cheese( cheeseType : type )
- Person( favouriteCheese == cheeseType ) )
-
-
-
-
- implicit root prefixAnd
-
- when
- Cheese( cheeseType : type )
- Person( favouriteCheese == cheeseType )
-
-
- Infix and is supported along with explicit
- grouping with parentheses, should it be needed. The symbol '&&',
- as an alternative to and, is deprecated although it
- is still supported in the syntax for legacy support reasons.
-
-
- infixAnd
-
-
-
-
-
-
-
-
-
- infixAnd
-
- //infixAnd
-Cheese( cheeseType : type ) and Person( favouriteCheese == cheeseType )
-//infixAnd with grouping
-( Cheese( cheeseType : type ) and
- ( Person( favouriteCheese == cheeseType ) or
- Person( favouriteCheese == cheeseType ) )
-
-
-
-
- Conditional Element or
-
- The Conditional Element or is used to group
- other Conditional Elements into a logical disjunction. Drools supports
- both prefix or and infix or, but
- prefix is the preferred option as its implicit grouping avoids
- confusion. The behavior of the Conditional Element or
- is different from the connective '||' for constraints and restrictions
- in field constraints. The engine actually has no understanding of the
- Conditional Element or; instead, via a number of
- different logic transformations, a rule with or is
- rewritten as a number of subrules. This process ultimately results in a
- rule that has a single or as the root node and one
- subrule for each of its CEs. Each subrule can activate and fire like any
- normal rule; there is no special behavior or interaction between these
- subrules. - This can be most confusing to new rule authors.
-
-
- prefixOr
-
-
-
-
-
-
-
-
-
- prefixOr
-
- (or Person( sex == "f", age > 60 )
- Person( sex == "m", age > 65 )
-
-
-
- Infix or is supported along with explicit
- grouping with parentheses, should it be needed. The symbol '||', as an
- alternative to or, is deprecated although it is still
- supported in the syntax for legacy support reasons.
-
-
- infixOr
-
-
-
-
-
-
-
-
-
- infixOr
-
- //infixOr
-Cheese( cheeseType : type ) or Person( favouriteCheese == cheeseType )
-//infixOr with grouping
-( Cheese( cheeseType : type ) or
- ( Person( favouriteCheese == cheeseType ) and
- Person( favouriteCheese == cheeseType ) )
-
-
- The Conditional Element or also allows for
- optional pattern binding. This means that each resulting subrule will
- bind its pattern to the pattern binding. Each pattern must be bound
- separately, using eponymous variables:
-
-
- or with binding
-
- (or pensioner : Person( sex == "f", age > 60 )
- pensioner : Person( sex == "m", age > 65 ) )
-
-
- Since the conditional element or results in
- multiple subrule generation, one for each possible logically outcome,
- the example above would result in the internal generation of two rules.
- These two rules work independently within the Working Memory, which
- means both can match, activate and fire - there is no
- shortcutting.
-
- The best way to think of the conditional element
- or is as a shortcut for generating two or more
- similar rules. When you think of it that way, it's clear that for a
- single rule there could be multiple activations if two or more terms of
- the disjunction are true.
-
-
-
- Conditional Element eval
-
-
- eval
-
-
-
-
-
-
-
-
- The CE eval is essentially a catch-all which
- allows any semantic code (that returns a primitive boolean) to be
- executed. This code can refer to variables that were bound in the LHS of
- the rule, and functions in the rule package. Overuse of eval reduces the
- declarativeness of your rules and can result in a poorly performing
- engine. While eval can be used anywhere in the
- patterns, the best practice is to add it as the last conditional element
- in the LHS of a rule.
-
- Evals cannot be indexed and thus are not as efficient as Field
- Constraints. However this makes them ideal for being used when functions
- return values that change over time, which is not allowed within Field
- Constraints.
-
- For folks who are familiar with Drools 2.x lineage, the old Drools
- parameter and condition tags are equivalent to binding a variable to an
- appropriate type, and then using it in an eval node.
-
-
- eval
-
- p1 : Parameter()
-p2 : Parameter()
-eval( p1.getList().containsKey(p2.getItem()) )
-// call function isValid in the LHS
-eval( isValid(p1, p2) )
-
-
-
-
- Conditional Element not
-
-
- not
-
-
-
-
-
-
-
-
- The CE not is first order logic's
- non-existential quantifier and checks for the non-existence of something
- in the Working Memory. Think of "not" as meaning "there must be none
- of...".
-
- The keyword not be followed by parentheses
- around the CEs that it applies to. In the simplest case of a single
- pattern (like below) you may optionally omit the parentheses.
-
-
- No Busses
-
- not Bus()
-
-
-
- No red Busses
-
- // Brackets are optional:
-not Bus(color == "red")
-// Brackets are optional:
-not ( Bus(color == "red", number == 42) )
-// "not" with nested infix and - two patterns,
-// brackets are requires:
-not ( Bus(color == "red") and
- Bus(color == "blue") )
-
-
-
-
- Conditional Element exists
-
-
- exists
-
-
-
-
-
-
-
-
- The CE exists is first order logic's
- existential quantifier and checks for the existence of something in the
- Working Memory. Think of "exists" as meaning "there is at least one..".
- It is different from just having the pattern on its own, which is more
- like saying "for each one of...". If you use exists
- with a pattern, the rule will only activate at most once, regardless of
- how much data there is in working memory that matches the condition
- inside of the exists pattern. Since only the
- existence matters, no bindings will be established.
-
- The keyword exists must be followed by
- parentheses around the CEs that it applies to. In the simplest case of a
- single pattern (like below) you may omit the parentheses.
-
-
- At least one Bus
-
- exists Bus()
-
-
-
- At least one red Bus
-
- exists Bus(color == "red")
-// brackets are optional:
-exists ( Bus(color == "red", number == 42) )
-// "exists" with nested infix and,
-// brackets are required:
-exists ( Bus(color == "red") and
- Bus(color == "blue") )
-
-
-
-
- Conditional Element forall
-
-
- forall
-
-
-
-
-
-
-
-
- The Conditional Element forall completes the
- First Order Logic support in Drools. The Conditional Element
- forall evaluates to true when all facts that match
- the first pattern match all the remaining patterns. Example:
-
- rule "All English buses are red"
-when
- forall( $bus : Bus( type == 'english')
- Bus( this == $bus, color = 'red' ) )
-then
- # all english buses are red
-end
-
-
- In the above rule, we "select" all Bus objects whose type is
- "english". Then, for each fact that matches this pattern we evaluate the
- following patterns and if they match, the forall CE will evaluate to
- true.
-
- To state that all facts of a given type in the working memory must
- match a set of constraints, forall can be written
- with a single pattern for simplicity. Example:
-
-
- Single Pattern Forall
-
- rule "All Buses are Red"
-when
- forall( Bus( color == 'red' ) )
-then
- # all asserted Bus facts are red
-end
-
-
-
- Another example shows multiple patterns inside the
- forall:
-
-
- Multi-Pattern Forall
-
- rule "all employees have health and dental care programs"
-when
- forall( $emp : Employee()
- HealthCare( employee == $emp )
- DentalCare( employee == $emp )
- )
-then
- # all employees have health and dental care
-end
-
-
-
- Forall can be nested inside other CEs.
- For instance, forall can be used inside a
- not CE. Note that only single patterns have optional
- parentheses, so that with a nested forall
- parentheses must be used:
-
-
- Combining Forall with Not CE
-
- rule "not all employees have health and dental care"
-when
- not ( forall( $emp : Employee()
- HealthCare( employee == $emp )
- DentalCare( employee == $emp ) )
- )
-then
- # not all employees have health and dental care
-end
-
-
-
- As a side note, forall( p1 p2 p3...) is
- equivalent to writing:
-
- not(p1 and not(and p2 p3...))
-
- Also, it is important to note that forall is a
- scope delimiter. Therefore, it can use any
- previously bound variable, but no variable bound inside it will be
- available for use outside of it.
-
-
-
- Conditional Element from
-
-
- from
-
-
-
-
-
-
-
-
- The Conditional Element from enables users to
- specify an arbitrary source for data to be matched by LHS patterns. This
- allows the engine to reason over data not in the Working Memory. The
- data source could be a sub-field on a bound variable or the results of a
- method call. It is a powerful construction that allows out of the box
- integration with other application components and frameworks. One common
- example is the integration with data retrieved on-demand from databases
- using hibernate named queries.
-
- The expression used to define the object source is any expression
- that follows regular MVEL syntax. Therefore, it allows you to easily use
- object property navigation, execute method calls and access maps and
- collections elements.
-
- Here is a simple example of reasoning and binding on another
- pattern sub-field:
-
- rule "validate zipcode"
-when
- Person( $personAddress : address )
- Address( zipcode == "23920W") from $personAddress
-then
- # zip code is ok
-end
-
-
- With all the flexibility from the new expressiveness in the Drools
- engine you can slice and dice this problem many ways. This is the same
- but shows how you can use a graph notation with the 'from':
-
- rule "validate zipcode"
-when
- $p : Person( )
- $a : Address( zipcode == "23920W") from $p.address
-then
- # zip code is ok
-end
-
-
- Previous examples were evaluations using a single pattern. The CE
- from also support object sources that return a
- collection of objects. In that case, from will
- iterate over all objects in the collection and try to match each of them
- individually. For instance, if we want a rule that applies 10% discount
- to each item in an order, we could do:
-
- rule "apply 10% discount to all items over US$ 100,00 in an order"
-when
- $order : Order()
- $item : OrderItem( value > 100 ) from $order.items
-then
- # apply discount to $item
-end
-
-
- The above example will cause the rule to fire once for each item
- whose value is greater than 100 for each given order.
-
- You must take caution, however, when using
- from, especially in conjunction with the
- lock-on-active rule attribute as it may produce
- unexpected results. Consider the example provided earlier, but now
- slightly modified as follows:
-
- rule "Assign people in North Carolina (NC) to sales region 1"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person( )
- $a : Address( state == "NC") from $p.address
-then
- modify ($p) {} #Assign person to sales region 1 in a modify block
-end
-
-rule "Apply a discount to people in the city of Raleigh"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person( )
- $a : Address( city == "Raleigh") from $p.address
-then
- modify ($p) {} #Apply discount to person in a modify block
-end
-
-
- In the above example, persons in Raleigh, NC should be assigned to
- sales region 1 and receive a discount; i.e., you would expect both rules
- to activate and fire. Instead you will find that only the second rule
- fires.
-
- If you were to turn on the audit log, you would also see that when
- the second rule fires, it deactivates the first rule. Since the rule
- attribute lock-on-active prevents a rule from
- creating new activations when a set of facts change, the first rule
- fails to reactivate. Though the set of facts have not changed, the use
- of from returns a new fact for all intents and
- purposes each time it is evaluated.
-
- First, it's important to review why you would use the above
- pattern. You may have many rules across different rule-flow groups. When
- rules modify working memory and other rules downstream of your RuleFlow
- (in different rule-flow groups) need to be reevaluated, the use of
- modify is critical. You don't, however, want other
- rules in the same rule-flow group to place activations on one another
- recursively. In this case, the no-loop attribute is
- ineffective, as it would only prevent a rule from activating itself
- recursively. Hence, you resort to
- lock-on-active.
-
- There are several ways to address this issue:
-
-
-
- Avoid the use of from when you can assert
- all facts into working memory or use nested object references in
- your constraint expressions (shown below).
-
-
-
- Place the variable assigned used in the modify block as the
- last sentence in your condition (LHS).
-
-
-
- Avoid the use of lock-on-active when you
- can explicitly manage how rules within the same rule-flow group
- place activations on one another (explained below).
-
-
-
- The preferred solution is to minimize use of
- from when you can assert all your facts into working
- memory directly. In the example above, both the Person and Address
- instance can be asserted into working memory. In this case, because the
- graph is fairly simple, an even easier solution is to modify your rules
- as follows:
-
- rule "Assign people in North Carolina (NC) to sales region 1"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person(address.state == "NC" )
-then
- modify ($p) {} #Assign person to sales region 1 in a modify block
-end
-
-rule "Apply a discount to people in the city of Raleigh"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person(address.city == "Raleigh" )
-then
- modify ($p) {} #Apply discount to person in a modify block
-end
-
-
- Now, you will find that both rules fire as expected. However, it
- is not always possible to access nested facts as above. Consider an
- example where a Person holds one or more Addresses and you wish to use
- an existential quantifier to match people with at least one address that
- meets certain conditions. In this case, you would have to resort to the
- use of from to reason over the collection.
-
- There are several ways to use from to achieve
- this and not all of them exhibit an issue with the use of
- lock-on-active. For example, the following use of
- from causes both rules to fire as expected:
-
- rule "Assign people in North Carolina (NC) to sales region 1"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person($addresses : addresses)
- exists (Address(state == "NC") from $addresses)
-then
- modify ($p) {} #Assign person to sales region 1 in a modify block
-end
-
-rule "Apply a discount to people in the city of Raleigh"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person($addresses : addresses)
- exists (Address(city == "Raleigh") from $addresses)
-then
- modify ($p) {} #Apply discount to person in a modify block
-end
-
-
- However, the following slightly different approach does exhibit
- the problem:
-
- rule "Assign people in North Carolina (NC) to sales region 1"
-ruleflow-group "test"
-lock-on-active true
-when
- $assessment : Assessment()
- $p : Person()
- $addresses : List() from $p.addresses
- exists (Address( state == "NC") from $addresses)
-then
- modify ($assessment) {} #Modify assessment in a modify block
-end
-
-rule "Apply a discount to people in the city of Raleigh"
-ruleflow-group "test"
-lock-on-active true
-when
- $assessment : Assessment()
- $p : Person()
- $addresses : List() from $p.addresses
- exists (Address( city == "Raleigh") from $addresses)
-then
- modify ($assessment) {} #Modify assessment in a modify block
-end
-
- In the above example, the $addresses variable is returned from the
- use of from. The example also introduces a new
- object, assessment, to highlight one possible solution in this case. If
- the $assessment variable assigned in the condition (LHS) is moved to the
- last condition in each rule, both rules fire as expected.
-
- Though the above examples demonstrate how to combine the use of
- from with lock-on-active where no
- loss of rule activations occurs, they carry the drawback of placing a
- dependency on the order of conditions on the LHS. In addition, the
- solutions present greater complexity for the rule author in terms of
- keeping track of which conditions may create issues.
-
- A better alternative is to assert more facts into working memory.
- In this case, a person's addresses may be asserted into working memory
- and the use of from would not be necessary.
-
- There are cases, however, where asserting all data into working
- memory is not practical and we need to find other solutions. Another
- option is to reevaluate the need for lock-on-active.
- An alternative to lock-on-active is to directly
- manage how rules within the same rule-flow group activate one another by
- including conditions in each rule that prevent rules from activating
- each other recursively when working memory is modified. For example, in
- the case above where a discount is applied to citizens of Raleigh, a
- condition may be added to the rule that checks whether the discount has
- already been applied. If so, the rule does not activate.
-
-
-
- Conditional Element collect
-
-
- collect
-
-
-
-
-
-
-
-
- The Conditional Element collect allows rules to
- reason over a collection of objects obtained from the given source or
- from the working memory. In First Oder Logic terms this is the
- cardinality quantifier. A simple example:
-
- import java.util.ArrayList
-
-rule "Raise priority if system has more than 3 pending alarms"
-when
- $system : System()
- $alarms : ArrayList( size >= 3 )
- from collect( Alarm( system == $system, status == 'pending' ) )
-then
- # Raise priority, because system $system has
- # 3 or more alarms pending. The pending alarms
- # are $alarms.
-end
-
-
- In the above example, the rule will look for all pending alarms in
- the working memory for each given system and group them in ArrayLists.
- If 3 or more alarms are found for a given system, the rule will
- fire.
-
- The result pattern of collect can be any
- concrete class that implements the java.util.Collection
- interface and provides a default no-arg public constructor. This means
- that you can use Java collections like ArrayList, LinkedList, HashSet,
- etc., or your own class, as long as it implements the
- java.util.Collection interface and provide a default no-arg
- public constructor.
-
- Both source and result patterns can be constrained as any other
- pattern.
-
- Variables bound before the collect CE are in
- the scope of both source and result patterns and therefore you can use
- them to constrain both your source and result patterns. But note that
- collect is a scope delimiter for bindings, so that
- any binding made inside of it is not available for use outside of
- it.
-
- Collect accepts nested from CEs. The following
- example is a valid use of "collect":
-
- import java.util.LinkedList;
-
-rule "Send a message to all mothers"
-when
- $town : Town( name == 'Paris' )
- $mothers : LinkedList()
- from collect( Person( gender == 'F', children > 0 )
- from $town.getPeople()
- )
-then
- # send a message to all mothers
-end
-
-
-
-
- Conditional Element accumulate
-
-
- accumulate
-
-
-
-
-
-
-
-
- The Conditional Element accumulate is a more
- flexible and powerful form of collect, the sense that
- it can be used to do what collect does and also
- achieve things that the CE collect is not capable of
- doing. Basically, what it does is that it allows a rule to iterate over
- a collection of objects, executing custom actions for each of the
- elements, and at the end it returns a result object.
-
- The general syntax of the accumulate CE
- is:
-
- <result pattern>from accumulate(<source pattern>,
- init(<init code>),
- action(<action code>),
- reverse(<reverse code>),
- result(<result expression>) )
-
-
- The meaning of each of the elements is the following:
-
-
-
- <source pattern>: the source
- pattern is a regular pattern that the engine will try to match
- against each of the source objects.
-
-
-
- <init code>: this is a semantic
- block of code in the selected dialect that will be executed once for
- each tuple, before iterating over the source objects.
-
-
-
- <action code>: this is a semantic
- block of code in the selected dialect that will be executed for each
- of the source objects.
-
-
-
- <reverse code>: this is an optional
- semantic block of code in the selected dialect that if present will
- be executed for each source object that no longer matches the source
- pattern. The objective of this code block is to undo any calculation
- done in the <action code> block, so that
- the engine can do decremental calculation when a source object is
- modified or retracted, hugely improving performance of these
- operations.
-
-
-
- <result expression>: this is a
- semantic expression in the selected dialect that is executed after
- all source objects are iterated.
-
-
-
- <result pattern>: this is a regular
- pattern that the engine tries to match against the object returned
- from the <result expression>. If it
- matches, the accumulate conditional element
- evaluates to true and the engine proceeds with
- the evaluation of the next CE in the rule. If it does not matches,
- the accumulate CE evaluates to
- false and the engine stops evaluating CEs for
- that rule.
-
-
-
- It is easier to understand if we look at an example:
-
- rule "Apply 10% discount to orders over US$ 100,00"
-when
- $order : Order()
- $total : Number( doubleValue > 100 )
- from accumulate( OrderItem( order == $order, $value : value ),
- init( double total = 0; ),
- action( total += $value; ),
- reverse( total -= $value; ),
- result( total ) )
-then
- # apply discount to $order
-end
-
-
- In the above example, for each Order in the Working
- Memory, the engine will execute the init code
- initializing the total variable to zero. Then it will iterate over all
- OrderItem objects for that order, executing the
- action for each one (in the example, it will sum
- the value of all items into the total variable). After iterating over
- all OrderItem objects, it will return the value
- corresponding to the result expression (in the
- above example, the value of variable total). Finally, the
- engine will try to match the result with the Number
- pattern, and if the double value is greater than 100, the rule will
- fire.
-
- The example used Java as the semantic dialect, and as such, note
- that the usage of the semicolon as statement delimiter is mandatory in
- the init, action and reverse code blocks. The result is an expression
- and, as such, it does not admit ';'. If the user uses any other dialect,
- he must comply to that dialect's specific syntax.
-
- As mentioned before, the reverse code is
- optional, but it is strongly recommended that the user writes it in
- order to benefit from the improved performance on update and
- retract.
-
- The accumulate CE can be used to execute any
- action on source objects. The following example instantiates and
- populates a custom object:
-
- rule "Accumulate using custom objects"
-when
- $person : Person( $likes : likes )
- $cheesery : Cheesery( totalAmount > 100 )
- from accumulate( $cheese : Cheese( type == $likes ),
- init( Cheesery cheesery = new Cheesery(); ),
- action( cheesery.addCheese( $cheese ); ),
- reverse( cheesery.removeCheese( $cheese ); ),
- result( cheesery ) );
-then
- // do something
-end
-
-
- Accumulate Functions
-
- The accumulate CE is a very powerful CE, but it gets real
- declarative and easy to use when using predefined functions that are
- known as Accumulate Functions. They work exactly like accumulate, but
- instead of explicitly writing custom code in every accumulate CE, the
- user can use predefined code for common operations.
-
- For instance, the rule to apply discount on orders written in
- the previous section, could be written in the following way, using
- Accumulate Functions:
-
- rule "Apply 10% discount to orders over US$ 100,00"
-when
- $order : Order()
- $total : Number( doubleValue > 100 )
- from accumulate( OrderItem( order == $order, $value : value ),
- sum( $value ) )
-then
- # apply discount to $order
-end
-
-
- In the above example, sum is an Accumulate Function and will sum
- the $value of all OrderItems and return the result.
-
- Drools ships with the following built-in accumulate
- functions:
-
-
-
- average
-
-
-
- min
-
-
-
- max
-
-
-
- count
-
-
-
- sum
-
-
-
- These common functions accept any expression as input. For
- instance, if someone wants to calculate the average profit on all
- items of an order, a rule could be written using the average
- function:
-
- rule "Average profit"
-when
- $order : Order()
- $profit : Number()
- from accumulate( OrderItem( order == $order, $cost : cost, $price : price )
- average( 1 - $cost / $price ) )
-then
- # average profit for $order is $profit
-end
-
-
- Accumulate Functions are all pluggable. That means that if
- needed, custom, domain specific functions can easily be added to the
- engine and rules can start to use them without any restrictions. To
- implement a new Accumulate Functions all one needs to do is to create
- a Java class that implements the
- org.drools.base.acumulators.AccumulateFunction interface
- and add a line to the configuration file or set a system property to
- let the engine know about the new function. As an example of an
- Accumulate Function implementation, the following is the
- implementation of the average function:
-
- /*
- * Copyright 2007 JBoss Inc
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Created on Jun 21, 2007
- */
-package org.drools.base.accumulators;
-
-
-/**
- * An implementation of an accumulator capable of calculating average values
- *
- * @author etirelli
- *
- */
-public class AverageAccumulateFunction implements AccumulateFunction {
-
- protected static class AverageData {
- public int count = 0;
- public double total = 0;
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#createContext()
- */
- public Object createContext() {
- return new AverageData();
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
- */
- public void init(Object context) throws Exception {
- AverageData data = (AverageData) context;
- data.count = 0;
- data.total = 0;
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object,
- * java.lang.Object)
- */
- public void accumulate(Object context,
- Object value) {
- AverageData data = (AverageData) context;
- data.count++;
- data.total += ((Number) value).doubleValue();
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object,
- * java.lang.Object)
- */
- public void reverse(Object context,
- Object value) throws Exception {
- AverageData data = (AverageData) context;
- data.count--;
- data.total -= ((Number) value).doubleValue();
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
- */
- public Object getResult(Object context) throws Exception {
- AverageData data = (AverageData) context;
- return new Double( data.count == 0 ? 0 : data.total / data.count );
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
- */
- public boolean supportsReverse() {
- return true;
- }
-
-}
-
-
- The code for the function is very simple, as we could expect, as
- all the "dirty" integration work is done by the engine. Finally, to
- plug the function into the engine, we added it to the configuration
- file:
-
- drools.accumulate.function.average =
- org.drools.base.accumulators.AverageAccumulateFunction
-
-
- Here, "drools.accumulate.function." is a prefix that must always
- be used, "average" is how the function will be used in the rule file,
- and "org.drools.base.accumulators.AverageAccumulateFunction" is the
- fully qualified name of the class that implements the function
- behavior.
-
-
-
-
-
- The Right Hand Side (then)
-
-
- Usage
-
- The Right Hand Side (RHS) is a common name for the consequence or
- action part of the rule; this part should contain a list of actions to
- be executed. It is bad practice to use imperative or conditional code in
- the RHS of a rule; as a rule should be atomic in nature - "when this,
- then do this", not "when this, maybe do this". The RHS part of a rule
- should also be kept small, thus keeping it declarative and readable. If
- you find you need imperative and/or conditional code in the RHS, then
- maybe you should be breaking that rule down into multiple rules. The
- main purpose of the RHS is to insert, retractor modify working memory
- data. To assist with that there are a few convenience methods you can
- use to modify working memory; without having to first reference a
- working memory instance.
-
- update(object,
- handle); will tell the engine that an
- object has changed (one that has been bound to something on the LHS) and
- rules may need to be reconsidered.
-
- update(object);
- can also be used; here the Knowledge Helper will look up the facthandle
- for you, via an identity check, for the passed object. (Note that if you
- provide Property Change Listeners to your Java beans that you are
- inserting into the engine, you can avoid the need to call
- update() when the object changes.)
-
- insert(new
- Something()); will place a new
- object of your creation into the Working Memory.
-
- insertLogical(new
- Something()); is similar to
- insert, but the object will be automatically retracted when there are no
- more facts to support the truth of the currently firing rule.
-
- retract(handle);
- removes an object from Working Memory.
-
- These convenience methods are basically macros that provide short
- cuts to the KnowledgeHelper instance that lets you access
- your Working Memory from rules files. The predefined variable
- drools of type KnowledgeHelper lets you call
- several other useful methods. (Refer to the KnowledgeHelper
- interface documentation for more advanced operations).
-
-
-
- The call drools.halt() terminates rule execution
- immediately. This is required for returning control to the point
- whence the current session was put to work with
- fireUntilHalt().
-
-
-
- Methods insert(Object o), update(Object
- o) and retract(Object o) can be called on
- drools as well, but due to their frequent use they can
- be called without the object reference.
-
-
-
- drools.getWorkingMemory() returns the
- WorkingMemory object.
-
-
-
- drools.setFocus( String s) sets the focus to the
- specified agenda group.
-
-
-
- drools.getRule().getName(), called from a rule's
- RHS, returns the name of the rule.
-
-
-
- drools.getTuple() returns the Tuple that matches
- the currently executing rule, and
- drools.getActivation() delivers the corresponding
- Activation. (These calls are useful for logging and debugging
- purposes.)
-
-
-
- The full Knowlege Runtime API is exposed through another
- predefined variable, kcontext, of type
- KnowledgeContext. Its method
- getKnowledgeRuntime() delivers an object of type
- KnowledgeRuntime, which, in turn, provides access to a
- wealth of methods, many of which are quite useful for coding RHS
- logic.
-
-
-
- The call kcontext.getKnowledgeRuntime().halt()
- terminates rule execution immediately.
-
-
-
- The accessor getAgenda() returns a reference to
- this session's Agenda, which in turn provides access to
- the various rule groups: activation groups, agenda groups, and rule
- flow groups. A fairly common paradigm is the activation of some
- agenda group, which could be done with the lengthy call:
-
-
-// give focus to the agenda group CleanUp
-kcontext.getKnowledgeRuntime().getAgenda().getAgendaGroup( "CleanUp" ).setFocus();
-
- (You can achieve the same using drools.setFocus(
- "CleanUp" ).)
-
-
-
- To run a query, you call getQueryResults(String
- query), whereupon you may process the results, as explained
- in section .
-
-
-
- A set of methods dealing with event management lets you, among
- other things, add and remove event listeners for the Working Memory
- and the Agenda.
-
-
-
- MethodgetKnowledgeBase() returns the
- KnowledgeBase object, the backbone of all the Knowledge
- in your system, and the originator of the current session.
-
-
-
- You can manage globals with setGlobal(...),
- getGlobal(...) and getGlobals().
-
-
-
- Method getEnvironment() returns the runtime's
- Environment which works much like what you know as your
- operating system's environment.
-
-
-
-
-
- The modify Statement
-
- This language extension provides a structured approach to fact
- updates. It combines the update operation with a number of setter calls
- to change the object's fields. This is the syntax schema for the
- modify statement:
-
- modify ( <fact-expression> ) {
- <expression> [ ,<expression> ]*
-}
-
- The parenthesized <fact-expression>
- must yield a fact object reference. The expression list in the block
- should consist of setter calls for the given object, to be written
- without the usual object reference, which is automatically prepended by
- the compiler.
-
- The example illustrates a simple fact modification.
-
-
- A modify statement
-
- rule "modify stilton"
-when
- $stilton : Cheese(type == "stilton")
-then
- modify( $stilton ){
- setPrice( 20 ),
- setAge( "overripe" )
- }
-end
-
-
-
-
-
- A Note on Auto-boxing and Primitive Types
-
- Drools attempts to preserve numbers in their primitive or object
- wrapper form, so a variable bound to an int primitive when used in a code
- block or expression will no longer need manual unboxing; unlike Drools 3.0
- where all primitives were autoboxed, requiring manual unboxing. A variable
- bound to an object wrapper will remain as an object; the existing JDK 1.5
- and JDK 5 rules to handle auto-boxing and unboxing apply in this case.
- When evaluating field constraints, the system attempts to coerce one of
- the values into a comparable format; so a primitive is comparable to an
- object wrapper.
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-TypeDeclaration.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-TypeDeclaration.xml
deleted file mode 100644
index b75065fd81..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Language_Reference/Section-TypeDeclaration.xml
+++ /dev/null
@@ -1,337 +0,0 @@
-
-
- Type Declaration
-
-
- meta_data
-
-
-
-
-
-
-
-
-
- type_declaration
-
-
-
-
-
-
-
-
- Type declarations have two main goals in the rules engine: to allow
- the declaration of new types, and to allow the declaration of metadata for
- types.
-
-
-
- Declaring new types: Drools works
- out of the box with plain Java objects as facts. Sometimes, however, users
- may want to define the model directly to the rules engine, without
- worrying about creating models in a lower level language like Java. At
- other times, there is a domain model already built, but eventually the
- user wants or needs to complement this model with additional entities
- that are used mainly during the reasoning process.
-
-
-
- Declaring metadata: facts may
- have meta information associated to them. Examples of meta information
- include any kind of data that is not represented by the fact attributes
- and is consistent among all instances of that fact type. This meta
- information may be queried at runtime by the engine and used in the
- reasoning process.
-
-
-
-
- Declaring New Types
-
- To declare a new type, all you need to do is use the keyword
- declare, followed by the list of fields, and the keyword
- end.
-
-
- Declaring a new fact type: Address
-
- declare Address
- number : int
- streetName : String
- city : String
-end
-
-
-
- The previous example declares a new fact type called
- Address. This fact type will have three attributes:
- number, streetName and city.
- Each attribute has a type that can be any valid
- Java type, including any other class created by the user or even other
- fact types previously declared.
-
- For instance, we may want to declare another fact type
- Person:
-
-
- declaring a new fact type: Person
-
- declare Person
- name : String
- dateOfBirth : java.util.Date
- address : Address
-end
-
-
- As we can see on the previous example,
- dateOfBirth is of type java.util.Date,
- from the Java API, while address is of the previously
- defined fact type Address.
-
- You may avoid having to write the fully qualified name of a class
- every time you write it by using the import clause, as previously
- discussed.
-
-
- Avoiding the need to use fully qualified class names by using
- import
-
- import java.util.Date
-
-declare Person
- name : String
- dateOfBirth : Date
- address : Address
-end
-
-
- When you declare a new fact type, Drools will, at compile time,
- generate bytecode that implements a Java class representing the fact
- type. The
- generated Java class will be a one-to-one Java Bean mapping of the type
- definition. So, for the previous example, the generated Java class would
- be:
-
-
- generated Java class for the previous Person fact type
- declaration
-
- public class Person implements Serializable {
- private String name;
- private java.util.Date dateOfBirth;
- private Address address;
-
- // getters and setters
- // equals/hashCode
- // toString
-}
-
-
- Since the generated class is a simple Java class, it can
- be used transparently in the rules, like any other fact.
-
-
- Using the declared types in rules
-
- rule "Using a declared Type"
-when
- $p : Person( name == "Bob" )
-then
- // Insert Mark, who is Bob's mate.
- Person mark = new Person();
- mark.setName("Mark");
- insert( mark );
-end
-
-
-
-
-
- Declaring Metadata
-
- Metadata may be assigned to several different constructions in
- Drools: fact types, fact attributes and rules. Drools uses the
- at sign ('@') to introduce metadata, and it always uses the form:
-
- @metadata_key( metadata_value )
- The parenthesized metadata_value is optional.
-
- For instance, if you want to declare a metadata attribute like
- author, whose value is Bob, you
- could simply write:
-
-
- Declaring a metadata attribute
-
- @author( Bob )
-
-
- Drools allows the declaration of any arbitrary metadata attribute,
- but some will have special meaning to the engine, while others are simply
- available for querying at runtime. Drools allows the declaration of
- metadata both for fact types and for fact attributes. Any metadata that is
- declared before the fields of a fact type are assigned to the fact type,
- while metadata declared after an attribute are assigned to that
- particular attribute.
-
-
- Declaring metadata attributes for fact types and
- attributes
-
- import java.util.Date
-
-declare Person
- @author( Bob )
- @dateOfCreation( 01-Feb-2009 )
-
- name : String @key @maxLength( 30 )
- dateOfBirth : Date
- address : Address
-end
-
-
- In the previous example, there are two metadata items declared for the
- fact type (@author and @dateOfCreation) and two
- more defined for the name attribute (@key and
- @maxLength). Please note that the @key metadata
- has no value, and so the parentheses and the value were omitted.
-
-
-
- Declaring Metadata for Existing Types
-
- Drools allows the declaration of metadata attributes for existing
- types in the same way as when declaring metadata attributes for new fact
- types. The only difference is that there are no fields in that
- declaration.
-
- For instance, if there is a class org.drools.examples.Person, and
- one wants to declare metadata for it, it's possible to write the following
- code:
-
-
- Declaring metadata for an existing type
-
- import org.drools.examples.Person
-
-declare Person
- @author( Bob )
- @dateOfCreation( 01-Feb-2009 )
-end
-
-
-
- Instead of using the import, it is also possible to reference the
- class by its fully qualified name, but since the class will also be
- referenced in the rules, it is usually shorter to add the import and use
- the short class name everywhere.
-
-
- Declaring metadata using the fully qualified class name
-
- declare org.drools.examples.Person
- @author( Bob )
- @dateOfCreation( 01-Feb-2009 )
-end
-
-
-
-
- Accessing Declared Types from the Application Code
-
- Declared types are usually used inside rules files, while Java
- models are used when sharing the model between rules and applications.
- Although, sometimes, the application may need to access and handle facts
- from the declared types, especially when the application is wrapping the
- rules engine and providing higher level, domain specific user interfaces
- for rules management.
-
- In such cases, the generated classes can be handled as usual with
- the Java Reflection API, but, as we know, that usually requires a lot of
- work for small results. Therefore, Drools provides a simplified API for the
- most common fact handling the application may want to do.
-
- The first important thing to realize is that a declared fact will
- belong to the package where it was declared. So, for instance, in the
- example below, Person will belong to the
- org.drools.examples package, and so the
- fully qualified name of the generated class will be
- org.drools.examples.Person.
-
-
- Declaring a type in the org.drools.examples package
-
- package org.drools.examples
-
-import java.util.Date
-
-declare Person
- name : String
- dateOfBirth : Date
- address : Address
-end
-
-
- Declared types, as discussed previously, are generated at knowledge
- base compilation time, i.e., the application will only have access to them
- at application run time. Therefore, these classes are not available for
- direct reference from the application.
-
- Drools then provides an interface through which users can handle
- declared types from the application code:
- org.drools.definition.type.FactType. Through this interface, the user can
- instantiate, read and write fields in the declared fact types.
-
-
- Handling declared fact types through the API
-
- // get a reference to a knowledge base with a declared type:
-KnowledgeBase kbase = ...
-
-// get the declared FactType
-FactType personType = kbase.getFactType( "org.drools.examples",
- "Person" );
-
-// handle the type as necessary:
-// create instances:
-Object bob = personType.newInstance();
-
-// set attributes values
-personType.set( bob,
- "name",
- "Bob" );
-personType.set( bob,
- "age",
- 42 );
-
-// insert fact into a session
-StatefulKnowledgeSession ksession = ...
-ksession.insert( bob );
-ksession.fireAllRules();
-
-// read attributes
-String name = personType.get( bob, "name" );
-int age = personType.get( bob, "age" );
-
-
-
-
- The API also includes other helpful methods, like setting all the
- attributes at once, reading values from a Map, or reading all attributes at
- once, into a Map.
-
- Although the API is similar to Java reflection (yet much simpler to
- use), it does not use reflection underneath, relying on much more
- performant accessors implemented in generated bytecode.
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Section-The_Basics.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Section-The_Basics.xml
deleted file mode 100644
index 040aecb8af..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Section-The_Basics.xml
+++ /dev/null
@@ -1,473 +0,0 @@
-
-
-
- The Basics
-
-
- Stateless Knowledge Session
-
- So where do we get started, there are so many use cases and so
- much functionality in a rule engine such as Drools that it becomes
- beguiling. Have no fear my intrepid adventurer, the complexity is
- layered and you can ease yourself into with simple use cases.
-
- Stateless session, not utilising inference, forms the simplest
- use case. A stateless session can be called like a function passing it
- some data and then receiving some results back. Some common use cases
- for stateless sessions are, but not limited to:
-
-
-
- Validation
-
-
-
- Is this person eligible for a mortgage?
-
-
-
-
-
- Calculation
-
-
-
- Compute a mortgage premium.
-
-
-
-
-
- Routing and Filtering
-
-
-
- Filter incoming messages, such as emails, into
- folders.
-
-
-
- Send incoming messages to a destination.
-
-
-
-
-
- So let's start with a very simple example using a driving license
- application.
-
- public class Applicant {
- private String name;
- private int age;
- private boolean valid;
- // getter and setter methods here
-}
-
-
- Now that we have our data model we can write our first rule. We
- assume that the application uses rules to refute invalid applications.
- As this is a simple validation use case we will add a
- single rule to disqualify any applicant younger than 18.
-
- package com.company.license
-
-rule "Is of valid age"
-when
- $a : Applicant( age < 18 )
-then
- $a.setValid( false );
-end
-
- To make the engine aware of data, so it can be processed against
- the rules, we have to insert the data, much like
- with a database. When
- the Applicant instance is inserted into the engine it is evaluated
- against the constraints of the rules, in this case just two constraints
- for one rule. We say two because the type Applicant
- is the first object
- type constraint, and age < 18 is the second field constraint.
- An object type constraint plus its zero or more field constraints is
- referred to as a pattern. When an inserted instance satisfies both the
- object type constraint and all the field constraints, it is said to be
- matched. The $a is a binding variable which permits us to reference
- the matched object in the consequence. There its properties can be
- updated. The dollar character ('$') is optional, but it helps to
- differentiate variable names from field names. The process of
- matching patterns against the inserted data is, not surprisingly,
- often referred to as pattern matching.
-
- Let's assume that the rules are in the same folder as the classes,
- so we can use the classpath resource loader to build our first
- KnowledgeBase. A Knowledge Base is what we call our collection of
- compiled rules, which are compiled using the KnowledgeBuilder.
-
- KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
-kbuilder.add( ResourceFactory.newClassPathResource( "licenseApplication.drl", getClass() ),
- ResourceType.DRL );
-if ( kbuilder.hasErrors() ) {
- System.err.println( builder.getErrors().toString() );
-}
-kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
-
- The above code snippet looks on the classpath for the
- licenseApplication.drl
- file, using the method newClassPathResource(). The resource type
- is DRL, short for "Drools Rule Language". Once the DRL file has been added
- we can check the Knowledge Builder object for any errors. If there are no
- errors, we can add the resulting packages to our Knowledge Base.
- Now we are ready to build our session and execute against some
- data:
-
- StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
-Applicant applicant = new Applicant( "Mr John Smith", 16 );
-assertTrue( applicant.isValid() );
-ksession.execute( applicant );
-assertFalse( applicant.isValid() );
-
-
- The preceding code executes the data against the rules. Since the applicant is
- under the age of 18, the application is marked as invalid.
-
- So far we've only used a single instance, but what if we want to use
- more than one? We can execute against any object implementing Iterable, such as
- a collection. Let's add another class called Application, which has the
- date of the application, and we'll also move the boolean valid field to the
- Application class.
-
- public class Applicant {
- private String name;
- private int age;
- // getter and setter methods here
-}
-
-public class Application {
- private Date dateApplied;
- private boolean valid;
- // getter and setter methods here
-}
-
- We can also add another rule to validate that the application
- was made within a period of time.
-
- package com.company.license
-
-rule "Is of valid age"
-when
- Applicant( age < 18 )
- $a : Application()
-then
- $a.setValid( false );
-end
-
-rule "Application was made this year"
-when
- $a : Application( dateApplied > "01-jan-2009" )
-then
- $a.setValid( false );
-end
-
-
- Unfortunately a Java array does not implement the
- Iterable
- interface, so we have to use the JDK converter method
- Arrays.asList(...). The code
- shown below executes against an iterable list, where all collection
- elements are inserted before any matched rules are fired.
-
- StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
-Applicant applicant = new Applicant( "Mr John Smith", 16 );
-Application application = new Application();
-assertTrue( application() );
-ksession.execute( Arrays.asList( new Object[] { application, applicant } ) );
-assertFalse( application() );
-
-
- The two execute methods execute(Object object) and
- execute(Iterable objects) are actually convenience methods for the
- interface BatchExecutor's method execute(Command command).
-
- A CommandFactory is used to create commands, so that the following is
- equivalent to execute(Iterable it):
-
- ksession.execute( CommandFactory.newInsertIterable( new Object[] { application, applicant } ) );
-
-
- Batch Executor and Command Factory are particularly useful when working
- with multiple Commands and with output identifiers for obtaining results.
-
- List<Command> cmds = new ArrayList<Command>();
-cmds.add( CommandFactory.newInsert( new Person( "Mr John Smith" ), "mrSmith" );
-cmds.add( CommandFactory.newInsert( new Person( "Mr John Doe" ), "mrDoe" );
-BatchExecutionResults results = ksession.execute( CommandFactory.newBatchExecution( cmds ) );
-assertEquals( new Person( "Mr John Smith" ), results.getValue( "mrSmith" ) );
-
-
- CommandFactory supports many other Commands that can be used in
- the BatchExecutor like StartProcess, Query, and
- SetGlobal.
-
-
-
- Stateful Knowledge Session
-
- Stateful Sessions are longer lived and allow iterative changes
- over time. Some common use cases for Stateful Sessions are, but not
- limited to:
-
-
-
- Monitoring
-
-
-
- Stock market monitoring and analysis for semi-automatic
- buying.
-
-
-
-
-
- Diagnostics
-
-
-
- Fault finding, medical diagnostics
-
-
-
-
-
- Logistics
-
-
-
- Parcel tracking and delivery provisioning
-
-
-
-
-
- Compliance
-
-
-
- Validation of legality for market trades.
-
-
-
-
-
- In contrast to a Stateless Session, the dispose()
- method must be called
- afterwards to ensure there are no memory leaks, as the Knowledge Base
- contains references to Stateful Knowledge Sessions when they are created.
- StatefulKnowledgeSession also supports the BatchExecutor
- interface, like StatelessKnowledgeSession, the only difference
- being that the FireAllRules command is not automatically called at the
- end for a Stateful Session.
-
- We illustrate the monitoring use case with an example for raising a
- fire alarm. Using just four classes, we represent rooms in a house, each of which
- has one sprinkler. If a fire starts in a room, we
- represent that with a single Fire instance.
-
- public class Room {
- private String name
- // getter and setter methods here
-}
-public classs Sprinkler {
- private Room room;
- private boolean on;
- // getter and setter methods here
-}
-public class Fire {
- private Room room;
- // getter and setter methods here
-}
-public class Alarm {
-}
-
-
- In the previous section on Stateless Sessions the concepts of
- inserting and matching against data was introduced. That example assumed
- that only a single instance of each object type was ever inserted and thus
- only used literal constraints. However, a house has many rooms, so rules
- must express relationships between objects, such as a sprinkler being in
- a certain room. This is best done by using a binding variable as a constraint
- in a pattern. This "join" process results in what is called cross products, which are
- covered in the next section.
-
- When a fire occurs an instance of the Fire class is created, for
- that room, and inserted into the session. The rule uses a binding on the
- room
- field of the Fire object to constrain matching to the sprinkler for that room,
- which is currently off. When this rule fires and the consequence is executed
- the sprinkler is turned on.
-
- rule "When there is a fire turn on the sprinkler"
-when
- Fire($room : room)
- $sprinkler : Sprinkler( room == $room, on == false )
-then
- modify( $sprinkler ) { setOn( true ) };
- System.out.println( "Turn on the sprinkler for room " + $room.getName() );
-end
-
- Whereas the Stateless Session uses standard Java syntax to modify
- a field, in the above rule we use the modify statement, which acts as a
- sort of "with" statement. It may contain a series of comma separated Java
- expressions, i.e., calls to setters of the object selected by the modify
- statement's control
- expression. This modifies the data, and makes the engine aware of those changes
- so it can reason over them once more. This process is called inference, and
- it's essential for the working of a Stateful Session. Stateless Sessions
- typically do not use inference, so the engine does not need to be aware of
- changes to data. Inference can also be turned off explicitly by using the
- sequential mode.
-
- So far we have rules that tell us when matching data exists, but
- what about when it does not exist? How do we determine
- that a fire has been extinguished, i.e., that there isn't a Fire
- object any more? Previously the constraints have been sentences according
- to Propositional Logic,
- where the engine is constraining against individual intances. Drools also has
- support for First Order Logic that allows you to look at sets of data.
- A pattern under the keyword not matches when something does not exist.
- The rule given below turns the sprinkler off as soon as the fire in that
- room has disappeared.
-
- rule "When the fire is gone turn off the sprinkler"
-when
- $room : Room( )
- $sprinkler : Sprinkler( room == $room, on == true )
- not Fire( room == $room )
-then
- modify( $sprinkler ) { setOn( false ) };
- System.out.println( "Turn off the sprinkler for room " + $room.getName() );
-end
-
- While there is one sprinkler per room, there is just a single alarm
- for the building. An Alarm object is created when a fire occurs,
- but only one Alarm is needed for the entire building, no matter
- how many fires occur. Previously not was introduced to match the absence of
- a fact; now we use its complement exists which matches for one or more
- instances of some category.
-
- rule "Raise the alarm when we have one or more fires"
-when
- exists Fire()
-then
- insert( new Alarm() );
- System.out.println( "Raise the alarm" );
-end
-
- Likewise, when there are no fires we want to remove the alarm, so
- the not keyword can be used again.
-
- rule "Cancel the alarm when all the fires have gone"
-when
- not Fire()
- $alarm : Alarm()
-then
- retract( $alarm );
- System.out.println( "Cancel the alarm" );
-end
-
-
-
- Finally there is a general health status message that is printed
- when the application first starts and after the alarm is removed and all
- sprinklers have been turned off.
-
- rule "Status output when things are ok"
-when
- not Alarm()
- not Sprinkler( on === true )
-then
- System.out.println( "Everything is ok" );
-end
-
- The above rules should be placed in a single DRL file and saved to
- some directory on the classpath and using the file name
- fireAlarm.drl,
- as in the Stateless Session example. We can then build a Knowledge Base,
- as before, just using the new name fireAlarm.drl.
- The difference is that
- this time we create a Stateful Session from the Knowledge Base, whereas
- before we created a Stateless Session.
-
- KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
-kbuilder.add( ResourceFactory.newClassPathResource( "fireAlarm.drl", getClass() ),
- ResourceType.DRL );
-if ( kbuilder.hasErrors() ) {
- System.err.println( builder.getErrors().toString() );
-}
-kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
-StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
-
- With the session created it is now possible to iteratvely work
- with it over time. Four Room objects are created and
- inserted, as well as one Sprinkler object for
- each room. At this point the engine has done all of its
- matching, but no rules have fired yet. Calling ksession.fireAllRules()
- allows the matched rules to fire, but without a fire that will
- just produce the health message.
-
- String[] names = new String[]{"kitchen", "bedroom", "office", "livingroom"};
-Map<String,Room> name2room = new HashMap<String,Room>();
-for( String name: names ){
- Room room = new Room( name );
- name2room.put( name, room );
- ksession.insert( room );
- Sprinkler sprinkler = new Sprinkler( room );
- ksession.insert( sprinkler );
-}
-
-ksession.fireAllRules()
-
-
- > Everything is ok
-
- We now create two fires and insert them; this time a reference is
- kept for the returned FactHandle. A Fact Handle is an
- internal engine reference to the inserted instance and allows instances to be
- retracted or modified at a later point in time. With the fires now in
- the engine, once fireAllRules() is called, the alarm is raised and the
- respective sprinklers are turned on.
-
- Fire kitchenFire = new Fire( name2room.get( "kitchen" ) );
-Fire officeFire = new Fire( name2room.get( "office" ) );
-
-FactHandle kitchenFireHandle = ksession.insert( kitchenFire );
-FactHandle officeFireHandle = ksession.insert( officeFire );
-
-ksession.fireAllRules();
-
- > Raise the alarm
-> Turn on the sprinkler for room kitchen
-> Turn on the sprinkler for room office
-
- After a while the fires will be put out and the Fire
- instances are retracted. This results in the sprinklers being turned off, the alarm
- being cancelled, and eventually the health message is printed again.
-
- ksession.retract( kitchenFireHandle );
-ksession.retract( officeFireHandle );
-
-ksession.fireAllRules();
-
- > Turn on the sprinkler for room office
-> Turn on the sprinkler for room kitchen
-> Cancel the alarm
-> Everything is ok
-
- Everyone still with me? That wasn't so hard and already I'm
- hoping you can start to see the value and power of a declarative rule
- system.
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Rule_Engine/Section-Rules.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Rule_Engine/Section-Rules.xml
deleted file mode 100755
index 7b8788e74a..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Rule_Engine/Section-Rules.xml
+++ /dev/null
@@ -1,357 +0,0 @@
-
-
- Knowledge Representation
-
-
-
-
- First Order Logic
-
- Rules are written using First Order Logic, or Predicate Logic, which
- extends Propositional Logic. Emil Leon Post
- was the first to develop an inference based system using symbols to
- express logic. As a consequence of this he was able to prove that any
- logical system (including mathematics) could be expressed with such a
- system.
-
- A proposition is a statement that can be classified as true or
- false. If the truth can be determined from the statement alone it is said
- to be a "closed statement". In programming terms this is an expression
- that does not reference any variables:
-
- 10 == 2 * 5
-
- Expressions that evaluate against one or more variables, the facts,
- are "open statements", in that we cannot determine whether the statement
- is true until we have a variable instance to evaluate against:
-
- Person.sex == "male"
-
- With SQL, the conclusion's action is to return the matched fact to
- the user:
-
- select * from Person where Person.sex == "male"
-
- For any rows, which represent our facts, that are returned we have
- inferred that those facts are male people. The following diagram shows how
- the above SQL statement and Person table can be represented in terms of an
- Inference Engine.
-
-
- SQL as a simplistic Inference Engine
-
-
-
-
-
-
-
-
- In Java we can write simple proposition as a boolean expression
- 'variable' 'operator' 'value', where 'value' frequently is a literal
- value, and such a proposition can be thought of as a field constraint.
- Furthermore, such a proposition can be combined with conjunctive and
- disjunctive connectives, which is the logic theorists' denomination for
- '&&' and '||'. The following expression shows two open
- propositional statements connected with a single disjunctive
- connective.
-
- person.getEyeColor().equals("blue") || person.getEyeColor().equals("green")
-
- This can be expressed using a disjunctive Conditional Element
- connective which actually results in the generation of two rules, to
- represent the two possible logic outcomes.
-
- Person( eyeColour == "blue" ) || Person( eyeColor == "green" )
-
- Disjunctive field constraints connectives could also be used and
- would not result in multiple rules.
-
- Person( eyeColour == "blue"||"green" )
-
- Propositional Logic is not Turing complete, limiting the problems
- you can define, because it cannot express criteria for the structure of
- data. First Order Logic (FOL), or Predicate Logic, extends Propositional
- Logic with two quantifier concepts to allow expressions defining
- structure, i.e., the universal and existential quantifiers. Universal
- quantifiers allow you to check that something is true for everything,
- normally supported by the forall conditional element.
- Existential quantifiers check for the existence of something, in that it
- occurs at least once, this being supported with not and
- exists conditional elements.
-
- Imagine we have two classes: Student and Module. Module represents
- each of the courses the Student attended for that semester, referenced by
- the List collection. At the end of the semester each Module has a score.
- If the Student has a Module score below 40 then they will fail that
- semester. The existential quantifier can be used used with the "less than
- 40" open proposition to check for the existence of a Module that is true
- for the specified criteria.
-
- public class Student {
- private String name;
- private List<Module> modules;
- ...
- }
-
-
- public class Module {
- private String name;
- private Student student;
- private int score;
- ...
- }
-
-
- Java is Turing complete in that you can write code, among other
- things, to iterate data structures to check for existence. The following
- should return a List of students who have failed the semester.
-
-
- List failedStudents = new ArrayList();
-
- for ( Student student: students ) {
- for ( Module module: student.getModules ) {
- if ( module.getScore() < 40 ) {
- failedStudents.add( student ) ;
- break;
- }
- }
- }
-
-
- Early SQL implementations were not Turing complete as they did not
- provide quantifiers to access the structure of data. Modern SQL engines do
- allow nesting of SQL, which can be combined with keywords like 'exists'
- and 'in'. The following snippets show SQL to return a set of students who
- have failed the semester, and a rule firing for such students.
-
-
-select
- *
-from
- Students s
-where exists (
- select
- *
- from
- Modules m
- where
- m.student_name = s.name and
- m.score < 40
-)
-
-
-
-
- rule "Failed_Students"
- when
- $s : Student()
- exists Module( student == $s, score < 40 )
- then
- # record $student as flunked
- end
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Rule_Engine/Section-The_Drools_Rule_Engine.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Rule_Engine/Section-The_Drools_Rule_Engine.xml
deleted file mode 100755
index fcc7ddda38..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Rule_Engine/Section-The_Drools_Rule_Engine.xml
+++ /dev/null
@@ -1,1121 +0,0 @@
-
-
- The Drools Rule Engine
-
-
- Overview
-
- Drools is split into two main parts: Authoring and Runtime.
-
- The authoring process involves the creation of DRL or XML files for
- rules which are fed into a parser - defined by an Antlr 3 grammar. The
- parser checks for correctly formed grammar and produces an intermediate
- structure for the "descr"; where the "descr" indicates the
- abstract syntax tree (AST) that
- "describes" the rules. The AST is then passed to the Package Builder which
- produces Packages. Package Builder also undertakes any code generation and
- compilation that is necessary for the creation of the Package. A Package
- object is self-contained and deployable, in that it is a serialized object
- consisting of one or more rules.
-
-
- Authoring Components
-
-
-
-
-
-
-
-
- A RuleBase is a runtime component which consists of one or more
- Packages. Packages can be added and removed from the RuleBase at any time.
- A RuleBase can instantiate one or more WorkingMemories at any time; a weak
- reference is maintained, unless configured otherwise. The Working Memory
- consists of a number of sub components, including Working Memory Event
- Support, Truth Maintenance System, Agenda and Agenda Event Support. Object
- insertion may result in the creation of one or more Activations. The
- Agenda is responsible for scheduling the execution of these
- Activations.
-
-
- Runtime Components
-
-
-
-
-
-
-
-
-
-
- Authoring
-
-
- PackageBuilder
-
-
-
-
-
-
-
-
- Four classes are used for authoring: DrlParser, XmlParser,
- ProcessBuilder and PackageBuilder. The two parser classes produce "descr"
- (description) AST models from a provided Reader instance. ProcessBuilder
- reads in an xstream serialization, i.e., a representation of the Rule Flow.
- PackageBuilder provides convenience APIs so that you can mostly forget
- about those classes. The three convenience methods are
- addPackageFromDrl, addPackageFromXml and addRuleFlow - all take an
- instance of Reader as an argument. The example below shows how to build a
- package that includes both XML and DRL rule files and a ruleflow file,
- which are in the classpath. Note that all added package sources must be of
- the same package namespace for the current PackageBuilder instance!
-
-
- Building a Package from Multiple Sources
-
- PackageBuilder builder = new PackageBuilder();
-builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "package1.drl" ) ) );
-builder.addPackageFromXml( new InputStreamReader( getClass().getResourceAsStream( "package2.xml" ) ) );
-builder.addRuleFlow( new InputStreamReader( getClass().getResourceAsStream( "ruleflow.rfm" ) ) );
-Package pkg = builder.getPackage();
-
-
- It is essential that you always check your PackageBuilder for errors
- before attempting to use it. While the ruleBase does throw an
- InvalidRulePackage when a broken Package is added, the detailed error
- information is stripped and only a toString() equivalent is available. If
- you interrogate the PackageBuilder itself much more information is
- available.
-
-
- Checking the PackageBuilder for errors
-
- PackageBuilder builder = new PackageBuilder();
-builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "package1.drl" ) ) );
-PackageBuilderErrors errors = builder.getErrors();
-
-
- PackageBuilder is configurable by using the PackageBuilderConfiguration
- class.
-
-
- PackageBuilderConfiguration
-
-
-
-
-
-
-
- The configuration has default values that can be overridden programmatically via
- setters, or on first use via property settings. At the heart of the
- settings is the ChainedProperties class which searches a number of
- locations looking for drools.packagebuilder.conf files; as it finds them
- it adds the properties to the master properties list; this provides a
- level precedence. In order of precedence those locations are: System
- Properties, user defined file in System Properties, user home directory,
- working directory, various META-INF locations. Further to this the
- drools-compiler jar has the default settings in its META-INF
- directory.
-
- Currently the PackageBuilderConfiguration handles the registry of
- Accumulate functions, the registry of Dialects and the main
- ClassLoader.
-
- Drools has a pluggable Dialect system, which allows other languages
- to compile and execute expressions and blocks. The two currently
- supported dialects are Java and MVEL. Each has its own
- DialectConfiguration Implementation; the javadocs provide details for each
- setter and getter, and the property names used to configure them.
-
-
- JavaDialectConfiguration
-
-
-
-
-
-
-
-
- The JavaDialectConfiguration allows the compiler and language levels
- to be supported. You can override by setting the
- drools.dialect.java.compiler property in a packagebuilder.conf file that
- the ChainedProperties instance will find, or you can do it at runtime as
- shown below.
-
-
- Configuring the JavaDialectConfiguration to use JANINO via a
- setter
-
- PackageBuilderConfiguration cfg = new PackageBuilderConfiguration( );
-JavaDialectConfiguration javaConf = (JavaDialectConfiguration) cfg.getDialectConfiguration( "java" );
-javaConf.setCompiler( JavaDialectConfiguration.JANINO );
-
-
- if you do not have Eclipse JDT Core in your classpath you must
- override the compiler setting before you instantiate this PackageBuilder,
- you can either do that with a packagebuilder properties file the
- ChainedProperties class will find, or you can do it programmatically as
- shown below. Note that this time I use properties to inject the value for
- startup.
-
-
- Configuring the JavaDialectConfiguration to use JANINO
-
- Properties properties = new Properties();
-properties.setProperty( "drools.dialect.java.compiler",
- "JANINO" );
-PackageBuilderConfiguration cfg = new PackageBuilderConfiguration( properties );
-JavaDialectConfiguration javaConf = (JavaDialectConfiguration) cfg.getDialectConfiguration( "java" );
-assertEquals( JavaDialectConfiguration.JANINO,
- javaConf.getCompiler() ); // demonstrate that the compiler is correctly configured
-
-
- Currently it allows alternative compilers (Janino, Eclipse JDT) to
- be specified, different JDK source levels ("1.4" and "1.5") and a parent
- class loader. The default compiler is Eclipse JDT Core at source level
- "1.4" with the parent class loader set to
- Thread.currentThread().getContextClassLoader().
-
- The following lines show how to specify the JANINO compiler
- programmatically:
-
-
- Configuring the PackageBuilder to use JANINO via a
- property
-
- PackageBuilderConfiguration conf = new PackageBuilderConfiguration();
-conf.setCompiler( PackageBuilderConfiguration.JANINO );
-PackageBuilder builder = new PackageBuilder( conf );
-
-
- The MVELDialectConfiguration is much simpler and only allows strict
- mode to be turned on and off. By default strict is true, which means that all
- method calls must be type safe either by inference or by explicit
- typing.
-
-
- MvelDialectConfiguration
-
-
-
-
-
-
-
-
-
-
- RuleBase
-
-
- RuleBaseFactory
-
-
-
-
-
-
-
-
- A RuleBase is instantiated using the RuleBaseFactory, by default
- this returns a ReteOO RuleBase. Packages are added, in turn, using the
- addPackage method. You may specify packages of any namespace, and multiple
- packages of the same namespace may be added.
-
-
- Adding a Package to a new RuleBase
-
- RuleBase ruleBase = RuleBaseFactory.newRuleBase();
-ruleBase.addPackage( pkg );
-
-
-
- RuleBase
-
-
-
-
-
-
-
-
- A RuleBase contains one or more more packages of rules, ready to be
- used, i.e., they have been validated and compiled, etc. A RuleBase is
- serializable so it can be deployed to JNDI or other such services.
- Typically, a rulebase would be generated and cached on first use, to
- avoid the repeated regeneration of the RuleBase, which is
- expensive.
-
- A RuleBase instance is thread safe, in the sense that you can have
- the one instance shared across threads in your application, which may be a
- web application, for instance. The most common operation on a rulebase is
- to create a new rule session; either stateful or stateless.
-
- The RuleBase also holds references to any stateful session that it
- has spawned, so that if rules are changing (or being added and removed)
- in a long running session, they can be updated with the latest rules
- without having to restart the session. You can specify not
- to maintain a reference, but only do so if you know the RuleBase will not
- be updated. References are not stored for stateless sessions.
-
- ruleBase.newStatefulSession(); // maintains a reference.
-ruleBase.newStatefulSession( false ); // do not maintain a reference
-
- Packages can be added and removed at any time, and all changes will be
- propagated to the existing stateful sessions, but don't forget to call
- fireAllRules() for resulting Activations to fire.
-
- ruleBase.addPackage( pkg ); // Add a package instance
-ruleBase.removePackage( "org.com.sample" ); // remove a package, and all its parts, by its namespace
-ruleBase.removeRule( "org.com.sample", "my rule" ); // remove a specific rule from a namespace
-
- While there is a method to remove an indivual rule, there is no
- method to add an individual rule. To achieve this, just add a new package
- with a single rule in it.
-
- RuleBaseConfigurator can be used to specify additional behavior of
- the RuleBase. RuleBaseConfiguration is set to immutable after it has been
- added to a RuleBase. Nearly all the engine optimizations can be turned on
- and off from here, and also the execution behavior can be set. Users will
- generally be concerned with insertion behavior (identity or equality) and
- cross product behavior (remove or keep identity equals across
- products).
-
- RuleBaseConfiguration conf = new RuleBaseConfiguration();
-conf.setAssertBehaviour( AssertBehaviour.IDENTITY );
-conf.setRemoveIdentities( true );
-RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );
-
-
- RuleBaseConfiguration
-
-
-
-
-
-
-
-
-
-
- WorkingMemory, Stateful and Stateless Sessions
-
-
- WorkingMemory
-
-
-
-
-
-
-
-
- The Working Memory holds references to all data that has been "inserted" into it and not yet retracted,
- and it is the place where the interaction with your
- application occurs. Working memories are stateful objects. They may be
- short-lived or long-lived.
-
-
- Facts
-
- Facts are objects (beans) from your application that you insert
- into the working memory. Facts are any Java objects which the rules can
- access. The rule engine does not "clone" facts at all, it is all
- references (or pointers) at the end of the day. Facts are the data of your application.
- Strings and other classes without getters and setters are not
- valid Facts and can't be used with Field Constraints which rely on the
- JavaBean standard of getters and setters to interact with the
- object.
-
-
-
- Insertion
-
- "Insert" is the act of telling the WorkingMemory about a fact, which you do
- by wm.insert(yourObject), for example. When you insert a fact, it
- is examined for matches against the rules. This means all of the
- work for deciding about firing or not firing a rule is done during
- insertion; no rule, however, is executed until you
- call fireAllRules(), which you call fireAllRules() after you
- have finished inserting your facts. It is a common misunderstanding for
- people to think the condition evaluation happens when you call fireAllRules(). Expert
- systems typically use the term assert or assertion to refer to facts
- made available to the system. However due to the assert being a keyword
- in most languages we have moved to use the insert keyword; so expect
- to hear the two used interchangeably.
-
-
-
- When an Object is inserted it returns a FactHandle. This FactHandle
- is the token used to represent your inserted object within the
- WorkingMemory. It is also used for interactions with the WorkingMemory
- when you wish to retract or modify an object.
-
- Cheese stilton = new Cheese("stilton");
-FactHandle stiltonHandle = session.insert( stilton );
-
- As mentioned in the Rule Base section a Working Memory may operate
- in two assertion modes, i.e., equality or identity, with identity being
- default.
-
- Identity means that the Working Memory uses an IdentityHashMap to store
- all asserted objects. New instance assertions always result in the
- return of a new FactHandle, but if an instance is asserted again then it
- returns the original fact handle, i.e., it ignores repeated insertions
- for the same fact.
-
- Equality means that the Working Memory uses a HashMap to store all
- asserted Objects. New instance assertions will only return a new
- FactHandle if no equal objects have been asserted.
-
-
-
- Retraction
-
- "Retraction" is the removal of a fact from the Working Memory,
- which means it will no longer track and match that fact, and any rules
- that are activated and dependent on that fact will be cancelled. Note
- that it is possible to have rules that depend on the nonexistence of
- a fact, in which case retracting a fact may cause a rule to activate
- (see the not and exist keywords). Retraction is done using the
- FactHandle that was returned during the assert.
-
- Cheese stilton = new Cheese("stilton");
-FactHandle stiltonHandle = session.insert( stilton );
-...
-session.retract( stiltonHandle );
-
-
-
- Update
-
- The Rule Engine must be notified of modified Facts, so that they can
- be reprocessed. Internally, modification is actually a retract and then an
- insert; so it removes the fact from the WorkingMemory and then
- inserts it again. You must use the update method to notify the
- WorkingMemory of changed objects for those objects that are
- not able to notify the WorkingMemory themselves.
- Notice that update always takes the modified object as a second
- parameter, which allows you to specify new instances for immutable
- objects. The update method can only be used with objects that have
- shadow proxies turned on. If you do not use shadow proxies then you must
- call wm.modifyRetract() before making your changes and
- wm.modifyInsert() after the changes.
-
- Cheese stilton = new Cheese("stilton");
-FactHandle stiltonHandle = workingMemory.insert( stilton );
-...
-stilton.setPrice( 100 );
-workingMemory.update( stiltonHandle, stilton );
-
-
-
- Globals
-
- Globals are named objects that can be passed in to the rule
- engine, without needing to insert them. Most often these are used for
- static information, or for services that are used in the RHS of a rule, or
- perhaps as a means to return objects from the rule engine. If you use a
- global on the LHS of a rule, make sure it is immutable. A global must
- first be declared in a rules file before it can be set on the session.
-
- global java.util.List list
-
- With the Rule Base now aware of the global identifier and its type,
- it is now possible to call session.setGlobal for any session. Failure to declare
- the global type and identifier first will result in an exception being
- thrown. To set the global on the session use session.setGlobal(identifier, value):
-
- List list = new ArrayList();
-session.setGlobal("list", list);
-
- If a rule evaluates on a global before you set it you will get a
- NullPointerException.
-
-
-
- Shadow Facts
-
- A shadow fact is a shallow copy of an asserted object. Shadow
- facts are cached copies of objects asserted to the working memory. The
- term "shadow fact" is commonly known as a feature of JESS (Java Expert
- System Shell).
-
- The origin of shadow facts traces back to the concept of truth
- maintenance. The basic idea is that an expert system should guarantee
- that the derived conclusions are accurate. A running system may alter a fact
- during evaluation. When this occurs, the rule engine must know a
- modification occurred and handle the change appropriately. There's
- generally two ways to guarantee truthfulness. The first is to lock all
- the facts during the inference process. The second is to make a cache
- copy of an object and force all modifications to go through the rule
- engine. This way, the changes are processed in an orderly fashion.
- Shadow facts are particularly important in multi-threaded environments,
- where an engine is shared by multiple sessions. Without truth
- maintenance, a system has a difficult time proving the results are
- accurate. The primary benefit of shadow facts is that they make development
- easier. When developers are forced to keep track of fact modifications,
- it can lead to errors which are difficult to debug. Building a
- moderately complex system using a rule engine is hard enough without
- adding the burden of tracking changes to facts and when they should
- notify the rule engine.
-
- Drools 4.0 has full support for Shadow Facts implemented as
- transparent lazy proxies. Shadow facts are enable by default and are not
- visible from external code, not even inside code blocks on rules.
-
- Since Drools
- implements Shadow Facts as Proxies, the fact classes must either be immutable or should not be final, nor have final methods. If a
- fact class is final or has final methods and is still a mutable class,
- the engine is not able to create a proper shadow fact for it which results
- in unpredictable behavior.
-
- Although shadow facts are a great way of ensuring the engine's
- integrity, they add some overhead to the the reasoning process. Therefore,
- Drools 4.0 supports fine-grained control over them with the ability to
- enable or disable them for each individual class.
-
-
- When is it possible to disable Shadow Facts?
-
- It is possible to disable shadow facts for your classes if you
- meet the following requirements:
-
-
-
- Immutable classes are safe.
- If a class is immutable it does not require shadow facts. Just to
- clarify, a class is immutable from the engine perspective if once an
- instance is asserted into the working memory, no attribute will change
- until it is retracted.
-
-
- Inside your rules, attributes are only
- changed using modify() blocks. Both Drools dialects (MVEL
- and Java) have the modify block construct. If all attribute value
- changes for a given class happen inside modify() blocks, you can
- disable shadow facts for that class.
-
- modify() block using Java dialect
-
- rule "Eat Cheese"
-when
- $p: Person( status == "hungry" )
- $c: Cheese( )
-then
- retract( $c );
- modify( $p ) {
- setStatus( "full" ),
- setAge( $p.getAge() + 1 )
- }
-end
-
-
-
- modify() block using MVEL dialect
-
- rule "Eat Cheese"
- dialect "mvel"
-when
- $p: Person( status == "hungry" )
- $c: Cheese( )
-then
- retract( $c );
- modify( $p ) {
- status = "full",
- age = $p.age + 1
- }
-end
-
-
- In your application, attributes are
- only changed between calls to modifyRetract() and
- modifyInsert(). This way, the engine becomes aware that
- attributes will be changed and can prepare itself for them.
-
- Safely modifying attributes in the application
- code
- // create session
- StatefulSession session = ruleBase.newStatefulSession();
-
- // get facts
- Person person = new Person( "Bob", 30 );
- person.setLikes( "cheese" );
-
- // insert facts
- FactHandle handle = session.insert( person );
-
- // do application stuff and/or fire rules
- session.fireAllRules();
-
- // wants to change attributes?
- session.modifyRetract( handle ); // call modifyRetract() before doing changes
- person.setAge( 31 );
- person.setLikes( "chocolate" );
- session.modifyInsert( handle, person ); // call modifyInsert() after the changes
-
-
-
-
-
-
- How to disable Shadow Facts
-
- To disable shadow facts for all classes set the following
- property in a configuration file of system property:
-
- drools.shadowProxy = false
-
- Alternatively, it is possible to disable shadow facts through an API
- call:
-
- RuleBaseConfiguration conf = new RuleBaseConfiguration();
-conf.setShadowProxy( false );
-...
-RuleBase ruleBase = RuleBaseFactory.newRuleBase( conf );
-
-
- To disable the shadow proxy for a list of classes only, use the
- following property instead, or the equivalent API:
-
- drools.shadowproxy.exclude = org.domainy.* org.domainx.ClassZ
-
- As shown above, a space separated list is used to specify more
- than one class, and '*' is used as a wild card.
-
-
-
-
- Property Change Listener
-
- If your fact objects are Java Beans, you can implement a property
- change listener for them, and then tell the rule engine about it. This
- means that the engine will automatically know when a fact has changed,
- and behave accordingly, without you having to tell it that the fact is modified.
- There are proxy libraries that can help automate this. (A future version
- of Drools will bundle some to make it easier.) To use an object in
- dynamic mode specify true for the second assertObject parameter.
-
- Cheese stilton = new Cheese("stilton");
-FactHandle stiltonHandle = workingMemory.insert( stilton, true ); //specifies that this is a dynamic fact
-
- To make a JavaBean dynamic add a PropertyChangeSupport field
- along with an add and a remove method, and make sure that each setter
- calls the PropertyChangeSupport instance with
- firePropertyChange.
-
- private final PropertyChangeSupport changes = new PropertyChangeSupport( this );
-...
-public void addPropertyChangeListener(final PropertyChangeListener l) {
- this.changes.addPropertyChangeListener( l );
-}
-
-public void removePropertyChangeListener(final PropertyChangeListener l) {
- this.changes.removePropertyChangeListener( l );
-}
-...
-
-public void setState(final String newState) {
- String oldState = this.state;
- this.state = newState;
- this.changes.firePropertyChange( "state",
- oldState,
- newState );
-}
-
-
-
- Initial Fact
-
- To support conditional elements like not (which will be covered
- later on), there is a need to "seed" the engine with something known as
- the "Initial Fact". This fact is a special fact that is not intended to
- be seen by the user.
-
- On the first working memory action (assert, fireAllRules) on a
- fresh working memory, the Initial Fact will be propagated through the
- RETE network. This lets you write rules that have an empty LHS, or do not use
- normal facts, such as rules that use from to pull data from an
- external source. For instance, if a new working memory is created, and
- no facts are asserted, calling the fireAllRules will cause the Initial
- Fact to propagate, possibly activating rules. If there were not even an
- initial fact, nothing at all would happen.
-
-
-
-
- StatefulSession
-
-
- StatefulSession
-
-
-
-
-
-
-
-
- The StatefulSession extends the WorkingMemory class. It simply adds
- async methods and a dispose() method. The RuleBase retains a reference to
- each StatefulSession it creates, so that it can update them when new rules
- are added. Thus, dispose() is needed to release the StatefulSession reference
- from the RuleBase, because without it you can get memory leaks.
-
-
- Creating a StatefulSession
- StatefulSession session = ruleBase.newStatefulSession();
-
-
-
-
- Stateless Session
-
-
- StatelessSession
-
-
-
-
-
-
-
- The StatelessSession wraps the WorkingMemory, instead of extending
- it. Its main focus is on decision service type scenarios.
-
-
- Creating a StatelessSession
- StatelessSession session = ruleBase.newStatelessSession();
-session.execute( new Cheese( "cheddar" ) );
-
-
- The API is reduced to the problem domain and is thus much simpler.
- This, in turn, can make maintenance of those services easier. The RuleBase
- never retains a reference to the StatelessSession, thus dispose() is not
- needed. The class only has an overloaded set of execute()
- methods, accepting either a single object, an array of objects or a
- collection of objects, but there are no insert and
- fireAllRules methods. The execute() method
- iterates over the objects, inserting each into the
- WorkingMemory, and calls fireAllRules() at the
- end, after which the session is finished. Should the session
- need access to any result information you can use the executeWithResults
- method, which returns a StatelessSessionResult. The reason for this is in
- remote situations where you do not always want the return payload, so this way
- it is optional.
-
- setAgendaFilter, setGlobal and setGlobalResolver share their state
- across sessions; so each call to execute() will use the set AgendaFilter,
- see any previously set globals, etc.
-
- StatelessSessions do not currently support
- PropertyChangeListeners.
-
- Async versions of the execute method are supported. Remember to
- override the ExecutorService implementation when in special managed thread
- environments such as JEE.
-
- StatelessSessions also supports sequential mode, which is a special
- optimized mode that uses less memory and executes faster; please see the
- Sequential section for more details.
-
-
- StatelessSessionResult
-
-
-
-
-
-
-
-
-
- StatelessSession.executeWithResults() returns an
- object from a class providing a minimal API to
- examine the session's data. You may iterate over inserted objects,
- execute queries and retrieve globals. Once the
- StatelessSessionResult is serialized it loses the reference to the
- underlying WorkingMemory and RuleBase, so queries can no longer be
- executed; it is, however, still possible to retrieve globals and ti
- iterate over objects. To
- retrieve globals they must be exported from the StatelessSession; the
- GlobalExporter strategy is set with StatelessSession.setGlobalExporter(
- GlobalExporter globalExporter ). Two implementations of GlobalExporter are
- available, and users may implement their own strategies.
- CopyIdentifiersGlobalExporter copies named identifiers into a new
- GlobalResolver that is passed to the StatelessSessionResult; its
- constructor takes a String array of identifiers, but if no identifiers are
- specified it copies all identifiers declared in the RuleBase.
- ReferenceOriginalGlobalExporter just passes a reference to the original
- GlobalResolver. The latter should be used with care as identifier
- instances can be changed at any time by the StatelessSession and the
- GlobalResolver may not be serializable-friendly.
-
-
- GlobalExporter with StatelessSessions
-
- StatelessSession session = ruleBase.newStatelessSession();
-session.setGlobalExporter( new CopyIdentifiersGlobalExporter( new String[]{"list"} ) );
-StatelessSessionResult result = session.executeWithResults( new Cheese( "stilton" ) );
-List list = ( List ) result.getGlobal( "list" );
-
-
-
-
- Agenda
-
-
- Agenda
-
-
-
-
-
-
-
-
- The Agenda is a RETE feature. During actions on the WorkingMemory,
- rules
- may become fully matched and eligible for execution; a single Working
- Memory Action can result in multiple eligible rules. When a rule is fully
- matched an Activation is created, referencing the rule and the matched
- facts, and placed onto the Agenda. The Agenda controls the execution order
- of these Activations using a Conflict Resolution strategy.
-
- The engine cycles repeatedly through two phases:
-
-
-
- Working Memory Actions. This is where most of the work takes
- place, either in the Consequence (the RHS itself) or the main Java
- application process. Once the Consequence has finished or the main Java
- application process calls fireAllRules() the engine switches to the
- Agenda Evaluation phase.
-
-
-
- Agenda Evaluation. This attempts to select a rule to fire. If no rule
- is found it exits, otherwise it fires the found rule,
- switching the phase back to Working Memory Actions.
-
-
-
-
- Two Phase Execution
-
-
-
-
-
-
-
-
- The process repeats until the agenda is clear, in which case
- control returns to the calling application. When Working Memory Actions
- are taking place, no rules are being fired.
-
-
- Conflict Resolution
-
- Conflict resolution is required when there are multiple rules on
- the agenda. As firing a rule may have side effects on working memory,
- the rule engine needs to know in what order the rules should fire (for
- instance, firing ruleA may cause ruleB to be removed from the
- agenda).
-
- The default conflict resolution strategies employed by Drools are:
- Salience and LIFO (last in, first out).
-
- The most visible one is "salience" or priority, in which case a
- user can specify that a certain rule has a higher priority (by giving it
- a higher number) than other rules. In that case, the rule with higher salience
- will be preferred. LIFO priorities are based on the assigned
- Working Memory Action counter value, with all rules created during the
- same action receiving the same value. The execution order of a set
- of firings with the same priority value is arbitrary.
-
- As a general rule, it is a good idea not to count on the rules
- firing in any particular order, and to author the rules without
- worrying about a "flow".
-
- Custom conflict resolution strategies can be specified by setting
- the Class in the RuleBaseConfiguration method setConflictResolver, or
- by using the property drools.conflictResolver.
-
-
-
- Agenda Groups
-
- Agenda groups are a way to partition rules (activations, actually)
- on the agenda. At any one time, only one group has "focus" which means
- that activations for rules in that group only will take effect. You
- can also have rules with "auto focus" which means that the focus is
- taken for its agenda group when that rule's conditions are true.
-
- Agenda groups are known as "modules" in CLIPS terminology. They
- provide a handy way to create a "flow" between grouped rules. You can
- switch the group which has focus either from within the rule engine, or
- via the API. If your rules have a clear need for multiple "phases" or
- "sequences" of processing, consider using agenda-groups for this
- purpose.
-
- Each time setFocus() is called it pushes that Agenda Group onto
- a stack. When the focus group is empty it is popped from the stack and the
- focus group that is now on top evaluates. An Agenda Group can
- appear in multiple locations
- on the stack. The default Agenda Group is "MAIN", with all rules which do not
- specify an Agenda Group being in this group. It is also always the first
- group on the stack, given focus initially, by default.
-
-
-
- Agenda Filters
-
-
- AgendaFilters
-
-
-
-
-
-
-
- Filters are optional implementations of the filter interface
- which are used to allow or deny the firing of an activation. What you
- filter on is entirely up to the implementation. Drools provides the
- following convenience default implementations, all of which may be
- used for allowing and denying. By default, they accept rules where
- the name, or part of it, matches the first constructor parameter.
-
-
-
- RuleNameEndsWithAgendaFilter
-
-
-
- RuleNameEqualsAgendaFilter
-
-
-
- RuleNameStartsWithAgendaFilter
-
-
-
- RuleNameMatchesAgendaFilter
-
-
-
- To use a filter specify it while calling FireAllRules. The
- following example permits only rules ending in the string Test.
- All others will be filtered out.
- workingMemory.fireAllRules( new RuleNameEndsWithAgendaFilter( "Test" ) );
-
-
-
-
- Event Model
-
- The event package provides means to be notified of rule engine
- events, including rules firing, objects being asserted, etc. This allows
- you, for instance, to separate logging and auditing activities from the
- main part of your application (and the rules).
-
- WorkingMemoryEventListener,
- AgendaEventListener and RuleFlowEventListener
- represent the three types of event listeners:
-
-
- WorkingMemoryEventListener
-
-
-
-
-
-
-
-
-
- AgendaEventListener
-
-
-
-
-
-
-
-
-
- RuleFlowEventListener
-
-
-
-
-
-
-
-
- Both stateful and stateless sessions implement the EventManager
- interface, which allows event listeners to be added to the session.
-
-
- EventManager
-
-
-
-
-
-
-
-
- All EventListeners have default implementations that implement each
- method, but do nothing; these are convienience classes that you can
- inherit from to avoid having to implement each method. The default classes
- are DefaultAgendaEventListener,
- DefaultWorkingMemoryEventListener and
- DefaultRuleFlowEventListener. The following code snippet
- shows how to extend DefaultAgendaEventListener and add an
- instance to the session. It prints events resulting from rules being
- fired.
-
- session.addEventListener( new DefaultAgendaEventListener() {
- public void afterActivationFired(AfterActivationFiredEvent event) {
- super.afterActivationFired( event );
- System.out.println( event );
- }
-});
-
- Drools also provides DebugWorkingMemoryEventListener,
- DebugAgendaEventListener and
- DebugRuleFlowEventListener which implement
- each method with a debug print statement. To print all Working
- Memory events, you add a listener like this:
-
- session.addEventListener( new DebugWorkingMemoryEventListener() );
-
- The Eclipse-based Rule IDE also provides an audit logger and
- graphical viewer, so that the rule engine can log events for later
- viewing, and auditing.
-
-
-
- Sequential Mode
-
- With Rete you have a stateful session where objects can be asserted
- and modified over time, and where rules can also be added and removed.
- Now what
- happens if we assume a stateless session, where after the initial data set
- no more data can be asserted or modified and rules cannot be added or
- removed? Certainly it won't be necessary to re-evaluate rules,
- and the engine will be able to operate in a simplified way.
-
-
-
- Order the Rules by salience and position in the ruleset (by
- setting a sequence attribute on the rule terminal node).
-
-
-
- Create an array, one element for each possible rule activation;
- element position indicates firing order.
-
-
-
- Turn off all node memories, except the right-input Object
- memory.
-
-
-
- Disconnect the LeftInputAdapterNode propagation, and let the
- Object plus the Node be referenced in a Command object, which is added to
- a list on the WorkingMemory for later execution.
-
-
-
- Assert all objects, and, when all assertions are finished and thus
- right-input node memories are populated, check the Command list and
- execute each in turn.
-
-
-
- All resulting Activations should be placed in the array, based
- upon the determined sequence number of the Rule. Record the first and
- last populated elements, to reduce the iteration range.
-
-
-
- Iterate the array of Activations, executing populated element in
- turn.
-
-
-
- If we have a maximum number of allowed rule executions, we can
- exit our network evaluations early to fire all the rules in the
- array.
-
-
-
- The LeftInputAdapterNode no longer creates a Tuple, adding the
- Object, and then propagate the Tuple – instead a Command Object is created
- and added to a list in the Working Memory. This Command Object holds a
- reference to the LeftInputAdapterNode and the propagated Object. This
- stops any left-input propagations at insertion time, so that we know that
- a right-input propagation will never need to attempt a join with the
- left-inputs (removing the need for left-input memory). All nodes have
- their memory turned off, including the left-input Tuple memory but
- excluding the right-input Object memory, which means that the only node
- remembering an insertion propagation is the right-input Object memory. Once
- all the assertions are finished and all right-input memories populated,
- we can then iterate the list of LeftInputAdatperNode Command objects
- calling each in turn; they will propagate down the network attempting to
- join with the right-input objects; not being remembered in the left input,
- as we know there will be no further object assertions and thus
- propagations into the right-input memory.
-
- There is no longer an Agenda, with a priority queue to schedule the
- Tuples, instead there is simply an array for the number of rules. The
- sequence number of the RuleTerminalNode indicates the element with the
- array to place the Activation. Once all Command Objects have finished we
- can iterate our array checking each element in turn and firing the
- Activations if they exist. To improve performance in the array we remember
- the first and last populated cells. The network is constructed
- where each RuleTerminalNode is given a sequence number, based on a
- salience number and its order of being added to the network.
-
- Typically the right-input node memories are HashMaps, for fast
- Object retraction; here, as we know there will be no Object retractions,
- we can
- use a list when the values of the Object are not indexed. For larger
- numbers of Objects indexed HashMaps provide a performance increase; if we
- know an Object type has a low number of instances then indexing is
- probably not of an advantage and an Object list can be used.
-
- Sequential mode can only be used with a StatelessSession and is off
- by default. To turn on either set the RuleBaseConfiguration.setSequential
- to true or set the rulebase.conf property drools.sequential to true.
- Sequential mode can fall back to a dynamic agenda with setSequentialAgenda
- to either SequentialAgenda.SEQUENTIAL or SequentialAgenda.DYNAMIC
- set by a call or via the "drools.sequential.agenda" property.
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Theory/Chapter-Theory.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Theory/Chapter-Theory.xml
deleted file mode 100644
index 8990081ade..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Theory/Chapter-Theory.xml
+++ /dev/null
@@ -1,307 +0,0 @@
-
-
- Advanced Concepts and Theory
-
-
- Truth Maintenance with
- Logical Object
- Logical Objects
-
- After regular inserts you have to retract facts explicitly. With
- logical assertions, the fact that was asserted will
- be automatically retracted when the conditions that asserted it in the
- first place are no longer true. Actually, it's even cleverer then that,
- because it will be retracted only if there isn't any single condition that
- supports the logical assertion.
-
- Normal insertions are said to be stated, i.e.,
- just like the intuitive meaning of "stating a fact" implies. Using a
- HashMap and a counter, we track how many times a particular
- equality is stated; this means we count how many
- different instances are equal.
-
- When we logically insert an object during a RHS
- execution we are said to justify it, and it is
- considered to be justified by the firing rule. For each logical insertion
- there can only be one equal object, and each subsequent equal logical
- insertion increases the justification counter for this logical assertion.
- A justification is removed by the LHS of the creating rule becoming
- untrue, and the counter is decreased accordingly. As soon as we have no
- more justifications the logical object is automatically retracted.
-
- If we try to logically insert an object when
- there is an equal stated object, this will fail and
- return null. If we state an object that has an
- existing equal object that is justified we override
- the Fact; how this override works depends on the configuration setting
- WM_BEHAVIOR_PRESERVE. When the property is set to discard we
- use the existing handle and replace the existing instance with the new
- Object, which is the default behavior; otherwise we override it to
- stated but we create an new
- FactHandle.
-
- This can be confusing on a first read, so hopefully the flow charts
- below help. When it says that it returns a new FactHandle,
- this also indicates the Object was propagated through the
- network.
-
-
- Stated Insertion
-
-
-
-
-
-
-
-
- Logical Insertion
-
-
-
-
-
-
-
-
-
- Example Scenario
-
- An example may make things clearer. Imagine a credit card
- processing application, processing transactions for a given account and
- we have a working memory accumulating knowledge about a single account
- transaction. The rule engine is doing its best to decide whether
- transactions are possibly fraudulent or not. Imagine that this rule base
- basically has rules that kick in when there is "reason to be suspicious"
- and when "everything is normal".
-
- Of course there are many rules that operate no matter what,
- performing standard calculations, etc. Now there are possibly many
- reasons as to what could trigger a "reason to be suspicious": someone
- notifying the bank, a sequence of large transactions, transactions for
- geographically disparate locations, or even reports of credit card
- theft. Rather then smattering all the little conditions in lots of
- rules, imagine there is a fact class called "SuspiciousAccount".
-
- Then there can be a series of rules whose job is to look for
- things that may raise suspicion, and if they fire, they
- logically insert a new SuspiciousAccount()
- instance. All the other rules just have conditions like "not
- SuspiciousAccount()" or "SuspiciousAccount()" depending on their needs.
- Note that this has the advantage of allowing there to be many rules
- around raising suspicion, without touching the other rules. After all
- the facts causing the SuspiciousAccount() insertion are removed, the
- account handling reverts to a normal mode of operation where, for
- instance, a rule with "not SuspiciousAccount()" may kick in, which
- flushes through any blocked transactions.
-
- If you have followed this far, you will note that truth
- maintenance, like logical assertions, allows rules to behave a little
- like a human would, and can certainly make the rules more
- manageable.
-
-
-
- Important note: Equality for Java objects
-
- It is important to note that for Truth Maintenance (and logical
- assertions) to work at all, your Fact objects (which may be JavaBeans)
- must override equals and hashCode methods (from java.lang.Object)
- correctly. As the truth maintenance system needs to know when two
- different physical objects are equal in value, both
- equals and hashCode must be overridden correctly, as per the Java
- standard.
-
- Two objects are equal if and only if their equals methods return
- true for each other and if their hashCode methods return the same
- values. See the Java API for more details (but do keep in mind you
- MUST override both equals and hashCode).
-
-
-
-
- Rete Algorithm
-
- The Rete algorithm was invented by Dr. Charles
- Forgy and documented in his PhD thesis in 1978-79. A simplified version of
- the paper was published in 1982 (http://citeseer.ist.psu.edu/context/505087/0).
- The latin word "rete" means "net" or "network". The Rete algorithm can be
- broken into 2 parts: rule compilation and runtime execution.
-
- The compilation algorithm describes how the Rules in the Production
- Memory are processed to generate an efficient discrimination network. In
- non-technical terms, a discrimination network is used to filter data as it
- propagates through the network. The nodes at the top of the network would
- have many matches, and as we go down the network, there would be fewer
- matches. At the very bottom of the network are the terminal nodes. In Dr.
- Forgy's 1982 paper, he described 4 basic nodes: root, 1-input, 2-input and
- terminal.
-
-
- Rete Nodes
-
-
-
-
-
-
-
-
- The root node is where all objects enter the network. From there, it
- immediately goes to the ObjectTypeNode. The purpose of the ObjectTypeNode
- is to make sure the engine doesn't do more work than it needs to. For
- example, say we have 2 objects: Account and Order. If the rule engine
- tried to evaluate every single node against every object, it would waste a
- lot of cycles. To make things efficient, the engine should only pass the
- object to the nodes that match the object type. The easiest way to do this
- is to create an ObjectTypeNode and have all 1-input and 2-input nodes
- descend from it. This way, if an application asserts a new Account, it
- won't propagate to the nodes for the Order object. In Drools when an
- object is asserted it retrieves a list of valid ObjectTypesNodes via a
- lookup in a HashMap from the object's Class; if this list doesn't exist it
- scans all the ObjectTypeNodes finding valid matches which it caches in the
- list. This enables Drools to match against any Class type that matches
- with an instanceof check.
-
-
- ObjectTypeNodes
-
-
-
-
-
-
-
-
- ObjectTypeNodes can propagate to AlphaNodes, LeftInputAdapterNodes
- and BetaNodes. AlphaNodes are used to evaluate literal conditions.
- Although the 1982 paper only covers equality conditions, many RETE
- implementations support other operations. For example, Account.name
- == "Mr Trout" is a literal condition. When a rule has multiple
- literal conditions for a single object type, they are linked together.
- This means that if an application asserts an Account object, it must first
- satisfy the first literal condition before it can proceed to the next
- AlphaNode. In Dr. Forgy's paper, he refers to these as IntraElement
- conditions. The following diagram shows the AlphaNode combinations for
- Cheese( name == "cheddar", strength == "strong" ):
-
-
- AlphaNodes
-
-
-
-
-
-
-
-
- Drools extends Rete by optimizing the propagation from
- ObjectTypeNode to AlphaNode using hashing. Each time an AlphaNode is added
- to an ObjectTypeNode it adds the literal value as a key to the HashMap
- with the AlphaNode as the value. When a new instance enters the ObjectType
- node, rather than propagating to each AlphaNode, it can instead retrieve
- the correct AlphaNode from the HashMap,thereby avoiding unnecessary
- literal checks.
-
- There are two two-input nodes, JoinNode and NotNode, and both are
- types of BetaNodes. BetaNodes are used to compare 2 objects, and their
- fields, to each other. The objects may be the same or different types. By
- convention we refer to the two inputs as left and right. The left input
- for a BetaNode is generally a list of objects; in Drools this is a Tuple.
- The right input is a single object. Two Nodes can be used to implement
- 'exists' checks. BetaNodes also have memory. The left input is called the
- Beta Memory and remembers all incoming tuples. The right input is called
- the Alpha Memory and remembers all incoming objects. Drools extends Rete
- by performing indexing on the BetaNodes. For instance, if we know that a
- BetaNode is performing a check on a String field, as each object enters we
- can do a hash lookup on that String value. This means when facts enter
- from the opposite side, instead of iterating over all the facts to find
- valid joins, we do a lookup returning potentially valid candidates. At any
- point a valid join is found the Tuple is joined with the Object; which is
- referred to as a partial match; and then propagated to the next
- node.
-
-
- JoinNode
-
-
-
-
-
-
-
-
- To enable the first Object, in the above case Cheese, to enter the
- network we use a LeftInputNodeAdapter - this takes an Object as an input
- and propagates a single Object Tuple.
-
- Terminal nodes are used to indicate a single rule having matched all
- its conditions; at this point we say the rule has a full match. A rule
- with an 'or' conditional disjunctive connective results in subrule
- generation for each possible logically branch; thus one rule can have
- multiple terminal nodes.
-
- Drools also performs node sharing. Many rules repeat the same
- patterns, and node sharing allows us to collapse those patterns so that
- they don't have to be re-evaluated for every single instance. The
- following two rules share the first pattern, but not the last:
-
-
-
- rule
- when
- Cheese( $chedddar : name == "cheddar" )
- $person : Person( favouriteCheese == $cheddar )
- then
- System.out.println( $person.getName() + " likes cheddar" );
- end
-
-
-
-
-
- rule
- when
- Cheese( $chedddar : name == "cheddar" )
- $person : Person( favouriteCheese != $cheddar )
- then
- System.out.println( $person.getName() + " does not like cheddar" );
- end
-
-
-
- As you can see below, the compiled Rete network shows that the alpha
- node is shared, but the beta nodes are not. Each beta node has its own
- TerminalNode. Had the second pattern been the same it would have also been
- shared.
-
-
- Node Sharing
-
-
-
-
-
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Chapter-Quick_Start.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Chapter-UserGuide.xml
similarity index 58%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Chapter-Quick_Start.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Chapter-UserGuide.xml
index b4a2c38faf..faab660b9c 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Chapter-Quick_Start.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Chapter-UserGuide.xml
@@ -4,10 +4,15 @@
xml:base="./" xmlns="http://docbook.org/ns/docbook" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
- Quick Start
+ User Guide
-
-
-
+
+
+
+
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Section-A_Little_More_Theory.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-A_Little_More_Theory.xml
similarity index 70%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Section-A_Little_More_Theory.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-A_Little_More_Theory.xml
index 8a34d6b68a..07b0da302a 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Section-A_Little_More_Theory.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-A_Little_More_Theory.xml
@@ -7,7 +7,183 @@
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:ns="http://docbook.org/ns/docbook">
- A Little Theory
+ Execution Control
+
+
+ Agenda
+
+ The Agenda is a Rete feature. During actions on
+ the WorkingMemory, rules may become fully matched and
+ eligible for execution; a single Working Memory Action can result in
+ multiple eligible rules. When a rule is fully matched an Activation is
+ created, referencing the rule and the matched facts, and placed onto the
+ Agenda. The Agenda controls the execution order of these Activations using
+ a Conflict Resolution strategy.
+
+ The engine cycles repeatedly through two phases:
+
+
+
+ Working Memory Actions. This is where most of the work takes
+ place, either in the Consequence (the RHS itself) or the main Java
+ application process. Once the Consequence has finished or the main
+ Java application process calls fireAllRules() the engine
+ switches to the Agenda Evaluation phase.
+
+
+
+ Agenda Evaluation. This attempts to select a rule to fire. If no
+ rule is found it exits, otherwise it fires the found rule, switching
+ the phase back to Working Memory Actions.
+
+
+
+
+ Two Phase Execution
+
+
+
+
+
+
+
+
+ The process repeats until the agenda is clear, in which case control
+ returns to the calling application. When Working Memory Actions are taking
+ place, no rules are being fired.
+
+
+ Agenda
+
+
+
+
+
+
+
+
+
+ Conflict Resolution
+
+ Conflict resolution is required when there are multiple rules on
+ the agenda. (The basics to this are covered in chapter "Quick Start".)
+ As firing a rule may have side effects on the working memory, the rule
+ engine needs to know in what order the rules should fire (for instance,
+ firing ruleA may cause ruleB to be removed from the agenda).
+
+ The default conflict resolution strategies employed by Drools are:
+ Salience and LIFO (last in, first out).
+
+ The most visible one is salience (or
+ priority), in which case a user can specify that a certain rule has a
+ higher priority (by giving it a higher number) than other rules. In that
+ case, the rule with higher salience will be preferred. LIFO priorities
+ are based on the assigned Working Memory Action counter value, with all
+ rules created during the same action receiving the same value. The
+ execution order of a set of firings with the same priority value is
+ arbitrary.
+
+ As a general rule, it is a good idea not to count on rules firing
+ in any particular order, and to author the rules without worrying about
+ a "flow". However when a flow is needed a number of possibilities exist,
+ including but not limited to: agenda groups, rule flow groups,
+ activation groups, control/semaphore facts. These are discussed in later
+ sections.
+
+ Drools 4.0 supported custom conflict resolution strategies; while
+ this capability still exists in Drools it has not yet been exposed to
+ the end user via knowledge-api in Drools 5.0.
+
+
+
+ AgendaGroup
+
+
+ AgendaGroup
+
+
+
+
+
+
+
+
+ Agenda groups are a way to partition rules (activations, actually)
+ on the agenda. At any one time, only one group has "focus" which means
+ that activations for rules in that group only will take effect. You can
+ also have rules with "auto focus" which means that the focus is taken
+ for its agenda group when that rule's conditions are true.
+
+ Agenda groups are known as "modules" in CLIPS terminology. While
+ it best to design rules that do not need control flow, this is not
+ always possible. Agenda groups provide a handy way to create a "flow"
+ between grouped rules. You can switch the group which has focus either
+ from within the rule engine, or via the API. If your rules have a clear
+ need for multiple "phases" or "sequences" of processing, consider using
+ agenda-groups for this purpose.
+
+ Each time setFocus() is called it pushes that Agenda
+ Group onto a stack. When the focus group is empty it is popped from the
+ stack and the focus group that is now on top evaluates. An Agenda Group
+ can appear in multiple locations on the stack. The default Agenda Group
+ is "MAIN", with all rules which do not specify an Agenda Group being in
+ this group. It is also always the first group on the stack, given focus
+ initially, by default.
+
+ ksession.getAgenda().getAgendaGroup( "Group A" ).setFocus();
+
+
+
+ ActivationGroup
+
+
+ ActivationGroup
+
+
+
+
+
+
+
+
+ An activation group is a set of rules bound together by the same
+ "activation-group" rule attribute. In this group only one rule can fire,
+ and after that rule has fired all the other rules are cancelled from the
+ agenda. The clear() method can be called at any time, which
+ cancels all of the activations before one has had a chance to
+ fire.
+
+ ksession.getAgenda().getActivationGroup( "Group B" ).clear();
+
+
+
+ RuleFlowGroup
+
+
+ RuleFlowGroup
+
+
+
+
+
+
+
+
+ A rule flow group is a group of rules associated by the
+ "ruleflow-group" rule attribute. These rules can only fire when the
+ group is activate. The group itself can only become active when the
+ elaboration of the ruleflow diagram reaches the node representing the
+ group. Here too, the clear() method can be called at any
+ time to cancels all activations still remaining on the Agenda.
+
+ ksession.getAgenda().getRuleFlowGroup( "Group C" ).clear();
+
+ Methods versus Rules
@@ -86,7 +262,7 @@ end
Sprinkler and every row in the Room table would be joined with
every row in the Sprinkler table resulting in the following output:
- room:office sprinker:office
+ room:office sprinkler:office
room:office sprinkler:kitchen
room:office sprinkler:livingroom
room:office sprinkler:bedroom
@@ -173,7 +349,7 @@ public AccountPeriod {
+ width="100%"/>
@@ -191,9 +367,9 @@ when
ap : AccountPeriod()
acc : Account( $accountNo : accountNo )
CashFlow( type == CREDIT,
- accountNo == $accountNo,
- date >= ap.start && <= ap.end,
- $amount : amount )
+ accountNo == $accountNo,
+ date >= ap.start && <= ap.end,
+ $amount : amount )
then
acc.balance += $amount;
end
@@ -203,9 +379,9 @@ when
ap : AccountPeriod()
acc : Account( $accountNo : accountNo )
CashFlow( type == DEBIT,
- accountNo == $accountNo,
- date >= ap.start && <= ap.end,
- $amount : amount )
+ accountNo == $accountNo,
+ date >= ap.start && <= ap.end,
+ $amount : amount )
then
acc.balance -= $amount;
end
@@ -222,7 +398,7 @@ end
-
+
@@ -242,7 +418,7 @@ end
-
+
@@ -255,7 +431,7 @@ end
-
+
@@ -269,7 +445,7 @@ end
-
+
@@ -281,7 +457,7 @@ end
-
+
@@ -323,7 +499,7 @@ end
-
+
@@ -377,7 +553,7 @@ where acc.accountNo == cf.accountNo and
-
+
@@ -428,7 +604,7 @@ end
than this, correct use of inference can crate more agile and less error
prone businesses with easier to maintain software.
- So what is inference? Something is inferred when we gain knowledge
+ So what is inference? Something is inferred when we gain knowledge
of something from using previous knowledge. For example given a Person
fact with an age field and a rule that provides age policy control, we can
infer whether a Person is an adult or a child and act on this.
@@ -458,7 +634,7 @@ IsAdult( person == $p )
-
+
@@ -471,7 +647,7 @@ IsAdult( person == $p )
This change management process and communication between departments
is not ideal for an agile environment and change become costly and error
prone. Also the card department is managing more information than it needs
- to be aware of with its "monolothic" approach to rules management which is
+ to be aware of with its "monolithic" approach to rules management which is
"leaking" information better placed else where. By this I mean that it
doesn't care what explicit "age >= 18" information determines whether
someone is an adult, only that they are an adult.
@@ -486,7 +662,7 @@ IsAdult( person == $p )
-
+
@@ -499,7 +675,7 @@ IsAdult( person == $p )
-
+
@@ -516,10 +692,10 @@ IsAdult( person == $p )
IsAdult also gave a semantic abstraction to the previously arbitrary logic
"age >= 18".
- So a general rule or thumb when doing your knowledge engineering
+ So a general rule or thumb when doing your knowledge engineering
is:
-
+
@@ -580,20 +756,20 @@ end
As before we can provide a more robust application with a separation
of concerns using inference. Notice this time we don't just insert the
- inferred object, we use "logicalInsert":
+ inferred object, we use "insertLogical":rule "Infer Child" when
$p : Person( age < 16 )
then
- logicalInsert( new IsChild( $p ) )
+ insertLogical( new IsChild( $p ) )
end
rule "Infer Adult" when
- $p : Person( age >= 16 )
+ $p : Person( age >= 16 )
then
- logicalInsert( new IsAdult( $p ) )
+ insertLogical( new IsAdult( $p ) )
end
- A "logicalInsert" is part of the Drools Truth Maintenance System
+ A "insertLogical" is part of the Drools Truth Maintenance System
(TMS). Here the fact is logically inserted, this fact is dependant on the
truth of the "when" clause. It means that when the rule becomes false the
fact is automatically retracted. This works particularly well as the two
@@ -601,22 +777,22 @@ end
16 it inserts an IsChild fact, once the person is 16 or over the IsChild
fact is automatically retracted and the IsAdult fact inserted.
- We can now bring back in the code to issue the passes, these two
- can also be logically inserted, as the TMS supports chaining of logical
+ We can now bring back in the code to issue the passes, these two can
+ also be logically inserted, as the TMS supports chaining of logical
insertions for a cascading set of retracts.rule "Issue Child Bus Pass" when
- $p : Person( )
- IsChild( person =$p )
+ $p : Person( )
+ IsChild( person == $p )
then
- logicalInsert(new ChildBusPass( $p ) );
+ insertLogical(new ChildBusPass( $p ) );
end
rule "Issue Adult Bus Pass" when
- $p : Person( age >= 16 )
- IsAdult( person =$p )
+ $p : Person( age >= 16 )
+ IsAdult( person =$p )
then
- logicalInsert(new AdultBusPass( $p ) );
+ insertLogical(new AdultBusPass( $p ) );
endNow when the person changes from being 15 to 16, not only is the
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Section-More_On_Building_And_Deploying.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-BuildingAndDeploying.xml
similarity index 95%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Section-More_On_Building_And_Deploying.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-BuildingAndDeploying.xml
index 2bb191be9a..2c4a0c8b70 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Quick_Start/Section-More_On_Building_And_Deploying.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-BuildingAndDeploying.xml
@@ -77,9 +77,9 @@ if ( kbuilder.hasErrors() ) {
Knowledge Agent
- The Knowlege Agent provides automatic loading, caching and
+ The Knowledge Agent provides automatic loading, caching and
re-loading of resources and is configured from a properties files. The
- Knowledge Agent can update or rebuild this Knowlege Base as the resources
+ Knowledge Agent can update or rebuild this Knowledge Base as the resources
it uses are changed. The strategy for this is determined by the
configuration given to the factory, but it is typically pull-based using
regular polling. We hope to add push-based updates and rebuilds in future
@@ -126,16 +126,16 @@ ResourceFactory.getResourceChangeScannerService().start();
Reuse KnowledgeBase ClassLoader
- Most of the times, the classloader you wan't to use in the
+ Most of the times, the classloader you want to use in the
compilation process of remote resources is the same needed in the
agent's kbase, so the rules could be executed. If you want to use this
approach, you will need to setup the desired ClassLoader to the
- agen't kbase and use the "drools.agent.useKBaseClassLoaderForCompiling"
+ agent kbase and use the "drools.agent.useKBaseClassLoaderForCompiling"
property of KnowledgeAgentConfiguration object.This approach lets you modify agent's kbuilder classloader in
runtime by modifying the classloader the agent's kbase uses. This will
serve also when not using incremental change set processing (see the
- section bellow). When the kbase is recreated its configuration is
+ section below). When the kbase is recreated its configuration is
reused, so the classloader is maintained.KnowledgeBaseConfiguration kbaseConfig =
KnowledgeBaseFactory.newKnowledgeBaseConfiguration(null, customClassLoader);
@@ -161,7 +161,7 @@ KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent(
KnowledgeAgentConfiguration object passed to the Agent's constructor.
- When "newInstace" is set to true (the default value), the agent
+ When "newInstance" is set to true (the default value), the agent
will destroy the cached Knowledge Base it contains and populate a
new one containing the change set modifications. When "newInstance"
is set to "false" change sets are applied directly to the cached
@@ -173,7 +173,7 @@ KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent(
The following code snippet creates a new Knowledge Agent with its
- "newInstace" property set to false
+ "newInstance" property set to false
KnowledgeAgentConfiguration aconf = KnowledgeAgentFactory.newKnowledgeAgentConfiguration();
aconf.setProperty("drools.agent.newInstance", "false");
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Authoring/Section-Decision_Tables.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-DecisionTables.xml
similarity index 63%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Authoring/Section-Decision_Tables.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-DecisionTables.xml
index 46ab3f643e..4f99094b5e 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Authoring/Section-Decision_Tables.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-DecisionTables.xml
@@ -20,9 +20,8 @@
When to Use Decision Tables
- Consider decision tables as a course of action if rules exist that can be expressed as rule
- templates and data: each row of a decision table provides data that is combined with a template to
- generate a rule.
+ Consider decision tables as a course of action if rules exist that can be expressed as rule templates and
+ data: each row of a decision table provides data that is combined with a template to generate a rule.Many businesses already use spreadsheets for managing data, calculations, etc. If you are happy to continue
this way, you can also manage your business rules this way. This also assumes you are happy to manage packages of
@@ -41,7 +40,7 @@
- Using Excel to edit a decision table
+ Using Excel to edit a decision table
@@ -53,7 +52,7 @@
- Multiple actions for a rule row
+ Multiple actions for a rule row
@@ -65,7 +64,7 @@
- Using OpenOffice.org
+ Using OpenOffice.org
@@ -91,14 +90,14 @@
As each row is a rule, the same principles apply. As the rule engine processes the facts, any rules that match
may fire. (Some people are confused by this. It is possible to clear the agenda when a rule fires and simulate a
- very simple decision table where only the first match effects an action.) Also note that you can have multiple tables on one
- spreadsheet. This way, rules can be grouped where they share common templates, yet at the end of the day they are
- all combined into one rule package. Decision tables are essentially a tool to generate DRL rules
+ very simple decision table where only the first match effects an action.) Also note that you can have multiple
+ tables on one spreadsheet. This way, rules can be grouped where they share common templates, yet at the end of the
+ day they are all combined into one rule package. Decision tables are essentially a tool to generate DRL rules
automatically.
- A real world example using multiple tables for grouping like rules
+ A real world example using multiple tables for grouping like rules
@@ -117,7 +116,7 @@
- Rows and columns
+ Rows and columns
@@ -138,7 +137,7 @@
- Expanded for rule templates
+ Expanded for rule templates
@@ -169,14 +168,14 @@
Row 15 contains declarations of ObjectTypes. The content in this row is optional, but
if this option is not in use, the row must be left blank; however this option is usually found to be quite useful.
When using this row, the values in the cells below (row 16) become constraints on that object type. In the above
- case, it generates Person(age=="42") and Cheese(type=="stilton"), where 42 and
- "stilton" come from row 18. In the above example, the "==" is implicit; if just a field name is given the
- translator assumes that it is to generate an exact match.
+ case, it generates Person(age=="42") and Cheese(type=="stilton"), where 42 and "stilton"
+ come from row 18. In the above example, the "==" is implicit; if just a field name is given the translator assumes
+ that it is to generate an exact match.An ObjectType declaration can span columns (via merged cells), meaning that all columns below the merged
- range are to be combined into one set of constraints within a single pattern matching a single fact at a time,
- as opposed to non-merged cells containing the same ObjectType, but resulting in different patterns, potentially
+ range are to be combined into one set of constraints within a single pattern matching a single fact at a time, as
+ opposed to non-merged cells containing the same ObjectType, but resulting in different patterns, potentially
matching different or identical facts.
@@ -187,7 +186,7 @@
Rows 18 and 19 show data, which will be combined (interpolated) with the templates in row 15, to generate
rules. If a cell contains no data, then its template is ignored. (This would mean that some condition or action does
- not apply for that rule row.) Rule rows are read until there is a blank row. Multiple RuleTables can exsist in a
+ not apply for that rule row.) Rule rows are read until there is a blank row. Multiple RuleTables can exist in a
sheet. Row 20 contains another keyword, and a value. The row positions of keywords like this do not matter (most
people put them at the top) but their column should be the same one where the RuleTable or RuleSet keywords should
appear. In our case column C has been chosen to be significant, but any other column could be used instead.
@@ -209,6 +208,10 @@ end
constraints, to be added to the respective ObjectType in the cell above. If the cells above were spanned, then
there could be multiple constraints on one "column".
+
+
+ Very large decision tables may have very large memory requirements.
+
@@ -217,43 +220,38 @@ end
Spreadsheet Structure
- There are two types of rectangular areas defining data that is used for generating a DRL file.
- One, marked by a cell labelled RuleSet, defines all DRL items except rules. The
- other one may occur repeatedly and is to the right and below a cell whose contents begin with
- RuleTable. These areas represent the actual decision tables, each area resulting
- in a set of rules of similar structure.
-
- A Rule Set area may contain cell pairs, one below the RuleSet cell and containing
- a keyword designating the kind of value contained in the other one that follows in the same row.
-
-
- The columns of a Rule Table area define patterns and constraints for the left hand sides of
- the rules derived from it, actions for the consequences of the rules, and the values of
- individual rule attributes. Thus, a Rule Table area should contain one or more columns, both for
- conditions and actions, and an arbitrary selection of columns for rule attributes, at most one
- column for each of these. The first four rows following the row with the cell marked with
- RuleTable are earmarked as header area, mostly used for the definition of code to
- construct the rules. It is any additional row below these four header rows that spawns another
- rule, with its data providing for variations in the code defined in the Rule Table header.
+ There are two types of rectangular areas defining data that is used for generating a DRL file. One, marked
+ by a cell labelled RuleSet, defines all DRL items except rules. The other one may occur repeatedly
+ and is to the right and below a cell whose contents begin with RuleTable. These areas represent the
+ actual decision tables, each area resulting in a set of rules of similar structure.
+
+ A Rule Set area may contain cell pairs, one below the RuleSet cell and containing a keyword
+ designating the kind of value contained in the other one that follows in the same row.
+
+ The columns of a Rule Table area define patterns and constraints for the left hand sides of the rules
+ derived from it, actions for the consequences of the rules, and the values of individual rule attributes. Thus, a
+ Rule Table area should contain one or more columns, both for conditions and actions, and an arbitrary selection of
+ columns for rule attributes, at most one column for each of these. The first four rows following the row with the
+ cell marked with RuleTable are earmarked as header area, mostly used for the definition of code to
+ construct the rules. It is any additional row below these four header rows that spawns another rule, with its data
+ providing for variations in the code defined in the Rule Table header.All keywords are case insensitive.Only the first worksheet is examined for decision tables.
-
+
Rule Set Entries
- Entries in a Rule Set area may define DRL constructs (except rules), and specify rule
- attributes. While entries for constructs may be used repeatedly, each rule attribute may be
- given at most once, and it applies to all rules unless it is overruled by the same attribute
- being defined within the Rule Table area.
+ Entries in a Rule Set area may define DRL constructs (except rules), and specify rule attributes. While
+ entries for constructs may be used repeatedly, each rule attribute may be given at most once, and it applies to
+ all rules unless it is overruled by the same attribute being defined within the Rule Table area.
- Entries must be given in a vertically stacked sequence of cell pairs. The first one
- contains a keyword and the one to its right the value, as shown in the table below.
- This sequence of cell pairs may be interrupted by blank rows or even a Rule Table, as long
- as the column marked by RuleSet is upheld as the one containing the keyword.
-
+ Entries must be given in a vertically stacked sequence of cell pairs. The first one contains a keyword and
+ the one to its right the value, as shown in the table below. This sequence of cell pairs may be interrupted by
+ blank rows or even a Rule Table, as long as the column marked by RuleSet is upheld as the one
+ containing the keyword.
Entries in the Rule Set area
@@ -262,7 +260,9 @@ end
Keyword
+
Value
+
Usage
@@ -270,50 +270,78 @@ end
RuleSet
- The package name for the generated DRL file.
- Optional, the default is rule_table.
+
+ The package name for the generated DRL file. Optional, the default is
+ rule_table.
+
Must be First entry.Sequential
- "true" or "false". If "true", then salience is used to ensure that
- rules fire from the top down.
+
+ "true" or "false". If "true", then salience is used to ensure that rules fire from the top
+ down.
+
Optional, at most once. If omitted, no firing order is imposed.
+
+ EscapeQuotes
+
+ "true" or "false". If "true", then quotation marks are escaped so that they appear literally in the
+ DRL.
+
+ Optional, at most once. If omitted, quotation marks are escaped.
+
+
Import
+
A comma-separated list of Java classes to import.
+
Optional, may be used repeatedly.Variables
- Declarations of DRL globals, i.e., a type followed by a variable name.
- Multiple global definitions must be separated with a comma.
+
+ Declarations of DRL globals, i.e., a type followed by a variable name. Multiple global definitions
+ must be separated with a comma.
+
Optional, may be used repeatedly.Functions
+
One or more function definitions, according to DRL syntax.
+
Optional, may be used repeatedly.Queries
+
One or more query definitions, according to DRL syntax.
+
+ Optional, may be used repeatedly.
+
+
+
+ Declare
+
+ One or more declarative types, according to DRL syntax.
+
Optional, may be used repeatedly.
- For defining rule attributes that apply to all rules in the generated DRL file
- you can use any of the entries in the following table. Notice, however, that the
- proper keyword must be used. Also, each of these attributes may be used only once.
-
+ For defining rule attributes that apply to all rules in the generated DRL file you can use any of the
+ entries in the following table. Notice, however, that the proper keyword must be used. Also, each of these
+ attributes may be used only once.
Rule attribute entries in the Rule Set area
@@ -322,7 +350,9 @@ end
Keyword
+
Initial
+
Value
@@ -330,89 +360,119 @@ end
PRIORITY
+
P
- An integer defining the "salience" value for the rule. Overriden by the "Sequential" flag.
+
+ An integer defining the "salience" value for the rule. Overridden by the "Sequential" flag.DURATION
+
D
+
A long integer value defining the "duration" value for the rule.
+
+ TIMER
+
+ T
+
+ A timer definition. See "Timers and Calendars".
+
+
+
+ CALENDARS
+
+ E
+
+ A calendars definition. See "Timers and Calendars".
+
+
NO-LOOP
+
U
+
A Boolean value. "true" inhibits looping of rules due to changes made by its consequence.LOCK-ON-ACTIVE
+
L
- A Boolean value. "true" inhibits additional activations of all rules with this flag set within
- the same ruleflow or agenda group.
+
+ A Boolean value. "true" inhibits additional activations of all rules with this flag set within the
+ same ruleflow or agenda group.AUTO-FOCUS
+
F
+
A Boolean value. "true" for a rule within an agenda group causes activations of the rule to
automatically give the focus to the group.ACTIVATION-GROUP
+
X
- A string identifying an activation (or XOR) group. Only one rule within
- an activation group will fire, i.e., the first one to fire cancels any existing activations of
- other rules within the same group.
+
+ A string identifying an activation (or XOR) group. Only one rule within an activation group will
+ fire, i.e., the first one to fire cancels any existing activations of other rules within the same
+ group.AGENDA-GROUP
+
G
- A string identifying an agenda group, which has to be activated by giving it the
- "focus", which is one way of controlling the flow between groups of rules.
+
+ A string identifying an agenda group, which has to be activated by giving it the "focus", which is
+ one way of controlling the flow between groups of rules.RULEFLOW-GROUP
+
R
+
A string identifying a rule-flow group.
-
-
Rule Tables
- All Rule Tables begin with a cell containing "RuleTable", optionally followed by a string
- within the same cell. The string is used as the initial part of the name for all rules derived
- from this Rule Table, with the row number appended for distinction. (This automatic naming can
- be overridden by using a NAME column.) All other cells defining rules of this Rule Table are
- below and to the right of this cell.
+ All Rule Tables begin with a cell containing "RuleTable", optionally followed by a string within the same
+ cell. The string is used as the initial part of the name for all rules derived from this Rule Table, with the row
+ number appended for distinction. (This automatic naming can be overridden by using a NAME column.) All other cells
+ defining rules of this Rule Table are below and to the right of this cell.
- The next row defines the column type, with each column resulting in a part of the
- condition or the consequence, or providing some rule attribute, the rule name or a comment.
- The table below shows which column headers are available; additional columns may be used
- according to the table showing rule attribute entries given in the preceding section.
- Note that each attribute column may be used at most once. For a column header, either
- use the keyword or any other word beginning with the letter given in the "Initial" column
- of these tables.
+ The next row defines the column type, with each column resulting in a part of the condition or the
+ consequence, or providing some rule attribute, the rule name or a comment. The table below shows which column
+ headers are available; additional columns may be used according to the table showing rule attribute entries given
+ in the preceding section. Note that each attribute column may be used at most once. For a column header, either
+ use the keyword or any other word beginning with the letter given in the "Initial" column of these tables.
- Column Headers in the Rule Table
+ Column Headers in the Rule TableKeyword
+
Initial
+
Value
+
Usage
@@ -420,109 +480,124 @@ end
NAME
+
N
- Provides the name for the rule generated from that row. The default is constructed
- from the text following the RuleTable tag and the row number.
+
+ Provides the name for the rule generated from that row. The default is constructed from the text
+ following the RuleTable tag and the row number.
+
At most one columnDESCRIPTION
+
I
+
A text, resulting in a comment within the generated rule.
+
At most one columnCONDITION
+
C
- Code snippet and interpolated values for constructing a constraint within
- a pattern in a condition.
+
+ Code snippet and interpolated values for constructing a constraint within a pattern in a
+ condition.
+
At least one per rule tableACTION
+
A
- Code snippet and interpolated values for constructing an action for the
- consequence of the rule.
+
+ Code snippet and interpolated values for constructing an action for the consequence of the
+ rule.
+
At least one per rule tableMETADATA
+
@
- Code snippet and interpolated values for constructing a metadata entry
- for the rule.
+
+ Code snippet and interpolated values for constructing a metadata entry for the rule.
+
Optional, any number of columns
-
Given a column headed CONDITION, the cells in successive lines result in a conditional element.
+
- Text in the first cell below CONDITION develops into a pattern for the rule condition, with
- the snippet in the next line becoming a constraint. If the cell is merged with one or more neighbours,
- a single pattern with multiple constraints is formed: all constraints are combined into a parenthesized
- list and appended to the text in this cell. The cell may be left blank, which means that the code
- snippet in the next row must result in a valid conditional element on its own.
+ Text in the first cell below CONDITION develops into a pattern for the rule condition, with the snippet
+ in the next line becoming a constraint. If the cell is merged with one or more neighbours, a single pattern
+ with multiple constraints is formed: all constraints are combined into a parenthesized list and appended to
+ the text in this cell. The cell may be left blank, which means that the code snippet in the next row must
+ result in a valid conditional element on its own.
- To include a pattern without constraints, you can write the pattern in front of the text
- for another pattern.
+ To include a pattern without constraints, you can write the pattern in front of the text for another
+ pattern.
- The pattern may be written with or without an empty pair of parentheses. A "from" clause may be
- appended to the pattern.
+ The pattern may be written with or without an empty pair of parentheses. A "from" clause may be appended
+ to the pattern.
- If the pattern ends with "eval", code snippets are supposed to produce boolean expressions
- for inclusion into a pair of parentheses after "eval".
+ If the pattern ends with "eval", code snippets are supposed to produce boolean expressions for inclusion
+ into a pair of parentheses after "eval".Text in the second cell below CONDITION is processed in two steps.
+
- The code snippet in this cell is modified by interpolating values from cells farther down in the column.
- If you want to create a constraint consisting of a comparison using "==" with the value from the cells below,
- the field selector alone is sufficient. Any other comparison operator must be specified as the last item
- within the snippet, and the value from the cells below is appended. For all other constraint forms, you must
- mark the position for including the contents of
- a cell with the symbol $param. Multiple insertions are possible by using the symbols
- $1, $2, etc., and a comma-separated list of values in the cells below.
+ The code snippet in this cell is modified by interpolating values from cells farther down in the
+ column. If you want to create a constraint consisting of a comparison using "==" with the value from the
+ cells below, the field selector alone is sufficient. Any other comparison operator must be specified as
+ the last item within the snippet, and the value from the cells below is appended. For all other constraint
+ forms, you must mark the position for including the contents of a cell with the symbol
+ $param. Multiple insertions are possible by using the symbols $1,
+ $2, etc., and a comma-separated list of values in the cells below.A text according to the pattern
forall(delimiter){snippet}
- is expanded by repeating the snippet once for each of the values of the comma-separated
- list of values in each of the cells below, inserting the value in place of the symbol $ and
- by joining these expansions by the given delimiter. Note that the forall construct may
- be surrounded by other text.
-
-
+ is expanded by repeating the snippet once for each of the values of the
+ comma-separated list of values in each of the cells below, inserting the value in place of the symbol
+ $ and by joining these expansions by the given delimiter. Note that the
+ forall construct may be surrounded by other text.
+
If the cell in the preceding row is not empty, the completed code snippet is added to the
- conditional element from that cell. A pair of parentheses is provided automatically, as well as
- a separating comma if multiple constraints are added to a pattern in a merged cell.
+ conditional element from that cell. A pair of parentheses is provided automatically, as well as a
+ separating comma if multiple constraints are added to a pattern in a merged cell.
+
If the cell above is empty, the interpolated result is used as is.
- Text in the third cell below CONDITION is for documentation only. It should be used to
- indicate the column's purpose to a human reader.
+ Text in the third cell below CONDITION is for documentation only. It should be used to indicate the
+ column's purpose to a human reader.
- From the fourth row on, non-blank entries provide data for interpolation as described
- above. A blank cell results in the omission of the conditional element or constaint for this
- rule.
+ From the fourth row on, non-blank entries provide data for interpolation as described above. A blank
+ cell results in the omission of the conditional element or constraint for this rule.Given a column headed ACTION, the cells in successive lines result in an action statement.
+
Text in the first cell below ACTION is optional. If present, it is interpreted as an object
@@ -531,21 +606,25 @@ end
Text in the second cell below ACTION is processed in two steps.
+
- The code snippet in this cell is modified by interpolating values from cells farther down in the column.
- For a singular insertion, mark the position for including the contents of a cell with the symbol
- $param. Multiple insertions are possible by using the symbols $1, $2,
- etc., and a comma-separated list of values in the cells below.
- A method call without interpolation can be achieved by a text without any marker symbols. In this case,
- use any non-blank entry in a row below to include the statement.
+ The code snippet in this cell is modified by interpolating values from cells farther down in the
+ column. For a singular insertion, mark the position for including the contents of a cell with the symbol
+ $param. Multiple insertions are possible by using the symbols $1,
+ $2, etc., and a comma-separated list of values in the cells below.
+
+ A method call without interpolation can be achieved by a text without any marker symbols. In this
+ case, use any non-blank entry in a row below to include the statement.
+
The forall construct is available here, too.
+
- If the first cell is not empty, its text, followed by a period, the text in the second cell
- and a terminating semicolon are stringed together, resulting in a method call which is added as an
- action statement for the consequence.
-
+ If the first cell is not empty, its text, followed by a period, the text in the second cell and a
+ terminating semicolon are stringed together, resulting in a method call which is added as an action
+ statement for the consequence.
+
If the cell above is empty, the interpolated result is used as is.
@@ -557,20 +636,19 @@ end
- From the fourth row on, non-blank entries provide data for interpolation as described
- above. A blank cell results in the omission of the action statement for this rule.
+ From the fourth row on, non-blank entries provide data for interpolation as described above. A blank
+ cell results in the omission of the action statement for this rule.
-
+
- Using $1 instead of $param works in most cases, but it will fail
- if the replacement text contains a comma: then, only the part preceding the first comma is inserted.
- Use this "abbreviation" judiciously.
+ Using $1 instead of $param works in most cases, but it will fail if the
+ replacement text contains a comma: then, only the part preceding the first comma is inserted. Use this
+ "abbreviation" judiciously.
-
- Given a column headed METADATA, the cells in successive lines result in a metadata annotation
- for the generated rules.
+ Given a column headed METADATA, the cells in successive lines result in a metadata annotation for the
+ generated rules.
@@ -578,25 +656,23 @@ end
- Text in the second cell below METADATA is subject to interpolation, as described above,
- using values from the cells in the rule rows. The metadata marker character @
- is prefixed automatically, and thus it should not be included in the text for this cell.
+ Text in the second cell below METADATA is subject to interpolation, as described above, using values
+ from the cells in the rule rows. The metadata marker character @ is prefixed automatically, and
+ thus it should not be included in the text for this cell.
- Text in the third cell below METADATA is for documentation only. It should be used to
- indicate the column's purpose to a human reader.
+ Text in the third cell below METADATA is for documentation only. It should be used to indicate the
+ column's purpose to a human reader.
- From the fourth row on, non-blank entries provide data for interpolation as described
- above. A blank cell results in the omission of the metadata annotation for this rule.
+ From the fourth row on, non-blank entries provide data for interpolation as described above. A blank
+ cell results in the omission of the metadata annotation for this rule.
-
-
Examples
@@ -608,81 +684,68 @@ end
If the template is Foo(bar == $param) and the cell is 42, then the result is
Foo(bar == 42).
- If the template is Foo(bar < $1, baz == $2) and the cell contains 42,43,
- the result will be Foo(bar < 42, baz ==43).
+ If the template is Foo(bar < $1, baz == $2) and the cell contains 42,43, the
+ result will be Foo(bar < 42, baz ==43).
- The template forall(&&){bar != $} with a cell containing 42,43
- results in bar != 42 && bar != 43.
+ The template forall(&&){bar != $} with a cell containing 42,43 results
+ in bar != 42 && bar != 43.
-
- The next example demonstrates the joint effect of a cell defining the pattern type and the code
- snippet below it.
-
+ The next example demonstrates the joint effect of a cell defining the pattern type and the code snippet
+ below it.
-
- This spreadsheet section shows how the Person type declaration spans 2 columns, and thus
- both constraints will appear as Person(age == ..., type == ...). Since only
- the field names are present in the snippet, they imply an equality test.
+ This spreadsheet section shows how the Person type declaration spans 2 columns, and
+ thus both constraints will appear as Person(age == ..., type == ...). Since only the field names are
+ present in the snippet, they imply an equality test.
- In the following example the marker symbol $param is used.
-
+ In the following example the marker symbol $param is used.
-
- The result of this column is the pattern Person(age == "42")). You may have
- noticed that the marker and the operator "==" are redundant.
+ The result of this column is the pattern Person(age == "42")). You may have noticed
+ that the marker and the operator "==" are redundant.
- The next example illustrates that a trailing insertion marker can be omitted.
-
+ The next example illustrates that a trailing insertion marker can be omitted.
-
- Here, appending the value from the cell is implied, resulting in Person(age < "42")).
-
+ Here, appending the value from the cell is implied, resulting in Person(age <
+ "42")).
- You can provide the definition of a binding variable, as in the example below.
- .
+ You can provide the definition of a binding variable, as in the example below. .
-
- Here, the result is c: Cheese(type == "stilton"). Note that the quotes are provided
- automatically. Actually, anything can be placed in the object type row. Apart from the definition
- of a binding variable, it could alse be an additional pattern that is to be inserted literally.
-
-
- A simple construction of an action statement with the insertion of a single value is shown
- below.
-
+ Here, the result is c: Cheese(type == "stilton"). Note that the quotes are provided
+ automatically. Actually, anything can be placed in the object type row. Apart from the definition of a binding
+ variable, it could also be an additional pattern that is to be inserted literally.
+
+ A simple construction of an action statement with the insertion of a single value is shown below.
+
-
- The cell below the ACTION header is left blank. Using this style, anything can be placed in the
- consequence, not just a sinle method call. (The same technique is applicable within a
- CONDITION column as well.)
-
- Below is a comprehensive example, showing the use of various column headers. It is not
- an error to have no value below a column header (as in the NO-LOOP column): here, the attribute
- will not be applied in any of the rules.
-
+ The cell below the ACTION header is left blank. Using this style, anything can be placed in the
+ consequence, not just a single method call. (The same technique is applicable within a CONDITION column as
+ well.)
+
+ Below is a comprehensive example, showing the use of various column headers. It is not an error to have no
+ value below a column header (as in the NO-LOOP column): here, the attribute will not be applied in any of the
+ rules.
- Example usage of keywords for imports, headers, etc.
+ Example usage of keywords for imports, headers, etc.
@@ -690,38 +753,30 @@ end
-
-
+
- And, finally, here is an example of Import, Variables and Functions.
-
-
- Example usage of keywords for functions, etc.
-
+ And, finally, here is an example of Import, Variables and Functions.
+
+ Example usage of keywords for functions, etc.
+
-
-
-
-
-
-
- Multiple package names within the same cell must be separated by a comma. Also, the
- pairs of type and variable names must be comma-separated. Functions, however, must be
- written as they appear in a DRL file. This should appear in the same column as the
- "RuleSet" keyword; it could be above, between or below all the rule rows.
+
+
+
+
+
+ Multiple package names within the same cell must be separated by a comma. Also, the pairs of type
+ and variable names must be comma-separated. Functions, however, must be written as they appear in a DRL file. This
+ should appear in the same column as the "RuleSet" keyword; it could be above, between or below all the rule
+ rows.
- It may be more convenient to use Import, Variables, Functions and Queries repeatedly
- rather than packing several definitions into a single cell.
+ It may be more convenient to use Import, Variables, Functions and Queries repeatedly rather than packing
+ several definitions into a single cell.
-
-
-
-
-
Creating and integrating Spreadsheet based Decision Tables
@@ -735,7 +790,7 @@ end
Workbench IDE), the wizard can generate a spreadsheet from a template (to edit it an xls compatible spreadsheet
editor will need to be used).
- Wizard in the IDE
+ Wizard in the IDE
@@ -800,7 +855,7 @@ end
such as validating fields. Lists that are stored in other worksheets can be used to provide valid lists of values
for cells, like in the following diagram.
- Wizard in the IDE
+ Wizard in the IDE
@@ -846,32 +901,29 @@ end
-
- A decision table-like example
-
- As an example, a more classic decision table is shown, but without any hidden rows for the rule meta data
- (so the spreadsheet only contains the raw data to generate the rules).
+ As an example, a more classic decision table is shown, but without any hidden rows for the rule meta data (so
+ the spreadsheet only contains the raw data to generate the rules).
-
-
- Template data
-
+
+
+ Template data
+
-
-
-
-
-
-
+
+
+
+
+
+
- See the ExampleCheese.xls in the examples download for the above spreadsheet.
+ See the ExampleCheese.xls in the examples download for the above spreadsheet.
- If this was a regular decision table there would be hidden rows before row 1 and between rows 1 and 2
- containing rule metadata. With rule templates the data is completely separate from the rules. This has two handy
- consequences - you can apply multiple rule templates to the same data and your data is not tied to your rules at
- all. So what does the template look like?
+ If this was a regular decision table there would be hidden rows before row 1 and between rows 1 and 2
+ containing rule metadata. With rule templates the data is completely separate from the rules. This has two handy
+ consequences - you can apply multiple rule templates to the same data and your data is not tied to your rules at
+ all. So what does the template look like?
-
+
1 template header
2 age
3 type
@@ -892,26 +944,49 @@ end
18 end
19
20 end template
-
-
- Referring to the above:
-
-
-Line 1: all rule templates start with "template header"
-Lines 2-4: following the header is the list of columns in the order they appear in the data. In this case we are calling the first column "age", the second "type" and the third "log".
-Lines 5: empty line signifying the end of the column definitions
-Lines 6-9: standard rule header text. This is standard rule DRL and will appear at the top of the generated DRL. Put the package statement and any imports and global definitions
-Line 10: The "template" keyword signals the start of a rule template. There can be more than one template in a template file. The template should have a unique name.
-Lines 11-18: The rule template - see below
-Line 20: "end template" signifies the end of the template.
- The rule templates rely on MVEL to do substitution using the syntax @{token_name}. There is currently one
- built-in expression, @{row.rowNumber} which gives a unique number for each row of data and enables you to generate
- unique rule names. For each row of data a rule will be generated with the values in the data substituted for the
- tokens in the template. With the example data above the following rule file would be generated:
+ Annotations to the preceding program listing:
+
+ Line 1: All rule templates start with template header.
+
-
+
+ Lines 2-4: Following the header is the list of columns in the order they appear in the data. In this
+ case we are calling the first column age, the second type and the third
+ log.
+
+
+
+ Line 5: An empty line signifies the end of the column definitions.
+
+
+
+ Lines 6-9: Standard rule header text. This is standard rule DRL and will appear at the top of the
+ generated DRL. Put the package statement and any imports and global and function definitions into this
+ section.
+
+
+
+ Line 10: The keyword template signals the start of a rule template. There can be more than
+ one template in a template file, but each template should have a unique name.
+
+
+
+ Lines 11-18: The rule template - see below for details.
+
+
+
+ Line 20: The keywords end template signify the end of the template.
+
+
+
+ The rule templates rely on MVEL to do substitution using the syntax @{token_name}. There is currently one
+ built-in expression, @{row.rowNumber} which gives a unique number for each row of data and enables you to generate
+ unique rule names. For each row of data a rule will be generated with the values in the data substituted for the
+ tokens in the template. With the example data above the following rule file would be generated:
+
+
package org.drools.examples.templates;
global java.util.List list;
@@ -933,9 +1008,11 @@ then
end
- The code to run this is simple:
+ The code to run this is simple:
- DecisionTableConfiguration dtableconfiguration = KnowledgeBuilderFactory.newDecisionTableConfiguration();
+
+DecisionTableConfiguration dtableconfiguration =
+ KnowledgeBuilderFactory.newDecisionTableConfiguration();
dtableconfiguration.setInputType( DecisionTableInputType.XLS );
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
@@ -945,6 +1022,5 @@ kbuilder.add( ResourceFactory.newClassPathResource( getSpreadsheetName(),
ResourceType.DTABLE,
dtableconfiguration );
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-ExecutionControl.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-ExecutionControl.xml
new file mode 100644
index 0000000000..029e995117
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-ExecutionControl.xml
@@ -0,0 +1,437 @@
+
+
+ Execution Control
+
+
+ Agenda
+
+ The Agenda is a Rete feature. It maintains set
+ of rules that are able to execute, it's job is to schedule that execution
+ in a deterministic order.
+
+ During actions on the WorkingMemory, rules may become
+ fully matched and eligible for execution; a single Working Memory Action
+ can result in multiple eligible rules. When a rule is fully matched an
+ Activation is created, referencing the rule and the matched facts, and
+ placed onto the Agenda. The Agenda controls the execution order of these
+ Activations using a Conflict Resolution strategy.
+
+ The engine cycles repeatedly through two phases:
+
+
+
+ Working Memory Actions. This is where most of the work takes
+ place, either in the Consequence (the RHS itself) or the main Java
+ application process. Once the Consequence has finished or the main
+ Java application process calls fireAllRules() the engine
+ switches to the Agenda Evaluation phase.
+
+
+
+ Agenda Evaluation. This attempts to select a rule to fire. If no
+ rule is found it exits, otherwise it fires the found rule, switching
+ the phase back to Working Memory Actions.
+
+
+
+
+ Two Phase Execution
+
+
+
+
+
+
+
+
+ The process repeats until the agenda is clear, in which case control
+ returns to the calling application. When Working Memory Actions are taking
+ place, no rules are being fired.
+
+
+
+ Activations and Conflict Sets.
+
+
+ Cashflow Example
+
+ So far the data and the matching process has been simple and
+ small. To mix things up a bit a new example will be explored that
+ handles cashflow calculations over date periods. The state of the engine
+ will be illustratively shown at key stages to help get a better
+ understanding of what is actually going on under the hood. Three classes
+ will be used, as shown below. This will help us grow our understanding
+ of pattern matching and joins further. We will then use this to
+ illustate different techniques for execution control.
+
+ public class CashFlow {
+ private Date date;
+ private double amount;
+ private int type;
+ long accountNo;
+ // getter and setter methods here
+}
+
+public class Account {
+ private long accountNo;
+ private double balance;
+ // getter and setter methods here
+}
+
+public AccountPeriod {
+ private Date start;
+ private Date end;
+ // getter and setter methods here
+}
+
+ By now you already know how to create Knowledge Bases and how to
+ instantiate facts to populate the StatefulKnowledgeSession,
+ so tables will be used to show the state of the inserted data, as it
+ makes things clearer for illustration purposes. The tables below show
+ that a single fact was inserted for the Account. Also
+ inserted are a series of debits and credits as CashFlow
+ objects for that account, extending over two quarters.
+
+
+ CashFlows and Account
+
+
+
+
+
+
+
+
+ Two rules can be used to determine the debit and credit for that
+ quarter and update the Account balance. The two rules below constrain
+ the cashflows for an account for a given time period. Notice the
+ "&&" which use short cut syntax to avoid repeating the field
+ name twice.
+
+
+
+
+
+
+
+ Earlier we showed how rules would equate to SQL, which can often
+ help people with an SQL background to understand rules. The two rules
+ above can be represented with two views and a trigger for each view, as
+ below:
+
+
+
+
+
+ select * from Account acc,
+ Cashflow cf,
+ AccountPeriod ap
+where acc.accountNo == cf.accountNo and
+ cf.type == CREDIT and
+ cf.date >= ap.start and
+ cf.date <= ap.end
+
+
+
+ select * from Account acc,
+ Cashflow cf,
+ AccountPeriod ap
+where acc.accountNo == cf.accountNo and
+ cf.type == DEBIT and
+ cf.date >= ap.start and
+ cf.date <= ap.end
+
+
+
+
+
+ trigger : acc.balance += cf.amount
+
+
+
+ trigger : acc.balance -= cf.amount
+
+
+
+
+
+ If the AccountPeriod is set to the first quarter we
+ constrain the rule "increase balance for credits" to fire on two rows of
+ data and "decrease balance for debits" to act on one row of data.
+
+
+ AccountingPeriod, CashFlows and Account
+
+
+
+
+
+
+
+
+ The two cashflow tables above represent the matched data for the
+ two rules. The data is matched during the insertion stage and, as you
+ discovered in the previous chapter, does not fire straight away, but
+ only after fireAllRules() is called. Meanwhile, the rule
+ plus its matched data is placed on the Agenda and referred to as an
+ Activation. The Agenda is a table of Activations that are able to fire
+ and have their consequences executed, as soon as fireAllRules() is
+ called. Activations on the Agenda are referred to as a
+ conflict set and their execution is determine by
+ a conflict resolution strategy. Notice that the order of execution so
+ far is considered arbitrary.
+
+
+ CashFlows and Account
+
+
+
+
+
+
+
+
+ After all of the above activations are fired, the account has a
+ balance of -25.
+
+
+ CashFlows and Account
+
+
+
+
+
+
+
+
+ If the AccountPeriod is updated to the second
+ quarter, we have just a single matched row of data, and thus just a
+ single Activation on the Agenda.
+
+ The firing of that Activation results in a balance of 25.
+
+
+ CashFlows and Account
+
+
+
+
+
+
+
+
+
+ CashFlows and Account
+
+
+
+
+
+
+
+
+
+
+ Conflict Resolution
+
+ What if you don't want the order of Activation execution to be
+ arbitrary? When there is one or more Activations on the Agenda they are
+ said to be in conflict, and a conflict resolutionr strategy is used to
+ determine the order of execution. The Drools strategy is very simple and
+ based around a salience value, which assigns a priority to a rule. Each
+ rule has a default value of 0, the higher the value the higher the
+ priority.
+
+ As a general rule, it is a good idea not to count on rules firing
+ in any particular order, and to author the rules without worrying about
+ a "flow". However when a flow is needed a number of possibilities exist
+ beyond salience: agenda groups, rule flow groups, activation groups and
+ control/semaphore facts.
+
+ Drools 4.x supported custom conflict resolution strategies; while
+ this capability still exists in Drools 5.x it not exposed to the end
+ user via knowledge-api.
+
+
+
+ Salience
+
+ To illustrate Salience we add a rule to print the account balance,
+ where we want this rule to be executed after all the debits and credits
+ have been applied for all accounts. We achieve this by assigning a
+ negative salience to this rule so that it fires after all rules with the
+ default salience 0.
+
+
+
+
+
+ rule "Print balance for AccountPeriod"
+ salience -50
+ when
+ ap : AccountPeriod()
+ acc : Account()
+ then
+ System.out.println( acc.accountNo + " : " + acc.balance );
+end
+
+
+
+
+
+ The table below depicts the resulting Agenda. The three debit and
+ credit rules are shown to be in arbitrary order, while the print rule is
+ ranked last, to execute afterwards.
+
+
+ CashFlows and Account
+
+
+
+
+
+
+
+
+
+
+ Agenda Groups
+
+ Agenda groups allow you to place rules into groups, and to place
+ those groups onto a stack. The stack has push/pop bevaviour. Calling
+ "setFocus" places the group onto the stack:
+
+ ksession.getAgenda().getAgendaGroup( "Group A" ).setFocus();
+
+ The agenda always evaluates the top of the stack. When all the
+ rules have fired for a group, it is poped from the stack and the next
+ group is evaluated.
+
+
+
+ First set the focus to the "report" group and then by placing the
+ focus on "calculation" we ensure that group is evaluated first.
+
+ Agenda agenda = ksession.getAgenda();
+agenda.getAgendaGroup( "report" ).setFocus();
+agenda.getAgendaGroup( "calculation" ).setFocus();
+ksession.fireAllRules();
+
+
+
+ Rule Flow
+
+ Drools also features ruleflow-group attributes which allows
+ workflow diagrams to declaratively specify when rules are allowed to
+ fire. The screenshot below is taken from Eclipse using the Drools
+ plugin. It has two ruleflow-group nodes which ensures that the
+ calculation rules are executed before the reporting rules.
+
+
+
+
+
+
+
+ The use of the ruleflow-group attribute in a rule is shown
+ below.
+
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-Inference.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-Inference.xml
new file mode 100644
index 0000000000..52a0d5c356
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-Inference.xml
@@ -0,0 +1,148 @@
+
+
+ Inference
+
+
+ Buss Pass Example
+
+ Inference has a bad names these days, as something not relevant to
+ business use cases and just too complicated to be useful. It is true that
+ contrived and complicated examples occur with inference, but that should
+ not detract from the fact that simple and useful ones exist too. But more
+ than this, correct use of inference can crate more agile and less error
+ prone businesses with easier to maintain software.
+
+ So what is inference? Something is inferred when we gain knowledge
+ of something from using previous knowledge. For example given a Person
+ fact with an age field and a rule that provides age policy control, we can
+ infer whether a Person is an adult or a child and act on this.
+
+ rule "Infer Adult"
+when
+ $p : Person( age >= 18 )
+then
+ insert( new IsAdult( $p ) )
+end
+
+ So in the above every Person who is 18 or over will have an instance
+ of IsAdult inserted for them. This fact is special in that it is known as
+ a relation. We can use this inferred relation in any rule:
+
+ $p : Person()
+IsAdult( person == $p )
+
+ So now we know what inference is, and have a basic example, how does
+ this facilitate good rule design and maintenance?
+
+ Let's take a government department that are responsible for issuing
+ ID cards when children become adults, hence forth referred to as ID
+ department. They might have a decision table that includes logic like
+ this, which says when an adult living in london is 18 or over, issue the
+ card:
+
+
+
+
+
+
+
+ However the ID department does not set the policy on who an adult
+ is. That's done at a central government level. If the central government
+ where to change that age to 21 there is a change management process.
+ Someone has to liaise with the ID department and make sure their systems
+ are updated, in time for the law going live.
+
+ This change management process and communication between departments
+ is not ideal for an agile environment and change become costly and error
+ prone. Also the card department is managing more information than it needs
+ to be aware of with its "monolithic" approach to rules management which is
+ "leaking" information better placed else where. By this I mean that it
+ doesn't care what explicit "age >= 18" information determines whether
+ someone is an adult, only that they are an adult.
+
+ Instead what if we were to split (de-couple) the authoring
+ responsibility, so the central government maintains its rules and the ID
+ department maintains its.
+
+ So its the central governments job to determine who is an adult and
+ if they change the law they just update their central repository with the
+ new rules, which others use:
+
+
+
+
+
+
+
+ The IsAdult fact, as discussed previously, is inferred from the
+ policy rules. It encapsulates the seemingly arbitrary piece of logic "age
+ >= 18" and provides semantic abstractions for it's meaning. Now if
+ anyone uses the above rules, they no longer need to be aware of explicit
+ information that determines whether someone is an adult or not. They can
+ just use the inferred fact:
+
+
+
+
+
+
+
+ While the example is very minimal and trivial it illustrates some
+ important points. We started with a monolithic and leaky approach to our
+ knowledge engineering. We create a single decision table that had all
+ possible information in it that leaks information from central government
+ that the ID department did not care about and did not want to
+ manage.
+
+ We first de-coupled the knowledge process so each department was
+ responsible for only what it needed to know. We then encapsulated this
+ leaky knowledge using an inferred fact IsAdult. The use of the term
+ IsAdult also gave a semantic abstraction to the previously arbitrary logic
+ "age >= 18".
+
+ So a general rule or thumb when doing your knowledge engineering
+ is:
+
+
+
+ Bad
+
+
+
+ Monolithic
+
+
+
+ Leaky
+
+
+
+
+
+ Good
+
+
+
+ De-couple knowledge responsibilities
+
+
+
+ Encapsulate knowledge
+
+
+
+ Provide semantic abstractions for those
+ encapsulations
+
+
+
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Authoring/Section-Templates.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-Templates.xml
similarity index 98%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Authoring/Section-Templates.xml
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-Templates.xml
index b56e8da656..14413ce93e 100644
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-Authoring/Section-Templates.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-Templates.xml
@@ -10,7 +10,7 @@
If you discover that you have a group of rules following
the same arrangement of patterns, constraints and actions on
the RHS, differing only in constants or names for objects or
- fields, you might think of employing Drool's rule template feature
+ fields, you might think of employing Drools's rule template feature
for generating the actual rules. You would write a
rule template file, containing the
textual skeleton of your rule and use the Drools template
@@ -68,8 +68,8 @@
parameter-name-1
...
parameter-name-n
-package ... # optional
-header text # optional
+package ... // optional
+header text // optional
templatetemplate-name
...
// template text
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-TheBasics.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-TheBasics.xml
new file mode 100644
index 0000000000..45f7c8df95
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-TheBasics.xml
@@ -0,0 +1,599 @@
+
+
+ The Basics
+
+
+ Stateless Knowledge Session
+
+ So where do we get started, there are so many use cases and so much
+ functionality in a rule engine such as Drools that it becomes beguiling.
+ Have no fear my intrepid adventurer, the complexity is layered and you can
+ ease yourself into with simple use cases.
+
+ Stateless session, not utilising inference, forms the simplest use
+ case. A stateless session can be called like a function passing it some
+ data and then receiving some results back. Some common use cases for
+ stateless sessions are, but not limited to:
+
+
+
+ Validation
+
+
+
+ Is this person eligible for a mortgage?
+
+
+
+
+
+ Calculation
+
+
+
+ Compute a mortgage premium.
+
+
+
+
+
+ Routing and Filtering
+
+
+
+ Filter incoming messages, such as emails, into
+ folders.
+
+
+
+ Send incoming messages to a destination.
+
+
+
+
+
+ So let's start with a very simple example using a driving license
+ application.
+
+ public class Applicant {
+ private String name;
+ private int age;
+ private boolean valid;
+ // getter and setter methods here
+}
+
+
+ Now that we have our data model we can write our first rule. We
+ assume that the application uses rules to refute invalid applications. As
+ this is a simple validation use case we will add a single rule to
+ disqualify any applicant younger than 18.
+
+ package com.company.license
+
+rule "Is of valid age"
+when
+ $a : Applicant( age < 18 )
+then
+ $a.setValid( false );
+end
+
+ To make the engine aware of data, so it can be processed against the
+ rules, we have to insert the data, much like with a
+ database. When the Applicant instance is inserted into the engine it is
+ evaluated against the constraints of the rules, in this case just two
+ constraints for one rule. We say two because the type
+ Applicant is the first object type constraint, and age <
+ 18 is the second field constraint. An object type constraint plus
+ its zero or more field constraints is referred to as a pattern. When an
+ inserted instance satisfies both the object type constraint and all the
+ field constraints, it is said to be matched. The $a is a
+ binding variable which permits us to reference the matched object in the
+ consequence. There its properties can be updated. The dollar character
+ ('$') is optional, but it helps to differentiate variable names from field
+ names. The process of matching patterns against the inserted data is, not
+ surprisingly, often referred to as pattern
+ matching.
+
+ Let's assume that the rules are in the same folder as the classes,
+ so we can use the classpath resource loader to build our first
+ KnowledgeBase. A Knowledge Base is what we call our
+ collection of compiled definitions, such as rules and processes, which are
+ compiled using the KnowledgeBuilder. Both the
+ KnowledgeBuilder and KnowledgeBase can be created from the factories
+ KnowledgeBuilderFactory and KnowledgeBaseFactory.
+
+ KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+kbuilder.add( ResourceFactory.newClassPathResource( "licenseApplication.drl", getClass() ),
+ ResourceType.DRL );
+if ( kbuilder.hasErrors() ) {
+ System.err.println( kbuilder.getErrors().toString() );
+}
+KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+
+ The above code snippet looks on the classpath for the
+ licenseApplication.drl file, using the method
+ newClassPathResource(). The resource type is DRL, short for
+ "Drools Rule Language". Once the DRL file has been added we can check the
+ Knowledge Builder object for any errors. If there are no errors, we can
+ add the resulting packages to our Knowledge Base. Now we are ready to
+ build our session and execute against some data:
+
+ StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
+Applicant applicant = new Applicant( "Mr John Smith", 16 );
+assertTrue( applicant.isValid() );
+ksession.execute( applicant );
+assertFalse( applicant.isValid() );
+
+
+ The preceding code executes the data against the rules. Since the
+ applicant is under the age of 18, the application is marked as
+ invalid.
+
+ So far we've only used a single instance, but what if we want to use
+ more than one? We can execute against any object implementing Iterable,
+ such as a collection. Let's add another class called
+ Application, which has the date of the application, and we'll
+ also move the boolean valid field to the Application
+ class.
+
+ public class Applicant {
+ private String name;
+ private int age;
+ // getter and setter methods here
+}
+
+public class Application {
+ private Date dateApplied;
+ private boolean valid;
+ // getter and setter methods here
+}
+
+ We can also add another rule to validate that the application was
+ made within a period of time.
+
+ package com.company.license
+
+rule "Is of valid age"
+when
+ Applicant( age < 18 )
+ $a : Application()
+then
+ $a.setValid( false );
+end
+
+rule "Application was made this year"
+when
+ $a : Application( dateApplied > "01-jan-2009" )
+then
+ $a.setValid( false );
+end
+
+
+ Unfortunately a Java array does not implement the
+ Iterable interface, so we have to use the JDK converter
+ method Arrays.asList(...). The code shown below executes
+ against an iterable list, where all collection elements are inserted
+ before any matched rules are fired.
+
+ StatelessKnowledgeSession ksession = kbase.newStatelessKnowledgeSession();
+Applicant applicant = new Applicant( "Mr John Smith", 16 );
+Application application = new Application();
+assertTrue( application.isValid() );
+ksession.execute( Arrays.asList( new Object[] { application, applicant } ) );
+assertFalse( application.isValid() );
+
+
+ The two execute methods execute(Object object) and
+ execute(Iterable objects) are actually convenience methods
+ for the interface BatchExecutor's method
+ execute(Command command).
+
+ A CommandFactory is used to create commands, so that
+ the following is equivalent to execute(Iterable it):
+
+ ksession.execute( CommandFactory.newInsertIterable( new Object[] { application, applicant } ) );
+
+
+ Batch Executor and Command Factory are particularly useful when
+ working with multiple Commands and with output identifiers for obtaining
+ results.
+
+ List<Command> cmds = new ArrayList<Command>();
+cmds.add( CommandFactory.newInsert( new Person( "Mr John Smith" ), "mrSmith" );
+cmds.add( CommandFactory.newInsert( new Person( "Mr John Doe" ), "mrDoe" );
+BatchExecutionResults results = ksession.execute( CommandFactory.newBatchExecution( cmds ) );
+assertEquals( new Person( "Mr John Smith" ), results.getValue( "mrSmith" ) );
+
+
+ CommandFactory supports many other Commands that can be
+ used in the BatchExecutor like StartProcess,
+ Query, and SetGlobal.
+
+
+
+ Stateful Knowledge Session
+
+ Stateful Sessions are longer lived and allow iterative changes over
+ time. Some common use cases for Stateful Sessions are, but not limited
+ to:
+
+
+
+ Monitoring
+
+
+
+ Stock market monitoring and analysis for semi-automatic
+ buying.
+
+
+
+
+
+ Diagnostics
+
+
+
+ Fault finding, medical diagnostics
+
+
+
+
+
+ Logistics
+
+
+
+ Parcel tracking and delivery provisioning
+
+
+
+
+
+ Compliance
+
+
+
+ Validation of legality for market trades.
+
+
+
+
+
+ In contrast to a Stateless Session, the dispose()
+ method must be called afterwards to ensure there are no memory leaks, as
+ the Knowledge Base contains references to Stateful Knowledge Sessions when
+ they are created. StatefulKnowledgeSession also supports the
+ BatchExecutor interface, like
+ StatelessKnowledgeSession, the only difference being that the
+ FireAllRules command is not automatically called at the end
+ for a Stateful Session.
+
+ We illustrate the monitoring use case with an example for raising a
+ fire alarm. Using just four classes, we represent rooms in a house, each
+ of which has one sprinkler. If a fire starts in a room, we represent that
+ with a single Fire instance.
+
+ public class Room {
+ private String name
+ // getter and setter methods here
+}
+public class Sprinkler {
+ private Room room;
+ private boolean on;
+ // getter and setter methods here
+}
+public class Fire {
+ private Room room;
+ // getter and setter methods here
+}
+public class Alarm {
+}
+
+
+ In the previous section on Stateless Sessions the concepts of
+ inserting and matching against data were introduced. That example assumed
+ that only a single instance of each object type was ever inserted and thus
+ only used literal constraints. However, a house has many rooms, so rules
+ must express relationships between objects, such as a sprinkler being in a
+ certain room. This is best done by using a binding variable as a
+ constraint in a pattern. This "join" process results in what is called
+ cross products, which are covered in the next section.
+
+ When a fire occurs an instance of the Fire class is
+ created, for that room, and inserted into the session. The rule uses a
+ binding on the room field of the Fire object to
+ constrain matching to the sprinkler for that room, which is currently off.
+ When this rule fires and the consequence is executed the sprinkler is
+ turned on.
+
+ rule "When there is a fire turn on the sprinkler"
+when
+ Fire($room : room)
+ $sprinkler : Sprinkler( room == $room, on == false )
+then
+ modify( $sprinkler ) { setOn( true ) };
+ System.out.println( "Turn on the sprinkler for room " + $room.getName() );
+end
+
+ Whereas the Stateless Session uses standard Java syntax to modify a
+ field, in the above rule we use the modify statement,
+ which acts as a sort of "with" statement. It may contain a series of comma
+ separated Java expressions, i.e., calls to setters of the object selected
+ by the modify statement's control expression. This
+ modifies the data, and makes the engine aware of those changes so it can
+ reason over them once more. This process is called inference, and it's
+ essential for the working of a Stateful Session. Stateless Sessions
+ typically do not use inference, so the engine does not need to be aware of
+ changes to data. Inference can also be turned off explicitly by using the
+ sequential mode.
+
+ So far we have rules that tell us when matching data exists, but
+ what about when it does not exist? How do we
+ determine that a fire has been extinguished, i.e., that there isn't a
+ Fire object any more? Previously the constraints have been
+ sentences according to Propositional Logic, where the engine is
+ constraining against individual instances. Drools also has support for
+ First Order Logic that allows you to look at sets of data. A pattern under
+ the keyword not matches when something does not exist.
+ The rule given below turns the sprinkler off as soon as the fire in that
+ room has disappeared.
+
+ rule "When the fire is gone turn off the sprinkler"
+when
+ $room : Room( )
+ $sprinkler : Sprinkler( room == $room, on == true )
+ not Fire( room == $room )
+then
+ modify( $sprinkler ) { setOn( false ) };
+ System.out.println( "Turn off the sprinkler for room " + $room.getName() );
+end
+
+ While there is one sprinkler per room, there is just a single alarm
+ for the building. An Alarm object is created when a fire
+ occurs, but only one Alarm is needed for the entire building,
+ no matter how many fires occur. Previously not was
+ introduced to match the absence of a fact; now we use its complement
+ exists which matches for one or more instances of some
+ category.
+
+ rule "Raise the alarm when we have one or more fires"
+when
+ exists Fire()
+then
+ insert( new Alarm() );
+ System.out.println( "Raise the alarm" );
+end
+
+ Likewise, when there are no fires we want to remove the alarm, so
+ the not keyword can be used again.
+
+ rule "Cancel the alarm when all the fires have gone"
+when
+ not Fire()
+ $alarm : Alarm()
+then
+ retract( $alarm );
+ System.out.println( "Cancel the alarm" );
+end
+
+
+
+ Finally there is a general health status message that is printed
+ when the application first starts and after the alarm is removed and all
+ sprinklers have been turned off.
+
+ rule "Status output when things are ok"
+when
+ not Alarm()
+ not Sprinkler( on == true )
+then
+ System.out.println( "Everything is ok" );
+end
+
+ The above rules should be placed in a single DRL file and saved to
+ some directory on the classpath and using the file name
+ fireAlarm.drl, as in the Stateless Session example.
+ We can then build a Knowledge Base, as before, just using the new name
+ fireAlarm.drl. The difference is that this time we
+ create a Stateful Session from the Knowledge Base, whereas before we
+ created a Stateless Session.
+
+ KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+kbuilder.add( ResourceFactory.newClassPathResource( "fireAlarm.drl", getClass() ),
+ ResourceType.DRL );
+if ( kbuilder.hasErrors() ) {
+ System.err.println( kbuilder.getErrors().toString() );
+}
+kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+
+ With the session created it is now possible to iteratively work with
+ it over time. Four Room objects are created and inserted, as
+ well as one Sprinkler object for each room. At this point the
+ engine has done all of its matching, but no rules have fired yet. Calling
+ ksession.fireAllRules() allows the matched rules to fire, but
+ without a fire that will just produce the health message.
+
+ String[] names = new String[]{"kitchen", "bedroom", "office", "livingroom"};
+Map<String,Room> name2room = new HashMap<String,Room>();
+for( String name: names ){
+ Room room = new Room( name );
+ name2room.put( name, room );
+ ksession.insert( room );
+ Sprinkler sprinkler = new Sprinkler( room );
+ ksession.insert( sprinkler );
+}
+
+ksession.fireAllRules();
+
+
+ > Everything is ok
+
+ We now create two fires and insert them; this time a reference is
+ kept for the returned FactHandle. A Fact Handle is an
+ internal engine reference to the inserted instance and allows instances to
+ be retracted or modified at a later point in time. With the fires now in
+ the engine, once fireAllRules() is called, the alarm is
+ raised and the respective sprinklers are turned on.
+
+ Fire kitchenFire = new Fire( name2room.get( "kitchen" ) );
+Fire officeFire = new Fire( name2room.get( "office" ) );
+
+FactHandle kitchenFireHandle = ksession.insert( kitchenFire );
+FactHandle officeFireHandle = ksession.insert( officeFire );
+
+ksession.fireAllRules();
+
+ > Raise the alarm
+> Turn on the sprinkler for room kitchen
+> Turn on the sprinkler for room office
+
+ After a while the fires will be put out and the Fire
+ instances are retracted. This results in the sprinklers being turned off,
+ the alarm being cancelled, and eventually the health message is printed
+ again.
+
+ ksession.retract( kitchenFireHandle );
+ksession.retract( officeFireHandle );
+
+ksession.fireAllRules();
+
+ > Cancel the alarm
+> Turn off the sprinkler for room office
+> Turn off the sprinkler for room kitchen
+> Everything is ok
+
+ Everyone still with me? That wasn't so hard and already I'm hoping
+ you can start to see the value and power of a declarative rule
+ system.
+
+
+
+ Methods versus Rules
+
+ People often confuse methods and rules, and new rule users regular
+ ask, "How do I call a rule?" After the last section, you are now feeling
+ like a rule expert and the answer to that is obvious, but let's summarize
+ the differences nonetheless.
+
+ public void helloWorld(Person person) {
+ if ( person.getName().equals( "Chuck" ) ) {
+ System.out.println( "Hello Chuck" );
+ }
+}
+
+
+
+ Methods are called directly.
+
+
+
+ Specific instances are passed.
+
+
+
+ One call results in a single execution.
+
+
+
+ rule "Hello World"
+ when
+ Person( name == "Chuck" )
+ then
+ System.out.println( "Hello Chuck" );
+ end
+
+
+
+ Rules execute by matching against any data as long it is
+ inserted into the engine.
+
+
+
+ Rules can never be called directly.
+
+
+
+ Specific instances cannot be passed to a rule.
+
+
+
+ Depending on the matches, a rule may fire once or several times,
+ or not at all.
+
+
+
+
+
+ Cross Products
+
+ Earlier the term "cross product" was mentioned, which is the result
+ of a join. Imagine for a moment that the data from the fire alarm example
+ were used in combination with the following rule where there ar no field
+ constraints:
+
+ rule
+when
+ $room : Room()
+ $sprinkler : Sprinkler()
+then
+ System.out.println( "room:" + $room.getName() +
+ " sprinkler:" + $sprinkler.getRoom().getName() );
+end
+
+ In SQL terms this would be like doing select * from Room,
+ Sprinkler and every row in the Room table would be joined with
+ every row in the Sprinkler table resulting in the following output:
+
+ room:office sprinkler:office
+room:office sprinkler:kitchen
+room:office sprinkler:livingroom
+room:office sprinkler:bedroom
+room:kitchen sprinkler:office
+room:kitchen sprinkler:kitchen
+room:kitchen sprinkler:livingroom
+room:kitchen sprinkler:bedroom
+room:livingroom sprinkler:office
+room:livingroom sprinkler:kitchen
+room:livingroom sprinkler:livingroom
+room:livingroom sprinkler:bedroom
+room:bedroom sprinkler:office
+room:bedroom sprinkler:kitchen
+room:bedroom sprinkler:livingroom
+room:bedroom sprinkler:bedroom
+
+ These cross products can obviously become huge, and they may very
+ well contain spurious data. The size of cross products is often the source
+ of performance problems for new rule authors. From this it can be seen
+ that it's always desirable to constrain the cross products, which is done
+ with the variable constraint.
+
+ rule
+when
+ $room : Room()
+ $sprinkler : Sprinkler( room == $room )
+then
+ System.out.println( "room:" + $room.getName() +
+ " sprinkler:" + $sprinkler.getRoom().getName() );
+end
+
+ This results in just four rows of data, with the correct Sprinkler
+ for each Room. In SQL (actually HQL) the corresponding query would be
+ select * from Room, Sprinkler where Room ==
+ Sprinkler.room.
+
+ room:office sprinkler:office
+room:kitchen sprinkler:kitchen
+room:livingroom sprinkler:livingroom
+room:bedroom sprinkler:bedroom
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-TruthMaintenance.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-TruthMaintenance.xml
new file mode 100644
index 0000000000..9e700a520d
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Chapter-UserGuide/Section-TruthMaintenance.xml
@@ -0,0 +1,189 @@
+
+
+ Truth Maintenance with
+ Logical Object
+ Logical Objects
+
+
+ Overview
+
+ After regular inserts you have to retract facts explicitly. With
+ logical assertions, the fact that was asserted will
+ be automatically retracted when the conditions that asserted it in the
+ first place are no longer true. Actually, it's even cleverer then that,
+ because it will be retracted only if there isn't any single condition that
+ supports the logical assertion.
+
+ Normal insertions are said to be stated, i.e.,
+ just like the intuitive meaning of "stating a fact" implies. Using a
+ HashMap and a counter, we track how many times a particular
+ equality is stated; this means we count how many
+ different instances are equal.
+
+ When we logically insert an object during a RHS
+ execution we are said to justify it, and it is
+ considered to be justified by the firing rule. For each logical insertion
+ there can only be one equal object, and each subsequent equal logical
+ insertion increases the justification counter for this logical assertion.
+ A justification is removed by the LHS of the creating rule becoming
+ untrue, and the counter is decreased accordingly. As soon as we have no
+ more justifications the logical object is automatically retracted.
+
+ If we try to logically insert an object when
+ there is an equal stated object, this will fail and
+ return null. If we state an object that has an
+ existing equal object that is justified we override
+ the Fact; how this override works depends on the configuration setting
+ WM_BEHAVIOR_PRESERVE. When the property is set to discard we
+ use the existing handle and replace the existing instance with the new
+ Object, which is the default behavior; otherwise we override it to
+ stated but we create an new
+ FactHandle.
+
+ This can be confusing on a first read, so hopefully the flow charts
+ below help. When it says that it returns a new FactHandle,
+ this also indicates the Object was propagated through the
+ network.
+
+
+ Stated Insertion
+
+
+
+
+
+
+
+
+
+ Logical Insertion
+
+
+
+
+
+
+
+
+
+ Bus Pass Example With Inference and TMS
+
+ The previous example was issuing ID cards to over 18s, in this
+ example we now issue bus passes, either a child or adult pass.
+
+ rule "Issue Child Bus Pass" when
+ $p : Person( age < 16 )
+then
+ insert(new ChildBusPass( $p ) );
+end
+
+rule "Issue Adult Bus Pass" when
+ $p : Person( age >= 16 )
+then
+ insert(new AdultBusPass( $p ) );
+end
+
+ As before the above example is considered monolithic, leaky and
+ providing poor separation of concerns.
+
+ As before we can provide a more robust application with a
+ separation of concerns using inference. Notice this time we don't just
+ insert the inferred object, we use "insertLogical":
+
+ rule "Infer Child" when
+ $p : Person( age < 16 )
+then
+ insertLogical( new IsChild( $p ) )
+end
+rule "Infer Adult" when
+ $p : Person( age >= 16 )
+then
+ insertLogical( new IsAdult( $p ) )
+end
+
+ A "insertLogical" is part of the Drools Truth Maintenance System
+ (TMS). Here the fact is logically inserted, this fact is dependant on
+ the truth of the "when" clause. It means that when the rule becomes
+ false the fact is automatically retracted. This works particularly well
+ as the two rules are mutually exclusive. So in the above rules if the
+ person is under 16 it inserts an IsChild fact, once the person is 16 or
+ over the IsChild fact is automatically retracted and the IsAdult fact
+ inserted.
+
+ We can now bring back in the code to issue the passes, these two
+ can also be logically inserted, as the TMS supports chaining of logical
+ insertions for a cascading set of retracts.
+
+ rule "Issue Child Bus Pass" when
+ $p : Person( )
+ IsChild( person == $p )
+then
+ insertLogical(new ChildBusPass( $p ) );
+end
+
+rule "Issue Adult Bus Pass" when
+ $p : Person( age >= 16 )
+ IsAdult( person =$p )
+then
+ insertLogical(new AdultBusPass( $p ) );
+end
+
+ Now when the person changes from being 15 to 16, not only is the
+ IsChild fact automatically retracted, so is the person's ChildBusPass
+ fact. For bonus points we can combine this with the 'not' conditional
+ element to handle notifications, in this situation a request for the
+ returning of the pass. So when the TMS automatically retracts the
+ ChildBusPass object, this rule triggers and sends a request to the
+ person:
+
+ rule "Return ChildBusPass Request "when
+ $p : Person( )
+ not( ChildBusPass( person == $p ) )
+then
+ requestChildBusPass( $p );
+end
+
+
+
+ Lazy Truth Maintenance
+
+ You no longer need to enable or disable truth maintenance, via the
+ kbase configuration. It is now handled automatically and turned on only
+ when needed. This was done along with the code changes so that all entry
+ points use the same code, previous to this the default entry point and
+ named entry points used different code, to avoid TMS overhead for event
+ processing.
+
+
+
+ Important note: Equality for Java objects
+
+ It is important to note that for Truth Maintenance (and logical
+ assertions) to work at all, your Fact objects (which may be JavaBeans)
+ must override equals and hashCode methods (from java.lang.Object)
+ correctly. As the truth maintenance system needs to know when two
+ different physical objects are equal in value, both
+ equals and hashCode must be overridden correctly, as per the Java
+ standard.
+
+ Two objects are equal if and only if their equals methods return
+ true for each other and if their hashCode methods return the same
+ values. See the Java API for more details (but do keep in mind you
+ MUST override both equals and hashCode).
+
+ TMS behaviour is not affected by theruntime configuration of
+ Identity vs Equality, TMS is always equality.
+
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Deployment/Chapter-DepymentAndTest.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Deployment/Chapter-DepymentAndTest.xml
deleted file mode 100755
index fb1cdeb8cd..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Deployment/Chapter-DepymentAndTest.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- Deployment and Testing
-
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Deployment/Section-Deployment.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Deployment/Section-Deployment.xml
deleted file mode 100755
index 4e4019a907..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Deployment/Section-Deployment.xml
+++ /dev/null
@@ -1,253 +0,0 @@
-
-
- Deployment options
-
- Once you have rules integrated in your application (or ideally before)
- you will need to plan how to deploy rules along with your application.
- Typically rules are used to allow changes to application business logic
- without re-deploying the whole application. This means that the rules must
- be provided to the application as data, not as part of the application (eg
- embedded in the classpath).
-
- The recommended way of deploying depends on how you are managing your
- rules. If you are using the BRMS, you should use the RuleAgent (the detailed
- documentation for this is in the chapter on the BRMS/Guvnor). You can still
- use the RuleAgent even without the BRMS, in which case you will need to use
- ant (the drools-ant task or something custom) to create serialized "Package"
- objects of your rules.
-
- As every organization is subtly different, and different deployment
- patterns will be needed. Many organizations have (or should have)
- configuration management processes for changes to production systems. It is
- best to think of rules as "data" rather then software in that regard.
- However, as rules can contain a considerable amount of powerful logic,
- proper procedures should be used in testing and verifying rule changes, and
- approving changes before exposing them to the world. If you need to "roll
- your own" deployment, or have specific deployment needs, the information is
- provided in this chapter for your reference, but for the most part, people
- should be able to deploy either as the agent, or in the classpath.
-
-
- Deployment using the KnowledgeAgent
-
- The easiest and most automated way to deploy rules is to use the
- Knowlegde Agent as described in the quick start guide. This can access rules from the file system, classpath, web server, the Guvnor server (which is really a web server) and more. Rules can be in DRL, XLS, compiled binary form and more.
-
-
-
- Deployment using drl source
-
- In some cases people may wish to deploy drl source. In that case all
- the drools-compiler dependencies will need to be on the classpath for your
- application. You can then load drl from file, classpath, or a database
- (for example) and compile as needed. The trick, as always, is knowing when
- rules change (this is also called "in process" deployment as described
- below).
-
-
-
- Deploying rules in your classpath
-
- If you have rules which do not change separate to your application,
- you can put packaged into your classpath. This can be done either as
- source (in which case the drl can be compiled, and the rulebase cached the
- first time it is needed) or else you can pre-compile packages, and just
- include the binary packages in the classpath.
-
- Keep in mind with this approach to make a rule change, you will both
- need to deploy your app (and if its a server - restart the
- application).
-
-
-
- Deployable objects, RuleBase, Package etc.
-
- In the simplest possible scenario, you would compile and construct a
- rulebase inside your application (from drl source), and then cache that
- rulebase. That rulebase can be shared across threads, spawning new working
- memories to process transactions (working memories are then discarded).
- This is essentially the stateless mode. To update the rulebase, a new
- rulebase is loaded, and then swapped out with the cached rulebase (any
- existing threads that happen to be using the old rulebase will continue to
- use it until they are finished, in which case it will eventually be
- garbage collected).
-
- There are many more sophisticated approaches to the above - Drools
- rule engine is very dynamic, meaning pretty much all the components can be
- swapped out on the fly (rules, packages) even when there are *existing*
- working memories in use. For instance rules can be retracted from a
- rulebase which has many in-use working memories - the RETE network will
- then be adjusted to remove that rule without having to assert all the
- facts again. Long running working memories are useful for complex
- applications where the rule engine builds up knowledge over time to assist
- with decision making for instance - it is in these cases that the
- dynamic-ness of the engine can really shine.
-
-
- DRL and PackageDescr
-
- One option is to deploy the rules in source form. This leaves the
- runtime engine (which must include the compiler components) to compile
- the rules, and build the rule base. A similar approach is to deploy the
- "PackageDescr" object, which means that the rules are pre-parsed (for
- syntactic errors) but not compiled into the binary form. Use the
- PackageBuilder class to achieve this. You can of course use the XML form
- for the rules if needed.
-
- PackageDescr, PackageBuilder, RuleBaseLoader
-
-
-
- Package
-
- This option is the most flexible. In this case, Packages are built
- from DRL source using PackageBuilder - but it is the binary Package
- objects that are actually deployed. Packages can be merged together.
- That means a package containing perhaps a single new rule, or a change
- to an existing rule, can be built on its own, and then merged in with an
- existing package in an existing RuleBase. The rulebase can then notify
- existing working memories that a new rule exists (as the RuleBase keeps
- "weak" links back to the Working Memory instances that it spawned). The
- rulebase keeps a list of Packages, and to merge into a package, you will
- need to know which package you need to merge into (as obviously, only
- rules from the same package name can be merged together).
-
- Package objects themselves are serializable, hence they can be
- sent over a network, or bound to JNDI, Session etc.
-
- PackageBuilder, RuleBase, org.drools.rule.Package
-
-
-
- RuleBase
-
- Compiled Packages are added to rulebases. RuleBases are
- serializable, so they can be a binary deployment unit themselves. This
- can be a useful option for when rulebases are updated as a whole - for
- short lived working memories. If existing working memories need to have
- rules changed on the fly, then it is best to deploy Package objects.
- Also beware that rulebases take more processing effort to serialize (may
- be an issue for some large rulebases).
-
- RuleBase, RuleBaseLoader
-
-
-
- Serializing
-
- Practically all of the rulebase related objects in Drools are
- serializable. For a working memory to be serializable, all of your
- objects must of course be serializable. So it is always possible to
- deploy remotely, and "bind" rule assets to JNDI as a means of using them
- in a container environment.
-
-
- Please note that when using package builder, you may want to check
- the hasError() flag before continuing deploying your rules (if there are
- errors, you can get them from the package builder - rather then letting it
- fail later on when you try to deploy).
-
-
-
- Deployment patterns
-
-
- In process rule building
-
- In this case, rules are provided to the runtime system in source
- form. The runtime system contains the drools-compiler component to build
- the rules. This is the simplest approach.
-
-
-
- Out of process rule building
-
- In this case, rules are built into their binary process outside of
- the runtime system (for example in a deployment server). The chief
- advantage of deploying from an outside process is that the runtime
- system can have minimal dependencies (just one jar). It also means that
- any errors to do with compiling are well contained and and known before
- deployment to the running system is attempted.
-
- Use the PackageBuilder class out of process, and then use
- getPackage() to get the Package object. You can then (for example)
- serialize the Package object to a file (using standard Java
- serialization). The runtime system, which only needs drools-core, can
- then load the file using
- RuleBaseFactory.newRuleBase().addPackage(deserialized package
- object).
-
-
-
- Some deployment scenarios
-
- This section contains some suggested deployment scenarios, of
- course you can use a variety of technologies as alternatives to the ones
- in the diagram.
-
-
- Pull style
-
- This pattern is what is used by the RuleAgent, by
- default.
-
- In this scenario, rules are pulled from the rule repository into
- the runtime system. The repository can be as simple as a file system,
- or a database. The trigger to pull the rules could be a timed task (to
- check for changes) or a request to the runtime system (perhaps via a
- JMX interface). This is possibly the more common scenario.
-
-
-
-
-
-
-
-
-
-
-
- Push style
-
- In this scenario, the rule deployment process/repository
- "pushes" rules into the runtime system (either in source or binary
- form, as described above). This gives more control as to when the new
- rules take effect.
-
-
-
-
-
-
-
-
-
-
-
-
-
- Web Services
-
- A possible deployment pattern for rules are to expose the rules as a
- web service. There a many ways to achieve this, but possibly the simplest
- way at present do achieve it is to use an interface-first process: Define
- the "facts" classes/templates that the rules will use in terms of XML
- Schema - and then use binding technologies to generate binding objects for
- the rules to actually operate against. A reverse possibility is to use a
- XSD/WSDL generator to generate XML bindings for classes that are hand
- built (which the rules work against). It is expected in a future version
- there will be an automated tool to expose rules as web services (and
- possibly use XSDs as facts for the rules to operate on).
-
-
-
- Future considerations
-
- A future release of Drools will contain a rule repository (server)
- component that will directly support the above patterns, and more.
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Deployment/Section-Testing.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Deployment/Section-Testing.xml
deleted file mode 100755
index 65a35c13ab..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Deployment/Section-Testing.xml
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
- Testing
-
- In recent years, practices such as Test Driven Development have become
- increasingly mainstream, as the value and quality that these techniques
- bring to software development has been realized. In a sense, rules are code
- (although at a high level), and a lot of the same principles apply.
-
- You can provide tests as a means to specify rule behavior before
- rules are even written. Further to this, tests are even more important in
- environments where rules change frequently. Tests can provide a baseline of
- confidence that the rule changes are consistent with what is specified in
- the tests. Of course, the rules may change in such a way as the tests are
- now wrong (or perhaps new tests need to be written to cover the new rule
- behavior). As in TDD practices, tests should be run often, and in a rule
- driven environment, this means that they should be run every time the rules
- change (even though the software may be static).
-
-
- Testing frameworks
-
- For developers, clearly JUnit (or TestNG) are popular tools for
- testing code, and these can also apply to rules. Keep in mind that rule
- changes may happen out of sync with code changes, so you should be
- prepared to keep these unit tests up to date with rules (may not be
- possible in all environments). Also, the best idea is to target testing
- some core features of the rule sets that are not as likely to change over
- time.
-
- Obviously, for rule tests, other non source code driven frameworks
- would be preferable to test rules in some environments. The following
- section outlines a rule testing component add on.
-
-
-
- FIT for Rules - a rule testing framework
-
- As a separate add-on, there is a testing framework available that is
- built on FIT (Framework for Integrated Testing). This allows rule test
- suites (functional) to be capture in Word documents, or Excel spreadsheets
- (in fact any tool that can save as HTML). It utilizes a tabular layout to
- capture input data, and make assertions over the rules of a rulesets
- execution for the given facts. As the tests are stored in documents, the
- scenarios and requirements can be (optionally) kept in the same
- documents, providing a single point of truth for rule behavior.
-
- Also, as the test documents are not code, they can be updated
- frequently, and kept with the rules, used to validate rule changes etc. As
- the input format is fairly simple to people familiar with the domain of
- the rules, it also facilitates "scenario testing" where different
- scenarios can be tried out with the rules - all external to the
- application that the rules are used in. These scenarios can then be kept
- as tests to increase confidence that a rule change is consistent with the
- users understanding.
-
- This testing framework is built on FIT and JSR-94, and is kept as a
- separate project to JBoss Rules. Due to it being built on FIT, it requires
- a different license (but is still open source). You can download and read
- more about this tool from this web page:
- Fit for rules
-
- The following screen captures show the fit for rules framework in
- action.
-
-
-
-
-
-
-
-
-
- Using Fit for rules, you capture test data, pass it to the rule
- engine and then verify the results (with documentation woven in with the
- test). It is expected that in future, the Drools Server tools will provide
- a similar integrated framework for testing (green means good ! red means a
- failure - with the expected values placed in the cell). Refer to
- http://fit.c2.com for more information on the FIT framework itself.
-
-
-
-
-
-
-
-
-
- More information and downloads from here
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Performance_Tuning/Section-Performance.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Performance_Tuning/Section-Performance.xml
deleted file mode 100755
index d95c52b89a..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Performance_Tuning/Section-Performance.xml
+++ /dev/null
@@ -1,311 +0,0 @@
-
-
- Performance considerations
-
- In any reasonably complex application, there are many things that may
- effect performance. The usual advice applies of course (ie don't speculate,
- measure, profile and plan). In terms of the rule engine, it does its best to
- be as efficient as possibly, without too much thought needed, most people
- should not need to read this chapter in detail.
-
- Note that for someone who is using a rule engine of the first time,
- the most noticeable "cost" will be the startup of the rule engine (which is
- actually compiling the rules) - this problem is easily solved - simply cache
- the RuleBase instances (or the rule packages) and only update rules as
- needed (there are many ways to achieve this in your application which will
- not be covered here).
-
- The remainder of this chapter is considerations on tuning the runtime
- performance of rules (not compiling), which is where performance often
- really counts.
-
-
- Beta Node Memory Indexing
-
- As explained in the chapter on the Rete Algorithm, BetaNodes are
- nodes that have two inputs: the left input (for tuples) and the right
- input (for single objects). Each beta node has two memories, one for each
- input: the left memory and the right memory.
-
- So, when a single object arrives at the right input of the node, it
- tries to match every tuple in the left memory according to the constraints
- defined for the given BetaNode. Those elements that match are propagated
- down through the network. The symmetrical behavior happens for when a
- tuple arrives at the left input of the node. See diagram bellow:
-
-
- Beta Node
-
-
-
-
-
-
-
-
-
-
-
-
- When the number of elements in each of the Beta Node Memories starts
- to grow, the matching process starts to slow down, as each new element
- that arrives needs to try to match all the elements in the opposite memory
- for the given constraints. This process becomes a serious limitation for
- real systems where thousands of facts are asserted into working memory and
- where the Rete Network has several Beta Nodes.
-
- One way of minimizing the problem is to index each of the BetaNode
- memories in a way that when a new element arrives, it does not need to
- iterate over all elements of the opposite memory in order to find its
- matches.
-
- So, for example, if we have a Rule like the following:
- rule "find brothers"
- when
- p1: Person( $mother : mother )
- p2: Person( mother == $mother )
- then
- // do something
-end
-
- If no indexing is used, each new Person object asserted into
- working memory will try to match each other previously asserted Person
- object to find those that have the same mother. So, if we have 1000 Person
- objects already asserted into working memory, and we assert a new one, the
- new one will try to match each of the 1000 previously asserted
- objects.
-
- If we index BetaNode memories by the “mother” attribute, though,
- when a new Person is asserted into memory, it will try to match only the
- previously asserted objects that have the same mother attribute, in a very
- efficient way using the previously built index. So, if the new object has
- only one brother previously asserted into memory, it will match only one
- object, avoiding the 999 tries that would fail.
-
- Drools implements BetaNode indexing exactly as described above in
- order to boost performance. The BetaNode indexing is enabled by default
- and users usually don’t need to worry about it. Although, for specific
- situations where a user has a limited amount of memory or for some reason
- does not want to incur in the indexing overhead, indexing can be disabled
- for each of the memories, by setting the following system properties to
- false:
- org.drools.reteoo.beta.index-left
-org.drools.reteoo.beta.index-right
-
-For example:
-..when you launch the application (or in the container as appropriate).
--Dorg.drools.reteoo.beta.index-right=false
--Dorg.drools.reteoo.beta.index-left=false
-
-
-
-
- Indexing Performance Tuning
-
- A good way to understand what happens when indexing is used is to
- make an analogy to databases systems. As we all know, indexing is a great
- mechanism for performance improvements on database queries, but also adds
- an overhead to other operations like insert, updates and deletes. Also,
- there is a memory consumption cost involved. A well planned set of indexes
- is essential for most enterprise applications and the responsible for
- defining them is usually the DBA. Once indexes are defined, when a query
- is executed against that database, a query planner component is used by
- database systems to estimate the best plan to run the query with the best
- performance, sometimes using the index, sometimes not.
-
- Working memory has the same issues and same thoughts are valid here.
- Drools implements an automatic indexing strategy to index beta node
- memories. Just to have some data to understand the consequences of it,
- lets use Manners 64 benchmark test results on a Pentium IV 3 Ghz HT
- machine with 1.0 Gb memory. This is not really a detailed benchmark test,
- but simply some rough numbers in order to make the scenario easier to
- understand:
- Manners 64 without indexes: 135000 millisec to run
-Manners 64 with BetaNode indexes: 10078 millisec to run on average
-
- It is obvious by the previous run times that indexes overall
- benefits pays off the overhead to keep them, at least in terms of
- performance. We are not analyzing limited memory environments here.
-
- Although, every system has its own peculiarities and sometimes it is
- possible to do some fine tuning on performance. For example, in our
- Manners 64 example, if we disable the right memory indexing we would have
- the following result:
- Manners 64 with BetaNode indexing only for left memory: 142000 millisec to run on average
-
- The above is even worse than no using any indexing. This
- happens clearly because for Manners 64, the left indexing overhead is
- bigger than its benefit. So, if we do the contrary, leaving right indexing
- enabled and disabling the left indexing, we get the following result:
- Manners 64 with BetaNode indexing only for right memory: 8765 millisec to run on average
-
- So, we have the best scenario now. For Manners 64, the best
- would be to disable left indexing, leaving only right indexing
- enabled.
-
-
- Re-arranging constraints
-
- Another tip to tune performance when using indexing is always to
- write your rules in a way that the most restrictive constraints are
- declared before the less restrictive ones in your rule. For example, if
- you have a rule with a column like this: Employee (department == $aDepartment, name == $aName)
- Rewriting it as shown bellow will probably give you a better
- performance, as “name” is probably a more restrictive constraint than
- “department”: Employee (name == $aName, department == $aDepartment)
- (Unless you work in an organization where there are more
- departments then employees, which could well be the case in a Government
- organization ;)
-
-
- Some other improvements are being developed for Drools in this area
- and will be documented as they become available in future versions.
-
-
-
- Large Ruleset
- For this section, large rulesets are define as the following
-
- 1-500 - small ruleset
- 500-2000 - medium ruleset
- 2000+ - large ruleset
- 10,000 - extremely large ruleset
-
- There are some cases where a rule engine has to handle 500,000 or 1 million rules.
- Those are primarily machine learning and AI systems, where a rule engine produces new
- rules, terms and facts at execution time. Those topics are beyond the scope of the
- documentation and aren't covered. The techniques described are focused on business rules.
- The first thing to do is identify why there are so many rules and whether or not
- rewriting the rules can solve the problem. There's a couple of things to look for.
-
- Do the rules have a lot of constant values hard coded in the conditions?
- Is the domain model a huge flat spreadsheet with 100+ columns?
- Do most of the rules share the same conditions?
- Can the logic be divided into stages?
-
- If you answer yes to any of the 4 questions, chances are you can solve the issue with
- changing the rules. Managing 100,000 rules or even 1,000,000 rules is a huge headache, so
- try to avoid it. Examine the rules and see if it matches any of the following scenarios.
-
-If
- customer.account == "abcd"
- customer.type == "basic"
- .....
-Then
- // do something
-
- The basic problem with rules sample above, is the rules have most of the values hard
- coded. If the average customer has 50 rules and there's 40 million customers, the system has
- 200 million rules. Let's use a more concrete example to flesh this out.
-
-If
- customer.accountId == "peter"
- customer.type == "level2"
- customer.favoriateActor == "jackie chan"
-Then
- recommend movies with jackie chan
-
-If
- customer.accountId == "peter"
- customer.type == "level2"
- customer.favoriateActor == "jet li"
-Then
- recommend movies with jet li
-
- Looking at the example, the first to question ask is "do these kinds of rules apply
- to all customers?" If it does, the first condition in the rule "customer.accountId" is
- pointless. It's pointless because all rules of this type will have that condition.
- Although the accountId changes, the rule can effectively ignore it. If we rewrite the rule
- this way, the rule can apply to any customer that likes jackie chan and jet li.
-
-If
- customer.type == "level2"
- customer.favoriateActor == "jackie chan"
-Then
- recommend movies with jackie chan
-
-If
- customer.type == "level2"
- customer.favoriateActor == "jet li"
-Then
- recommend movies with jet li
-
- The reason we do this is straight forward. The rules reason over data. Having a
- ton of rules with the customer's accountId hard coded doesn't do any good, because we
- want the rule engine to only evaluate the active sessions. We don't want to load all
- the customers into the rule engine. We can take it a step further and make the rule more
- general.
-
-If
- customer.type == "level2"
- customer.accountId ?id // bind the account id to a variable
- favorites.accountId ?id // find the list of favorites by the account id
-Then
- recommend all items in the favorites
-
- With this change, it can reduce the number of rules significantly. This is one
- reason the RETE approach is often called "data driven approach". Let's take this example
- a bit further and define 10 types of customers from level1 to level10. Say we run a mega
- online store and customers can define their favorites in each of the categories (books,
- videos, music, toys, electronics, clothing). What happens if a customer has different
- levels for each category. Using the hard coded approach, one might have to add more rules.
- If we change the rule and make it more generalized, the same rule can handle multiple
- categories.
-
-If
- recommendation.level ?lvl // bind the recommendation level to a variable
- recommendation.category ?rcat // bind the recommendation category
- customer.accountId ?id // bind the account id to a variable
- favorites.accountId ?id // find the list of favorites by the account id
- favorites.category ?rcat // match favorite to recommendation category
- favorites.level ?lvl // match the favorite level to recommendation level
-Then
- recommend all items in the favorites
-
- So what is the cost of making the rule dynamic and data driven? Obviously, hard
- coding a rule is going to be faster than making it generalized, but the performance delta
- should be small. In the case where a ruleset is small, the hard coded approach may have a
- slight performance lead. Why is that? Lets look at 2 different types of rule engines:
- procedural and RETE.
- In a procedural engine, one can build a decision tree and end the evaluation once
- the data fails to satisfy the conditions at a given level. As the rule count increases,
- there are more rules the engine has to evaluate. In a procedural approach, the rules have
- to be sequenced in the optimal order to get the best results. The limitation of sorting
- the rules in optimal sequence is that many cases it's not possible to pre-sort. If we use
- a RETE rule engine, the hard coded rules result in fewer joins for a small number of rules.
- As the rule count grows, the single rule will perform better. The equation to estimate the
- threshold where the generalized form is faster than hard coding the constants.
- bn = join nodes, lf = left facts, rf = right facts, ae = average number of
- evaluation descending from the object type node for a random sample, f = facts,
- hd = hard coded constants in the rules, general = generalized form using joins
- general( sum( bn(lf * rf) ) + sum(ae * f) ) < hd( sum( bn(lf * rf) ) + sum(ae * f) )
- The best way to quantify the threshold is to write rules in both formats and run a
- series of tests. Given that most projects are under tight schedules, developers don't
- always have time to do this. The other common problem is using really large flat objects.
- In a nutshell, using large flat objects leads to the same problem as hard coding the
- constants in the rules. The solution to the problem is to change the domain objects,
- such that it models the business concepts in a concise manner. That isn't always an
- option.
- When most of the rules share the same conditions, there's two solutions. The best
- solution is to rewrite the rules to use chaining. Identify the common conditions and extract
- it into a generalized rule. The generalized rule then trigger subsequent rules by asserting
- a new fact. Often this can reduce the rules by an order of magnitude or more. The second
- option is to put common conditions at the beginning of the rule. What this does is it
- allows RETE rule engines to share those nodes. When the nodes are shared, it reduces the
- cost from a memory and performance perspective.
- If the ruleset can be divided into smaller chunks, it's a good idea to divide it into
- discrete stages and load each ruleset on a different JVM or server. Depending on the
- situation, this may not be an option. So what can you do when the ruleset is large and
- rewriting the rules isn't an option?
- The only viable option is to scale the hardware and use a different JVM. This means
- using 64bit JVM from SUN, IBM or BEA JRockit on a machine with at least 8Gb RAM. Depending
- on the ruleset, the system may need more RAM.
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Chapter-RuleLanguage.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Chapter-RuleLanguage.xml
deleted file mode 100755
index 700110129d..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Chapter-RuleLanguage.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
- The Rule Language
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Comments.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Comments.xml
deleted file mode 100755
index 2eb987251b..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Comments.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
- Comments
-
-
- (updated to Drools 4.0)
-
-
- Comments are sections of text that are ignored by the rule engine.
- They are stripped out when they are encountered, except inside semantic code
- blocks, like the RHS of a rule.
-
-
- Single line comment
-
-
- Single line comment
-
-
-
-
-
-
-
-
- To create single line comments, you can use either '#' or '//'. The
- parser will ignore anything in the line after the comment symbol.
- Example:
-
- rule "Testing Comments"
-when
- # this is a single line comment
- // this is also a single line comment
- eval( true ) # this is a comment in the same line of a pattern
-then
- // this is a comment inside a semantic code block
- # this is another comment in a semantic code block
-end
-
-
-
-
- Multi-line comment
-
-
- Multi-line comment
-
-
-
-
-
-
-
-
- Multi-line comments are used to comment blocks of text, both in and
- outside semantic code blocks. Example:
-
- rule "Test Multi-line Comments"
-when
- /* this is a multi-line comment
- in the left hand side of a rule */
- eval( true )
-then
- /* and this is a multi-line comment
- in the right hand side of a rule */
-end
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-DSL.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-DSL.xml
deleted file mode 100755
index 24905d52d6..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-DSL.xml
+++ /dev/null
@@ -1,400 +0,0 @@
-
-
- Domain Specific Languages
-
- As mentioned previously,
- Domain Specific Languages
- (or DSLs) are a way of extending the rule language to your
- problem domain. They are wired in to the rule language for you, and can make
- use of all the underlying rule language and engine features.
-
- DSLs are used both in the IDE, as well as the web based BRMS. Of
- course as rules are text, you can use them even without this tooling.
-
-
- When to use a DSL
-
- DSLs can serve as a layer of separation between rule authoring (and
- rule authors) and the domain objects that the engine operates on. DSLs can
- also act as "templates" of conditions or actions that are used over and
- over in your rules, perhaps only with parameters changing each time. If
- your rules need to be read and validated by less technical folk, (such as
- Business Analysts) the DSLs are definitely for you. If the conditions or
- consequences of your rules follow similar patterns which you can express
- in a template. You wish to hide away your implementation details, and
- focus on the business rule. You want to provide a controlled means of
- editing rules based on pre-defined templates.
-
- DSLs have no impact on the rules at runtime, they are just a
- parse/compile time feature.
-
- Note that Drools 4 DSLs are quite different from Drools 2 XML based
- DSLs. It is still possible to do Drools 2 style XML languages - if you
- require this, then take a look at the Drools 4 XML rule language, and
- consider using XSLT to map from your XML language to the Drools 4 XML
- language.
-
-
-
- Editing and managing a DSL
-
- A DSL's configuration like most things is stored in plain text. If
- you use the IDE, you get a nice graphical editor (with some validation),
- but the format of the file is quite simple, and is basically a properties
- file.
-
- Note that since Drools 4.0, DSLs have become more powerful in
- allowing you to customise almost any part of the language, including
- keywords. Regular expressions can also be used to match words/sentences if
- needed (this is provided for enhanced localisation). However, not all
- features are supported by all the tools (although you can use them, the
- content assistance just may not be 100% accurate in certain cases).
-
-
- Example
- DSL
- mapping
-
- [when]This is {something}=Something(something=={something})
-
-
- Referring to the above example, the [when] refers to the scope of
- the expression: ie does it belong on the LHS or the RHS of a rule. The
- part after the [scope] is the expression that you use in the rule
- (typically a natural language expression, but it doesn't have to be). The
- part on the right of the "=" is the mapping into the rule language (of
- course the form of this depends on if you are talking about the RHS or the
- LHS - if its the LHS, then its the normal LHS syntax, if its the RHS then
- its fragments of Java code for instance).
-
- The parser will take the expression you specify, and extract the
- values that match where the {something} (named Tokens) appear in the
- input. The values that match the tokens are then interpolated with the
- corresponding {something} (named Tokens) on the right hand side of the
- mapping (the target expression that the rule engine actually uses).
-
- Note also that the "sentences" above can be regular expressions.
- This means the parser will match the sentence fragements that match the
- expressions. This means you can use (for instance) the '?' to indicate the
- character before it is optional (think of each sentence as a regular
- expression pattern - this means if you want to use regex characters - you
- will need to escape them with a '\' of course.
-
- It is important to note that the DSL expressions are processed one
- line at a time. This means that in the above example, all the text after
- "This is " to the end of the line will be included as the value for
- "{something}" when it is interpolated into the target string. This may not
- be exactly what you want, as you may want to "chain" together different
- DSL expressions to generate a target expression. The best way around this
- is to make sure that the {tokens} are enclosed with characters or words.
- This means that the parser will scan along the sentence, and pluck out the
- value BETWEEN the characters (in the example below they are
- double-quotes). Note that the characters that surround the token are not
- included in when interpolating, just the contents between them (rather
- then all the way to the end of the line, as would otherwise be the
- case).
-
- As a rule of thumb, use quotes for textual data that a rule editor
- may want to enter. You can also wrap words around the {tokens} to make
- sure you enclose the data you want to capture (see other example).
-
-
- Example with quotes
-
- [when]This is "{something}" and "{another}"=Something(something=="{something}", another=="{another}")
-[when]This is {also} valid=Another(something=="{also}")
-
-
- It is a good idea to try and avoid punctuation in your DSL
- expressions where possible, other then quotes and the like - keep it
- simple and things will be easier. Using a DSL can make debugging slightly
- harder when you are first building rules, but it can make the maintenance
- easier (and of course the readability of the rules).
-
- The "{" and "}" characters should only be used on the left hand side
- of the mapping (the expression) to mark tokens. On the right hand side you
- can use "{" and "}" on their own if needed - such as
- if (foo) \{
- doSomething();\ }
- as well as with the token names as shown
- above.
- PLEASE NOTE that if you want curly braces to appear literally as curly braces, then escape them with a backslack (\). Otherwise it may think it is a token to be replaced.
-
- Don't forget that if you are capturing strings from users, you will
- also need the quotes on the right hand side of the mapping, just like a
- normal rule, as the result of the mapping must be a valid expression in
- the rule language.
-
-
- Some more examples
-
- #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
-
-
- Referring to the above examples, this would render the following
- input as shown below:
-
- 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" ---> 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")
-
-
-
-
- Using a DSL in your rules
-
- 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 recognize
- 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).
-
- Also, it is better to rename the extension of your rules file from
- ".drl" to ".dslr" when you start using DSLs, as that will allow the IDE to
- correctly recognize and work with your rules file.
-
- As you work through building up your DSL, you will find that the DSL
- configuration stabilizes 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.
-
- 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.
- PackageBuilder builder = new PackageBuilder();
-builder.addPackageFromDrl( source, dsl );
-//source is a reader for the rule source, dsl is a reader for the DSL configuration
-
- You will also need to specify the expander by name in the
- rule source file:
- expander your-expander.dsl
-
- 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.
-
- 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:
-
-
- Chaining DSL Expressions
- There is a person called Bob who is happy
- Or
-There is a person called Mike who is sad
-
-
-
- Of course this assumes that "Or" is mapped to the "or" conditional
- element (which is a sensible thing to do).
-
-
-
- Adding constraints to facts
-
- A common requirement when writing rule conditions is to be able to
- add many constraints to fact declarations. A fact may have many (dozens)
- of fields, all of which could be used or not used at various times. To
- come up with every combination as separate DSL statements would in many
- cases not be feasible.
-
- The DSL facility allows you to achieve this however, with a simple
- convention. If your DSL expression starts with a "-", then it will be
- assumed to be a field constraint, which will be added to the declaration
- that is above it (one per line).
-
- This is easier to explain with an example. Lets take look at Cheese
- class, with the following fields: type, price, age, country. We can
- express some LHS condition in normal DRL like the following
- Cheese(age < 5, price == 20, type=="stilton", country=="ch")
- If you know ahead of time that you will use all the fields, all the time,
- it is easy to do a mapping using the above techniques. However, chances
- are that you will have many fields, and many combinations. If this is the
- case, you can setup your mappings like so:
- [when]There is a Cheese with=Cheese()
-[when]- age is less than {age}=age<{age}
-[when]- type is '{type}'=type=='{type}'
-[when]- country equal to '{country}'=country=='{country}'
-
- IMPORTANT: It is NOT possible to
- use the "-" feature after an accumulate
- statement to add constraints to the accumulate pattern. This limitation
- will be removed in the future.
-
- You can then write rules with conditions like the following:
- There is a Cheese with
- - age is less than 42
- - type is 'stilton' The parser will pick up the "-"
- lines (they have to be on their own line) and add them as constraints to
- the declaration above. So in this specific case, using the above mappings,
- is the equivalent to doing (in DRL): Cheese(age<42, type=='stilton')
- The parser will do all the work for you, meaning you just define mappings
- for individual constraints, and can combine them how you like (if you are
- using context assistant, if you press "-" followed by CTRL+space it will
- conveniently provide you with a filtered list of field constraints to
- choose from.
-
- To take this further, after alter the DSL to have
- [when][org.drools.Cheese]- age is less than {age} ... (and similar to all
- the items in the example above).
-
- The extra [org.drools.Cheese] indicates that the sentence only
- applies for the main constraint sentence above it (in this case "There is
- a Cheese with"). For example, if you have a class called "Cheese" - then
- if you are adding contraints to the rule (by typing "-" and waiting for
- content assistance) then it will know that only items marked as having an
- object-scope of "com.yourcompany.Something" are valid, and suggest only
- them. This is entirely optional (you can leave out that section if needed
- - OR it can be left blank).
-
-
-
- How it works
-
- 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.
-
- 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).
-
- 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).
-
-
-
- Creating a DSL from scratch
-
- DSLs can be aid with capturing rules if the rules are well known,
- just not in any technically usable format (ie. sitting around in people
- brains). Until we are able to have those little sockets in our necks like
- in the Matrix, our means of getting stuff into computers is still the old
- fashioned way.
-
- Rules engines require an object or a data model to operate on - in many
- cases you may know this up front. In other cases the model will be
- discovered with the rules. In any case, rules generally work better with
- simpler flatter object models. In some cases, this may mean having a rule
- object model which is a subset of the main applications model (perhaps
- mapped from it). Object models can often have complex relationships and
- hierarchies in them - for rules you will want to simplify and flatten the
- model where possible, and let the rule engine infer relationships (as it
- provides future flexibility). As stated previously, DSLs can have an
- advantage of providing some insulation between the object model and the
- rule language.
-
- Coming up with a DSL is a collaborative approach for both technical
- and domain experts. Historically there was a role called "knowledge
- engineer" which is someone skilled in both the rule technology, and in
- capturing rules. Over a short period of time, your DSL should stabilize,
- which means that changes to rules are done entirely using the DSL. A
- suggested approach if you are starting from scratch is the following
- workflow:
-
- Capture rules as loose "if then" statements - this is really
- to get an idea of size and complexity (possibly in a text
- document).
-
-
-
- Look for recurring statements in the rules captured. Also look
- for the rule objects/fields (and match them up with what may already
- be known of the object model).
-
-
-
- Create a new DSL, and start adding statements from the above
- steps. Provide the "holes" for data to be edited (as many statements
- will be similar, with only some data changing).
-
-
-
- Use the above DSL, and try to write the rules just like that
- appear in the "if then" statements from the first and second steps.
- Iterate this process until patterns appear and things stabilize. At
- this stage, you are not so worried about the rule language
- underneath, just the DSL.
-
-
-
- At this stage you will need to look at the Objects, and the
- Fields that are needed for the rules, reconcile this with the
- datamodel so far.
-
-
-
- Map the DSL statements to the rule language, based on the
- object model. Then repeat the process. Obviously this is best done
- in small steps, to make sure that things are on the right
- track.
-
-
-
-
-
- Scope and keywords
-
- If you are editing the DSL with the GUI, or as text, you will notice
- there is a [scope] item at the start of each mapping line. This indicates
- if the sentence/word applies to the LHS, RHS or is a keyword. Valid values
- for this are [condition], [consequence] and [keyword] (with [when] and
- [then] being the same as [condition] and [consequence] respectively). When
- [keyword] is used, it means you can map any keyword of the language like
- "rule" or "end" to something else. Generally this is only used when you
- want to have a non English rule language (and you would ideally map it to
- a single word).
-
-
-
- DSLs in the BRMS and IDE
-
- You can use DSLs in the BRMS in both guided editor rules, and
- textual rules that use a dsl. (In fact, the same applies to the
- IDE).
-
- In the guided editor - the DSLs generally have to be simpler - what
- you are doing is defining little "forms" to capture data from users in
- text fields (ie as you pick a DSL expression - it will add an item to the
- GUI which only allows you enter data in the {token} parts of a DSL
- expression). You can not use sophisticated regular expressions to match
- text. However, in textual rules (which have a .dslr extension in the IDE)
- you are free to use the full power as needed.
-
- In the BRMS - when you build a package the DSLs are already included
- and all the work is done for you. In the IDE (or in any IDE) - you will
- either need to use the drools-ant task, or otherwise use the code shown in
- sections above.
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-ErrorMessages.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-ErrorMessages.xml
deleted file mode 100755
index 019aeb597c..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-ErrorMessages.xml
+++ /dev/null
@@ -1,324 +0,0 @@
-
-
- Error Messages
-
-
- (updated to Drools 5.0)
-
-
- Drools 5 introduces standardized error messages. This standardization
- aims to help users to find and resolve problems in a easier and faster way.
- In this section you will learn how to identify and interpret those error
- messages, and you will also receive some tips on how to solve the problems
- associated with them.
-
-
- Message format
-
- The standardization includes the error message format and to better
- explain this format, let's use the following example:
-
-
- Error Message Format
-
-
-
-
-
-
-
-
- 1st Block: This area identifies the
- error code.
-
- 2nd Block: Line:column
- information.
-
- 3rd Block: Some text describing the
- problem.
-
- 4th Block: This is the first
- context. Usually indicates the rule, function, template or query where the
- error occurred. This block is not mandatory.
-
- 5th Block: Identifies the pattern
- where the error occurred. This block is not mandatory.
-
-
-
- Error Messages Description
-
-
- 101: No viable alternative
-
- Indicates the most common errors, where the parser came to a
- decision point but couldn't identify an alternative. Here are some
- examples:
-
-
- 1: rule one
-2: when
-3: exists Foo()
-4: exits Bar()
-5: then
-6: end
-
-
-
- The above example generates this message:
-
-
-
- [ERR 101] Line 4:4 no viable alternative at input 'exits' in
- rule one
-
-
-
- At first glance this seems to be valid syntax, but it is not (exits
- != exists). Let's take a look at next example:
-
-
- 1: package org.drools;
-2: rule
-3: when
-4: Object()
-5: then
-6: System.out.println("A RHS");
-7: end
-
-
-
- Now the above code generates this message:
-
-
-
- [ERR 101] Line 3:2 no viable alternative at input
- 'WHEN'
-
-
-
- This message means that the parser could identify the WHEN hard keyword, but it is not an option here.
- In this case, it is missing the rule name.
-
- No viable alternative error occurs also when you have lexical
- problems. Here is a sample of a lexical problem:
-
-
- 1: rule simple_rule
-2: when
-3: Student( name == "Andy )
-4: then
-5: end
-
-
-
- The above code misses to close the quotes and because of this the
- parser generates this error message:
-
-
-
- [ERR 101] Line 0:-1 no viable alternative at input
- '<eof>' in rule simple_rule in pattern Student
-
-
-
-
- Usually the Line and Column information are accurate, but in
- some cases (like unclosed quotes), the parser generates a 0:-1
- position. In this case you should check whether you didn't forget to close
- quotes, apostrophes or parentheses.
-
-
-
-
- 102: Mismatched input
-
- Indicates that the parser was looking for a particular symbol that
- it didn’t find at the current input position. Here are some
- samples:
-
-
- 1: rule simple_rule
-2: when
-3: foo3 : Bar(
-
-
-
- The above example generates this message:
-
-
-
- [ERR 102] Line 0:-1 mismatched input '<eof>' expecting
- ')' in rule simple_rule in pattern Bar
-
-
-
- To fix this problem, it is necessary to complete the rule
- statement.
-
-
- Usually when you get a 0:-1 position, it means that parser
- reached the end of source.
-
-
- The following code generates more than one error message:
-
-
- 1: package org.drools;
-2:
-3: rule "Avoid NPE on wrong syntax"
-4: when
-5: not( Cheese( ( type == "stilton", price == 10 ) || ( type == "brie", price == 15 ) ) from $cheeseList )
-6: then
-7: System.out.println("OK");
-8: end
-
-
-
- These are the errors associated with this source:
-
-
-
- [ERR 102] Line 5:36 mismatched input ',' expecting ')' in rule
- "Avoid NPE on wrong syntax" in pattern Cheese
-
-
-
- [ERR 101] Line 5:57 no viable alternative at input 'type' in
- rule "Avoid NPE on wrong syntax"
-
-
-
- [ERR 102] Line 5:106 mismatched input ')' expecting 'then' in
- rule "Avoid NPE on wrong syntax"
-
-
-
- Note that the second problem is related to the first. To fix it,
- just replace the commas (",") by AND operator ("&&").
-
-
- In some situations you can get more than one error message. Try to
- fix one by one, starting at the first one. Some error messages are
- generated merely as consequences of other errors.
-
-
-
-
- 103: Failed predicate
-
- A validating semantic predicate evaluated to false. Usually these
- semantic predicates are used to identify soft keywords. This sample
- shows exactly this situation:
-
-
- 1: package nesting;
- 2: dialect "mvel"
- 3:
- 4: import org.drools.Person
- 5: import org.drools.Address
- 6:
- 7: fdsfdsfds
- 8:
- 9: rule "test something"
-10: when
-11: p: Person( name=="Michael" )
-12: then
-13: p.name = "other";
-14: System.out.println(p.name);
-15: end
-
-
-
- With this sample, we get this error message:
-
-
-
- [ERR 103] Line 7:0 rule 'rule_key' failed predicate:
- {(validateIdentifierKey(DroolsSoftKeywords.RULE))}? in rule
-
-
-
- The fdsfdsfds text is invalid and
- the parser couldn’t identify it as the soft keyword "rule".
-
-
- This error is very similar to 102: Mismatched input, but usually
- involves soft keywords.
-
-
-
-
- 104: Trailing semi-colon not allowed
-
- This error is associated with the "eval" clause, where its
- expression may not be terminated with a semi-colon. Check this
- example:
-
-
- 1: rule simple_rule
-2: when
-3: eval(abc();)
-4: then
-5: end
-
-
-
- Due to the trailing semi-colon within eval, we get this error
- message:
-
-
-
- [ERR 104] Line 3:4 trailing semi-colon not allowed in rule
- simple_rule
-
-
-
- This problem is simple to fix: just remove the
- semi-colon.
-
-
-
- 105: Early Exit
-
- The recognizer came to a (..)+ EBNF subrule that must match an
- alternative at least once, but the subrule did not match anything.
- Simply put: the parser has entered a branch from where there is no
- way out. This example tries to illustrates it:
-
-
- 1: template test_error
-2: aa s 11;
-3: end
-
-
-
- This is the message associated to the above sample:
-
-
-
- [ERR 105] Line 2:2 required (...)+ loop did not match anything
- at input 'aa' in template test_error
-
-
-
- To fix this problem it is necessary to remove the numeric value
- as it is neither a valid data type which might begin a new template
- slot nor a possible start for any other rule file construct.
-
-
-
-
- Other Messages
-
- If you get any other message, means that something bad happened, so
- please contact the development team.
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Function.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Function.xml
deleted file mode 100755
index d1c40f54dc..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Function.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
- Function
-
-
- (updated to Drools 4.0)
-
-
-
- function
-
-
-
-
-
-
-
-
- Functions are a way to put semantic code in your rule source file, as
- opposed to in normal Java classes. They can't do anything more then what you
- can do with helper classes (in fact, the compiler generates the helper class
- for you behind the scenes). The main advantage of using functions in a rule
- is that you can keep the logic all in one place, and you can change the
- functions as needed (this can be a good and bad thing). Functions are most
- useful for invoking actions on the consequence ("then") part of a rule,
- especially if that particular action is used over and over (perhaps with
- only differing parameters for each rule - for example the contents of an
- email message).
-
- A typical function declaration looks like:
-
- function String hello(String name) {
- return "Hello "+name+"!";
-}
-
-
- Note that the "function" keyword is used, even though its not really
- part of Java. Parameters to the function are just like a normal method (and
- you don't have to have parameters if they are not needed). Return type is
- just like a normal method.
-
- An alternative to the use of a function, could be to use a static
- method in a helper class: Foo.hello(). Drools 4.0 supports the use of
- function imports, so all you would need to do is:
-
- import function my.package.Foo.hello
-
- In both cases above, to use the function, just call it by its name in
- the consequence or inside a semantic code block. Example:
-
- rule "using a static function"
-when
- eval( true )
-then
- System.out.println( hello( "Bob" ) );
-end
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Keywords.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Keywords.xml
deleted file mode 100755
index 716a62908d..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Keywords.xml
+++ /dev/null
@@ -1,241 +0,0 @@
-
-
-
-
- (updated to Drools 5.0)
-
-
-
- Keywords
-
- Drools 5 introduces the concept of Hard and Soft keywords.
-
- Hard keywords are reserved, you cannot use any hard keyword when
- naming your domain objects, properties, methods, functions and other
- elements that are used in the rule text.
-
- Here is a list of hard keywords that must be avoided as identifiers
- when writing rules:
-
-
-
- true
-
-
-
- false
-
-
-
- accumulate
-
-
-
- collect
-
-
-
- from
-
-
-
- null
-
-
-
- over
-
-
-
- then
-
-
-
- when
-
-
-
- Soft keywords are just recognized in their context, enabling you to
- use this words in any other place you wish. Here is a list of soft
- keywords:
-
-
-
- lock-on-active
-
-
-
- date-effective
-
-
-
- date-expires
-
-
-
- no-loop
-
-
-
- auto-focus
-
-
-
- activation-group
-
-
-
- agenda-group
-
-
-
- ruleflow-group
-
-
-
- entry-point
-
-
-
- duration
-
-
-
- package
-
-
-
- import
-
-
-
- dialect
-
-
-
- salience
-
-
-
- enabled
-
-
-
- attributes
-
-
-
- rule
-
-
-
- extend
-
-
-
- template
-
-
-
- query
-
-
-
- declare
-
-
-
- function
-
-
-
- global
-
-
-
- eval
-
-
-
- not
-
-
-
- in
-
-
-
- or
-
-
-
- and
-
-
-
- exists
-
-
-
- forall
-
-
-
- action
-
-
-
- reverse
-
-
-
- result
-
-
-
- end
-
-
-
- init
-
-
-
- Of course, you can have these (hard and soft) words as part of a
- method name in camel case, like notSomething() or accumulateSomething() -
- there are no issues with that scenario.
-
- Another improvement on DRL language is the ability to escape hard
- keywords on rule text. This new feature enables you to use your existing
- domain objects without worrying about keyword collision. To escape a word,
- simple type it between grave accents, like this:
-
- Holiday( `when` == "july" )
-
- The escape should be used everywehere in rule text, except within code
- expressions in the LHS or RHS code block. Here are examples of
- usage:
-
- rule "validate holiday by eval"
-dialect "mvel"
-when
- h1 : Holiday( )
- eval( h1.when == "july" )
-then
- System.out.println(h1.name + ":" + h1.when);
-end
-
-
- rule "validate holiday"
-dialect "mvel"
-when
- h1 : Holiday( `when` == "july" )
-then
- System.out.println(h1.name + ":" + h1.when);
-end
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Overview.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Overview.xml
deleted file mode 100755
index f99dcbc48e..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Overview.xml
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
- Overview
-
-
- (updated to Drools 4.0)
-
-
- Drools 4.0 has a "native" rule language that is non XML textual
- format. This format is very light in terms of punctuation, and supports
- natural and domain specific languages via "expanders" that allow the
- language to morph to your problem domain. This chapter is mostly concerted
- with the native rule format. The Diagrams used are known as "rail road"
- diagrams, and are basically flow charts for the language terms. For the
- technically very keen, you can also refer to "DRL.g" which is the Antlr3
- grammar for the rule language. If you use the Rule Workbench, a lot of the
- rule structure is done for you with content assistance, for example, type
- "ru" and press ctrl+space, and it will build the rule structure for
- you.
-
-
- A rule file
-
- A rule file is typically a file with a .drl extension. In a drl file
- you can have multiple rules, queries and functions, as well as some
- resource declarations like imports, globals and attributes that are
- assigned and used by your rules and queries. However, you are also able to
- spread your rules across multiple rule files (in that case, the extension
- .rule is suggested, but not required) - spreading rules across files can
- help with managing large numbers of rules. A DRL file is simply a text
- file.
-
- The overall structure of a rule file is:
-
-
- Rules file
-
- package package-name
-
-imports
-
-globals
-
-functions
-
-queries
-
-rules
-
-
-
- The order in which the elements are declared is not important,
- except for the package name that, if declared, must be the first element
- in the rules file. All elements are optional, so you will use only those
- you need. We will discuss each of them in the following sections.
-
-
-
- What makes a rule
-
- For the inpatients, just as an early view, a rule has the following
- rough structure:rule"name"
- attributes
- when
- LHS
- then
- RHS
-end
-It's really that simple. Mostly punctuation is not needed,
- even the double quotes for "name" are optional, as are newlines.
- Attributes are simple (always optional) hints to how the rule should
- behave. LHS is the conditional parts of the rule, which follows a certain
- syntax which is covered below. RHS is basically a block that allows
- dialect specific semantic code to be executed.
-
- It is important to note that white space is not important,
- except in
- these case of domain specific languages, in which case each line is
- processed before the following line (and spaces may be significant to the
- domain language).
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Package.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Package.xml
deleted file mode 100755
index 5142ede329..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Package.xml
+++ /dev/null
@@ -1,175 +0,0 @@
-
-
- Package
-
-
- (updated to Drools 4.0)
-
-
- A package is a collection of rules and other related constructs, such
- as imports and globals. The package members are typically related to each
- other - perhaps HR rules, for instance. A package represents a namespace,
- which ideally is kept unique for a given grouping of rules. The package name
- itself is the namespace, and is not related to files or folders in any
- way.
-
- It is possible to assemble rules from multiple rule sources, and have
- one top level package configuration that all the rules are kept under (when
- the rules are assembled). Although, it is not possible to merge into the
- same package resources declared under different names. A single Rulebase,
- can though, contain multiple packages built on it. A common structure, is to
- have all the rules for a package in the same file as the package declaration
- (so that is it entirely self contained).
-
- The following railroad diagram shows all the components that may make
- up a package. Note that a package must have a namespace and be declared
- using standard Java conventions for package names; i.e., 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 semicolons are optional.
-
-
- package
-
-
-
-
-
-
-
-
-
-
- import
-
-
- import
-
-
-
-
-
-
-
-
-
- Import statements work like import statements in Java. You need to
- specify the fully qualified paths and type names for any objects you want
- to use in the rules. Drools automatically imports classes from the same
- named Java package and from the java.lang package.
-
-
-
- expander
-
-
- expander
-
-
-
-
-
-
-
-
-
- The expander statement (optional) is used to specify domain specific
- language (DSL) configurations (which are normally stored in a separate
- file). This provides clues to the parser how to understand what you are
- raving on about in your rules. It is important to note that in Drools 4.0
- (that is different from Drools 3.x) the expander declaration is mandatory
- for the tools to provide you context assistacnce and to avoid error reporting,
- but the API allows the program to apply DSL templates, even if the
- expanders are not declared in the source file.
-
-
-
- global
-
-
- global
-
-
-
-
-
-
-
-
-
- Globals are global variables. They are used to make application
- objects available to the rules, and are typically used to provide data or
- services that the rules use (specially application services used in rule
- consequences), to return data from the rules (like logs or values added in
- rules consequence) or for the rules to interact with the application doing
- callbacks. Globals are not inserted into the Working Memory so they should
- never be reasoned over; you should use them in rules' LHS only if the global has a
- constant immutable value. The engine cannot be notified about value
- changes of globals, and does not track their changes. Incorrect use
- of globals in constraints may yield
- surprising results - surprising in a bad way, like when a doctor says
- "thats interesting" to a chest XRay of yours.
-
- If multiple packages declare globals with the same identifier they
- must be of the same type and all of them will reference the same global
- value.
-
- In order to use globals you must:
-
-
-
- Declare your global variable in your rules file and use it in
- rules. Example:
-
- global java.util.List myGlobalList;
-
-rule "Using a global"
-when
- eval( true )
-then
- myGlobalList.add( "Hello World" );
-end
-
-
-
-
- Set the global value on your working memory. It is a best
- practice to set all global values before asserting any fact to the
- working memory. Example:
-
- List list = new ArrayList();
-WorkingMemory wm = rulebase.newStatefulSession();
-wm.setGlobal( "myGlobalList", list );
-
-
-
-
- Note that these are just named instances of objects that you pass in
- from your application to the working memory. This means you can pass in
- any object you want: you could pass in a service locator, or perhaps a
- service itself. With the new 'from' element it is now common to pass a
- Hibernate session as a global, to allow 'from' to pull data from a named
- Hibernate query.
-
- One example may be an instance of a Email service. In your
- integration code that is calling the rule engine, you get your
- emailService object, and then set it in the working memory. In the DRL,
- you declare that you have a global of type EmailService, and give it a
- name "email". Then in your rule consequences, you can use things like
- email.sendSMS(number, message).
-
- Globals are not designed to share data between rules and they should
- never be used for that purpose. Rules always reason and react to the
- working memory state, so if you want to "share" data between rules, assert
- the data to the working memory.
-
- It is strongly discouraged to set (or change) a global value from
- inside your rules. We recommend to you always set the value from your
- application using the working memory interface.
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Query.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Query.xml
deleted file mode 100755
index 092ec7c75b..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Query.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
- Query
-
-
- query
-
-
-
-
-
-
-
-
- A query contains the structure of the LHS of a rule only (you don't
- specify "when" or "then"). It is simply a way to query the working memory
- for facts that match the conditions stated. A query has an optional set of
- parameters, each of which can also be optionally typed. If type is not
- given then Object type is assumed. The engine will attempt to co-erce
- the values as needed. Query names are global to the RuleBase, so do
- not add queries of the same name to different packages for the same Rule
- Base.
-
- To return the results use WorkingMemory.getQueryResults("name"),
- where "name" is the query's name. This returns a list of query results,
- which allow you to to get to the objects that matched the query.
-
- The first example creates a simple query for all the people over
- the age of 30. The second one, using parameters, combines the age limit
- with a location.
-
-
- Query People over the age of 30
-
- query "people over the age of 30"
- person : Person( age > 30 )
-end
-
-
-
- Query People over the age of x, and who live in y
-
- query "people over the age of x" (int x, String y)
- person : Person( age > x, location == y )
-end
-
-
- We iterate over the returned QueryResults using a standard 'for' loop.
- Each element returns a QueryResult which we can use to access each of the
- columns in the Tuple. Those columns can be accessed by bound declaration name
- or index position.
-
-
- Query People over the age of 30
-
- QueryResults results = workingMemory.getQueryResults( "people over the age of 30" );
-System.out.println( "we have " + results.size() + " people over the age of 30" );
-
-System.out.println( "These people are are over 30:" );
-
-for ( Iterator it = results.iterator; it.hasNext(); ) {
- QueryResult result = ( QueryResult ) it.next();
- Person person = ( Person ) result.get( "person" );
- System.out.println( person.getName() + "\n" );
-}
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Rule.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Rule.xml
deleted file mode 100755
index f9f0c9cd97..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-Rule.xml
+++ /dev/null
@@ -1,2235 +0,0 @@
-
-
- Rule
-
-
- rule
-
-
-
-
-
-
-
-
- A rule specifies that "when" a particular set of conditions occur,
- specified in the Left Hand Side (LHS), then do this, which is specified as a
- list of actions in the Right Hand Side (RHS). A common question from users
- is "why use when instead of if". "when" was chosen over "if" because "if" is
- normally part of a procedural execution flow, where at a specific point in
- time it checks the condition. Where as "when" indicates it's not tied to a
- specific evaluation sequence or point in time, at any time during the life
- time of the engine "when" this occurs, do that Rule.
-
- A rule must have a name, unique within its rule package. If
- you define a rule twice in the same DRL it produces an error while loading.
- If you add a DRL that includes a rule name already in the package, it
- replaces the previous rule. If a rule name is to have spaces, then it
- will need to be enclosd in double quotes (it is best to always use double
- quotes).
-
- Attributes are optional, and are described below (they are best kept
- as one per line).
-
- The LHS of the rule follows the "when" keyword (ideally on a new
- line), similarly the RHS follows the "then" keyword (ideally on a newline).
- The rule is terminated by the keyword "end". Rules cannot be nested of
- course.
-
-
- Rule Syntax Overview Example
-
- rule "<name>"
- <attribute>*
-when
- <conditional element>*
-then
- <action>*
-end
-
-
-
- A rule example
-
- rule "Approve if not rejected"
- salience -100
- agenda-group "approval"
- when
- not Rejection()
- p : Policy(approved == false, policyState:status)
- exists Driver(age > 25)
- Process(status == policyState)
- then
- log("APPROVED: due to no objections.");
- p.setApproved(true);
-end
-
-
-
- Rule Attributes
-
- Rule attributes provide a declarative way to influence the behavior
- of the rule. Some are quite simple, while others are part of complex sub
- systems such as ruleflow. To get the most from Drools you should make
- sure you have a proper understanding of each attribute.
-
-
- rule attributes
-
-
-
-
-
-
-
-
-
-
- no-loop
-
-
- default value: false
-
- type: Boolean
-
- When the Rule's consequence modifies a fact it may cause
- the Rule to activate again, causing recursion. Setting no-loop
- to true means the attempt to create the Activation for the
- current set of data will be ignored.
-
-
-
-
-
- lock-on-active
-
-
- default value: false
-
- type: Boolean
- Whenever a ruleflow-group becomes active or an
- agenda-group receives the focus, any rule within that
- group that has lock-on-active set to true will not be
- activated any more; irrespective of the origin of the
- update, the activation of a matching rule is discarded.
- This is a stronger version of no-loop, because the change
- could now be caused not only by the rule itself. It's
- ideal for calculation rules where you have a number of
- rules that modify a fact and you don't want any rule
- re-matching and firing again. Only when the ruleflow-group
- is no longer active or the agenda-group loses the focus
- those rules with lock-on-active set to true become
- eligible again for their activations to be placed onto
- the agenda.
-
-
-
-
- salience
-
-
- default value : 0
-
- type : integer
-
- Each rule has a salience attribute that can be assigned
- an Integer number, defaults to zero, the Integer and can be
- negative or positive. Salience is a form of priority where
- rules with higher salience values are given higher priority
- when ordered in the Activation queue.
- Drools also supports dynamic salience where you can use andexpression involving bound variables.
-
-
- Dynamic Salience
- rule "Fire in rank order 1,2,.."
- salience( -$rank )
- when
- Element( $rank : rank,... )
- then
- ...
- end
-
-
-
-
-
-
- agenda-group
-
-
- default value: MAIN
-
- type: String
-
- Agenda group's allow the user to partition the Agenda providing more execution control. Only rules in the focus group are allowed to fire.
-
-
-
-
- auto-focus
-
-
- default value: false
-
- type: Boolean
-
- When a rule is activated if the auto-focus value is true and the Rule's agenda-group does not have focus then it is given focus, allowing the rule to potentially fire.
-
-
-
-
- activation-group
-
-
- default value: N/A
-
- type: String
-
- Rules that belong to the same named activation-group will only fire exclusively. In other words, the first rule in an activation-group to fire will cancel the other rules activations (stop them from firing). The Activation group attribute is any string, as long as the string is identical for all the rules you need to be in the one group.
-
- NOTE: this used to be called Xor group, but technically its not quite an Xor, but you may hear people mention Xor group, just swap that term in your mind with activation-group.
-
-
-
-
- dialect
-
-
- default value : as specified by the package
-
- type : String
-
- possible values: "java" or "mvel"
-
- The dialect species the language to be used for any code
- expressions in the LHS or the RHS code block. Currently two dialects are available, Java and MVEL. While the dialect can be specified at the package level, this attribute allows the package definition to be overridden.
-
-
-
-
-
- date-effective
-
-
- default value: N/A
-
- type: String, which contains a date and time definition
-
- A rule can only activate if the current date and time is after date-effective attribute.
-
-
-
-
- date-expires
-
-
- default value: N/A
-
- type: String, which contains a date and time definition
-
- A rule cannot activate if the current date and time is after date-expires attribute.
-
-
-
-
- duration
-
-
- default value: no default value
-
- type: long
-
- The duration dictates that the rule will fire after a specified duration, if it is still true.
-
-
-
-
-
- Some attribute examples
-
- rule "my rule"
- salience 42
- agenda-group "number 1"
- when ...
-
-
-
- Timers and Calendars
-
- Rule's now suport both interval and cron based timers, which
- replace the now deprecated duration attribute.
-
-
- Sample timer attribute uses
-
- timer ( int: <initial delay> <repeat interval>? )
-timer ( int: 30s )
-timer ( int: 30s 5m )
-
-timer ( cron: <cron expression> )
-timer ( cron:* 0/15 * * * ? )
-
-
- Interval "int:" timers follow the JDK semantics for initial delay
- optionally followed by a repeat interval. Cron "cron:" timers follow
- standard cron expressions:
-
-
- A Cron Example
-
- rule "Send SMS every 15 minutes"
- timer (cron:* 0/15 * * * ?)
-when
- $a : Alarm( on == true )
-then
- channels[ "sms" ].insert( new Sms( $a.mobileNumber, "The alarm is still on" );
-end
-
-
- Calendars can now controll when rules can fire. The Calendar api
- is modelled on Quartz
- http://www.quartz-scheduler.org/ :
-
-
- Adapting a Quartz Calendar
-
- Calendar weekDayCal = QuartzHelper.quartzCalendarAdapter(org.quartz.Calendar quartzCal)
-
-
- Calendars are registered with the StatefulKnowledgeSession:
-
-
- Registering a Calendar
-
- ksession.getCalendars().set( "week day", weekDayCal );
-
-
- They can be used in conjunction with normal rules and rules
- including timers. The rule calendar attribute can have one or more comma
- calendar names.
-
-
- Using Calendars and Timers together
-
- rule "weekdays are high priority"
- calendars "weekday"
- timer (int:0 1h)
-when
- Alarm()
-then
- send( "priority high - we have an alarm” );
-end
-
-rule "weekend are low priority"
- calendars "weekend"
- timer (int:0 4h)
-when
- Alarm()
-then
- send( "priority low - we have an alarm” );
-end
-
-
-
-
-
- Left Hand Side (when) Conditional Elements
-
- The Left Hand Side (LHS) is a common name for the conditional part
- of the rule. It consists of zero or more Conditional Elements. If the LHS
- is left empty it is re-written as eval(true), which means the rule is
- always true, and will be activated when a new Working Memory session is
- created.
-
-
- Left Hand Side
-
-
-
-
-
-
-
-
-
- Rule without a Conditional Element
-
- rule "no CEs"
-when
-then
- <action>*
-end
-
- Is internally re-written as:
-
- rule "no CEs"
-when
- eval( true )
-then
- <action>*
-end
-
-
- Conditional elements work on one or more patterns (which are
- described below). The most common one is "and" which is implicit when you
- have multiple patterns in the LHS of a rule that are not connected in
- any way. Note that an 'and' cannot have a leading declaration binding like
- 'or'. This is obvious, since a declaration can only
- reference a single fact, and when the 'and' is satisfied it matches more than
- one fact - which fact would the declaration bind to?
-
-
- Pattern
-
- The pattern element is the most important Conditional Element. The
- entity relationship diagram below provides an overview of the various
- parts that make up the pattern's constraints and how they work together;
- each is then covered in more detail with railroad diagrams and
- examples.
-
-
- Pattern Entity Relationship Diagram
-
-
-
-
-
-
-
-
- At the top of the ER diagram you can see that the pattern consists
- of zero or more constraints and has an optional pattern binding. The
- railroad diagram below shows the syntax for this.
-
-
- Pattern
-
-
-
-
-
-
-
-
- In its simplest form, with no constraints, it simply matches against a
- type. In the following case the type is "Cheese", which means that the pattern
- will match against all Cheese objects in the Working Memory.
-
-
- Simple Pattern
-
- Cheese( )
-
-
- To be able to refer to the matched object use a pattern binding
- variable such as '$c'. While this example variable is prefixed with a $
- symbol, it is optional, but can be useful in complex rules as it helps
- to more easily differentiation between variables and fields.
-
-
- Pattern with a binding variable
-
- $c : Cheese( )
-
-
- Inside of the pattern parenthesis is where all the action happens.
- A constraint can be either a Field Constraint, Inline Eval (called a
- predicate in 3.0) or a Constraint Group. Constraints can be separated by
- the following symbols: ',', '&&' or '||'.
-
-
- Constraints
-
-
-
-
-
-
-
-
-
- Constraint
-
-
-
-
-
-
-
-
-
- Group Constraint
-
-
-
-
-
-
-
-
-
- The ',' (comma) character is used to separate constraint groups.
- It has implicit 'and' connective semantics.
- Constraint Group connective ','
-
- # Cheese type is stilton and price < 10 and age is mature.
-Cheese( type == "stilton", price < 10, age == "mature" )
- The above example has 3 constraint groups, each with a
- single constraint:
-
-
-
- group 1: type is stilton -> type == "stilton"
-
-
-
- group 2: price is less than 10 -> price < 10
-
-
-
- group 3: age is mature -> age == "mature"
-
-
-
- The '&&' (and) and '||' (or) constraint connectives allow
- constraint groups to have multiple constraints. Example:
-
-
- && and || Constraint Connectives
-
- Cheese( type == "stilton" && price < 10, age == "mature" ) // Cheese type is "stilton" and price < 10, and age is mature
-Cheese( type == "stilton" || price < 10, age == "mature" ) // Cheese type is "stilton" or price < 10, and age is mature
-
-
- The above example has two constraint groups. The first has 2
- constraints and the second has one constraint.
-
- The connectives are evaluated in the following order, from first
- to last:
-
-
-
- &&
-
-
-
- ||
-
-
-
- ,
-
-
-
- It is possible to change the evaluation priority by using
- parenthesis, as in any logic or mathematical expression. Example:
-
-
- Using parenthesis to change evaluation priority
-
- # Cheese type is stilton and ( price is less than 20 or age is mature ).
-Cheese( type == "stilton" && ( price < 20 || age == "mature" ) )
-
- In the above example, the use of parenthesis makes the ||
- connective be evaluated before the && connective.
-
- Also, it is important to note that besides having the same
- semantics, the connectives '&&' and ',' are resolved with
- different priorities and ',' cannot be embedded in a composite
- constraint expression.
-
-
- Not Equivalent connectives
-
- Cheese( ( type == "stilton", price < 10 ) || age == "mature" ) // invalid as ',' cannot be embedded in an expression
-Cheese( ( type == "stilton" && price < 10 ) || age == "mature") // valid as '&&' can be embedded in an expression
-
-
-
- Field Constraints
-
- A Field constraint specifies a restriction to be used on a field
- name; the field name can have an optional variable binding.
-
-
- fieldConstraint
-
-
-
-
-
-
-
-
-
- There are three types of restrictions; Single Value Restriction,
- Compound Value Restriction and Multi Restriction.
-
-
- restriction
-
-
-
-
-
-
-
-
-
-
- JavaBeans as facts
-
- A field is an accessible method on the object. If your model
- objects follow the Java bean pattern, then fields are exposed using
- "getXXX" or "isXXX" methods (these are methods that take no
- arguments, and return something). You can access fields either by
- using the bean naming convention (so "getType" can be accessed as
- "type") - we use the standard jdk Introspector class to do this
- mapping.
-
- For example, referring to our Cheese class, the pattern
- Cheese(type == ...) applies the getType() method to a Cheese
- instance. If a field name cannot be found it will resort to calling
- the name as a no argument method; "toString()" on the Object for
- instance can be used with Cheese(toString == ..) - you use the full
- name of the method with correct capitalization, but without parentheses. Do
- please make sure that you are accessing methods that take no
- parameters, and are in-fact "accessors" which don't change
- the state of the object in a way that may effect the rules.
- Remember that the rule engine effectively caches the results of its
- matching in between invocations to make it faster.
-
-
-
- Values
-
- The field constraints can take a number of values; including
- literal, qualifiedIdentifier (enum), variable and
- returnValue.
-
-
- literal
-
-
-
-
-
-
-
-
-
- qualifiedIdentifier
-
-
-
-
-
-
-
-
-
- variable
-
-
-
-
-
-
-
-
-
-
- returnValue
-
-
-
-
-
-
-
-
- You can do checks against fields that are or may be null, using
- == and != as you would expect, and the literal "null" keyword, like:
- Cheese(type != null). If a field is null the evaluator will not
- throw an exception and will only return true if the value is null.
- Coercion is always attempted if the field and the value are
- of different types; exceptions will be thrown if bad coercions are
- attempted. For instance, if "ten" is provided as a string in a number
- evaluator an exception is thrown, whereas "10" would coerce to a
- numeric 10. Coercion is
- always in favor of the field type and not the value type.
-
-
-
- Single Value Restriction
-
-
- singleValueRestriction
-
-
-
-
-
-
-
-
-
- Operators
-
-
- Operators
-
-
-
-
-
-
-
-
- Valid operators are dependent on the field type. Generally
- they are self explanatory based on the type of data: for instance,
- for date fields, "<" means "before". "Matches" is
- only applicable to string fields, "contains" and "not contains" is
- only applicable to Collection type fields. These operators can be
- used with any value and coercion to the correct value for the
- evaluator and field will be attempted, as mentioned in the "Values"
- section.
-
-
- Matches Operator
-
- Matches a field against any valid Java
- regular expression
- Regular Expression. Typically that regexp is a
- String, but variables that resolve to a valid regexp are also
- allowed. It is important to note that, different from
- Java, if you write a String regexp directly on the
- source file, you don't need to escape '\'.
- Example:
-
-
- Regular Expression Constraint
-
- Cheese( type matches "(Buffalo)?\S*Mozerella" )
-
-
-
-
- Not Matches Operator
-
- Any valid Java
- regular expression
- Regular Expression can be used to match String
- fields. This operator returns true when the match is false. Typically that
- regexp is a String, but variables that resolve to a valid regexp
- are also allowed. It is important to note that,
- different from Java, if you write a String
- regexp directly on the source file, you don't need to
- escape '\'. Example:
-
-
- Regular Expression Constraint
-
- Cheese( type not matches "(Buffulo)?\S*Mozerella" )
-
-
-
-
- Contains Operator
-
- 'contains' is used to check if a
- field's
- Collection
- Collection or array contains the specified
- value.
-
-
- Contains with Collections
-
- CheeseCounter( cheeses contains "stilton" ) // contains with a String literal
-CheeseCounter( cheeses contains $var ) // contains with a variable
-
-
-
-
- not contains
-
- 'not contains' is used to check if a
- field's
- Collection
- Collection or array does not contain an
- object.
-
-
- Literal Constraints with Collections
-
- CheeseCounter( cheeses not contains "cheddar" ) // not contains with a String literal
-CheeseCounter( cheeses not contains $var ) // not contains with a variable
-
-
-
- NOTE: for backward
- compatibility, the 'excludes' operator is supported as a
- synonym for 'not
- contains'.
-
-
-
-
- memberOf
-
- 'memberOf' is used to check if a field is a
- member of a collection or array; that collection must be be a
- variable.
-
-
- Literal Constraints with Collections
-
- CheeseCounter( cheese memberOf $matureCheeses )
-
-
-
-
- not memberOf
-
- 'not memberOf' is used to check if a field is not
- a member of a collection or array; that collection must be be a
- variable.
-
-
- Literal Constraints with Collections
-
- CheeseCounter( cheese not memberOf $matureCheeses )
-
-
-
-
- soundslike
-
- Similar to 'matches', but checks if a word has
- almost the same sound as the given value. Uses the
- Soundex algorithm.
-
-
- Text with soundslike (Sounds Like)
-
- Cheese( name soundslike 'foobar' )
-
- This will match a cheese with a name of "fubar"
-
-
-
-
- Literal Restrictions
-
- Literal restrictions are the simplest form of restrictions
- and evaluate a field against a specified literal; numeric, date,
- string or boolean.
-
-
- literalRestriction
-
-
-
-
-
-
-
-
- Literal Restrictions using the '==' operator, provide for
- faster execution as we can index using hashing to improve
- performance.
-
-
- Numeric
-
- All standard Java numeric primitives are supported.
-
-
- Numeric Literal Restriction
-
- Cheese( quantity == 5 )
-
-
-
-
- Date
-
- The date format "dd-mmm-yyyy" is supported by default. You
- can customize this by providing an alternative date format mask
- as a System property ("drools.dateformat" is the name of the
- property). If more control is required, use the inline-eval
- constraint.
-
-
- Date Literal Restriction
-
- Cheese( bestBefore < "27-Oct-2007" )
-
-
-
-
- String
-
- Any valid Java String is allowed.
-
-
- String Literal Restriction
-
- Cheese( type == "stilton" )
-
-
-
-
- Boolean
-
- Only true or false can be used; 0 and 1 are not
- recognized. A Boolean field alone (as in
- Cheese( smelly ) is not permitted.
-
-
- Boolean Literal Restriction
-
- Cheese( smelly == true )
-
-
-
-
- Qualified Identifier
-
- Enums can be used as well, both jdk1.4 and jdk5 style
- enums are supported. For the latter you must be executing on a
- jdk5 environment.
-
-
- Boolean Literal Restriction
-
- Cheese( smelly == SomeClass.TRUE )
-
-
-
-
-
- Bound Variable Restriction
-
-
- variableRestriction
-
-
-
-
-
-
-
-
-
- Variables can be bound to Facts and their Fields and then
- used in subsequent Field Constraints. A bound variable is called a
-
- declaration
- Declaration. Valid operators are determined by the
- type of the field being constrained; coercion will be attempted
- where possible. Bound Variable Restrictions using '==' operator,
- provide for very fast execution as we can index using hashing to
- improve performance.
-
-
- Bound Field using '==' operator
-
- Person( likes : favouriteCheese )
-Cheese( type == likes )
-
- 'likes' is our variable, our Declaration, that is bound to
- the favouriteCheese field for any matching Person instance and
- is used to constrain the type of Cheese in the following
- pattern. Any valid Java variable name can be used, and it may
- be prefixed with a '$', which you will often see used to help differentiate
- declarations from fields. The example below shows a declaration
- bound to the pattern's Object Type instance itself and used with
- a 'contains' operator. Note the optional use of '$'.
-
-
-
- Bound Fact using 'contains' operator
-
- $stilton : Cheese( type == "stilton" )
-Cheesery( cheeses contains $stilton )
-
-
-
-
- Return Value Restriction
-
-
- returnValueRestriction
-
-
-
-
-
-
-
-
- A
- Return Value
- Return Value restriction can use any valid Java
- primitive or object. Avoid using any Drools keywords as
- Declaration identifiers. Functions used in a Return Value
- Restriction must return time constant results. Previously bound
- declarations can be used in the expression.
-
-
- Return Value Restriction
-
- Person( girlAge : age, sex == "F" )
-Person( age == ( girlAge + 2) ), sex == 'M' )
-
-
-
-
-
-
- Compound Value Restriction
-
- The compound value restriction is used where there is more
- than one possible value, currently only the 'in' and 'not in'
- evaluators support this. The operator takes a parenthesis enclosed
- comma separated list of values, which can be a variable, literal,
- return value or qualified identifier. The 'in' and 'not in'
- evaluators are actually sugar and are rewritten as a multi
- restriction list of != and == restrictions.
-
-
- compoundValueRestriction
-
-
-
-
-
-
-
-
-
-
-
- Compound Restriction using 'in'
-
- Person( $cheese : favouriteCheese )
-Cheese( type in ( "stilton", "cheddar", $cheese )
-
-
-
-
-
- Multi Restriction
-
- Multi restriction allows you to place more than one
- restriction on a field using the '&&' or '||' restriction
- connectives. Grouping via parenthesis is also allowed; which adds a
- recursive nature to this restriction.
-
-
- multiRestriction
-
-
-
-
-
-
-
-
-
- restrictionGroup
-
-
-
-
-
-
-
-
-
-
-
- Multi Restriction
-
- Person( age > 30 && < 40 ) // simple multi restriction using a single &&
-Person( age ( (> 30 && < 40) || (> 20 && < 25) ) ) // more complex multi restriction using groupings of multi restrictions
-Person( age > 30 && < 40 || location == "london" ) // mixing muti restrictions with constraint connectives
-
-
-
-
-
- Inline Eval Constraints
-
-
- Inline Eval Expression
-
-
-
-
-
-
-
-
- An
- Predicate
- inline-eval constraint can use any valid dialect
- expression as long as it is evaluated to a primitive boolean - avoid
- using any Drools keywords as Declaration identifiers. The expression
- must be time constant. Any previously bound variable, from the current
- or previous pattern, can be used; autovivification is also used to
- auto-create field binding variables. When an identifier is found that
- is not a current variable the builder looks to see if the identifier
- is a field on the current object type, if it is, the field binding
- is auto-created as a variable of the same name. This is called
- autovivification of field variables inside of inline evals.
-
- This example will find all male-female pairs where the
- male is 2 years older than the female; the boyAge variable is
- auto-created by the autovivification process.
-
-
- Return Value operator
-
- Person( girlAge : age, sex = "F" )
-Person( eval( age == girlAge + 2 ), sex = 'M' )
-
-
-
-
-
- Nested Accessors
-
- Drools does allow for nested accessors in in the field
- constraints using the MVEL accessor graph notation. Field constraints
- involving nested accessors are actually re-written as an MVEL dialect
- inline-eval. Care should be taken when using nested accessors as the
- Working Memory is not aware of any of the nested values, and do not
- know when they change; they should be considered immutable while any
- of their parent references are inserted into the Working Memory. If
- you wish to modify a nested value you should remove the parent objects
- first and re-assert afterwards. If you only have a single parent at
- the root of the graph, when in the MVEL dialect, you can use the
- 'modify' keyword and its block setters to write the nested accessor
- assignments while retracting and inserting the the root parent object
- as required. Nested accessors can be used either side of the operator
- symbol.
-
-
- Nested Accessors
-
- $p : Person( )
-Pet( owner == $p, age > $p.children[0].age ) // Find a pet who is older than their owners first born child
-
- is internally rewriten as an MVEL inline eval:
-
- $p : Person( )
-Pet( owner == $p, eval( age > $p.children[0].age ) ) // Find a pet who is older than their owners first born child
-
-
- NOTE: nested accessors have a much greater performance cost
- than direct field access, so use them carefully.
-
-
-
-
- 'and'
-
- The 'and' Conditional Element is used to group together other
- Conditional Elements. The root element of the LHS is an implicit prefix
- And and doesn't need to be specified. Drools supports both prefix and
- infix; although prefix is the preferred option as grouping is implicit
- which avoids confusion.
-
-
- prefixAnd
-
-
-
-
-
-
-
-
-
-
-
- prefixAnd
-
- (and Cheese( cheeseType : type )
- Person( favouriteCheese == cheeseType ) )
-
-
-
-
- implicit root prefixAnd
-
- when
- Cheese( cheeseType : type )
- Person( favouriteCheese == cheeseType )
-
-
- Infix 'and' is supported along with explicit grouping with
- parenthesis, should it be needed. The '&&' symbol, as an
- alternative to 'and', is deprecated although it is still supported in
- the syntax for legacy support reasons.
-
-
- infixAnd
-
-
-
-
-
-
-
-
-
- infixAnd
-
- Cheese( cheeseType : type ) and Person( favouriteCheese == cheeseType ) //infixAnd
-(Cheese( cheeseType : type ) and (Person( favouriteCheese == cheeseType ) or Person( favouriteCheese == cheeseType ) ) //infixAnd with grouping
-
-
-
-
- 'or'
-
- The 'or' Conditional Element is used to group together other
- Conditional Elements. Drools supports both prefix and infix; although
- prefix is the preferred option as grouping is implicit which avoids
- confusion. The behavior of the 'or' Conditional Element is different
- than the '||' connective for constraints and restrictions in field
- constraints. The engine actually has no understanding of 'or'
- Conditional Elements, instead via a number of different logic
- transformations the rule is re-written as a number of subrules; the rule
- now has a single 'or' as the root node and a subrule per logical
- outcome. Each subrule can activate and fire like any normal rule, there
- is no special behavior or interactions between the subrules - this can
- be most confusing to new rule authors.
-
-
- prefixOr
-
-
-
-
-
-
-
-
-
- prefixOr
-
- (or Person( sex == "f", age > 60 )
- Person( sex == "m", age > 65 )
-
-
-
- Infix 'or' is supported along with explicit grouping with
- parenthesis, should it be needed. The '||' symbol, as an alternative to
- 'or', is deprecated although it is still supported in the syntax for
- legacy support reasons.
-
-
- infixOr
-
-
-
-
-
-
-
-
-
- infixOr
-
- Cheese( cheeseType : type ) or Person( favouriteCheese == cheeseType ) //infixOr
-(Cheese( cheeseType : type ) or (Person( favouriteCheese == cheeseType ) and Person( favouriteCheese == cheeseType ) ) //infixOr with grouping
-
-
- The 'or' Conditional Element also allows for optional pattern
- binding; which means each resulting subrule will bind its pattern to
- the pattern binding. Each pattern must be bound separately,
- using eponymous variables:
-
-
- or with binding
-
- (or pensioner : Person( sex == "f", age > 60 )
- pensioner : Person( sex == "m", age > 65 ) )
-
-
- The 'or' conditional element results in multiple rule generation,
- called sub rules, for each possible logically outcome. The example above
- would result in the internal generation of two rules. These two rules
- work independently within the Working Memory, which means both can
- match, activate and fire - there is no shortcutting.
-
- The best way to think of the OR conditional element is as a
- shortcut for generating two or more similar rules. When you think
- of it that
- way, it's clear that for a single rule there could be multiple
- activations if both sides of the OR conditional element are true.
-
-
-
- 'eval'
-
-
- eval
-
-
-
-
-
-
-
-
- Eval is essentially a catch all which allows any semantic code
- (that returns a primitive boolean) to be executed. This can refer to
- variables that were bound in the LHS of the rule, and functions in the
- rule package. Overuse of eval reduces the declarative-ness of your rules
- and can result in a poor performing engine. While 'evals' can be used
- anywhere in the Pattern the best practice is to add it as the last
- conditional element in the LHS of a rule.
-
- Evals cannot be indexed and thus are not as optimal as using Field
- Constraints. However this makes them ideal for being used when functions
- return values that change over time, which is not allowed within Field
- Constraints.
-
- For folks who are familiar with Drools 2.x lineage, the old Drools
- parameter and condition tags are equivalent to binding a variable to an
- appropriate type, and then using it in an eval node.
-
-
- eval
-
- p1 : Parameter()
-p2 : Parameter()
-eval( p1.getList().containsKey(p2.getItem()) )
-eval( isValid(p1, p2) ) //this is how you call a function in the LHS - a function called "isValid"
-
-
-
-
- 'not'
-
-
- not
-
-
-
-
-
-
-
-
-
- 'not' is first order logic's Non-Existential Quantifier and checks
- for the non existence of something in the Working Memory. Think of 'not'
- as meaning "there must be none of...".
-
- A 'not' statement must be followed by parentheses around the CEs
- that it applies to. In the simplest case of a single pattern (like
- below) you may optionally omit the parentheses.
-
-
- No Busses
-
- not Bus()
-
-
-
- No red Busses
-
- not Bus(color == "red") //brackets are optional for this simple pattern
-not ( Bus(color == "red", number == 42) ) //brackets are optional for this simple case
-not ( Bus(color == "red") and Bus(color == "blue")) // not with nested 'and' infix used here as only two patterns
- (but brackets are required).
-
-
-
-
- 'exists'
-
-
- exists
-
-
-
-
-
-
-
-
-
- 'exists' is first order logic's Existential Quantifier and checks
- for the existence of something in the Working Memory. Think of exist as
- meaning "at least one..". It is different from just having the Pattern
- on its own; which is more like saying "for each one of...". If you use
- exist with a Pattern, then the rule will only activate at most once,
- regardless
- of how much data there is in working memory that matches that
- condition. Since only the existence matters, no bindings will be
- established.
-
- An 'exists' statement must be followed by parentheses around the
- CEs that it applies to. In the simplest case of a single pattern (like
- below) you may omit the parentheses.
-
-
- At least one Bus
-
- exists Bus()
-
-
-
- At least one red Bus
-
- exists Bus(color == "red")
-exists ( Bus(color == "red", number == 42) ) // brackets are optional
-exists ( Bus(color == "red") and Bus(color == "blue")) // exists with nested 'and' infix used here as only two patterns
-
-
-
-
- 'forall'
-
-
- forall
-
-
-
-
-
-
-
-
-
- The forall Conditional Element
- completes the First Order Logic support in Drools. The forall Conditional Element will evaluate to true
- when all facts that match the first pattern match all the remaining
- patterns. Example:
-
- rule "All english buses are red"
-when
- forall( $bus : Bus( type == 'english')
- Bus( this == $bus, color = 'red' ) )
-then
- # all english buses are red
-end
-
-
- In the above rule, we "select" all Bus objects whose type is
- "english". Then, for each fact that matches this pattern we evaluate the
- following patterns and if they match, the forall CE will evaluate to
- true.
-
- To state that all facts of a given type in the working memory must
- match a set of constraints, forall can be written with a single pattern
- for simplicity. Example:
-
-
- Single Pattern Forall
-
- rule "All Buses are Red"
-when
- forall( Bus( color == 'red' ) )
-then
- # all asserted Bus facts are red
-end
-
-
-
- Her is another example of a multi-pattern forall:
-
- Multi-Pattern Forall
-
- rule "all employees have health and dental care programs"
-when
- forall( $emp : Employee()
- HealthCare( employee == $emp )
- DentalCare( employee == $emp )
- )
-then
- # all employees have health and dental care
-end
-
-
-
- Forall can be nested inside other CEs.
- For instance, forall can be used inside
- a not CE, but note that only single
- patterns have optional parentheses; therefore, with a nested forall parentheses
- must be used:
-
- Combining Forall with Not CE
-
- rule "not all employees have health and dental care"
-when
- not ( forall( $emp : Employee()
- HealthCare( employee == $emp )
- DentalCare( employee == $emp ) )
- )
-then
- # not all employees have health and dental care
-end
-
-
-
- As a side note, forall( p1 p2 p3...) is
- equivalent to writing:
-
- not(p1 and not(and p2 p3...))
-
- Also, it is important to note that forall is
- a scope delimiter, so it can use any previously bound
- variable, but no variable bound inside it will be available for use
- outside of it.
-
-
-
- From
-
-
- from
-
-
-
-
-
-
-
-
- The from Conditional Element
- allows users to specify a source for patterns to reason over. This
- allows the engine to reason over data not in the Working Memory. This
- could be a sub-field on a bound variable or the results of a method
- call. It is a powerful construction that allows out of the box
- integration with other application components and frameworks. One common
- example is the integration with data retrieved on-demand from databases
- using hibernate named queries.
-
- The expression used to define the object source is any expression
- that follows regular MVEL syntax. I.e., it allows you to easily use
- object property navigation, execute method calls and access maps and
- collections elements.
-
- Here is a simple example of reasoning and binding on another
- pattern sub-field:
-
- rule "validate zipcode"
-when
- Person( $personAddress : address )
- Address( zipcode == "23920W") from $personAddress
-then
- # zip code is ok
-end
-
-
- With all the flexibility from the new expressiveness in the Drools
- engine you can slice and dice this problem many ways. This is the same
- but shows how you can use a graph notation with the 'from':
-
- rule "validate zipcode"
-when
- $p : Person( )
- $a : Address( zipcode == "23920W") from $p.address
-then
- # zip code is ok
-end
-
-
- Previous examples were reasoning over a single pattern. The
- from CE also support object sources
- that return a collection of objects. In that case, from will iterate over all objects in the
- collection and try to match each of them individually. For instance, if
- we want a rule that applies 10% discount to each item in an order, we
- could do:
-
- rule "apply 10% discount to all items over US$ 100,00 in an order"
-when
- $order : Order()
- $item : OrderItem( value > 100 ) from $order.items
-then
- # apply discount to $item
-end
-
-
- The above example will cause the rule to fire once for each item
- whose value is greater than 100 for each given order.
-
- You must take caution, however, when using from, especially in conjunction with the
- lock-on-active rule attribute
- as it may produce unexpected results. Consider the example provided earlier, but
- now slightly modified as follows:
-
- rule "Assign people in North Carolina (NC) to sales region 1"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person( )
- $a : Address( state == "NC") from $p.address
-then
- modify ($p) {} #Assign person to sales region 1 in a modify block
-end
-
-rule "Apply a discount to people in the city of Raleigh"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person( )
- $a : Address( city == "Raleigh") from $p.address
-then
- modify ($p) {} #Apply discount to person in a modify block
-end
-
-
-
- In the above example, persons in Raleigh, NC should be assigned to sales region 1 and
- receive a discount; i.e., you would expect both rules to activate and fire. Instead you
- will find that only the second rule fires.
-
- If you were to turn on the audit log, you would also see that when the second rule fires,
- it deactivates the first rule. Since the rule attribute lock-on-active
- prevents a rule from creating new activations when a set of facts change, the first rule fails to
- reactivate. Though the set of facts have not changed, the use of
- from returns a new fact for all intents and purposes each time
- it is evaluated.
-
-
- First, it's important to review why you would use the above pattern. You may have
- many rules across different rule-flow groups. When rules modify working memory and other rules
- downstream of your RuleFlow (in different rule-flow groups) need to be reevaluated, the use of modify
- is critical. You don't, however, want other rules in the same rule-flow group to place
- activations on one another recursively. In this case, the no-loop
- attribute is ineffective, as it would only prevent a rule from activating itself recursively. Hence,
- you resort to lock-on-active.
-
-
-
- There are several ways to address this issue:
-
-
-
- Avoid the use of from when you can assert all facts into working memory
- or use nested object references in your constraint expressions (shown below)
-
-
- Place the variable assigned used in the modify block as the last sentence in your condition (LHS)
-
-
- Avoid the use of lock-on-active when you can
- explicitly manage how rules within the same rule-flow group place activations on one another
- (explained below)
-
-
-
- The preferred solution is to minimize use of from
- when you can assert all your facts into working memory directly. In the example above,
- both the Person and Address instance can be asserted into working memory. In this case, because
- the graph is fairly simple, an even easier solution is to modify your rules as follows:
-
-
- rule "Assign people in North Carolina (NC) to sales region 1"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person(address.state == "NC" )
-then
- modify ($p) {} #Assign person to sales region 1 in a modify block
-end
-
-rule "Apply a discount to people in the city of Raleigh"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person(address.city == "Raleigh" )
-then
- modify ($p) {} #Apply discount to person in a modify block
-end
-
-
- Now, you will find that both rules fire as expected. However, it is not
- always possible to access nested facts as above. Consider an example where a Person
- holds one or more Addresses and you wish to use an existential quantifier to
- match people with at least one address that meets certain conditions.
- In this case, you would have to resort to
- the use of from to reason over the collection.
-
-
- There are several ways to use from
- to achieve this and not all of them exhibit an issue
- with the use of lock-on-active. For example,
- the following use of from causes both rules to fire as expected:
-
-
- rule "Assign people in North Carolina (NC) to sales region 1"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person($addresses : addresses)
- exists (Address(state == "NC") from $addresses)
-then
- modify ($p) {} #Assign person to sales region 1 in a modify block
-end
-
-rule "Apply a discount to people in the city of Raleigh"
-ruleflow-group "test"
-lock-on-active true
-when
- $p : Person($addresses : addresses)
- exists (Address(city == "Raleigh") from $addresses)
-then
- modify ($p) {} #Apply discount to person in a modify block
-end
-
-
- However, the following slightly different approach does exhibit the problem:
-
- rule "Assign people in North Carolina (NC) to sales region 1"
-ruleflow-group "test"
-lock-on-active true
-when
- $assessment : Assessment()
- $p : Person()
- $addresses : List() from $p.addresses
- exists (Address( state == "NC") from $addresses)
-then
- modify ($assessment) {} #Modify assessment in a modify block
-end
-
-rule "Apply a discount to people in the city of Raleigh"
-ruleflow-group "test"
-lock-on-active true
-when
- $assessment : Assessment()
- $p : Person()
- $addresses : List() from $p.addresses
- exists (Address( city == "Raleigh") from $addresses)
-then
- modify ($assessment) {} #Modify assessment in a modify block
-end
-
- In the above example, the $addresses variable is returned from the
- use of from. The example also introduces
- a new object, assessment, to highlight one possible solution in this case.
- If the $assessment variable assigned in the condition (LHS) is moved to the last condition
- in each rule, both rules fire as expected.
-
-
-
- Though the above examples demonstrate how to combine the use of from
- with lock-on-active where no loss of rule activations occurs,
- they carry the drawback of placing a dependency on the order of conditions on the LHS. In addition,
- the solutions present greater complexity for the rule author in terms of keeping track of
- which conditions may create issues.
-
-
- A better alternative is to
- assert more facts into working memory. In this case, a person's addresses
- may be asserted into working memory and the use of from
- would not be necessary.
-
- There are cases, however, where asserting all data into working memory is not
- practical and we need to find other solutions. Another option is to reevaluate the
- need for lock-on-active.
- An alternative to lock-on-active is to
- directly manage how rules within the same rule-flow group activate one another
- by including conditions in each rule that prevent rules from activating each other recursively
- when working memory is modified. For example, in the case above where a
- discount is applied to citizens of Raleigh, a condition may be added to the rule
- that checks whether the discount has already been applied. If so, the rule does not
- activate.
-
-
-
-
- 'collect'
-
-
- collect
-
-
-
-
-
-
-
-
-
- The collect Conditional Element
- allows rules to reason over collection of objects collected from the
- given source or from the working memory. In first oder logic terms this
- is Cardinality Quantifier. A simple example:
-
- import java.util.ArrayList
-
-rule "Raise priority if system has more than 3 pending alarms"
-when
- $system : System()
- $alarms : ArrayList( size >= 3 )
- from collect( Alarm( system == $system, status == 'pending' ) )
-then
- # Raise priority, because system $system has
- # 3 or more alarms pending. The pending alarms
- # are $alarms.
-end
-
-
- In the above example, the rule will look for all pending alarms in
- the working memory for each given system and group them in ArrayLists.
- If 3 or more alarms are found for a given system, the rule will
- fire.
-
- The collect CE result pattern can
- be any concrete class that implements tha java.util.Collection interface
- and provides a default no-arg public constructor. I.e., you can use
- default Java collections like ArrayList, LinkedList, HashSet, etc, or
- your own class, as long as it implements the java.util.Collection
- interface and provide a default no-arg public constructor.
-
- Both source and result patterns can be constrained as any other
- pattern.
-
- Variables bound before the collect CE are in the scope of both source and
- result patterns and as so, you can use them to constrain both your
- source and result patterns. Although, the collect( ...
- ) is a scope delimiter for bindings, meaning that any binding
- made inside of it, is not available for use outside of it.
-
- Collect accepts nested from
- elements, so the following example is a valid use of collect:
-
- import java.util.LinkedList;
-
-rule "Send a message to all mothers"
-when
- $town : Town( name == 'Paris' )
- $mothers : LinkedList()
- from collect( Person( gender == 'F', children > 0 )
- from $town.getPeople()
- )
-then
- # send a message to all mothers
-end
-
-
-
-
- 'accumulate'
-
-
- accumulate
-
-
-
-
-
-
-
-
- The accumulate Conditional
- Element is a more flexible and powerful form of collect Conditional Element, in the sense that it
- can be used to do what collect CE does
- and also do things that collect CE is
- not capable to do. Basically what it does is it allows a rule to iterate
- over a collection of objects, executing custom actions for each of the
- elements, and at the end return a result object.
-
- The general syntax of the accumulate CE is:
-
- <result pattern> from accumulate( <source pattern>,
- init( <init code> ),
- action( <action code> ),
- reverse( <reverse code> ),
- result( <result expression> ) )
-
-
- The meaning of each of the elements is the following:
-
-
-
- <source pattern>: the
- source pattern is a regular pattern that the engine will try to
- match against each of the source objects.
-
-
-
- <init code>: this is a
- semantic block of code in the selected dialect that will be executed
- once for each tuple, before iterating over the source
- objects.
-
-
-
- <action code>: this is
- a semantic block of code in the selected dialect that will be
- executed for each of the source objects.
-
-
-
- <reverse code>: this is
- an optional semantic block of code in the selected dialect that if
- present will be executed for each source object that no longer
- matches the source pattern. The objective of this code block is to
- "undo" any calculation done in the <action code> block, so
- that the engine can do decremental calculation when a source object
- is modified or retracted, hugely improving performance of these
- operations.
-
-
-
- <result expression>:
- this is a semantic expression in the selected dialect that is
- executed after all source objects are iterated.
-
-
-
- <result pattern>: this
- is a regular pattern that the engine tries to match against the
- object returned from the <result expression>. If it matches,
- the accumulate conditional element
- evaluates to true and the engine
- proceeds with the evaluation of the next CE in the rule. If it does
- not matches, the accumulate CE
- evaluates to false and the engine
- stops evaluating CEs for that rule.
-
-
-
- It is easier to understand if we look at an example:
-
- rule "Apply 10% discount to orders over US$ 100,00"
-when
- $order : Order()
- $total : Number( doubleValue > 100 )
- from accumulate( OrderItem( order == $order, $value : value ),
- init( double total = 0; ),
- action( total += $value; ),
- reverse( total -= $value; ),
- result( total ) )
-then
- # apply discount to $order
-end
-
-
- In the above example, for each Order() in the working memory, the
- engine will execute the init code
- initializing the total variable to zero. Then it will iterate over all
- OrderItem() objects for that order, executing the action for each one (in the example, it will sum
- the value of all items into the total variable). After iterating over
- all OrderItem, it will return the value corresponding to the result expression (in the above example, the
- value of the total variable). Finally, the engine will try to match the
- result with the Number() pattern and if the double value is greater than
- 100, the rule will fire.
-
- The example used Java as the semantic dialect, and as such, note
- that the usage of ';' is mandatory in the init, action and reverse code
- blocks. The result is an expression and as such, it does not admit ';'.
- If the user uses any other dialect, he must comply to that dialect
- specific syntax.
-
- As mentioned before, the reverse
- code is optional, but it is strongly recommended that the
- user writes it in order to benefit from the improved
- performance on update and retracts.
-
- The accumulate CE can be used to
- execute any action on source objects. The following example instantiates
- and populates a custom object:
-
- rule "Accumulate using custom objects"
-when
- $person : Person( $likes : likes )
- $cheesery : Cheesery( totalAmount > 100 )
- from accumulate( $cheese : Cheese( type == $likes ),
- init( Cheesery cheesery = new Cheesery(); ),
- action( cheesery.addCheese( $cheese ); ),
- reverse( cheesery.removeCheese( $cheese ); ),
- result( cheesery ) );
-then
- // do something
-end
-
-
- Accumulate Functions
-
- The accumulate CE is a very powerful CE, but it gets real
- declarative and easy to use when using predefined functions that are
- known as Accumulate Functions. They work exactly like accumulate, but
- instead of explicitly writing custom code in every accumulate CE, the
- user can use predefined code for common operations.
-
- For instance, the rule to apply discount on orders written in
- the previous section, could be written in the following way, using
- Accumulate Functions:
-
- rule "Apply 10% discount to orders over US$ 100,00"
-when
- $order : Order()
- $total : Number( doubleValue > 100 )
- from accumulate( OrderItem( order == $order, $value : value ),
- sum( $value ) )
-then
- # apply discount to $order
-end
-
-
- In the above example, sum is an Accumulate Function and will sum
- the $value of all OrderItems and return the result.
-
- Drools 4.0 ships with the following built in accumulate
- functions:
-
-
-
- average
-
-
-
- min
-
-
-
- max
-
-
-
- count
-
-
-
- sum
-
-
-
- These common functions accept any expression as input. For
- instance, if someone wants to calculate the average profit on all
- items of an order, a rule could be written using the average
- function:
-
- rule "Average profit"
-when
- $order : Order()
- $profit : Number()
- from accumulate( OrderItem( order == $order, $cost : cost, $price : price )
- average( 1 - $cost / $price ) )
-then
- # average profit for $order is $profit
-end
-
-
- Accumulate Functions are all pluggable. That means that if
- needed, custom, domain specific functions can easily be added to the
- engine and rules can start to use them without any restrictions. To
- implement a new Accumulate Functions all one needs to do is to create
- a Java class that implements the
- org.drools.base.acumulators.AccumulateFunction interface and add a
- line to the configuration file or set a system property to let the
- engine know about the new function. As an example of an Accumulate
- Function implementation, the following is the implementation of the
- "average" function:
-
- /*
- * Copyright 2007 JBoss Inc
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * Created on Jun 21, 2007
- */
-package org.drools.base.accumulators;
-
-
-/**
- * An implementation of an accumulator capable of calculating average values
- *
- * @author etirelli
- *
- */
-public class AverageAccumulateFunction implements AccumulateFunction {
-
- protected static class AverageData {
- public int count = 0;
- public double total = 0;
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#createContext()
- */
- public Object createContext() {
- return new AverageData();
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#init(java.lang.Object)
- */
- public void init(Object context) throws Exception {
- AverageData data = (AverageData) context;
- data.count = 0;
- data.total = 0;
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#accumulate(java.lang.Object, java.lang.Object)
- */
- public void accumulate(Object context,
- Object value) {
- AverageData data = (AverageData) context;
- data.count++;
- data.total += ((Number) value).doubleValue();
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#reverse(java.lang.Object, java.lang.Object)
- */
- public void reverse(Object context,
- Object value) throws Exception {
- AverageData data = (AverageData) context;
- data.count--;
- data.total -= ((Number) value).doubleValue();
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#getResult(java.lang.Object)
- */
- public Object getResult(Object context) throws Exception {
- AverageData data = (AverageData) context;
- return new Double( data.count == 0 ? 0 : data.total / data.count );
- }
-
- /* (non-Javadoc)
- * @see org.drools.base.accumulators.AccumulateFunction#supportsReverse()
- */
- public boolean supportsReverse() {
- return true;
- }
-
-}
-
-
- The code for the function is very simple, as we could expect, as
- all the "dirty" integration work is done by the engine. Finally, to
- plug the function into the engine, we added it to the configuration
- file:
-
- drools.accumulate.function.average = org.drools.base.accumulators.AverageAccumulateFunction
-
-
- Where "drools.accumulate.function." is a prefix that must always
- be used, "average" is how the function will be used in the rule file,
- and "org.drools.base.accumulators.AverageAccumulateFunction" is the
- fully qualified name of the class that implements the function
- behavior.
-
-
-
-
-
- The Right Hand Side (then)
-
- The Right Hand Side (RHS) is a common name for the consequence or
- action part of the rule; this part should contain a list of actions to be
- executed. It is bad practice to use imperative or conditional code in the
- RHS of a rule; as a rule should be atomic in nature - "when this, then do
- this", not "when this, maybe do this". The RHS part of a rule should also
- be kept small, thus keeping it declarative and readable. If you find you
- need imperative and/or conditional code in the RHS, then maybe you should
- be breaking that rule down into multiple rules. The main purpose of the
- RHS is to insert, retractor modify working memory data. To assist with
- that there are a few convenience methods you can use to modify working
- memory; without having to first reference a working memory
- instance.
-
- "update(object, handle);" will tell the engine that an object has
- changed (one that has been bound to something on the LHS) and rules may
- need to be reconsidered.
-
- "update(object);" can also be used, here the KnowledgeHelper will
- lookup the facthandle for you, via an identity check, for the passed object.
-
- "insert(new Something());" will place a new object of your creation
- in working memory.
-
- "insertLogical(new Something());" is similar to insert, but the
- object will be automatically retracted when there are no more facts to
- support the truth of the currently firing rule.
-
- "retract(handle);" removes an object from working memory.
-
- These convenience methods are basically macros that provide short
- cuts to the KnowledgeHelper instance (refer to the KnowledgeHelper
- interface for more advanced operations). The KnowledgeHelper interface is
- made available to the RHS code block as a variable called "drools". If you
- provide "Property Change Listeners" to your Java beans that you are
- inserting into the engine, you can avoid the need to call "update" when
- the object changes.
-
-
-
- A note on auto boxing/unboxing and primitive types
-
- Drools attempts to preserve numbers in their primitive or object
- wrapper form, so a variable bound to an int primitive when used in a code
- block or expression will no longer need manual unboxing; unlike Drools 3.0
- where all primitives was autoboxed, requiring manual unboxing. A variable
- bound to an object wrapper will remain as an object; the existing jdk1.5
- and jdk5 rules to handling auto boxing/unboxing apply in this case. When
- evaluating field constraints the system attempts to coerce one of the
- values into a comparable format; so a primitive is comparable to an object
- wrapper.
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-TypeDeclaration.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-TypeDeclaration.xml
deleted file mode 100755
index 44aef806ae..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-TypeDeclaration.xml
+++ /dev/null
@@ -1,332 +0,0 @@
-
-
- Type Declaration
-
-
- (updated to Drools 5.0)
-
-
-
- FIXME: add syntax diagram for declare
-
-
- Type declarations have two main goals in the rules engine: to allow the
- declaration of new types, and to allow the declaration of metadata for
- types.
-
-
-
- Declaring new types: Drools works
- out of the box with plain POJOs as facts. Although, sometimes the users
- may want to define the model directly to the rules engine, without
- worrying to create their models in a lower level language like Java.
- At other times, there is a domain model already built, but eventually the
- user wants or needs to complement this model with additional entities
- that are used mainly during the reasoning process.
-
-
-
- Declaring metadata: facts may
- have meta information associated to them. Examples of meta information
- include any kind of data that is not represented by the fact attributes
- and are consistent among all instances of that fact type. This meta
- information may be queried at runtime by the engine and used in the
- reasoning process.
-
-
-
-
- Declaring New Types
-
- To declare a new type, all you need to do is use the keyword
- declare, followed by the list of fields
- and the keyword end.
-
-
- declaring a new fact type: Address
-
- declare Address
- number : int
- streetName : String
- city : String
-end
-
-
-
- The previous example declares a new fact type called
- Address. This fact type will have 3 attributes:
- number, streetName and
- city. Each attribute has a type that can be any valid
- Java type, including any other class created by the user or even other
- fact types previously declared.
-
- For instance, we may want to declare another fact type
- Person:
-
-
- declaring a new fact type: Person
-
- declare Person
- name : String
- dateOfBirth : java.util.Date
- address : Address
-end
-
-
- As we can see on the previous example,
- dateOfBirth is of type java.util.Date,
- from the Java API, while address is of the previously
- defined fact type Address.
-
- You may avoid having to write the fully qualified name of a class
- every time you write it by using the import clause, previously discussed.
-
-
- avoiding the need to use fully qualified class names by using
- import
-
- import java.util.Date
-
-declare Person
- name : String
- dateOfBirth : Date
- address : Address
-end
-
-
- When you declare a new fact type, Drools will, at compile time,
- generate bytecode implementing a POJO that represents the fact type. The generated Java
- class will be a one-to-one Java Bean mapping of the type definition. So,
- for the previous example, the generated Java class would be:
-
-
- generated Java class for the previous Person fact type
- declaration
-
- public class Person implements Serializable {
- private String name;
- private java.util.Date dateOfBirth;
- private Address address;
-
- // getters and setters
- // equals/hashCode
- // toString
-}
-
-
- Since it is a simple POJO, the generated class can be used
- transparently in the rules, like any other fact.
-
-
- using the declared types in rules
-
- rule "Using a declared Type"
-when
- $p : Person( name == "Bob" )
-then
- System.out.println( "The name of the person is "+ )
- // lets insert Mark, that is Bob's mate
- Person mark = new Person();
- mark.setName("Mark");
- insert( mark );
-end
-
-
-
-
-
- Declaring Metadata
-
- Metadata may be assigned to several different constructions in
- Drools, like fact types, fact attributes and rules. Drools uses the
- @ symbol to introduce metadata, and it
- always uses the form:
-
- @matadata_key( metadata_value )
-
- The parenthesis and the metadata_value are optional.
-
- For instance, if you want to declare a metadata attribute like
- author, whose value is Bob, you
- could simply write:
-
-
- declaring an arbitrary metadata attribute
-
- @author( Bob )
-
-
- Drools allows the declaration of any arbitrary metadata attribute,
- but some will have special meaning to the engine, while others are simply
- available for querying at runtime. Drools allows the declaration of
- metadata both for fact types and for fact attributes. Any metadata that is
- declared before the fields of a fact type are assigned to the fact type,
- while metadata declared after an attribute are assigned to the attribute
- in particular.
-
-
- declaring metadata attributes for fact types and
- attributes
-
- import java.util.Date
-
-declare Person
- @author( Bob )
- @dateOfCreation( 01-Feb-2009 )
-
- name : String @key @maxLength( 30 )
- dateOfBirth : Date
- address : Address
-end
-
-
- In the previous example, there are two metadata declared for the
- fact type (@author and
- @dateOfCreation), and two more defined for the name
- attribute (@key and @maxLength).
- Please note that the @key metadata has no value, and
- so the parenthesis and the value were omitted.
-
-
-
- Declaring Metadata for Existing Types
-
- Drools allows the declaration of metadata attributes for existing
- types in the same way as when declaring metadata attributes for new fact
- types. The only difference is that there are no fields in that
- declaration.
-
- For instance, if there is a class org.drools.examples.Person, and
- one wants to declare metadata for it, just write the following code:
-
-
- declaring metadata for an existing type
-
- import org.drools.examples.Person
-
-declare Person
- @author( Bob )
- @dateOfCreation( 01-Feb-2009 )
-end
-
-
-
- Instead of using the import, it is also possible to reference the
- class by its fully qualified name, but since the class will also be
- referenced in the rules, usually it is shorter to add the import and use
- the short class name everywhere.
-
-
- declaring metadata using the fully qualified class name
-
- declare org.drools.examples.Person
- @author( Bob )
- @dateOfCreation( 01-Feb-2009 )
-end
-
-
-
-
- Accessing Declared Types from the Application Code
-
- Declared types are usually used inside rules files, while Java
- models are used when sharing the model between rules and applications.
- Although, sometimes, the application may need to access and handle facts
- from the declared types, specially when the application is wrapping the
- rules engine and providing higher level, domain specific, user interfaces
- for rules management.
-
- In such cases, the generated classes can be handled as usual with
- the Java Reflection APIs, but as we know, that usually requires a lot of
- work for small results. This way, Drools provides a simplified API for the
- most common fact handling the application may want to do.
-
- The first important thing to realize is that a declared fact will
- belong to the package where it was declared. So, for instance, in the
- example below, Person will belong to the
- org.drools.examples package, and so the generated
- class fully qualified name will be:
- org.drools.examples.Person.
-
-
- declaring a type in the org.drools.examples package
-
- package org.drools.examples
-
-import java.util.Date
-
-declare Person
- name : String
- dateOfBirth : Date
- address : Address
-end
-
-
- Declared types, as discussed previously, are generated at knowledge
- base compilation time, i.e., the application will only have access to them
- at application run time. As so, these classes are not available for direct
- reference from the application.
-
- Drools then provides an interface through which the users can handle
- declared types from the application code:
- org.drools.definition.type.FactType. Through this interface, the user can
- instantiate, read and write fields in the declared fact types.
-
-
- handling declared fact types through the API
-
- // get a reference to a knowledge base with a declared type:
-KnowledgeBase kbase = ...
-
-// get the declared FactType
-FactType personType = kbase.getFactType( "org.drools.examples",
- "Person" );
-
-// handle the type as necessary:
-// create instances:
-Object bob = personType.newInstance();
-
-// set attributes values
-personType.set( bob,
- "name",
- "Bob" );
-personType.set( bob,
- "age",
- 42 );
-
-// insert fact into a session
-StatefulKnowledgeSession ksession = ...
-ksession.insert( bob );
-ksession.fireAllRules();
-
-// read attributes
-String name = personType.get( bob, "name" );
-int age = personType.get( bob, "age" );
-
-
-
-
- The API also includes other helpful methods, like setting all the
- attributes at once, reading values from a Map, or read all attributes at
- once, populating a Map.
-
- Although the API is similar to Java reflection (yet much simpler to
- use), it does not use reflection underneath, relying in much more
- performant bytecode generated accessors.
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-XML.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-XML.xml
deleted file mode 100755
index 5f042bdc81..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/Obsolete-Chapter-Rule_Language/Section-XML.xml
+++ /dev/null
@@ -1,333 +0,0 @@
-
-
- XML Rule Language
-
- As an option, Drools also supports a "native"
- XML
- 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.
-
-
- When to use XML
-
- 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.
-
- If you do want to edit XML by hand, use a good schema aware editor
- that provides nice hierarchical views of the XML, ideally visually
- (commercial tools like XMLSpy, Oxygen etc are good, but cost money, but
- then so do headache tablets).
-
- Other scenarios 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.
-
- 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).
-
-
-
- The XML format
-
- 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.
-
-
- A rule in XML
- XML Rule
-
-
- <?xml version="1.0" encoding="UTF-8"?>
-
-<package name="com.sample"
- xmlns="http://drools.org/drools-4.0"
- xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
- xs:schemaLocation="http://drools.org/drools-4.0 drools-4.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="simple_rule">
-<rule-attribute name="salience" value="10" />
-<rule-attribute name="no-loop" value="true" />
-<rule-attribute name="agenda-group" value="agenda-group" />
-<rule-attribute name="activation-group" value="activation-group" />
-
-<lhs>
- <pattern identifier="foo2" object-type="Bar" >
- <or-constraint-connective>
- <and-constraint-connective>
- <field-constraint field-name="a">
- <or-restriction-connective>
- <and-restriction-connective>
- <literal-restriction evaluator=">" value="60" />
- <literal-restriction evaluator="<" value="70" />
- </and-restriction-connective>
- <and-restriction-connective>
- <literal-restriction evaluator="<" value="50" />
- <literal-restriction evaluator=">" value="55" />
- </and-restriction-connective>
- </or-restriction-connective>
- </field-constraint>
-
- <field-constraint field-name="a3">
- <literal-restriction evaluator="==" value="black" />
- </field-constraint>
- </and-constraint-connective>
-
- <and-constraint-connective>
- <field-constraint field-name="a">
- <literal-restriction evaluator="==" value="40" />
- </field-constraint>
-
- <field-constraint field-name="a3">
- <literal-restriction evaluator="==" value="pink" />
- </field-constraint>
- </and-constraint-connective>
-
- <and-constraint-connective>
- <field-constraint field-name="a">
- <literal-restriction evaluator="==" value="12"/>
- </field-constraint>
-
- <field-constraint field-name="a3">
- <or-restriction-connective>
- <literal-restriction evaluator="==" value="yellow"/>
- <literal-restriction evaluator="==" value="blue" />
- </or-restriction-connective>
- </field-constraint>
- </and-constraint-connective>
- </or-constraint-connective>
- </pattern>
-
- <not>
- <pattern object-type="Person">
- <field-constraint field-name="likes">
- <variable-restriction evaluator="==" identifier="type"/>
- </field-constraint>
- </pattern>
-
- <exists>
- <pattern object-type="Person">
- <field-constraint field-name="likes">
- <variable-restriction evaluator="==" identifier="type"/>
- </field-constraint>
- </pattern>
- </exists>
- </not>
-
- <or-conditional-element>
- <pattern identifier="foo3" object-type="Bar" >
- <field-constraint field-name="a">
- <or-restriction-connective>
- <literal-restriction evaluator="==" value="3" />
- <literal-restriction evaluator="==" value="4" />
- </or-restriction-connective>
- </field-constraint>
- <field-constraint field-name="a3">
- <literal-restriction evaluator="==" value="hello" />
- </field-constraint>
- <field-constraint field-name="a4">
- <literal-restriction evaluator="==" value="null" />
- </field-constraint>
- </pattern>
-
- <pattern identifier="foo4" object-type="Bar" >
- <field-binding field-name="a" identifier="a4" />
- <field-constraint field-name="a">
- <literal-restriction evaluator="!=" value="4" />
- <literal-restriction evaluator="!=" value="5" />
- </field-constraint>
- </pattern>
- </or-conditional-element>
-
- <pattern identifier="foo5" object-type="Bar" >
- <field-constraint field-name="b">
- <or-restriction-connective>
- <return-value-restriction evaluator="==" >a4 + 1</return-value-restriction>
- <variable-restriction evaluator=">" identifier="a4" />
- <qualified-identifier-restriction evaluator="==">
- org.drools.Bar.BAR_ENUM_VALUE
- </qualified-identifier-restriction>
- </or-restriction-connective>
- </field-constraint>
- </pattern>
-
- <pattern identifier="foo6" object-type="Bar" >
- <field-binding field-name="a" identifier="a4" />
- <field-constraint field-name="b">
- <literal-restriction evaluator="==" value="6" />
- </field-constraint>
- </pattern>
- </lhs>
- <rhs>
- if ( a == b ) {
- assert( foo3 );
- } else {
- retract( foo4 );
- }
- System.out.println( a4 );
- </rhs>
-</rule>
-
-</package>
-
-
-
-
- In the preceding XML text you will see the typical XML
- element, the package declaration, imports, globals, functions,
- and the rule itself. Most of the elements are self explanatory
- if you have some understanding of the Drools features.
-
- The import elements import the types you wish to
- use in the rule.
-
- The global elements define global objects that can
- be referred to in the rules.
-
- The function contains a function declaration, for
- a function to be used in the rules. You have to specify a return type,
- a unique name and parameters, in the body goes a snippet of code.
-
- The rule is discussed below.
-
-
- Detail of rule element
-
- <rule name="simple_rule">
-<rule-attribute name="salience" value="10" />
-<rule-attribute name="no-loop" value="true" />
-<rule-attribute name="agenda-group" value="agenda-group" />
-<rule-attribute name="activation-group" value="activation-group" />
-
-<lhs>
- <pattern identifier="cheese" object-type="Cheese">
- <from>
- <accumulate>
- <pattern object-type="Person"></pattern>
- <init>
- int total = 0;
- </init>
- <action>
- total += $cheese.getPrice();
- </action>
- <result>
- new Integer( total ) );
- </result>
- </accumulate>
- </from>
- </pattern>
-
- <pattern identifier="max" object-type="Number">
- <from>
- <accumulate>
- <pattern identifier="cheese" object-type="Cheese"></pattern>
- <external-function evaluator="max" expression="$price"/>
- </accumulate>
- </from>
- </pattern>
-</lhs>
-<rhs>
- list1.add( $cheese );
-</rhs>
-</rule>
-
-
-
- In the above detail of the rule we see that the rule has 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 as it contains nested elements for conditional elements,
- constraints and restrictions.
-
-
-
-
- A key element of the LHS is the Pattern element. This allows you to
- specify a type (class) and perhaps bind a variable to an instance of that
- class. Nested under the pattern object are constraints and restrictions
- that have to be met. The Predicate and Return Value constraints
- allow Java expressions to be embedded.
-
- That leaves the conditional elements, not, exists, and, or etc. They
- work like their DRL counterparts. Elements that are nested under and an
- "and" element are logically "anded" together. Likewise with "or" (and you
- can nest things further). "Exists" and "Not" work around patterns, to check
- for the existence or nonexistence of a fact meeting the pattern's
- constraints.
-
- The Eval element allows the execution of a valid snippet of Java
- code - as long as it evaluates to a boolean (do not end it with a
- semi-colon, as it is just a fragment) - this can include calling a
- function. The Eval is less efficient than the columns, as the rule engine
- has to evaluate it each time, but it is a "catch all" feature for when you
- can express what you need to do with Column constraints.
-
-
-
- Legacy Drools 2.x XML rule format
- The Drools 2.x legacy XML format is no longer supported by Drools XML parser
-
-
-
- Automatic transforming between formats (XML and DRL)
-
- Drools comes with some utility classes to transform between formats.
- This works by parsing the rules from the source format into the AST, and
- then "dumping" out to the appropriate target format. This allows you, for
- example, to write rules in DRL, and when needed, export to XML if
- necessary at some point in the future.
-
- The classes to look at if you need to do this are: XmlDumper - for exporting XML.
-DrlDumper - for exporting DRL.
-DrlParser - reading DRL.
-XmlPackageReader - reading XML.
- Using combinations of the above, you can convert between any
- format (including round trip). Note that DSLs will not be preserved (from
- DRLs that are using a DSL) - but they will be able to be converted.
-
-Feel free to make use of XSLT to provide all sorts of possibilities
- for XML, XSLT and its ilk are what make XML powerful.
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/PongExample/pong.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/PongExample/pong.png
new file mode 100644
index 0000000000..2cc9bd32b5
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/PongExample/pong.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku1.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku1.png
index 142dc7d1ab..0e199abab2 100755
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku1.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku1.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku2.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku2.png
index 5396889551..80ec54254c 100755
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku2.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku2.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku3.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku3.png
index 99e61d4fe6..88a38de3e6 100755
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku3.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku3.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku4.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku4.png
index 9f3f6b0946..9278628313 100755
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku4.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku4.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku5.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku5.png
index 85f1274823..fb4b748971 100755
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku5.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku5.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku6.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku6.png
deleted file mode 100755
index bfb4044b0b..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku6.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku7.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku7.png
deleted file mode 100755
index 7135cc6065..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku7.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku8.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku8.png
deleted file mode 100755
index 0aad3ba331..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/SudokuExample/sudoku8.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/TextAdventureExample/textadventure.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/TextAdventureExample/textadventure.png
new file mode 100644
index 0000000000..a5b59cfd42
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/TextAdventureExample/textadventure.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus1.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus1.png
new file mode 100644
index 0000000000..ec2ec6368e
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus1.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus2.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus2.png
new file mode 100644
index 0000000000..ccd0ba3701
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus2.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus3.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus3.png
new file mode 100644
index 0000000000..82b40c9306
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus3.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus4.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus4.png
new file mode 100644
index 0000000000..917a318e44
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus4.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus5.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus5.png
new file mode 100644
index 0000000000..05b87fe3d7
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Examples/WumpusWorldExample/wumpus5.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/all.jpg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/all.jpg
deleted file mode 100755
index 3666f0dc12..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/all.jpg and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/all.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/all.png
new file mode 100644
index 0000000000..635918c753
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/all.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-add.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-add.png
new file mode 100644
index 0000000000..4d27399648
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-add.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-add2.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-add2.png
new file mode 100644
index 0000000000..bda5d0551e
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-add2.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-newproject.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-newproject.png
new file mode 100644
index 0000000000..4eaa731320
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-newproject.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-project.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-project.png
new file mode 100644
index 0000000000..2b565d6f08
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes-project.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes.png
new file mode 100644
index 0000000000..4be9ed9425
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes2.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes2.png
new file mode 100644
index 0000000000..ec9a3efb59
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes2.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes3.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes3.png
new file mode 100644
index 0000000000..5bd15fbee2
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/drools-runtimes3.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project1.jpg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project1.jpg
deleted file mode 100755
index 97c0b692b2..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project1.jpg and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project1.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project1.png
new file mode 100644
index 0000000000..aeb6fb62fd
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project1.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project2.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project2.png
old mode 100755
new mode 100644
index 0e908368a4..318ea574eb
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project2.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/new_project2.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/preferences.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/preferences.png
new file mode 100644
index 0000000000..283e5694f0
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/preferences.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/wizards.jpg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/wizards.jpg
deleted file mode 100755
index 6efba7d4a3..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/wizards.jpg and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/wizards.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/wizards.png
new file mode 100644
index 0000000000..8f98f7fdd6
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-IDE/wizards.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Introduction/book_recommendations.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Introduction/book_recommendations.png
new file mode 100644
index 0000000000..345bcb94fc
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Introduction/book_recommendations.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Introduction/drools_book_recommendations.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Introduction/drools_book_recommendations.png
new file mode 100644
index 0000000000..b7ff4f783b
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Introduction/drools_book_recommendations.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Introduction/expertsytem_history.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Introduction/expertsytem_history.png
new file mode 100644
index 0000000000..8bf9e31baa
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Introduction/expertsytem_history.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateAction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateAction.png
new file mode 100644
index 0000000000..25e681105b
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateAction.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateAction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateAction.svg
new file mode 100644
index 0000000000..68cceaaf67
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateAction.svg
@@ -0,0 +1,52 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateClause.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateClause.png
new file mode 100644
index 0000000000..e227793172
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateClause.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateClause.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateClause.svg
new file mode 100644
index 0000000000..7da5568e82
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateClause.svg
@@ -0,0 +1,64 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateFunction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateFunction.png
new file mode 100644
index 0000000000..e5068e1a34
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateFunction.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateFunction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateFunction.svg
new file mode 100644
index 0000000000..91efff7e04
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateFunction.svg
@@ -0,0 +1,51 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateInit.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateInit.png
new file mode 100644
index 0000000000..3535310e49
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateInit.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateInit.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateInit.svg
new file mode 100644
index 0000000000..5a82e4233b
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateInit.svg
@@ -0,0 +1,52 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateResult.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateResult.png
new file mode 100644
index 0000000000..dd4411b15c
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateResult.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateResult.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateResult.svg
new file mode 100644
index 0000000000..44a08e9353
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateResult.svg
@@ -0,0 +1,30 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateReverse.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateReverse.png
new file mode 100644
index 0000000000..7487d43507
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateReverse.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateReverse.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateReverse.svg
new file mode 100644
index 0000000000..22e6858224
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateReverse.svg
@@ -0,0 +1,52 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateSteps.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateSteps.png
new file mode 100644
index 0000000000..278bd59e77
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateSteps.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateSteps.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateSteps.svg
new file mode 100644
index 0000000000..bfe9b7ba30
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AccumulateSteps.svg
@@ -0,0 +1,44 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Accumulations.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Accumulations.png
new file mode 100644
index 0000000000..b4a1b3d849
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Accumulations.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Accumulations.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Accumulations.svg
new file mode 100644
index 0000000000..44d0d5a5d8
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Accumulations.svg
@@ -0,0 +1,39 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AdditiveExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AdditiveExpr.png
new file mode 100644
index 0000000000..deb5d6e317
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AdditiveExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AdditiveExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AdditiveExpr.svg
new file mode 100644
index 0000000000..217445d231
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AdditiveExpr.svg
@@ -0,0 +1,71 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Annotation.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Annotation.png
new file mode 100644
index 0000000000..5ff82d07e8
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Annotation.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Annotation.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Annotation.svg
new file mode 100644
index 0000000000..83d5f80046
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Annotation.svg
@@ -0,0 +1,81 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Arguments.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Arguments.png
new file mode 100644
index 0000000000..2414cb1745
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Arguments.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Arguments.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Arguments.svg
new file mode 100644
index 0000000000..ca7e435c97
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Arguments.svg
@@ -0,0 +1,34 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayCreatorRest.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayCreatorRest.png
new file mode 100644
index 0000000000..68796728a2
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayCreatorRest.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayCreatorRest.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayCreatorRest.svg
new file mode 100644
index 0000000000..2430bdca9b
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayCreatorRest.svg
@@ -0,0 +1,82 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayInitializer.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayInitializer.png
new file mode 100644
index 0000000000..95baa101a5
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayInitializer.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayInitializer.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayInitializer.svg
new file mode 100644
index 0000000000..acdc5bd202
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ArrayInitializer.svg
@@ -0,0 +1,69 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AssignmentOperator.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AssignmentOperator.png
new file mode 100644
index 0000000000..ec4e106681
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AssignmentOperator.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AssignmentOperator.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AssignmentOperator.svg
new file mode 100644
index 0000000000..9596638af6
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/AssignmentOperator.svg
@@ -0,0 +1,76 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BindingPattern.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BindingPattern.png
new file mode 100644
index 0000000000..94819e6f78
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BindingPattern.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BindingPattern.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BindingPattern.svg
new file mode 100644
index 0000000000..692d1e336f
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BindingPattern.svg
@@ -0,0 +1,73 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Block.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Block.png
new file mode 100644
index 0000000000..01d03e26fd
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Block.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Block.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Block.svg
new file mode 100644
index 0000000000..927be20407
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Block.svg
@@ -0,0 +1,32 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BooleanLiteral.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BooleanLiteral.png
new file mode 100644
index 0000000000..20aa92390b
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BooleanLiteral.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BooleanLiteral.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BooleanLiteral.svg
new file mode 100644
index 0000000000..edaa74330f
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/BooleanLiteral.svg
@@ -0,0 +1,30 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CompilationUnit.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CompilationUnit.png
new file mode 100644
index 0000000000..79d9865fff
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CompilationUnit.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CompilationUnit.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CompilationUnit.svg
new file mode 100644
index 0000000000..79d9622e81
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CompilationUnit.svg
@@ -0,0 +1,74 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalAnd.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalAnd.png
new file mode 100644
index 0000000000..cf26c2c0a7
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalAnd.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalAnd.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalAnd.svg
new file mode 100644
index 0000000000..6c18b0205e
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalAnd.svg
@@ -0,0 +1,31 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElement.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElement.png
new file mode 100644
index 0000000000..543e12eb92
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElement.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElement.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElement.svg
new file mode 100644
index 0000000000..5d9601643b
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElement.svg
@@ -0,0 +1,194 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementAccumulate.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementAccumulate.png
new file mode 100644
index 0000000000..c785ea88c7
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementAccumulate.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementAccumulate.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementAccumulate.svg
new file mode 100644
index 0000000000..fb7c5515de
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementAccumulate.svg
@@ -0,0 +1,50 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementEval.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementEval.png
new file mode 100644
index 0000000000..e86812b3a2
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementEval.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementEval.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementEval.svg
new file mode 100644
index 0000000000..c249e4547a
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementEval.svg
@@ -0,0 +1,30 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementExists.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementExists.png
new file mode 100644
index 0000000000..d67e5eab27
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementExists.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementExists.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementExists.svg
new file mode 100644
index 0000000000..0c493dfe18
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementExists.svg
@@ -0,0 +1,44 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementForall.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementForall.png
new file mode 100644
index 0000000000..d4caa900d6
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementForall.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementForall.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementForall.svg
new file mode 100644
index 0000000000..372929a060
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementForall.svg
@@ -0,0 +1,40 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementNot.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementNot.png
new file mode 100644
index 0000000000..f7860d9a6f
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementNot.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementNot.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementNot.svg
new file mode 100644
index 0000000000..6fcd52234a
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalElementNot.svg
@@ -0,0 +1,44 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalExpr.png
new file mode 100644
index 0000000000..0a6df0cfbb
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalExpr.svg
new file mode 100644
index 0000000000..78078199c6
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalExpr.svg
@@ -0,0 +1,46 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOr.png
new file mode 100644
index 0000000000..6d3019c2bf
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOr.svg
new file mode 100644
index 0000000000..073285cef2
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOr.svg
@@ -0,0 +1,31 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOrExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOrExpr.png
new file mode 100644
index 0000000000..336ae8baa5
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOrExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOrExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOrExpr.svg
new file mode 100644
index 0000000000..7f30c4346b
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ConditionalOrExpr.svg
@@ -0,0 +1,106 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Constraints.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Constraints.png
new file mode 100644
index 0000000000..85cc2accce
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Constraints.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Constraints.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Constraints.svg
new file mode 100644
index 0000000000..dd12da5ce9
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Constraints.svg
@@ -0,0 +1,72 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CreatedName.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CreatedName.png
new file mode 100644
index 0000000000..3a2ef3e24b
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CreatedName.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CreatedName.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CreatedName.svg
new file mode 100644
index 0000000000..e09e07f187
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/CreatedName.svg
@@ -0,0 +1,59 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Creator.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Creator.png
new file mode 100644
index 0000000000..520197c422
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Creator.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Creator.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Creator.svg
new file mode 100644
index 0000000000..e6a5e21e1d
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Creator.svg
@@ -0,0 +1,52 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Definition.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Definition.png
new file mode 100644
index 0000000000..b529d1c6c1
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Definition.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Definition.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Definition.svg
new file mode 100644
index 0000000000..6e5fd37adc
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Definition.svg
@@ -0,0 +1,65 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Digit.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Digit.png
new file mode 100644
index 0000000000..3747d310c6
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Digit.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Digit.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Digit.svg
new file mode 100644
index 0000000000..a34dd54936
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Digit.svg
@@ -0,0 +1,14 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocation.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocation.png
new file mode 100644
index 0000000000..57436fcfb4
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocation.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocation.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocation.svg
new file mode 100644
index 0000000000..1ab0226f33
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocation.svg
@@ -0,0 +1,22 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocationSuffix.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocationSuffix.png
new file mode 100644
index 0000000000..ed1a101998
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocationSuffix.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocationSuffix.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocationSuffix.svg
new file mode 100644
index 0000000000..16189dfc07
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExplicitGenericInvocationSuffix.svg
@@ -0,0 +1,42 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Exponent.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Exponent.png
new file mode 100644
index 0000000000..6dadfb002a
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Exponent.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Exponent.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Exponent.svg
new file mode 100644
index 0000000000..281aeb073c
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Exponent.svg
@@ -0,0 +1,72 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Expression.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Expression.png
new file mode 100644
index 0000000000..5d487589d8
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Expression.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Expression.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Expression.svg
new file mode 100644
index 0000000000..83deb95e0a
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Expression.svg
@@ -0,0 +1,38 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExpressionList.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExpressionList.png
new file mode 100644
index 0000000000..cb3657d31c
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExpressionList.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExpressionList.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExpressionList.svg
new file mode 100644
index 0000000000..2405da4ef3
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ExpressionList.svg
@@ -0,0 +1,29 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Field.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Field.png
new file mode 100644
index 0000000000..1146dc1a5d
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Field.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Field.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Field.svg
new file mode 100644
index 0000000000..2ea53890d1
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Field.svg
@@ -0,0 +1,74 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Fraction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Fraction.png
new file mode 100644
index 0000000000..3235db0253
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Fraction.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Fraction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Fraction.svg
new file mode 100644
index 0000000000..bf5176d548
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Fraction.svg
@@ -0,0 +1,72 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromAccumulateClause.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromAccumulateClause.png
new file mode 100644
index 0000000000..035a236e6d
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromAccumulateClause.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromAccumulateClause.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromAccumulateClause.svg
new file mode 100644
index 0000000000..0f14943e9c
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromAccumulateClause.svg
@@ -0,0 +1,22 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromClause.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromClause.png
new file mode 100644
index 0000000000..7218e1dfc7
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromClause.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromClause.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromClause.svg
new file mode 100644
index 0000000000..2f98f0a711
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromClause.svg
@@ -0,0 +1,22 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromCollectClause.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromCollectClause.png
new file mode 100644
index 0000000000..16738e25fb
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromCollectClause.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromCollectClause.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromCollectClause.svg
new file mode 100644
index 0000000000..9e8a2a220a
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FromCollectClause.svg
@@ -0,0 +1,36 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FunctionDefinition.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FunctionDefinition.png
new file mode 100644
index 0000000000..a08dfcbb67
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FunctionDefinition.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FunctionDefinition.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FunctionDefinition.svg
new file mode 100644
index 0000000000..bfb877fc65
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/FunctionDefinition.svg
@@ -0,0 +1,50 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/GlobalDefinition.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/GlobalDefinition.png
new file mode 100644
index 0000000000..2a2fcecdd8
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/GlobalDefinition.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/GlobalDefinition.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/GlobalDefinition.svg
new file mode 100644
index 0000000000..601e8e8a3b
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/GlobalDefinition.svg
@@ -0,0 +1,28 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IdentifierSuffix.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IdentifierSuffix.png
new file mode 100644
index 0000000000..3b6c5778be
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IdentifierSuffix.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IdentifierSuffix.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IdentifierSuffix.svg
new file mode 100644
index 0000000000..33dce6a73a
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IdentifierSuffix.svg
@@ -0,0 +1,77 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ImportDefinition.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ImportDefinition.png
new file mode 100644
index 0000000000..06e905868d
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ImportDefinition.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ImportDefinition.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ImportDefinition.svg
new file mode 100644
index 0000000000..d0acf1392d
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ImportDefinition.svg
@@ -0,0 +1,70 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InExpr.png
new file mode 100644
index 0000000000..290282b888
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InExpr.svg
new file mode 100644
index 0000000000..9bf64ca92a
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InExpr.svg
@@ -0,0 +1,65 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineListExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineListExpr.png
new file mode 100644
index 0000000000..10703bdea1
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineListExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineListExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineListExpr.svg
new file mode 100644
index 0000000000..415417136e
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineListExpr.svg
@@ -0,0 +1,34 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineMapExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineMapExpr.png
new file mode 100644
index 0000000000..2cfc2551fb
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineMapExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineMapExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineMapExpr.svg
new file mode 100644
index 0000000000..04610e6278
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InlineMapExpr.svg
@@ -0,0 +1,47 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InnerCreator.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InnerCreator.png
new file mode 100644
index 0000000000..e5847c5945
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InnerCreator.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InnerCreator.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InnerCreator.svg
new file mode 100644
index 0000000000..f026ccc6d8
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InnerCreator.svg
@@ -0,0 +1,22 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InstanceOfExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InstanceOfExpr.png
new file mode 100644
index 0000000000..9733dd361a
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InstanceOfExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InstanceOfExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InstanceOfExpr.svg
new file mode 100644
index 0000000000..56cd059fa5
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/InstanceOfExpr.svg
@@ -0,0 +1,38 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IntLiteral.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IntLiteral.png
new file mode 100644
index 0000000000..354ff13166
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IntLiteral.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IntLiteral.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IntLiteral.svg
new file mode 100644
index 0000000000..b40f5d8697
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/IntLiteral.svg
@@ -0,0 +1,99 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Literal.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Literal.png
new file mode 100644
index 0000000000..9d981a26b1
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Literal.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Literal.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Literal.svg
new file mode 100644
index 0000000000..5d97f53a23
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Literal.svg
@@ -0,0 +1,44 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ModifyStatement.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ModifyStatement.png
new file mode 100644
index 0000000000..35dcbf9aab
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ModifyStatement.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ModifyStatement.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ModifyStatement.svg
new file mode 100644
index 0000000000..a0c6a310a6
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ModifyStatement.svg
@@ -0,0 +1,65 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/NonWildcardTypeArguments.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/NonWildcardTypeArguments.png
new file mode 100644
index 0000000000..4438e12a0d
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/NonWildcardTypeArguments.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/NonWildcardTypeArguments.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/NonWildcardTypeArguments.svg
new file mode 100644
index 0000000000..5a30a713fb
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/NonWildcardTypeArguments.svg
@@ -0,0 +1,37 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OrRestriction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OrRestriction.png
new file mode 100644
index 0000000000..6eaec209fe
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OrRestriction.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OrRestriction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OrRestriction.svg
new file mode 100644
index 0000000000..0662137c4f
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OrRestriction.svg
@@ -0,0 +1,42 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OverClause.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OverClause.png
new file mode 100644
index 0000000000..e4a24a9e8c
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OverClause.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OverClause.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OverClause.svg
new file mode 100644
index 0000000000..b723545f69
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/OverClause.svg
@@ -0,0 +1,69 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Parameters.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Parameters.png
new file mode 100644
index 0000000000..fd3475ce86
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Parameters.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Parameters.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Parameters.svg
new file mode 100644
index 0000000000..bac5792c71
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Parameters.svg
@@ -0,0 +1,69 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Pattern.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Pattern.png
new file mode 100644
index 0000000000..1581635c92
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Pattern.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Pattern.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Pattern.svg
new file mode 100644
index 0000000000..566a238d96
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Pattern.svg
@@ -0,0 +1,54 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Placeholders.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Placeholders.png
new file mode 100644
index 0000000000..8f47d1ee17
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Placeholders.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Placeholders.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Placeholders.svg
new file mode 100644
index 0000000000..799cbd9092
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Placeholders.svg
@@ -0,0 +1,47 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Primary.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Primary.png
new file mode 100644
index 0000000000..ce9bdaf55e
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Primary.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Primary.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Primary.svg
new file mode 100644
index 0000000000..58b0462fe6
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Primary.svg
@@ -0,0 +1,204 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/PrimitiveType.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/PrimitiveType.png
new file mode 100644
index 0000000000..8e14836cee
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/PrimitiveType.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/PrimitiveType.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/PrimitiveType.svg
new file mode 100644
index 0000000000..2eba75f316
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/PrimitiveType.svg
@@ -0,0 +1,72 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QualifiedName.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QualifiedName.png
new file mode 100644
index 0000000000..a651fe8400
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QualifiedName.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QualifiedName.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QualifiedName.svg
new file mode 100644
index 0000000000..13f1147430
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QualifiedName.svg
@@ -0,0 +1,29 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryDefinition.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryDefinition.png
new file mode 100644
index 0000000000..b3a0ce4b15
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryDefinition.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryDefinition.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryDefinition.svg
new file mode 100644
index 0000000000..4de0108dec
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryDefinition.svg
@@ -0,0 +1,48 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryOptions.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryOptions.png
new file mode 100644
index 0000000000..9fe87dc807
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryOptions.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryOptions.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryOptions.svg
new file mode 100644
index 0000000000..ca0edfbcb5
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/QueryOptions.svg
@@ -0,0 +1,54 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealLiteral.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealLiteral.png
new file mode 100644
index 0000000000..d1fca60d3f
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealLiteral.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealLiteral.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealLiteral.svg
new file mode 100644
index 0000000000..55e14ef768
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealLiteral.svg
@@ -0,0 +1,134 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealTypeSuffix.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealTypeSuffix.png
new file mode 100644
index 0000000000..9305d084ef
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealTypeSuffix.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealTypeSuffix.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealTypeSuffix.svg
new file mode 100644
index 0000000000..d2e1646a47
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RealTypeSuffix.svg
@@ -0,0 +1,44 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalExpr.png
new file mode 100644
index 0000000000..1775ed985c
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalExpr.svg
new file mode 100644
index 0000000000..f4f379f8ee
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalExpr.svg
@@ -0,0 +1,30 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalOperator.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalOperator.png
new file mode 100644
index 0000000000..8f22b6ad3f
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalOperator.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalOperator.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalOperator.svg
new file mode 100644
index 0000000000..3260874d91
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RelationalOperator.svg
@@ -0,0 +1,103 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RhsStatement.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RhsStatement.png
new file mode 100644
index 0000000000..bab85bc62c
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RhsStatement.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RhsStatement.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RhsStatement.svg
new file mode 100644
index 0000000000..61d3469dd5
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RhsStatement.svg
@@ -0,0 +1,30 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttribute.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttribute.png
new file mode 100644
index 0000000000..c386af4594
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttribute.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttribute.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttribute.svg
new file mode 100644
index 0000000000..e2ae931b08
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttribute.svg
@@ -0,0 +1,172 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttributes.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttributes.png
new file mode 100644
index 0000000000..caa0656946
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttributes.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttributes.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttributes.svg
new file mode 100644
index 0000000000..8b84224950
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleAttributes.svg
@@ -0,0 +1,79 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleDefinition.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleDefinition.png
new file mode 100644
index 0000000000..1808ad0e7b
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleDefinition.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleDefinition.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleDefinition.svg
new file mode 100644
index 0000000000..923f0f3dec
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleDefinition.svg
@@ -0,0 +1,50 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleOptions.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleOptions.png
new file mode 100644
index 0000000000..49660ae529
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleOptions.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleOptions.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleOptions.svg
new file mode 100644
index 0000000000..56a2632319
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/RuleOptions.svg
@@ -0,0 +1,62 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Selector.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Selector.png
new file mode 100644
index 0000000000..462079f515
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Selector.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Selector.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Selector.svg
new file mode 100644
index 0000000000..0973930b1d
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Selector.svg
@@ -0,0 +1,108 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ShiftExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ShiftExpr.png
new file mode 100644
index 0000000000..c16e42f7c3
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ShiftExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ShiftExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ShiftExpr.svg
new file mode 100644
index 0000000000..b3f2afa489
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ShiftExpr.svg
@@ -0,0 +1,46 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SingleRestriction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SingleRestriction.png
new file mode 100644
index 0000000000..30f5703dc8
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SingleRestriction.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SingleRestriction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SingleRestriction.svg
new file mode 100644
index 0000000000..00e1ee8a55
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SingleRestriction.svg
@@ -0,0 +1,44 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SourcePattern.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SourcePattern.png
new file mode 100644
index 0000000000..924bc8e072
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SourcePattern.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SourcePattern.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SourcePattern.svg
new file mode 100644
index 0000000000..c6640d113d
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SourcePattern.svg
@@ -0,0 +1,100 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/StringId.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/StringId.png
new file mode 100644
index 0000000000..8b2097e4f7
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/StringId.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/StringId.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/StringId.svg
new file mode 100644
index 0000000000..fdaaa2b1a9
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/StringId.svg
@@ -0,0 +1,30 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SuperSuffix.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SuperSuffix.png
new file mode 100644
index 0000000000..7cdfdb6de3
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SuperSuffix.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SuperSuffix.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SuperSuffix.svg
new file mode 100644
index 0000000000..c6bca418e9
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/SuperSuffix.svg
@@ -0,0 +1,50 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ThenPart.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ThenPart.png
new file mode 100644
index 0000000000..86c008a4d7
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ThenPart.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ThenPart.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ThenPart.svg
new file mode 100644
index 0000000000..37dcbfbf98
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/ThenPart.svg
@@ -0,0 +1,36 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Type.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Type.png
new file mode 100644
index 0000000000..f68ab06c06
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Type.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Type.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Type.svg
new file mode 100644
index 0000000000..f5eb84eb98
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Type.svg
@@ -0,0 +1,91 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArgument.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArgument.png
new file mode 100644
index 0000000000..13e81e7cab
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArgument.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArgument.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArgument.svg
new file mode 100644
index 0000000000..04136d7b6f
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArgument.svg
@@ -0,0 +1,64 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArguments.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArguments.png
new file mode 100644
index 0000000000..8cf09063e0
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArguments.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArguments.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArguments.svg
new file mode 100644
index 0000000000..7cab349f16
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeArguments.svg
@@ -0,0 +1,37 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeDefinition.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeDefinition.png
new file mode 100644
index 0000000000..4b7f867ba7
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeDefinition.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeDefinition.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeDefinition.svg
new file mode 100644
index 0000000000..e3687f3cb5
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeDefinition.svg
@@ -0,0 +1,48 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeOptions.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeOptions.png
new file mode 100644
index 0000000000..1829990877
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeOptions.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeOptions.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeOptions.svg
new file mode 100644
index 0000000000..5b7c221032
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/TypeOptions.svg
@@ -0,0 +1,46 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExpr.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExpr.png
new file mode 100644
index 0000000000..d8328e721d
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExpr.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExpr.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExpr.svg
new file mode 100644
index 0000000000..8303de35cc
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExpr.svg
@@ -0,0 +1,69 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExprNotPlusMinus.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExprNotPlusMinus.png
new file mode 100644
index 0000000000..e5947397ad
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExprNotPlusMinus.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExprNotPlusMinus.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExprNotPlusMinus.svg
new file mode 100644
index 0000000000..0b8bdb2025
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/UnaryExprNotPlusMinus.svg
@@ -0,0 +1,133 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Value.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Value.png
new file mode 100644
index 0000000000..a0350cbb07
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Value.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Value.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Value.svg
new file mode 100644
index 0000000000..28dffa8742
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/Value.svg
@@ -0,0 +1,61 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/VariableInitializer.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/VariableInitializer.png
new file mode 100644
index 0000000000..11a63ae4cb
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/VariableInitializer.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/VariableInitializer.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/VariableInitializer.svg
new file mode 100644
index 0000000000..d6606f26ab
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/VariableInitializer.svg
@@ -0,0 +1,30 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/WhenPart.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/WhenPart.png
new file mode 100644
index 0000000000..251dc1e5d3
Binary files /dev/null and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/WhenPart.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/WhenPart.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/WhenPart.svg
new file mode 100644
index 0000000000..14cf2bf1a0
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/WhenPart.svg
@@ -0,0 +1,44 @@
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/drl.BNF b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/drl.BNF
new file mode 100644
index 0000000000..d65d93b292
--- /dev/null
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Language_Reference/drl.BNF
@@ -0,0 +1,390 @@
+#
+# Drools DRL Syntax definitions for Ebnf2eps
+#
+# V 1.0 for Drools 5.2.0
+
+CompilationUnit = [ "package" QualifiedName [ ";" ] ] { Definition [ ";" ] } ;
+
+Definition =
+ ( RuleAttribute
+ | ImportDefinition
+ | GlobalDefinition
+ | FunctionDefinition
+ | TypeDefinition
+ | RuleDefinition
+ | QueryDefinition
+ );
+
+ImportDefinition =
+ "import" [ "function" | "static" ] QualifiedName [ "." "*" ] ;
+
+GlobalDefinition = "global" Type Identifier ;
+
+FunctionDefinition = "function" [ Type ] Identifier Parameters Block ;
+
+Parameters = "(" [ ( Type Identifier { "[" "]" } ) / "," ] ")" ;
+
+TypeDefinition = "declare" QualifiedName TypeOptions { Field } "end" ;
+
+TypeOptions = [ "extends" QualifiedName ] { Annotation } ;
+
+Annotation =
+ "@" Identifier [ "(" ( Tokens | ( Identifier "=" Value ) / "," ) ")" ] ;
+
+Value =
+ ( "{" [ Value / "," ] "}"
+ | ConditionalExpr
+ );
+
+Field =
+ Identifier ":" QualifiedName [ "=" ConditionalExpr ]
+ { Annotation } [ ";" ] ;
+
+QueryDefinition = "query" StringId QueryOptions { ConditionalOr } "end" ;
+
+QueryOptions = [ Parameters | Placeholders ] { Annotation } ;
+
+Placeholders = "(" [ Identifier / "," ] ")" ;
+
+RuleDefinition =
+ "rule" StringId RuleOptions
+ [ WhenPart ] ThenPart
+ ;
+
+RuleOptions =
+ [ "extends" StringId ]
+ { Annotation } [ RuleAttributes ]
+ ;
+
+WhenPart = "when" [ ":" ] { ConditionalOr } ;
+
+RuleAttributes = [ "attributes" [ ":" ] ] [ RuleAttribute / [ "," ] ] ;
+
+RuleAttribute =
+ "salience" ConditionalExpr
+ | "enabled" ConditionalExpr
+ | ( "auto-focus"
+ | "no-loop"
+ | "lock-on-active" ) [ BooleanLiteral ]
+ | ( "agenda-group"
+ | "activation-group"
+ | "date-effective"
+ | "date-expires"
+ | "dialect"
+ | "ruleflow-group" ) StringLiteral
+ | "timer" "(" Tokens ")"
+ | "calendars" StringLiteral / ","
+ ;
+
+ConditionalOr = ConditionalAnd / "or" ;
+
+ConditionalAnd = ConditionalElement / "and" ;
+
+ConditionalElement =
+ ( ( "exists" | "not" ) ( BindingPattern | "(" ConditionalOr ")" )
+ | "eval" "(" ConditionalExpr ")"
+ | "forall" "(" BindingPattern+ ")"
+ | "accumulate" "(" ConditionalAnd [ "," ] Accumulations ")"
+ | "(" ConditionalOr ")"
+ | BindingPattern
+ ) [ ";" ]
+ ;
+
+
+# lhsPatternBind
+BindingPattern =
+ [ Identifier ":" ] ( SourcePattern | "(" SourcePattern / "or" ")" ) ;
+
+# lhsPattern
+SourcePattern =
+ Pattern
+ [ OverClause ]
+ [ "from" ( ConditionalOrExpr
+ | "collect" "(" BindingPattern ")"
+ | "entry-point" StringId
+ | AccumulateClause
+ ) ]
+ ;
+
+# lhsPattern
+Pattern =
+ [ "?" ] QualifiedName "(" [ Constraints ] ")" ;
+
+OverClause =
+ "over" Identifier ":" Identifier "(" [ ConditionalExpr / "," ] ")" ;
+
+Accumulations = ( Identifier ":" AccumulateFunction ) / "," ;
+
+AccumulateClause =
+ "accumulate"
+ "(" ConditionalAnd [ "," ]
+ ( AccumulateSteps | AccumulateFunction ) ")"
+ ;
+
+AccumulateSteps =
+ AccumulateInit AccumulateAction [ AccumulateReverse ] AccumulateResult ;
+
+AccumulateInit = "init" "(" { Statement } ")" [ "," ] ;
+AccumulateAction = "action" "(" { Statement } ")" [ "," ] ;
+AccumulateReverse = "reverse" "(" { Statement } ")" [ "," ] ;
+AccumulateResult = "result" "(" ConditionalExpr ")" ;
+
+AccumulateFunction = Identifier "(" { ConditionalExpr / "," } ")" ;
+
+### Snippets for manual
+
+ConditionalElementEval = "eval" "(" ConditionalExpr ")" ;
+ConditionalElementExists = "exists" ( BindingPattern | "(" ConditionalOr ")" ) ;
+ConditionalElementNot = "not" ( BindingPattern | "(" ConditionalOr ")" ) ;
+ConditionalElementForall = "forall" "(" BindingPattern+ ")" ;
+ConditionalElementAccumulate =
+ "accumulate" "(" ConditionalAnd [ "," ] Accumulations ")" ;
+
+FromClause = "from" ConditionalOrExpr ;
+FromCollectClause = "from" "collect" "(" SourcePattern ")" ;
+FromAccumulateClause = "from" AccumulateClause ;
+###
+
+Constraints =
+ [ ( ConditionalOrExpr / "," ) ";" ]
+ [ ConditionalOrExpr / "," ] ;
+
+ThenPart = "then" { RhsStatement } "end" ;
+
+RhsStatement =
+ ModifyStatement
+ | Statement
+ ;
+
+ModifyStatement =
+ "modify" "(" ConditionalExpr ")"
+ "{" { ConditionalExpr / "," } "}"
+ ;
+
+Block = "{" { Statement } "}" ;
+
+QualifiedName = Identifier / "." ;
+
+
+Expression = ConditionalExpr [ AssignmentOperator Expression ] ;
+
+ConditionalExpr =
+ ConditionalOrExpr [ "?" Expression ":" Expression ];
+
+ConditionalOrExpr =
+ (((( (InstanceOfExpr / ( "==" | "!=" ) ) / "&" ) / "^" ) / "|" ) / "&&" ) / "||" ;
+
+# ConditionalOrExpr = ConditionalAndExpr / "||" ;
+# ConditionalAndExpr = InclusiveOrExpr / "&&" ;
+# InclusiveOrExpr = ExclusiveOrExpr / "|" ;
+# ExclusiveOrExpr = AndExpr / "^" ;
+# AndExpr = EqualityExpr / "&" ;
+# EqualityExpr = InstanceOfExpr / ( "==" | "!=" ) ;
+
+InstanceOfExpr = InExpr [ "instanceof" Type ] ;
+
+InExpr = RelationalExpr [ "not" ] "in" "(" Expression / "," ")" ;
+
+RelationalExpr = ShiftExpr { OrRestriction } ;
+
+OrRestriction = ( SingleRestriction / "&&" ) / "||" ;
+
+# OrRestriction = AndRestriction / "||" ;
+# AndRestriction = SingleRestriction / "&&" ;
+
+SingleRestriction =
+ ( RelationalOperator ShiftExpr
+ | "(" OrRestriction ")"
+ );
+
+ShiftExpr = AdditiveExpr / ( "<<" | ">>" | ">>>" ) ;
+
+AdditiveExpr =
+ ( UnaryExpr / ( "*" | "/" | "%" ) ) / ( "+" | "-" ) ;
+
+# AdditiveExpr = MultiplicativeExpr / ( "+" | "-" ) ;
+# MultiplicativeExpr = UnaryExpr / ( "*" | "/" | "%" ) ;
+
+UnaryExpr =
+ ( ( "+" | "-" ) UnaryExpr
+ | ( "++" | "--" ) Primary
+ | UnaryExprNotPlusMinus
+ );
+
+UnaryExprNotPlusMinus =
+ ( ( "~"
+ | "!"
+ | "(" ( PrimitiveType | Type ) ")"
+ ) UnaryExpr
+ | [ Identifier ( ":" | ":=" ) ] Primary [ "++" | "--" ]
+ );
+
+PrimitiveType =
+ ( "boolean"
+ | "char"
+ | "byte"
+ | "short"
+ | "int"
+ | "long"
+ | "float"
+ | "double"
+ );
+
+Primary =
+ ( "(" Expression ")"
+ | NonWildcardTypeArguments ( ExplicitGenericInvocationSuffix | "this" Arguments )
+ | Literal
+ | "super" SuperSuffix
+ | "new" Creator
+ | PrimitiveType { "[" "]" } "." "class"
+ | "void" "." "class"
+ | "this"
+ | InlineMapExpr
+ | InlineListExpr
+ | ( Identifier / "." ) [ IdentifierSuffix ]
+ );
+
+InlineListExpr = "[" [ ExpressionList ] "]" ;
+
+InlineMapExpr = "[" ( ( Expression ":" Expression ) / "," ) "]" ;
+
+IdentifierSuffix =
+ ( ( "[" "]" )+ "." "class"
+ | ( "[" Expression "]" )+
+ | Arguments
+ );
+
+Creator =
+ [ NonWildcardTypeArguments ] CreatedName
+ ( ArrayCreatorRest | Arguments )
+ ;
+
+CreatedName =
+ ( ( Identifier [ TypeArguments ] ) / "."
+ | PrimitiveType
+ );
+
+InnerCreator = Identifier Arguments ;
+
+ArrayCreatorRest =
+ ( ( "[" "]" )+ ArrayInitializer
+ | ( "[" Expression "]" )+ { "[" "]" }
+ )
+ ;
+
+VariableInitializer = ArrayInitializer | Expression ;
+
+ArrayInitializer = "{" [ { VariableInitializer / "," } [ "," ] ] "}" ;
+
+ExplicitGenericInvocation = NonWildcardTypeArguments Arguments ;
+
+NonWildcardTypeArguments = "<" ( Type / "," ) ">" ;
+
+ExplicitGenericInvocationSuffix =
+ ( "super" SuperSuffix
+ | Identifier Arguments
+ );
+
+Selector =
+ ( "." "super" SuperSuffix
+ | "." "new" [ NonWildcardTypeArguments ] InnerCreator
+ | "." Identifier [ Arguments ]
+ | "[" Expression "]"
+ );
+
+SuperSuffix =
+ ( Arguments
+ | "." Identifier [ Arguments ]
+ );
+
+Arguments = "(" [ ExpressionList ] ")" ;
+
+ExpressionList = Expression / "," ;
+
+AssignmentOperator =
+ ( "="
+ | "+="
+ | "-="
+ | "*="
+ | "/="
+ | "&="
+ | "|="
+ | "^="
+ | "%="
+ | "<<="
+ | ">>>="
+ | ">>="
+ );
+
+RelationalOperator =
+ ( "=="
+ | "!="
+ | "<="
+ | ">="
+ | "<"
+ | ">"
+ | [ "not" ] Identifier [ "[" [ ExpressionList ] "]" ]
+ );
+
+
+#
+# Type
+#
+
+Type =
+ ( PrimitiveType { "[" "]" }
+ | ( ( Identifier [ TypeArguments ] ) / "." ) { "[" "]" }
+ );
+
+TypeArguments = "<" ( TypeArgument / "," ) ">" ;
+
+TypeArgument =
+ ( Type
+ | "?" [ ( "extends" | "super" ) Type ]
+ );
+
+
+Literal =
+ ( IntLiteral
+ | RealLiteral
+ | BooleanLiteral
+ | StringLiteral
+ );
+
+
+StringId =
+ ( Identifier
+ | StringLiteral
+ );
+
+BooleanLiteral = "true" | "false" ;
+
+IntLiteral = [ "+" | "-" ] ( Digit+ | "0x" ( Digit | "'a'..'f'" | "'A'..'F'" )+ ) ;
+
+RealLiteral = [ "+" | "-" ]
+ ( ( Fraction [ Exponent ]
+ | Digit+ Exponent
+ ) [ RealTypeSuffix ]
+ | Digit+ RealTypeSuffix
+ )
+ ;
+
+Fraction = Digit+ "." { Digit } | "." Digit+ ;
+
+Exponent = ( "e" | "E" ) [ "+" | "-" ] Digit+ ;
+
+RealTypeSuffix = "f" | "F" | "d" | "D" ;
+
+Digit = "'0'..'9'" ;
+
+StringLiteral = X ;
+
+Identifier = X ;
+
+Statement = X ;
+
+X = "asinjava" ;
+
+Tokens = X ;
+
+
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/multiRestriction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/abbreviatedCombinedRelationCondition.png
similarity index 100%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/multiRestriction.png
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/abbreviatedCombinedRelationCondition.png
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/multiRestriction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/abbreviatedCombinedRelationCondition.svg
similarity index 100%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/multiRestriction.svg
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/abbreviatedCombinedRelationCondition.svg
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restrictionGroup.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/abbreviatedCombinedRelationConditionGroup.png
similarity index 100%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restrictionGroup.png
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/abbreviatedCombinedRelationConditionGroup.png
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restrictionGroup.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/abbreviatedCombinedRelationConditionGroup.svg
similarity index 100%
rename from drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restrictionGroup.svg
rename to drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/abbreviatedCombinedRelationConditionGroup.svg
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraint.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraint.png
deleted file mode 100755
index da47e6985b..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraint.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraint.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraint.svg
deleted file mode 100755
index 92f3e7e200..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraint.svg
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraintGroup.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraintGroup.png
deleted file mode 100755
index 12bb453e4f..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraintGroup.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraintGroup.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraintGroup.svg
deleted file mode 100755
index 334057eb58..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraintGroup.svg
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraints.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraints.png
deleted file mode 100755
index ef34581e1b..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraints.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraints.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraints.svg
deleted file mode 100755
index 3854cd82b6..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/constraints.svg
+++ /dev/null
@@ -1,103 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/fieldConstraint.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/fieldConstraint.png
deleted file mode 100755
index f073983d32..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/fieldConstraint.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/fieldConstraint.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/fieldConstraint.svg
deleted file mode 100755
index b14727ce3e..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/fieldConstraint.svg
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/identifier.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/identifier.png
deleted file mode 100755
index 776144ad2f..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/identifier.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/identifier.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/identifier.svg
deleted file mode 100755
index 196499b19f..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/identifier.svg
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literal.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literal.png
deleted file mode 100755
index a563494038..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literal.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literal.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literal.svg
deleted file mode 100755
index cd67ea356e..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literal.svg
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literalRestriction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literalRestriction.png
deleted file mode 100755
index 8d5b2b252f..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literalRestriction.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literalRestriction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literalRestriction.svg
deleted file mode 100755
index 6cc634460e..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/literalRestriction.svg
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/patternER.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/patternER.png
deleted file mode 100755
index a44fdcd6aa..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/patternER.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/patternER.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/patternER.svg
deleted file mode 100755
index 1a3042280d..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/patternER.svg
+++ /dev/null
@@ -1,814 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifier.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifier.png
deleted file mode 100755
index 32a4c702d2..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifier.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifier.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifier.svg
deleted file mode 100755
index 1112331d65..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifier.svg
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifierRestriction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifierRestriction.png
deleted file mode 100755
index 8cc25536a0..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifierRestriction.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifierRestriction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifierRestriction.svg
deleted file mode 100755
index cb74144b47..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/qualifiedIdentifierRestriction.svg
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restriction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restriction.png
deleted file mode 100755
index d121726528..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restriction.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restriction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restriction.svg
deleted file mode 100755
index d9635a0817..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/restriction.svg
+++ /dev/null
@@ -1,123 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValue.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValue.png
deleted file mode 100755
index 26688a84dc..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValue.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValue.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValue.svg
deleted file mode 100755
index d90b0ec2ca..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValue.svg
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValueRestriction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValueRestriction.png
deleted file mode 100755
index 08e107a020..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValueRestriction.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValueRestriction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValueRestriction.svg
deleted file mode 100755
index a8e7830a9c..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/returnValueRestriction.svg
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/singleValueRestriction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/singleValueRestriction.png
deleted file mode 100755
index c6faf82373..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/singleValueRestriction.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/singleValueRestriction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/singleValueRestriction.svg
deleted file mode 100755
index 1c9f8cd004..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/singleValueRestriction.svg
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/variableRestriction.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/variableRestriction.png
deleted file mode 100755
index 19cd1c3f26..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/variableRestriction.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/variableRestriction.svg b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/variableRestriction.svg
deleted file mode 100755
index 4e87ef32cf..0000000000
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-Rule_Language/variableRestriction.svg
+++ /dev/null
@@ -1,92 +0,0 @@
-
-
-
-
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Activation.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Activation.png
index 1350906c88..c32f9c87f8 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Activation.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Activation.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ActivationGroup.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ActivationGroup.png
index 85af377e49..938c566824 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ActivationGroup.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ActivationGroup.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Agenda.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Agenda.png
index 05fcdf627d..cd419e76b4 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Agenda.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Agenda.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/AgendaFilter.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/AgendaFilter.png
index 4c143269b9..92ee133dc6 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/AgendaFilter.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/AgendaFilter.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/AgendaGroup.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/AgendaGroup.png
index 8254fcedc2..63d84b2ef0 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/AgendaGroup.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/AgendaGroup.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/BatchExecutionHelperProvider.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/BatchExecutionHelperProvider.png
index efa4e66c20..32c4255681 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/BatchExecutionHelperProvider.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/BatchExecutionHelperProvider.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ChangeSet.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ChangeSet.png
index b24ae4b049..39fe8a416f 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ChangeSet.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ChangeSet.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/CommandExecutor.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/CommandExecutor.png
index 902df0bb3f..bbc6c76b42 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/CommandExecutor.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/CommandExecutor.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/CommandFactory.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/CommandFactory.png
index 86dc972a5c..67f15c36e5 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/CommandFactory.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/CommandFactory.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ExecutionResults.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ExecutionResults.png
index 22bd06c0b4..3bb9294fac 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ExecutionResults.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ExecutionResults.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgent.ResourceStatus.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgent.ResourceStatus.png
index 46d9bd9da0..2941f7ce6c 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgent.ResourceStatus.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgent.ResourceStatus.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgent.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgent.png
index 8e9f4be63e..cf605ca48d 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgent.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgent.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgentConfiguration.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgentConfiguration.png
index a7151e451b..5b74d084a6 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgentConfiguration.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgentConfiguration.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgentFactory.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgentFactory.png
index fc83ee6cd5..e9da393ef1 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgentFactory.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeAgentFactory.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBase.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBase.png
index ac590e51ef..d5f27c0ca3 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBase.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBase.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBaseConfiguration.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBaseConfiguration.png
index 875b9ff55d..1e050ce6d9 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBaseConfiguration.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBaseConfiguration.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBaseFactory.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBaseFactory.png
index 745caffb41..2555695ef1 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBaseFactory.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBaseFactory.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBuilder.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBuilder.png
index 160cf589d4..5152d8e9b7 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBuilder.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBuilder.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBuilderFactory.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBuilderFactory.png
index b88558ce29..454aab9fab 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBuilderFactory.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeBuilderFactory.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgePackage.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgePackage.png
index 5b83afcd90..bd48d94d64 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgePackage.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgePackage.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntime.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntime.png
index 8be0631fb6..f0ea956e20 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntime.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntime.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeEvent.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeEvent.png
index c3cb7bd2ff..b5761f49bc 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeEvent.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeEvent.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeEventManager.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeEventManager.png
index ea7c9eefd1..5325271f67 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeEventManager.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeEventManager.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeLoggerFactory.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeLoggerFactory.png
index a0572f3354..a549ecd2a6 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeLoggerFactory.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeRuntimeLoggerFactory.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeSessionConfiguration.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeSessionConfiguration.png
index e18a683e17..47e3a87ee8 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeSessionConfiguration.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/KnowledgeSessionConfiguration.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/MarshallerFactory.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/MarshallerFactory.png
index 0c5d4d42f1..0b091cc223 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/MarshallerFactory.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/MarshallerFactory.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ObjectFilter.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ObjectFilter.png
index dae266b5f9..0f2538577b 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ObjectFilter.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ObjectFilter.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/PipelineFactory.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/PipelineFactory.png
deleted file mode 100644
index d8c1ed129e..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/PipelineFactory.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Process.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Process.png
index 341b42d214..0d9c6449a6 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Process.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Process.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/QueryResults.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/QueryResults.png
index 741c46766f..1dff263d8d 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/QueryResults.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/QueryResults.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/QueryResultsRow.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/QueryResultsRow.png
index 616ddb1e66..6430d9a182 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/QueryResultsRow.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/QueryResultsRow.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ResultHandler.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ResultHandler.png
deleted file mode 100644
index ba629b22dc..0000000000
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ResultHandler.png and /dev/null differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Rule.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Rule.png
index 98b8358b84..30b6add58d 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Rule.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/Rule.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/RuleFlowGroup.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/RuleFlowGroup.png
index 7ef0aaf283..04c4a78dca 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/RuleFlowGroup.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/RuleFlowGroup.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatefulKnowledgeSession.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatefulKnowledgeSession.png
index a27385caa5..6d58d711a4 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatefulKnowledgeSession.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatefulKnowledgeSession.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatefulRuleSession.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatefulRuleSession.png
index bf818c66a6..ab0fe11766 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatefulRuleSession.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatefulRuleSession.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatelessKnowledgeSession.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatelessKnowledgeSession.png
index 67e0536650..7fc4c665c1 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatelessKnowledgeSession.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatelessKnowledgeSession.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatelessKnowledgeSessionResults.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatelessKnowledgeSessionResults.png
index 08eb507ca8..c85b78d23c 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatelessKnowledgeSessionResults.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/StatelessKnowledgeSessionResults.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ViewChangedEventListener.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ViewChangedEventListener.png
index 7aae52773c..58a3bf7b24 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ViewChangedEventListener.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/ViewChangedEventListener.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemory.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemory.png
index 327a31ee71..055eeff3f9 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemory.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemory.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemoryEntryPoint.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemoryEntryPoint.png
index 14b75835d4..45303de85d 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemoryEntryPoint.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemoryEntryPoint.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemoryEventManager.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemoryEventManager.png
index 2b07fc8376..377d83599b 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemoryEventManager.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/WorkingMemoryEventManager.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/builder.png b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/builder.png
index f679f6a1e9..10f1635f1d 100644
Binary files a/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/builder.png and b/drools-docs/drools-expert-docs/src/main/docbook/en-US/images/Chapter-User_Guide/builder.png differ
diff --git a/drools-docs/drools-expert-docs/src/main/docbook/en-US/master.xml b/drools-docs/drools-expert-docs/src/main/docbook/en-US/master.xml
index 0198d83d39..73e58eae44 100755
--- a/drools-docs/drools-expert-docs/src/main/docbook/en-US/master.xml
+++ b/drools-docs/drools-expert-docs/src/main/docbook/en-US/master.xml
@@ -7,7 +7,7 @@
Drools Expert User Guide
- 5.2.0-SNAPSHOT
+ Version &project.version;The JBoss Drools team
@@ -33,15 +33,11 @@
-
-
-
-
-
+
+
+
-
+
-
-
diff --git a/drools-docs/drools-fusion-docs/pom.xml b/drools-docs/drools-fusion-docs/pom.xml
index a2e9855b29..61d8f80ba0 100755
--- a/drools-docs/drools-fusion-docs/pom.xml
+++ b/drools-docs/drools-fusion-docs/pom.xml
@@ -6,7 +6,7 @@
org.droolsdrools-docs
- 5.2.0-SNAPSHOT
+ 5.5.0-SNAPSHOTdrools-fusion-docs
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-EventProcessingModes/Section-EventProcessingModes_CloudMode.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-EventProcessingModes/Section-EventProcessingModes_CloudMode.xml
index 0de68f92d0..88aec08079 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-EventProcessingModes/Section-EventProcessingModes_CloudMode.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-EventProcessingModes/Section-EventProcessingModes_CloudMode.xml
@@ -34,7 +34,7 @@
There is no requirement on event ordering. The engine looks at the
- events as an unnordered cloud against which the engine tries to match
+ events as an unordered cloud against which the engine tries to match
rules.
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-EventProcessingModes/Section-EventProcessingModes_StreamMode.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-EventProcessingModes/Section-EventProcessingModes_StreamMode.xml
index 2aab0e54fa..d9e9983f2d 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-EventProcessingModes/Section-EventProcessingModes_StreamMode.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-EventProcessingModes/Section-EventProcessingModes_StreamMode.xml
@@ -124,7 +124,7 @@ end
This behaviour allows the engine to keep consistency when
dealing with negative patterns and temporal constraints at the same time.
- The above would be the same as writing the rule as bellow, but does not
+ The above would be the same as writing the rule as below, but does not
burden the user to calculate and explicitly write the appropriate duration
parameter:
@@ -137,6 +137,26 @@ when
not( SprinklerActivated( this after[0s,10s] $f ) )
then
// sound the alarm
+end
+
+
+ The following rule expects every 10 seconds at least one
+ “Heartbeat” event, if not the rule fires. The special case in this rule
+ is that we use the same type of the object in the first pattern and in
+ the negative pattern. The negative pattern has the temporal constraint to
+ wait between 0 to 10 seconds before firing and it excludes the Heartbeat
+ bound to $h. Excluding the bound Heartbeat is important since the
+ temporal constraint [0s, ...] does not exclude by itself the bound event
+ $h from being matched again, thus preventing the rule to fire.
+
+ excluding bound events in negative patterns
+
+ rule "Sound the alarm"
+when
+ $h: Heartbeat( ) from entry-point "MonitoringStream"
+ not( Heartbeat( this != $h, this after[0s,10s] $h ) from entry-point "MonitoringStream" )
+then
+ // Sound the alarm
end
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_Declaration.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_Declaration.xml
index aca752a0af..5318b7f561 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_Declaration.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_Declaration.xml
@@ -22,7 +22,7 @@
- For instance, the example bellow is declaring that the fact type
+ For instance, the example below is declaring that the fact type
StockTick in a stock broker application shall be handled as an event.
@@ -41,7 +41,7 @@
code would be:
- declaring a fact type and assiging it the event role
+ declaring a fact type and assigning it the event roledeclare StockTick
@role( event )
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_EventsMetadata.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_EventsMetadata.xml
index 2036d64e3a..a57a9df928 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_EventsMetadata.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_EventsMetadata.xml
@@ -1,16 +1,19 @@
+ xml:base="../../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
Event MetadataAll events have a set of metadata associated to them. Most of the
metadata values have defaults that are automatically assigned to each event
when they are inserted into the working memory, but it is possible to change
the default on an event type basis, using the metadata tags listed
- bellow.
+ below.For the examples, lets assume the user has the following class in the
application domain model:
@@ -54,7 +57,7 @@ public class VoiceCall {
-
+
@@ -141,17 +144,18 @@ public class VoiceCall {
user would write:
- declaring the expiration offset for the VoiceCall
- events
+ declaring the expiration offset for the VoiceCall events
- declare VoiceCall
+ declare VoiceCall
@role( event )
@timestamp( callDateTime )
@duration( callDuration )
@expires( 1h35m )
end
-
+
-
+ The @expires policy will take precedence and override the implicit
+ expiration offset calculated from temporal constraints and sliding windows
+ in the knowledge base.
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_Semantics.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_Semantics.xml
index 2e466bc65a..3b9a6069e3 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_Semantics.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Events/Section-Events_Semantics.xml
@@ -19,12 +19,12 @@
optimizations and for the specification of the event lifecycle. This
does not mean that the java object representing the object must be
immutable. Quite the contrary, the engine does not enforce immutability
- of the object model, because one of the most common usecases for rules
+ of the object model, because one of the most common use cases for rules
is event data enrichment.
As a best practice, the application is allowed to populate
- un-populated event attributes (to enrich the event with infered data),
+ un-populated event attributes (to enrich the event with inferred data),
but already populated attributes should never be changed.
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Examples/Section-Examples.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Examples/Section-Examples.xml
index bf2ded417d..1bfa921988 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Examples/Section-Examples.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-Examples/Section-Examples.xml
@@ -5,4 +5,6 @@
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:ns="http://docbook.org/ns/docbook">
Examples
+ There is a broker examples in the module droolsjbpm-integration-examples. Note: that is in a different download,
+ the droolsjbpm-integration download.
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-RulebasePartitioning/Section-RulebasePartitioning.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-RulebasePartitioning/Section-RulebasePartitioning.xml
index da562d6fc7..f39e258c75 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-RulebasePartitioning/Section-RulebasePartitioning.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-RulebasePartitioning/Section-RulebasePartitioning.xml
@@ -1,14 +1,18 @@
- Knowledgebase Partitioning
+ xml:base="./" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
+ KnowledgeBase Partitioning
- This is an experimental feature, subject to changes in the
- future.
+ THIS FEATURE IS NO LONGER SUPPORTED. It may be reintroduced in the
+ future, but trying to use it in the current version will raise an
+ exception.The classic Rete algorithm is usually executed using a single thread.
@@ -24,7 +28,7 @@
multiple partitions may be "active" at a single point in time.Everything should be transparent to the user, except that all working
- memory actions (insert/retract/modify) are executed assynchronously.
+ memory actions (insert/retract/modify) are executed asynchronously.
This feature enables parallel LHS evaluation, but does not change
@@ -33,7 +37,8 @@
+
-
+
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-RulebasePartitioning/Section-RulebasePartitioning_WhenPartitioningIsUseful.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-RulebasePartitioning/Section-RulebasePartitioning_WhenPartitioningIsUseful.xml
index 66a647e526..fd69d4aaeb 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-RulebasePartitioning/Section-RulebasePartitioning_WhenPartitioningIsUseful.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-RulebasePartitioning/Section-RulebasePartitioning_WhenPartitioningIsUseful.xml
@@ -9,7 +9,7 @@
Knowledge base partitioning is a very powerful feature for specific
scenarios, but it is not a general case solution. To understand if this
feature would be useful for a given scenario, the user may follow the
- checklist bellow:
+ checklist below:
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SessionClock/Section-SessionClock.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SessionClock/Section-SessionClock.xml
index 7d3f507339..c641109d7a 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SessionClock/Section-SessionClock.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SessionClock/Section-SessionClock.xml
@@ -22,7 +22,7 @@
Rules testing: testing always
- requires a controled environment, and when the tests include rules with
+ requires a controlled environment, and when the tests include rules with
temporal constraints, it is necessary to not only control the input
rules and facts, but also the flow of time.
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SessionClock/Section-SessionClock_AvailableClockImplementations.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SessionClock/Section-SessionClock_AvailableClockImplementations.xml
index 6a8ce67a73..c6a5ec1246 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SessionClock/Section-SessionClock_AvailableClockImplementations.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SessionClock/Section-SessionClock_AvailableClockImplementations.xml
@@ -31,7 +31,7 @@ config.setOption( ClockTypeOption.get("realtime") );
Drools also offers out of the box an implementation of a clock that
is controlled by the application that is called Pseudo Clock. This clock
is specially useful for unit testing temporal rules since it can be
- controled by the application and so the results become
+ controlled by the application and so the results become
deterministic.To configure the pseudo session clock, do:
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows.xml
index 11d8a4c129..ac6a33911c 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows.xml
@@ -1,15 +1,18 @@
+ xml:base="./" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
Sliding Windows
- Sliding Window is a way to scope the events of interest as a the ones
- belonging to a window that is constantly moving. The two most common sliding
- window implementations are time based windows and length based windows.
-
+ Sliding Windows are a way to scope the events of interest by defining
+ a window that is constantly moving. The two most common types of sliding
+ window implementations are time based windows and length based
+ windows.The next sections will detail each of them.
@@ -19,7 +22,16 @@
STREAM mode works.
-
-
+
+ Sliding windows start to match immediately and defining a sliding
+ window does not imply that the rule has to wait for the sliding window to
+ be "full" in order to match. For instance, a rule that calculates the
+ average of an event property on a window:length(10) will start calculating
+ the average immediately, and it will start at 0 (zero) for no-events, and
+ will update the average as events arrive one by one.
+
+
+
+
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows_SlidingLengthWindows.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows_SlidingLengthWindows.xml
index 80a7dc3749..972742737c 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows_SlidingLengthWindows.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows_SlidingLengthWindows.xml
@@ -1,19 +1,23 @@
+ xml:base="../../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
Sliding Length Windows
- Sliding Length Windows work the same way as Time Windows, but discard
- events based on the arrival of new events instead of flow of time.
+ Sliding Length Windows work the same way as Time Windows, but consider
+ events based on order of their insertion into the session instead of flow of
+ time.
- For instance, if the user wants to consider only the last 10 IBM Stock
+ For instance, if the user wants to consider only the last 10 RHT Stock
Ticks, independent of how old they are, the pattern would look like
this:
- StockTick( company == "IBM" ) over window:length( 10 )
+ StockTick( company == "RHT" ) over window:length( 10 )As you can see, the pattern is similar to the one presented in the
previous section, but instead of using window:time to define the sliding
@@ -25,9 +29,9 @@
like:
- aggregating values over length windows
+ aggregating values over length windows
- rule "Sound the alarm in case temperature rises above threshold"
+ rule "Sound the alarm in case temperature rises above threshold"
when
TemperatureThreshold( $max : max )
Number( doubleValue > $max ) from accumulate(
@@ -36,6 +40,24 @@ when
then
// sound the alarm
end
-
- The engine will keep only the last 100 readings.
+
+
+ The engine will keep only consider the last 100 readings to calculate
+ the average temperature.
+
+
+ Please note that falling off a length based window is not criteria
+ for event expiration in the session. The engine disregards events that
+ fall off a window when calculating that window, but does not remove the
+ event from the session based on that condition alone as there might be
+ other rules that depend on that event.
+
+
+
+ Please note that length based windows do not define temporal
+ constraints for event expiration from the session, and the engine will not
+ consider them. If events have no other rules defining temporal constraints
+ and no explicit expiration policy, the engine will keep them in the
+ session indefinitely.
+
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows_SlidingTimeWindows.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows_SlidingTimeWindows.xml
index c69bc0b987..cea89e04a2 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows_SlidingTimeWindows.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-SlidingWindows/Section-SlidingWindows_SlidingTimeWindows.xml
@@ -1,30 +1,33 @@
+ xml:base="../../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
Sliding Time WindowsSliding Time Windows allow the user to write rules that will only
- match events occurring in the last X time units.
+ match events occurring in the last X time units.
For instance, if the user wants to consider only the Stock Ticks that
happened in the last 2 minutes, the pattern would look like this:StockTick() over window:time( 2m )
- Drools uses the "over" keyword to associate windows to patterns.
-
+ Drools uses the "over" keyword to associate windows to
+ patterns.On a more elaborate example, if the user wants to sound an alarm in
case the average temperature over the last 10 minutes read from a sensor is
above the threshold value, the rule would look like:
- aggregating values over time windows
+ aggregating values over time windows
- rule "Sound the alarm in case temperature rises above threshold"
+ rule "Sound the alarm in case temperature rises above threshold"
when
TemperatureThreshold( $max : max )
Number( doubleValue > $max ) from accumulate(
@@ -34,7 +37,18 @@ then
// sound the alarm
end
-
- The engine will automatically discard any SensorReading older
- than 10 minutes and keep the calculated average consistent.
+
+
+ The engine will automatically disregard any SensorReading older than
+ 10 minutes and keep the calculated average consistent.
+
+
+ Please note that time based windows are considered when calculating
+ the interval an event remains in the working memory before being expired,
+ but an event falling off a sliding window does not mean by itself that the
+ event will be discarded from the working memory, as there might be other
+ rules that depend on that event. The engine will discard events only when
+ no other rules depend on that event and the expiration policy for that
+ event type is fulfilled.
+
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-StreamsSupport/Section-StreamsSupport_DeclaringAndUsingStreams.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-StreamsSupport/Section-StreamsSupport_DeclaringAndUsingStreams.xml
index 57a92e80f6..5e9dc3401b 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-StreamsSupport/Section-StreamsSupport_DeclaringAndUsingStreams.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-StreamsSupport/Section-StreamsSupport_DeclaringAndUsingStreams.xml
@@ -9,7 +9,7 @@
Entry points are declared implicitly in Drools by directly making use
of them in rules. I.e. referencing an entry point in a rule will make the
engine, at compile time, to identify and create the proper internal
- structures to suppor that entry point.
+ structures to support that entry point.
So, for instance, lets imagine a banking application, where
transactions are fed into the system coming from streams. One of the streams
@@ -65,7 +65,7 @@ end
Inserting events into an entry point is equally simple. Instead of
inserting events directly into the working memory, insert them into the
- entry point as shown in the example bellow:
+ entry point as shown in the example below:Inserting facts into an entry point
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-TemporalReasoning/Section-TemporalReasoning.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-TemporalReasoning/Section-TemporalReasoning.xml
index 16ab99e32a..6d6da96b28 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-TemporalReasoning/Section-TemporalReasoning.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-TemporalReasoning/Section-TemporalReasoning.xml
@@ -1,9 +1,12 @@
+ xml:base="./" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
Temporal ReasoningTemporal reasoning is another requirement of any CEP system. As
@@ -12,7 +15,7 @@
Temporal reasoning is an extensive field of research, from its roots
on Temporal Modal Logic to its more practical applications in business
- systems. There are hundreds of papers and thesis written and approches are
+ systems. There are hundreds of papers and thesis written and approaches are
described for several applications. Drools once more takes a pragmatic and
simple approach based on several sources, but specially worth noting the
following papers:
@@ -80,12 +83,17 @@
-
+
Drools implements the Interval-based Time Event Semantics described by
Allen, and represents Point-in-Time Events as Interval-based evens with
duration 0 (zero).
-
+
+ For all temporal operator intervals, the "*" (star) symbol is used
+ to indicate positive infinity and the "-*" (minus
+ star) is used to indicate negative infinity.
+
+
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-TemporalReasoning/Section-TemporalReasoning_TemporalOperators.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-TemporalReasoning/Section-TemporalReasoning_TemporalOperators.xml
index 1beb9a1220..0e309ed479 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-TemporalReasoning/Section-TemporalReasoning_TemporalOperators.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Features/Chapter-TemporalReasoning/Section-TemporalReasoning_TemporalOperators.xml
@@ -1,9 +1,12 @@
+ xml:base="../../" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:ns="http://docbook.org/ns/docbook">
Temporal OperatorsDrools implements all 13 operators defined by Allen and also their
@@ -15,9 +18,9 @@
The after evaluator correlates two events and matches when the
temporal distance from the current event to the event being correlated
- belongs to the distance range declared for the operator.
+ belongs to the distance range declared for the operator.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this after[ 3m30s, 4m ] $eventB )
@@ -28,29 +31,29 @@
3m30s <= $eventA.startTimestamp - $eventB.endTimeStamp <= 4m
- The temporal distance interval for the after operator is optional:
-
+ The temporal distance interval for the after operator is
+ optional:
- If two values are defined (like in the example bellow), the
- interval starts on the first value and finishes on the second.
+ If two values are defined (like in the example below), the
+ interval starts on the first value and finishes on the second.If only one value is defined, the interval starts on the value
- and finishes on the positive infinity.
+ and finishes on the positive infinity.
If no value is defined, it is assumed that the initial value is
- 1ms and the final value is the positive infinity.
+ 1ms and the final value is the positive infinity.
It is possible to define negative distances for this operator.
- Example:
+ Example:
$eventA : EventA( this after[ -3m30s, -2m ] $eventB )
@@ -59,11 +62,21 @@
If the first value is greater than the second value, the engine
automatically reverses them, as there is no reason to have the first
value greater than the second value. Example: the following two patterns
- are considered to have the same semantics:
+ are considered to have the same semantics:
$eventA : EventA( this after[ -3m30s, -2m ] $eventB )
$eventA : EventA( this after[ -2m, -3m30s ] $eventB )
+
+
+ The after, before and
+ coincides operators can be used to define
+ constraints between events, java.util.Date attributes, and long
+ attributes (interpreted as timestamps since epoch) in any combination.
+ Example:
+
+ EventA( this after $someDate )
+
@@ -71,10 +84,9 @@ $eventA : EventA( this after[ -2m, -3m30s ] $eventB )
The before evaluator correlates two events and matches when the
temporal distance from the event being correlated to the current
- correlated belongs to the distance range declared for the operator.
-
+ correlated belongs to the distance range declared for the operator.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this before[ 3m30s, 4m ] $eventB )
@@ -85,18 +97,18 @@ $eventA : EventA( this after[ -2m, -3m30s ] $eventB )
3m30s <= $eventB.startTimestamp - $eventA.endTimeStamp <= 4m
- The temporal distance interval for the before operator is optional:
-
+ The temporal distance interval for the before operator is
+ optional:
- If two values are defined (like in the example bellow), the
- interval starts on the first value and finishes on the second.
+ If two values are defined (like in the example below), the
+ interval starts on the first value and finishes on the second.If only one value is defined, then the interval starts on the
- value and finishes on the positive infinity.
+ value and finishes on the positive infinity.
@@ -107,7 +119,7 @@ $eventA : EventA( this after[ -2m, -3m30s ] $eventB )
It is possible to define negative distances for this operator.
- Example:
+ Example:
$eventA : EventA( this before[ -3m30s, -2m ] $eventB )
@@ -116,11 +128,21 @@ $eventA : EventA( this after[ -2m, -3m30s ] $eventB )
If the first value is greater than the second value, the engine
automatically reverses them, as there is no reason to have the first
value greater than the second value. Example: the following two patterns
- are considered to have the same semantics:
+ are considered to have the same semantics:
$eventA : EventA( this before[ -3m30s, -2m ] $eventB )
$eventA : EventA( this before[ -2m, -3m30s ] $eventB )
+
+
+ The after, before and
+ coincides operators can be used to define
+ constraints between events, java.util.Date attributes, and long
+ attributes (interpreted as timestamps since epoch) in any combination.
+ Example:
+
+ EventA( this after $someDate )
+
@@ -128,23 +150,23 @@ $eventA : EventA( this before[ -2m, -3m30s ] $eventB )
The coincides evaluator correlates two events and matches when both
happen at the same time. Optionally, the evaluator accept thresholds for
- the distance between events' start and finish timestamps.
+ the distance between events' start and finish timestamps.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this coincides $eventB ) The previous pattern will match if and only if the start timestamps
of both $eventA and $eventB are the same AND the end timestamp of both
- $eventA and $eventB also are the same.
+ $eventA and $eventB also are the same.
Optionally, this operator accepts one or two parameters. These
parameters are the thresholds for the distance between matching
- timestamps.
+ timestamps.
- If only one paratemer is given, it is used for both start and
+ If only one parameter is given, it is used for both start and
end timestamps.
@@ -155,11 +177,11 @@ $eventA : EventA( this before[ -2m, -3m30s ] $eventB )
- In other words:
+ In other words:$eventA : EventA( this coincides[15s, 10s] $eventB )
- Above pattern will match if and only if:
+ Above pattern will match if and only if:abs( $eventA.startTimestamp - $eventB.startTimestamp ) <= 15s &&
abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 10s
@@ -168,28 +190,38 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 10s
It makes no sense to use negative interval values for the
parameters and the engine will raise an error if that happens.
+
+
+ The after, before and
+ coincides operators can be used to define
+ constraints between events, java.util.Date attributes, and long
+ attributes (interpreted as timestamps since epoch) in any combination.
+ Example:
+
+ EventA( this after $someDate )
+ DuringThe during evaluator correlates two events and matches when the
- current event happens during the occurrence of the event being correlated.
-
+ current event happens during the occurrence of the event being
+ correlated.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this during $eventB ) The previous pattern will match if and only if the $eventA starts
- after $eventB starts and finishes before $eventB finishes.
+ after $eventB starts and finishes before $eventB finishes.
- In other words:
+ In other words:$eventB.startTimestamp < $eventA.startTimestamp <= $eventA.endTimestamp < $eventB.endTimestamp
- The during operator accepts 1, 2 or 4 optional parameters as follow:
-
+ The during operator accepts 1, 2 or 4 optional parameters as
+ follow:
@@ -212,7 +244,7 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 10s
If two values are defined, the first value will be the minimum
distance between the timestamps of both events, while the second value
will be the maximum distance between the timestamps of both events.
- Example:
+ Example:
$eventA : EventA( this during[ 5s, 10s ] $eventB )
@@ -245,28 +277,28 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 10s
The finishes evaluator correlates two events and matches when the
current event's start timestamp happens after the correlated event's start
- timestamp, but both end timestamps occur at the same time.
+ timestamp, but both end timestamps occur at the same time.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this finishes $eventB ) The previous pattern will match if and only if the $eventA starts
- after $eventB starts and finishes at the same time $eventB finishes.
-
+ after $eventB starts and finishes at the same time $eventB
+ finishes.
- In other words:
+ In other words:$eventB.startTimestamp < $eventA.startTimestamp &&
$eventA.endTimestamp == $eventB.endTimestamp The finishes evaluator accepts one optional parameter. If it is
defined, it determines the maximum distance between the end timestamp of
- both events in order for the operator to match. Example:
+ both events in order for the operator to match. Example:
$eventA : EventA( this finishes[ 5s ] $eventB )
- Will match if and only if:
+ Will match if and only if:$eventB.startTimestamp < $eventA.startTimestamp &&
abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
@@ -283,28 +315,28 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
The finishedby evaluator correlates two events and matches when the
current event start timestamp happens before the correlated event start
timestamp, but both end timestamps occur at the same time. This is the
- symmetrical opposite of finishes evaluator.
+ symmetrical opposite of finishes evaluator.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this finishedby $eventB ) The previous pattern will match if and only if the $eventA starts
- before $eventB starts and finishes at the same time $eventB finishes.
-
+ before $eventB starts and finishes at the same time $eventB
+ finishes.
- In other words:
+ In other words:$eventA.startTimestamp < $eventB.startTimestamp &&
$eventA.endTimestamp == $eventB.endTimestamp The finishedby evaluator accepts one optional parameter. If it is
defined, it determines the maximum distance between the end timestamp of
- both events in order for the operator to match. Example:
+ both events in order for the operator to match. Example:
$eventA : EventA( this finishedby[ 5s ] $eventB )
- Will match if and only if:
+ Will match if and only if:$eventA.startTimestamp < $eventB.startTimestamp &&
abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
@@ -320,21 +352,21 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
The includes evaluator correlates two events and matches when the
event being correlated happens during the current event. It is the
- symmetrical opposite of during evaluator.
+ symmetrical opposite of during evaluator.
Lets look at an example:$eventA : EventA( this includes $eventB ) The previous pattern will match if and only if the $eventB starts
- after $eventA starts and finishes before $eventA finishes.
+ after $eventA starts and finishes before $eventA finishes.
- In other words:
+ In other words:$eventA.startTimestamp < $eventB.startTimestamp <= $eventB.endTimestamp < $eventA.endTimestamp The includes operator accepts 1, 2 or 4 optional parameters as
- follow:
+ follow:
@@ -377,7 +409,7 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
$eventA : EventA( this includes[ 2s, 6s, 4s, 10s ] $eventB )
- Will match if and only if:
+ Will match if and only if:2s <= $eventB.startTimestamp - $eventA.startTimestamp <= 6s &&
4s <= $eventA.endTimestamp - $eventB.endTimestamp <= 10s
@@ -390,27 +422,27 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
The meets evaluator correlates two events and matches when the
current event's end timestamp happens at the same time as the correlated
- event's start timestamp.
+ event's start timestamp.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this meets $eventB ) The previous pattern will match if and only if the $eventA finishes
at the same time $eventB starts.
- In other words:
+ In other words:abs( $eventB.startTimestamp - $eventA.endTimestamp ) == 0 The meets evaluator accepts one optional parameter. If it is
defined, it determines the maximum distance between the end timestamp of
current event and the start timestamp of the correlated event in order for
- the operator to match. Example:
+ the operator to match. Example:
$eventA : EventA( this meets[ 5s ] $eventB )
- Will match if and only if:
+ Will match if and only if:abs( $eventB.startTimestamp - $eventA.endTimestamp) <= 5s
@@ -425,27 +457,27 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
The metby evaluator correlates two events and matches when the
current event's start timestamp happens at the same time as the correlated
- event's end timestamp.
+ event's end timestamp.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this metby $eventB ) The previous pattern will match if and only if the $eventA starts at
- the same time $eventB finishes.
+ the same time $eventB finishes.
- In other words:
+ In other words:abs( $eventA.startTimestamp - $eventB.endTimestamp ) == 0 The metby evaluator accepts one optional parameter. If it is
defined, it determines the maximum distance between the end timestamp of
the correlated event and the start timestamp of the current event in order
- for the operator to match. Example:
+ for the operator to match. Example:
$eventA : EventA( this metby[ 5s ] $eventB )
- Will match if and only if:
+ Will match if and only if:abs( $eventA.startTimestamp - $eventB.endTimestamp) <= 5s
@@ -461,13 +493,13 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
The overlaps evaluator correlates two events and matches when the
current event starts before the correlated event starts and finishes after
the correlated event starts, but before the correlated event finishes. In
- other words, both events have an overlapping period.
+ other words, both events have an overlapping period.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this overlaps $eventB )
- The previous pattern will match if and only if:
+ The previous pattern will match if and only if:$eventA.startTimestamp < $eventB.startTimestamp < $eventA.endTimestamp < $eventB.endTimestamp
@@ -512,24 +544,24 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
The overlappedby evaluator correlates two events and matches when
the correlated event starts before the current event starts and finishes
after the current event starts, but before the current event finishes. In
- other words, both events have an overlapping period.
+ other words, both events have an overlapping period.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this overlappedby $eventB )
- The previous pattern will match if and only if:
+ The previous pattern will match if and only if:$eventB.startTimestamp < $eventA.startTimestamp < $eventB.endTimestamp < $eventA.endTimestamp The overlappedby operator accepts 1 or 2 optional parameters as
- follow:
+ follow:
If one parameter is defined, this will be the maximum distance
between the start timestamp of the current event and the end timestamp
- of the correlated event. Example:
+ of the correlated event. Example:
$eventA : EventA( this overlappedby[ 5s ] $eventB )
@@ -545,7 +577,7 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
If two values are defined, the first value will be the minimum
distance and the second value will be the maximum distance between the
start timestamp of the current event and the end timestamp of the
- correlated event. Example:
+ correlated event. Example:
$eventA : EventA( this overlappedby[ 5s, 10s ] $eventB )
@@ -556,7 +588,7 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
-
+
@@ -564,28 +596,27 @@ abs( $eventA.endTimestamp - $eventB.endTimestamp ) <= 5s
The starts evaluator correlates two events and matches when the
current event's end timestamp happens before the correlated event's end
- timestamp, but both start timestamps occur at the same time.
+ timestamp, but both start timestamps occur at the same time.
- Lets look at an example:
+ Lets look at an example:$eventA : EventA( this starts $eventB ) The previous pattern will match if and only if the $eventA finishes
- before $eventB finishes and starts at the same time $eventB starts.
-
+ before $eventB finishes and starts at the same time $eventB starts.
- In other words:
+ In other words:$eventA.startTimestamp == $eventB.startTimestamp &&
$eventA.endTimestamp < $eventB.endTimestamp The starts evaluator accepts one optional parameter. If it is
defined, it determines the maximum distance between the start timestamp of
- both events in order for the operator to match. Example:
+ both events in order for the operator to match. Example:
$eventA : EventA( this starts[ 5s ] $eventB )
- Will match if and only if:
+ Will match if and only if:abs( $eventA.startTimestamp - $eventB.startTimestamp ) <= 5s &&
$eventA.endTimestamp < $eventB.endTimestamp
@@ -602,26 +633,25 @@ $eventA.endTimestamp < $eventB.endTimestamp
The startedby evaluator correlates two events and matches when the
correlating event's end timestamp happens before the current event's end
timestamp, but both start timestamps occur at the same time. Lets look at
- an example:
+ an example:
$eventA : EventA( this startedby $eventB ) The previous pattern will match if and only if the $eventB finishes
- before $eventA finishes and starts at the same time $eventB starts.
-
+ before $eventA finishes and starts at the same time $eventB starts.
- In other words:
+ In other words:$eventA.startTimestamp == $eventB.startTimestamp &&
$eventA.endTimestamp > $eventB.endTimestamp The startedby evaluator accepts one optional parameter. If it is
defined, it determines the maximum distance between the start timestamp of
- both events in order for the operator to match. Example:
+ both events in order for the operator to match. Example:
$eventA : EventA( this starts[ 5s ] $eventB )
- Will match if and only if:
+ Will match if and only if:abs( $eventA.startTimestamp - $eventB.startTimestamp ) <= 5s &&
$eventA.endTimestamp > $eventB.endTimestamp
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Introduction/Section-ComplexEventProcessing.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Introduction/Section-ComplexEventProcessing.xml
index 674d3dd789..b885ca7c0d 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Introduction/Section-ComplexEventProcessing.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Introduction/Section-ComplexEventProcessing.xml
@@ -43,7 +43,7 @@
of event processing. Two trends were born under the names of Event Stream
Processing and Complex Event Processing.
- In the very begginings, Event Stream Processing was focused on the
+ In the very beginnings, Event Stream Processing was focused on the
capabilities of processing streams of events in (near) real time, where the
main focus of Complex Event Processing was on the correlation and
composition of atomic events into complex (compound) events. An important
@@ -51,11 +51,11 @@
Luckham's book "The Power of Events" in 2002. In the book, Dr Luckham
introduces the concept of Complex Event Processing and how it can be used to
enhance systems that deal with events. Over the years, both trends converged
- to a common understanding and today these systems are all refered as CEP
+ to a common understanding and today these systems are all referred as CEP
systems.This is a very simplistic explanation to a really complex and fertile
- field of research, but sets a very highlevel and common understanding for
+ field of research, but sets a very high level and common understanding for
the concepts this guide will introduce.The current understanding of what Complex Event Processing is may be
@@ -78,7 +78,7 @@
In other words, CEP is about detecting and selecting the interesting
events (and only them) from an event cloud, finding their relationships and
- infering new data from them and their relationships.
+ inferring new data from them and their relationships.For the remaining of this guide, we will use the terms
Complex Event Processing
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Introduction/Section-DroolsFusion.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Introduction/Section-DroolsFusion.xml
index ddbdada211..90bbb7cbb8 100644
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Introduction/Section-DroolsFusion.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/Chapter-Introduction/Section-DroolsFusion.xml
@@ -44,7 +44,7 @@
- Both require seemless integration with the enterprise
+ Both require seamless integration with the enterprise
infrastructure and applications, specially on autonomous governance,
including, but not limited to, lifecycle management, auditing, security,
etc.
@@ -68,7 +68,7 @@
Drools was also born as a rules engine several years ago, but
following the vision of becoming a single platform for behavioral
modelling, it soon realized that it could only achieve this goal by
- crediting the same importante to the three complementary business
+ crediting the same importance to the three complementary business
modelling techniques:
@@ -91,7 +91,7 @@
Supporting Complex Event Processing, though, is much more than simply
understanding what an event is. CEP scenarios share several common and
- distiguishing characteristics:
+ distinguishing characteristics:
@@ -132,7 +132,7 @@
- Support Events, with their propper semantics, as first class
+ Support Events, with their proper semantics, as first class
citizens.
diff --git a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/master.xml b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/master.xml
index fba4930005..3d72351663 100755
--- a/drools-docs/drools-fusion-docs/src/main/docbook/en-US/master.xml
+++ b/drools-docs/drools-fusion-docs/src/main/docbook/en-US/master.xml
@@ -7,7 +7,7 @@
Drools Fusion User Guide
- 5.2.0-SNAPSHOT
+ Version &project.version;The JBoss Drools team
@@ -36,6 +36,4 @@
-
-
diff --git a/drools-docs/pom.xml b/drools-docs/pom.xml
index 0d9ec48959..be3a8044b7 100755
--- a/drools-docs/pom.xml
+++ b/drools-docs/pom.xml
@@ -6,13 +6,14 @@
org.droolsdrools-multiproject
- 5.2.0-SNAPSHOT
+ 5.5.0-SNAPSHOTdrools-docspomDrools Expert and Fusion Documentation
+ Drools documentation multiprojectdrools-expert-docs