[jboss-svn-commits] JBL Code SVN: r5412 - in labs/jbossrules/trunk: documentation/manual/en/Chapter-Decision_Tables drools-decisiontables drools-decisiontables/src/main/java/org/drools/decisiontable/model drools-decisiontables/src/main/java/org/drools/decisiontable/parser drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls drools-decisiontables/src/test/java/org drools-decisiontables/src/test/java/org/acme drools-decisiontables/src/test/java/org/acme/insurance drools-decisiontables/src/test/java/org/acme/insurance/launcher drools-decisiontables/src/test/java/org/drools/decisiontable drools-decisiontables/src/test/java/org/drools/decisiontable/parser drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls drools-decisiontables/src/test/resources/data drools-examples/src/main/java/org/drools/examples drools-ex! amples/src/main/java/org/drools/examples/decisiontable drools-examples/src/main/rules/org/drools/examples drools-ide/src/main/java/org/drools/ide/wizard/decisiontable drools-ide/src/main/java/org/drools/ide/wizard/project

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Aug 2 12:02:33 EDT 2006


Author: michael.neale at jboss.com
Date: 2006-08-02 12:01:15 -0400 (Wed, 02 Aug 2006)
New Revision: 5412

Added:
   labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/consequence.png
   labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/operator_completion.png
   labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/spanned_column.png
   labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/with_binding.png
   labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/with_param.png
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/LhsBuilder.java
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RhsBuilder.java
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SourceBuilder.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Driver.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Policy.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/launcher/
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/launcher/PricingRuleLauncher.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/LhsBuilderTest.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RhsBuilderTest.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/ExamplePolicyPricing.xls
   labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/PricingRuleDTExample.java
   labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/
   labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Driver.java
   labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Policy.java
   labs/jbossrules/trunk/drools-examples/src/main/rules/org/drools/examples/ExamplePolicyPricing.xls
Removed:
   labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/CorruptTeamAllocationExample.xls
Modified:
   labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/Section-Spreadsheet.xml
   labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/expanded.png
   labs/jbossrules/trunk/drools-decisiontables/.classpath
   labs/jbossrules/trunk/drools-decisiontables/pom.xml
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/model/Rule.java
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/ActionType.java
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SheetListener.java
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvParser.java
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/ExcelParser.java
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/NullSheetListener.java
   labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/PropertiesSheetListener.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetIntegrationTest.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/PropertiesSheetListenerTest.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseTest.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvParserTest.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls/ExcelParserTest.java
   labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/BasicWorkbook.xls
   labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/ComplexWorkbook.csv
   labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/ComplexWorkbook.xls
   labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/IntegrationExampleTest.xls
   labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/MultiSheetDST.xls
   labs/jbossrules/trunk/drools-ide/src/main/java/org/drools/ide/wizard/decisiontable/template.xls
   labs/jbossrules/trunk/drools-ide/src/main/java/org/drools/ide/wizard/project/Sample.drl.template
Log:
JBRULES-386 - merged from 3.0.x branch, enhancements to decision tables + doco changes and a new example

Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/Section-Spreadsheet.xml
===================================================================
--- labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/Section-Spreadsheet.xml	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/Section-Spreadsheet.xml	2006-08-02 16:01:15 UTC (rev 5412)
@@ -86,7 +86,7 @@
     is conventional to use colour to make it obvious what the different areas
     of the table mean.</para>
 
-    <para>Note that although the decision tables look like the process top
+    <para>Note that although the decision tables look like they process top
     down, this is not necessarily the case. It is ideal if you can author
     rules in such a way as order does not matter (simply as it makes
     maintenance easier, you are not trying to shift rows around all the time).
@@ -152,27 +152,40 @@
 
     <para>Now you can see the hidden magic that makes it work. The RuleSet
     keyword indicates the name to be used in the "rule package" that all the
-    rules will come under (this is optional, it will have a default) in the
-    cell immediately to the right. The other keywords visible in Column C are:
-    Import, Sequential which will be covered later - just note that in general
-    the keywords make up name/value pairs. The RuleTable keyword is important
-    as it indicates that a chunk of rules will follow, based on some rule
-    templates. After the RuleTable keyword there is a name - this name is used
-    to prefix the generated rules names (the row numbers are appended to
-    create unique rule names). The column of RuleTable indicates the column in
-    which the rules start.</para>
+    rules will come under (the name is optional, it will have a default but
+    you MUST have the "RuleSet" keyword) in the cell immediately to the right.
+    The other keywords visible in Column C are: Import, Sequential which will
+    be covered later - just note that in general the keywords make up
+    name/value pairs. The RuleTable keyword is important as it indicates that
+    a chunk of rules will follow, based on some rule templates. After the
+    RuleTable keyword there is a name - this name is used to prefix the
+    generated rules names (the row numbers are appended to create unique rule
+    names). The column of RuleTable indicates the column in which the rules
+    start (columns to the left are ignored).</para>
 
     <para>Referring to row 14 (the row immediately after RuleTable): the
     keywords CONDITION and ACTION indicate that the data in the columns below
     are for either the LHS or the RHS parts of a rule. There are other
-    attributes on the rule which can also be optionally set this way. Row 15
-    contains the rule templates themselves: note that they use the "$para"
-    place holder to indicate where data from the cells below will be populated
-    (you can use $param, or $1, $2 etc to indicate parameters from a comma
-    seperated list in a cell below). Row 16 is ignored - it is textual
-    descriptions of the rule template.</para>
+    attributes on the rule which can also be optionally set this way.</para>
 
-    <para>Row 17 to 18 shows data, which will be combined (interpolated) with
+    <para>Row 15 contains declarations of "ObjectTypes" - the content in this
+    row is optional (if you are not using it, you must leave a blank row - but
+    you *will* want to use it !). When you use this row, the values in the
+    cells below (row 16) become constraints on that object type. In the above
+    case, it will generate: Person(age=="42") etc (where 42 comes from row
+    18). In the above example, the "==" is implicit (if you just put a field
+    name, it will assume that you are looking for exact matches). Also note
+    that you can have a ObjectType declaration span columns (via merged cells)
+    - and that means that all columns below the merged range will be combined
+    into the one set of contraints.</para>
+
+    <para>Row 16 contains the rule templates themselves: note that they can
+    use the "$para" place holder to indicate where data from the cells below
+    will be populated (you can use $param, or $1, $2 etc to indicate
+    parameters from a comma seperated list in a cell below). Row 17 is ignored
+    - it is textual descriptions of the rule template.</para>
+
+    <para>Row 18 to 19 shows 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 (eg it means that condition, or action, does
     not apply for that rule-row). Rule rows are read until there is a BLANK
@@ -182,6 +195,21 @@
     same one where the RuleTable or RuleSet keywords should appear (in this
     case column C has been chosen to be significant, but you can use column A
     if you like).</para>
+
+    <para>In the above example, rules would be rendered like the following (as
+    it uses the "ObjectType" row): <programlisting>//row 18
+rule "Cheese_fans_18"
+  when
+    Person(age=="42")
+    Cheese(type=="stilton")
+  then
+    list.add("Old man stilton");
+end
+
+</programlisting> Note that the [age=="42"] and [type=="stilton"] are
+    interpreted as single 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".</para>
   </section>
 
   <section>
@@ -191,18 +219,81 @@
       <title>Syntax of templates</title>
 
       <para>The syntax of what goes in the templates is dependent on if it is
-      a CONDITION column or ACTION column. In either case, it is identical to
+      a CONDITION column or ACTION column. In mosts cases, it is identical to
       "vanilla" DRL for the LHS or RHS respectively. This means in the LHS,
       the constraint language must be used, and in the RHS it is a snippet of
       code to be executed.</para>
 
-      <para>The "$para" place holder is used in templates to indicate where
+      <para>The "$param" place holder is used in templates to indicate where
       data form the cell will be interpolated. You can also use "$1" to the
       same effect. If the cell contains a comma seperated list of values, $1
       and $2 etc. may be used to indicate which positional parameter from the
       list of values in the cell will be used. <programlisting>For example: If the templates is [Foo(bar == $param)] and the cell is [ 42 ] then the result will be [Foo(bar == 42)]
 If the template is [Foo(bar &lt; $1, baz == $2)] and the cell is [42,42] then the result will be [Foo(bar &gt; 42, baz ==42)]
 </programlisting></para>
+
+      <para>For conditions: How snippets are rendered depends on if there is
+      anything in the row above (where ObjectType declarations may appear). If
+      there is, then the snippets are rendered as individual constraints on
+      that ObjectType. If there isn't, then they are just rendered as is (with
+      values substituted). If you put just a plain field (as in the example
+      above) then it will assume you mean equality. If you put another
+      operator at the end of the snippet, then the values will put
+      interpolated at the end of the contraint, otherwise it will look for
+      "$param" as outlined previously.</para>
+
+      <para>For consequences: How snippets are rendered also depends on if
+      there is anything in the row immediately above it. If there is nothing
+      there, the output is simple the interpolated snippets. If there is
+      something there (which would typically be a bound variable or a global
+      like in the example above) then it will append it as a method call on
+      that object (refer to the above example).</para>
+
+      <para>This may be easiest to understand with some examples below.
+      <screenshot>
+          <mediaobject>
+            <imageobject>
+              <imagedata fileref="spanned_column.png" />
+            </imageobject>
+          </mediaobject>
+        </screenshot> The above shows how the Person ObjectType declaration
+      spans 2 columns in the spreadsheet, thus both constraints will appear as
+      Person(age == ... , type == ...). As before, as only the field names are
+      present in the snippet, they imply an equality test. <screenshot>
+          <mediaobject>
+            <imageobject>
+              <imagedata fileref="with_param.png" />
+            </imageobject>
+          </mediaobject>
+        </screenshot> The above condition example shows how you use
+      interpolation to place the values in the snippet (in this case it would
+      result in Person(age == "42")).<screenshot>
+          <mediaobject>
+            <imageobject>
+              <imagedata fileref="operator_completion.png" />
+            </imageobject>
+          </mediaobject>
+        </screenshot> The above condition example show that if you put an
+      operator on the end by itself, the values will be placed after the
+      operator automatically. <screenshot>
+          <mediaobject>
+            <imageobject>
+              <imagedata fileref="with_binding.png" />
+            </imageobject>
+          </mediaobject>
+        </screenshot> You can of course put a binding in before the column
+      (the constraints will be added from the cells below). You can put
+      anything in the ObjectType row (eg it could be a pre condition for the
+      columns in the spreadsheet columns that follow).<screenshot>
+          <mediaobject>
+            <imageobject>
+              <imagedata fileref="consequence.png" />
+            </imageobject>
+          </mediaobject>
+        </screenshot> This shows how the consequence could be done the by
+      simple interpolation (just leave the cell above blank, the same applies
+      to condition columns) - with this style you can put whatever you want in
+      the consequence (not just one method call).</para>
     </section>
 
     <section>

Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/consequence.png
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/consequence.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/expanded.png
===================================================================
(Binary files differ)

Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/operator_completion.png
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/operator_completion.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/spanned_column.png
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/spanned_column.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/with_binding.png
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/with_binding.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/with_param.png
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/documentation/manual/en/Chapter-Decision_Tables/with_param.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: labs/jbossrules/trunk/drools-decisiontables/.classpath
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/.classpath	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/.classpath	2006-08-02 16:01:15 UTC (rev 5412)
@@ -1,30 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-  <classpathentry kind="src" path="src/main/java"/>
-  <classpathentry kind="src" path="src/main/resources"/>
-  <classpathentry kind="src" path="src/test/java" output="target/test-classes"/>
-  <classpathentry kind="src" path="src/test/resources" output="target/test-classes"/>
-  <classpathentry kind="output" path="target/classes"/>
-  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-  <classpathentry kind="var" path="M2_REPO/org/eclipse/jdt/core/3.2.0.666/core-3.2.0.666.jar"/>
-  <classpathentry kind="src" path="/drools-compiler"/>
-  <classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-jci-core/1.0-406301/commons-jci-core-1.0-406301.jar"/>
-  <classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar"/>
-  <classpathentry kind="var" path="M2_REPO/xstream/xstream/1.1.3/xstream-1.1.3.jar"/>
-  <classpathentry kind="var" path="M2_REPO/janino/janino/2.4.3/janino-2.4.3.jar"/>
-  <classpathentry kind="src" path="/drools-core"/>
-  <classpathentry kind="var" path="M2_REPO/org/antlr/antlr/3.0ea8/antlr-3.0ea8.jar"/>
-  <classpathentry kind="var" path="M2_REPO/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar"/>
-  <classpathentry kind="var" path="M2_REPO/jung/jung/1.7.2/jung-1.7.2.jar"/>
-  <classpathentry kind="var" path="M2_REPO/commons-lang/commons-lang/2.1/commons-lang-2.1.jar"/>
-  <classpathentry kind="var" path="M2_REPO/colt/colt/1.2.0/colt-1.2.0.jar"/>
-  <classpathentry kind="var" path="M2_REPO/commons-collections/commons-collections/3.1/commons-collections-3.1.jar"/>
-  <classpathentry kind="var" path="M2_REPO/commons-io/commons-io/1.1/commons-io-1.1.jar"/>
-  <classpathentry kind="var" path="M2_REPO/concurrent/concurrent/1.3.4/concurrent-1.3.4.jar"/>
-  <classpathentry kind="var" path="M2_REPO/poi/poi/2.5.1-final-20040804/poi-2.5.1-final-20040804.jar"/>
-  <classpathentry kind="var" path="M2_REPO/xerces/xercesImpl/2.6.2/xercesImpl-2.6.2.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-jci-eclipse/3.2.0.666/commons-jci-eclipse-3.2.0.666.jar"/>
-  <classpathentry kind="var" path="M2_REPO/xpp3/xpp3/1.1.3.4.O/xpp3-1.1.3.4.O.jar"/>
-  <classpathentry kind="var" path="M2_REPO/antlr/antlr/2.7.6/antlr-2.7.6.jar"/>
-  <classpathentry kind="var" path="M2_REPO/antlr/stringtemplate/2.3b6/stringtemplate-2.3b6.jar"/>
-  <classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-jci-janino/2.4.3/commons-jci-janino-2.4.3.jar"/>
-</classpath>
\ No newline at end of file
+	<classpathentry kind="src" path="src/main/java"/>
+	<classpathentry kind="src" path="src/main/resources"/>
+	<classpathentry output="target/test-classes" kind="src" path="src/test/java"/>
+	<classpathentry output="target/test-classes" kind="src" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="var" path="M2_REPO/org/eclipse/jdt/core/3.2.0.666/core-3.2.0.666.jar"/>
+	<classpathentry kind="src" path="/drools-compiler"/>
+	<classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-jci-core/1.0-406301/commons-jci-core-1.0-406301.jar"/>
+	<classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar"/>
+	<classpathentry kind="var" path="M2_REPO/xstream/xstream/1.1.3/xstream-1.1.3.jar"/>
+	<classpathentry kind="var" path="M2_REPO/janino/janino/2.4.3/janino-2.4.3.jar"/>
+	<classpathentry kind="src" path="/drools-core"/>
+	<classpathentry kind="var" path="M2_REPO/org/antlr/antlr/3.0ea8/antlr-3.0ea8.jar"/>
+	<classpathentry kind="var" path="M2_REPO/commons-logging/commons-logging-api/1.0.4/commons-logging-api-1.0.4.jar"/>
+	<classpathentry kind="var" path="M2_REPO/jung/jung/1.7.2/jung-1.7.2.jar"/>
+	<classpathentry kind="var" path="M2_REPO/commons-lang/commons-lang/2.1/commons-lang-2.1.jar"/>
+	<classpathentry kind="var" path="M2_REPO/colt/colt/1.2.0/colt-1.2.0.jar"/>
+	<classpathentry kind="var" path="M2_REPO/commons-collections/commons-collections/3.1/commons-collections-3.1.jar"/>
+	<classpathentry kind="var" path="M2_REPO/commons-io/commons-io/1.1/commons-io-1.1.jar"/>
+	<classpathentry kind="var" path="M2_REPO/concurrent/concurrent/1.3.4/concurrent-1.3.4.jar"/>
+	<classpathentry kind="var" path="M2_REPO/xerces/xercesImpl/2.6.2/xercesImpl-2.6.2.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-jci-eclipse/3.2.0.666/commons-jci-eclipse-3.2.0.666.jar"/>
+	<classpathentry kind="var" path="M2_REPO/xpp3/xpp3/1.1.3.4.O/xpp3-1.1.3.4.O.jar"/>
+	<classpathentry kind="var" path="M2_REPO/antlr/antlr/2.7.6/antlr-2.7.6.jar"/>
+	<classpathentry kind="var" path="M2_REPO/antlr/stringtemplate/2.3b6/stringtemplate-2.3b6.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-jci-janino/2.4.3/commons-jci-janino-2.4.3.jar"/>
+	<classpathentry kind="var" path="M2_REPO/jexcelapi/jxl/2.4.2/jxl-2.4.2.jar"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

Modified: labs/jbossrules/trunk/drools-decisiontables/pom.xml
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/pom.xml	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/pom.xml	2006-08-02 16:01:15 UTC (rev 5412)
@@ -2,7 +2,7 @@
   <parent>
     <artifactId>drools</artifactId>
     <groupId>org.drools</groupId>
-    <version>3.0.2</version>
+    <version>3.0.3</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
@@ -10,7 +10,7 @@
   <artifactId>drools-decisiontables</artifactId>
 
   <name>Drools :: Decision Tables</name>
-  <version>3.0.2</version>
+  <version>3.0.3</version>
   
   <repositories>
     <repository>
@@ -21,9 +21,9 @@
   
   <dependencies>  
 	<dependency>
-		<groupId>poi</groupId>
-		<artifactId>poi</artifactId>
-		<version>2.5.1-final-20040804</version>
+		<groupId>jexcelapi</groupId>
+		<artifactId>jxl</artifactId>
+		<version>2.4.2</version>
 	</dependency>
     <dependency>
       <groupId>org.drools</groupId>
@@ -66,4 +66,4 @@
   
 
 
-</project>
\ No newline at end of file
+</project>

Modified: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/model/Rule.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/model/Rule.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/model/Rule.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -17,10 +17,13 @@
  */
 
 import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.drools.decisiontable.parser.SourceBuilder;
+
 /**
  * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale </a>
  * 
@@ -54,7 +57,7 @@
     private List             _rhs;
 
     private int              _spreadsheetRow;
-
+    
     /**
      * Create a new rule. Note that the rule name should be post-fixed with the row number,
      * as one way of providing tracability for errors back to the originating spreadsheet.
@@ -75,6 +78,7 @@
         this._rhs = new LinkedList();
         this._spreadsheetRow = spreadsheetRow;
     }
+    
 
     public void addCondition(final Condition con) {
         this._lhs.add( con );

Modified: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/ActionType.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/ActionType.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/ActionType.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -26,7 +26,7 @@
  * you can expect to see in the rows directly below.
  * 
  * There are five types of columns relevant to a rule table.
- * @author <a href="mailto:Michael.Neale at gmail.com"> Michael Neale</a>
+ * @author Michael Neale
  */
 public class ActionType {
 
@@ -56,19 +56,31 @@
 
     int                     type;
 
-    String                  value;
+    private SourceBuilder sourceBuilder = null;
 
-    ActionType(final int actionType,
-               final String cellValue) {
+//    private String                  value;
+
+    ActionType(final int actionType) {
         this.type = actionType;
-        this.value = cellValue;
     }
+        
 
-    String getSnippet(final String cellValue) {
-        final SnippetBuilder builder = new SnippetBuilder( this.value );
-        return builder.build( cellValue );
+    /**
+     * This is only set for LHS or RHS building. 
+     */
+    public void setSourceBuilder(SourceBuilder src) {
+        this.sourceBuilder = src;
     }
+    
+    public SourceBuilder getSourceBuilder() {
+        return this.sourceBuilder;
+    }
 
+//    String getSnippet(final String cellValue) {
+//        final SnippetBuilder builder = new SnippetBuilder( this.value );
+//        return builder.build( cellValue );
+//    }
+
     /**
      * Create a new action type that matches this cell, and add it to the map,
      * keyed on that column.
@@ -79,12 +91,10 @@
                                         final int row) {
         if ( value.toUpperCase().startsWith( "C" ) ) {
             actionTypeMap.put( new Integer( column ),
-                               new ActionType( ActionType.CONDITION,
-                                               null ) );
+                               new ActionType( ActionType.CONDITION) );
         } else if ( value.toUpperCase().startsWith( "A" ) ) {
             actionTypeMap.put( new Integer( column ),
-                               new ActionType( ActionType.ACTION,
-                                               null ) );
+                               new ActionType( ActionType.ACTION) );
         } else if ( value.toUpperCase().startsWith( "P" ) ) // if the title cell
         // value starts with
         // "P" then put a
@@ -93,8 +103,7 @@
         // list
         {
             actionTypeMap.put( new Integer( column ),
-                               new ActionType( ActionType.PRIORITY,
-                                               null ) );
+                               new ActionType( ActionType.PRIORITY ) );
         } else if ( value.toUpperCase().startsWith( "D" ) ) // if the title cell
         // value starts with
         // "D" then put a
@@ -103,8 +112,7 @@
         // list
         {
             actionTypeMap.put( new Integer( column ),
-                               new ActionType( ActionType.DURATION,
-                                               null ) );
+                               new ActionType( ActionType.DURATION ) );
         } else if ( value.toUpperCase().startsWith( "N" ) ) // if the title cell
         // value starts with
         // "N" then put a
@@ -113,8 +121,7 @@
         // list
         {
             actionTypeMap.put( new Integer( column ),
-                               new ActionType( ActionType.NAME,
-                                               null ) );
+                               new ActionType( ActionType.NAME ) );
         } else if ( value.toUpperCase().startsWith( "I" ) ) // if the title cell
         // value starts with
         // "I" then put a
@@ -123,9 +130,8 @@
         // list
         {
             actionTypeMap.put( new Integer( column ),
-                               new ActionType( ActionType.DESCRIPTION,
-                                               null ) );
-        } else if ( value.toUpperCase().startsWith( "U" ) ) // if the title cell
+                               new ActionType( ActionType.DESCRIPTION ) );
+        } else if ( value.toUpperCase().startsWith( "U" ) || value.toUpperCase().equals( "NO-LOOP" ) ) // if the title cell
         // value starts with
         // "U" then put a
         // ActionType.NOLOOP
@@ -133,9 +139,8 @@
         // list
         {
             actionTypeMap.put( new Integer( column ),
-                               new ActionType( ActionType.NOLOOP,
-                                               null ) );
-        } else if ( value.toUpperCase().startsWith( "X" ) ) // if the title cell
+                               new ActionType( ActionType.NOLOOP ) );
+        } else if ( value.toUpperCase().startsWith( "X" ) || value.toUpperCase().equals( "ACTIVATION-GROUP" ) ) // if the title cell
         // value starts with
         // "X" then put a
         // ActionType.XORGROUP
@@ -143,11 +148,26 @@
         // list
         {
             actionTypeMap.put( new Integer( column ),
-                               new ActionType( ActionType.ACTIVATIONGROUP,
-                                               null ) );
+                               new ActionType( ActionType.ACTIVATIONGROUP ) );
         } else {
             throw new DecisionTableParseException( "Invalid column header (ACTION type), " + "should be CONDITION or ACTION (etc..) row number:" + (row + 1) + " cell number:" + (column + 1) + " - does not contain a leading C or A identifer." );
         }
     }
 
+    /**
+     * This is where a code snippet template is added.
+     */
+    public void addTemplate(int col, String content) {
+        this.sourceBuilder.addTemplate(  col, content );        
+    }
+    
+    /**
+     * Values are added to populate the template.
+     * The source builder contained needs to be "cleared" when the resultant snippet is extracted.
+     */
+    public void addCellValue(int col, String content) {
+        this.sourceBuilder.addCellValue( col, content );
+    }
+    
+
 }
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/LhsBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/LhsBuilder.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/LhsBuilder.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,163 @@
+package org.drools.decisiontable.parser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.drools.decisiontable.model.SnippetBuilder;
+
+/**
+ * This utility will build up a list of constraints for a column.
+ * For instance, the column has been spanned across multiple cells, and the cells below
+ * contain the constraints.
+ * @author Michael Neale
+ *
+ */
+public class LhsBuilder implements SourceBuilder {
+
+    private String column;
+    private Map    constraints;
+    private List    values;
+    private boolean hasValues;
+    private static Set operators;
+
+    static {
+        operators = new HashSet();
+        operators.add( "==" );
+        operators.add( "=" );
+        operators.add( "!=" );
+        operators.add( "<" );
+        operators.add( ">" );
+        operators.add( "<=" );
+        operators.add( ">=" );
+        operators.add( "contains" );
+        operators.add( "matches" );
+    }
+    
+    
+    /**
+     * @param colDefinition The initial column definition that is shared via merged cells.
+     */
+    public LhsBuilder(String colDefinition) {
+        this.column = colDefinition == null ? "" : colDefinition;
+        this.constraints = new HashMap();
+        this.values = new ArrayList();
+    }
+
+    public void addTemplate(int column, String content) {
+        Integer key = new Integer( column );
+        content = content.trim();
+        if ( constraints.containsKey( key ) ) {
+            throw new IllegalArgumentException( "Internal error: Can't have a constraint added twice to one spreadsheet col." );
+        }
+        
+        //we can wrap all values in quotes, it all works
+        FieldType fieldType = calcFieldType( content );
+        if (fieldType == FieldType.NORMAL_FIELD || !isMultipleConstraints()) {
+            constraints.put( key,
+                             content );            
+        } else if (fieldType == FieldType.SINGLE_FIELD) {
+            constraints.put( key, content + " == \"$param\"" );
+        } else if (fieldType == FieldType.OPERATOR_FIELD) {
+            constraints.put( key, content + " \"$param\"" );
+        }
+        
+    }
+    
+    public void clearValues() {
+        this.hasValues = false;
+        this.values.clear();
+    }
+
+    public void addCellValue(int col,
+                             String value) {
+        this.hasValues = true;
+        Integer key = new Integer( col );
+        String content = (String) this.constraints.get( key );
+
+        SnippetBuilder snip = new SnippetBuilder( content );
+        String result = snip.build( value );
+        this.values.add( result );
+
+    }
+
+    public String getResult() {
+        StringBuffer buf = new StringBuffer();
+        if ( !isMultipleConstraints() ) {
+            for ( Iterator iter = values.iterator(); iter.hasNext(); ) {
+                String content = (String) iter.next();
+                buf.append( content );
+                if (iter.hasNext()) {
+                    buf.append( '\n' );
+                }
+            }
+            return buf.toString();
+        } else {
+            buf.append( this.column );
+            buf.append( '(' );
+            for ( Iterator iter = values.iterator(); iter.hasNext(); ) {
+                buf.append( iter.next());
+                if (iter.hasNext()) {
+                    buf.append( ", " );
+                }
+                
+            }
+            buf.append( ')' );
+            return buf.toString();
+        }
+    }
+
+    /** Returns true if this is building up multiple constraints as in:
+     * Foo(a ==b, c == d) etc...
+     * If not, then it it really just like the "classic" style DTs.
+     */
+    boolean isMultipleConstraints() {
+        if ( "".equals( column ) ) {
+            return false;
+        } else {
+            if ( column.endsWith( ")" ) ) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+    }
+
+    /**
+     * Work out the type of "field" that is being specified, 
+     * as in :
+     * age 
+     * age <
+     * age == $param
+     * 
+     * etc. as we treat them all differently.
+     */
+    public FieldType calcFieldType(String content) {
+        if (content.indexOf( "$param" ) != -1 || content.indexOf( "$1" ) != -1 ) {
+            return FieldType.NORMAL_FIELD;
+        }
+        for ( Iterator iter = operators.iterator(); iter.hasNext(); ) {
+            String op = (String) iter.next();
+            if (content.endsWith( op )) {
+                return FieldType.OPERATOR_FIELD;
+            }            
+        }
+        return FieldType.SINGLE_FIELD;
+    }
+    
+    static class FieldType {
+        public static final FieldType SINGLE_FIELD = new FieldType();
+        public static final FieldType OPERATOR_FIELD = new FieldType();
+        public static final FieldType NORMAL_FIELD = new FieldType();
+    }
+
+    public boolean hasValues() {
+        return hasValues;
+        
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/LhsBuilder.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RhsBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RhsBuilder.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RhsBuilder.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,80 @@
+package org.drools.decisiontable.parser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.decisiontable.model.SnippetBuilder;
+
+/**
+ * Builds up a consequence entry.
+ * @author Michael Neale
+ *
+ */
+public class RhsBuilder implements SourceBuilder {
+
+    private Map     templates;
+    private String  variable;
+    private List    values;
+    private boolean hasValues;
+
+    /**
+     * @param boundVariable Pass in a bound variable if there is one.
+     * Any cells below then will be called as methods on it. 
+     * Leaving it blank will make it work in "classic" mode.
+     */
+    public RhsBuilder(String boundVariable) {
+        this.variable = boundVariable == null ? "" : boundVariable.trim();
+        this.templates = new HashMap();
+        this.values = new ArrayList();
+    }
+
+    public void addTemplate(int col,
+                                       String content) {
+        Integer key = new Integer( col );
+        content = content.trim();
+        if ( isBoundVar() ) {
+            content = variable + "." + content + ";";
+        }
+        this.templates.put( key,
+                            content );
+    }
+
+    private boolean isBoundVar() {
+        return !("".equals( variable ));
+    }
+
+    public void addCellValue(int col,
+                             String value) {
+        hasValues = true;
+        String template = (String) this.templates.get( new Integer( col ) );
+        SnippetBuilder snip = new SnippetBuilder(template);
+        
+        this.values.add(snip.build( value ));
+
+    }
+    
+    public void clearValues() {
+        this.hasValues = false;
+        this.values.clear();
+    }
+    
+    public String getResult() {
+        StringBuffer buf = new StringBuffer();
+        for ( Iterator iter = this.values.iterator(); iter.hasNext(); ) {            
+            buf.append( iter.next() );
+            if (iter.hasNext()) {
+                buf.append( '\n' );
+            }
+        }
+        return buf.toString();
+    }
+
+    public boolean hasValues() {
+        
+        return hasValues;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RhsBuilder.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -45,7 +46,11 @@
  * row after the table identifier defines the column type: either a condition
  * ("C") or consequence ("A" for action), and so on.
  * 
- * The second row identifies the java code block associated with the condition
+ * The second row contains ObjectType declarations (optionally, or can be left blank).
+ * If cells are merged, then all snippets below the merged bit will become part of
+ * the same column as seperate constraints.
+ * 
+ * The third row identifies the java code block associated with the condition
  * or consequence. This code block will include a parameter marker for the
  * attribute defined by that column.
  * 
@@ -65,8 +70,9 @@
     public static final String      RULE_TABLE_TAG         = "RuleTable";
     public static final String      RULESET_TAG            = "RuleSet";
     private static final int        ACTION_ROW             = 1;
-    private static final int        CODE_ROW               = 2;
-    private static final int        LABEL_ROW              = 3;
+    private static final int		OBJECT_TYPE_ROW		   = 2;
+    private static final int        CODE_ROW               = 3;
+    private static final int        LABEL_ROW              = 4;
 
     //state machine variables for this parser
     private boolean                 _isInRuleTable         = false;
@@ -79,9 +85,12 @@
 
     //accumulated output
     private Map                     _actions;
-    private final HashMap                 _cellComments          = new HashMap();
-    private final List                    _ruleList              = new LinkedList();
-
+    private final HashMap           _cellComments                = new HashMap();
+    private final List              _ruleList                    = new LinkedList();
+    
+    //need to keep an ordered list of this to make conditions appear in the right order
+    private List                    sourceBuilders               = new ArrayList();
+    
     private final PropertiesSheetListener _propertiesListner     = new PropertiesSheetListener();
 
     /**
@@ -142,6 +151,7 @@
     public void finishSheet() {
         this._propertiesListner.finishSheet();
         finishRuleTable();
+        flushRule();
     }
 
     /*
@@ -151,10 +161,35 @@
      */
     public void newRow(final int rowNumber,
                        final int columns) {
+        if (_currentRule != null)
+            flushRule();
         // nothing to see here... these aren't the droids your looking for..
         // move along...
     }
 
+    /**
+     * This makes sure that the rules have all their components added.
+     * As when there are merged/spanned cells, they may be left out.
+     */
+    private void flushRule() {        
+        for ( Iterator iter = sourceBuilders.iterator(); iter.hasNext(); ) {
+            SourceBuilder src = (SourceBuilder) iter.next();
+            if (src.hasValues()) {
+                if (src instanceof LhsBuilder) {
+                    Condition con = new Condition();
+                    con.setSnippet( src.getResult() );
+                    _currentRule.addCondition( con );
+                } else if (src instanceof RhsBuilder ) {
+                    Consequence con = new Consequence();
+                    con.setSnippet( src.getResult() );
+                    _currentRule.addConsequence( con );
+                }
+                src.clearValues();
+            }
+        }
+        
+    }
+
     /*
      * (non-Javadoc)
      * 
@@ -162,14 +197,19 @@
      */
     public void newCell(final int row,
                         final int column,
-                        final String value) {
+                        final String value, 
+                        int mergedColStart) {
         if ( isCellValueEmpty( value ) ) {
             return;
         }
+        if (_isInRuleTable && row == this._ruleStartRow) {
+        	return;
+        }
         if ( this._isInRuleTable ) {
             processRuleCell( row,
                              column,
-                             value );
+                             value, 
+                             mergedColStart);
         } else {
             processNonRuleCell( row,
                                 column,
@@ -186,6 +226,7 @@
 
         this._isInRuleTable = true;
         this._actions = new HashMap();
+        this.sourceBuilders = new ArrayList();
         this._ruleStartColumn = column;
         this._ruleStartRow = row;
         this._ruleRow = row + RuleSheetListener.LABEL_ROW + 1;
@@ -210,6 +251,7 @@
         if ( this._isInRuleTable ) {
             this._currentSequentialFlag = false;
             this._isInRuleTable = false;
+            
         }
     }
 
@@ -223,13 +265,14 @@
         } else {
             this._propertiesListner.newCell( row,
                                         column,
-                                        value );
+                                        value, SheetListener.NON_MERGED);
         }
     }
 
     private void processRuleCell(final int row,
                                  final int column,
-                                 final String value) {
+                                 final String value,
+                                 final int mergedColStart) {
         if ( value.startsWith( RuleSheetListener.RULE_TABLE_TAG ) ) {
             finishRuleTable();
             initRuleTable( row,
@@ -255,6 +298,12 @@
                                              column,
                                              row );
                 break;
+            case OBJECT_TYPE_ROW :
+            	objectTypeRow( row, 
+                               column,
+                               value,
+                               mergedColStart);
+            	break;
             case CODE_ROW :
                 codeRow( row,
                          column,
@@ -264,26 +313,80 @@
                 labelRow( row,
                           column,
                           value );
-                break;
+                break;                
             default :
-                nextRule( row,
+                nextDataCell( row,
                           column,
                           value );
                 break;
         }
     }
 
+    /**
+     * This is for handling a row where an object declaration may appear,
+     * this is the row immediately above the snippets.
+     * It may be blank, but there has to be a row here.
+     * 
+     * Merged cells have "special meaning" which is why this is so freaking hard.
+     * A future refactor may be to move away from an "event" based listener.
+     */
+    private void objectTypeRow(final int row,
+                         final int column,
+                         final String value,
+                         final int mergedColStart) {
+        if (value.indexOf( "$param" ) > -1 || value.indexOf( "$1" ) > -1) {
+            throw new DecisionTableParseException("It looks like you have snippets in the row that is " +
+                                    "meant for column declarations." +
+                                    " Please insert an additional row before the snippets." +
+                                    " Row number: " + (row + 1));
+        }
+        ActionType action = getActionForColumn( row, column );
+        if (mergedColStart == SheetListener.NON_MERGED) {
+            if (action.type == ActionType.CONDITION) {
+                SourceBuilder src = new LhsBuilder(value);
+                action.setSourceBuilder(src);
+                this.sourceBuilders.add(src);
+                
+            } else if (action.type == ActionType.ACTION) {
+                SourceBuilder src = new RhsBuilder(value);
+                action.setSourceBuilder(src);
+                this.sourceBuilders.add(src);
+            }
+        } else {
+            if (column == mergedColStart) {
+                if (action.type == ActionType.CONDITION) {                    
+                    action.setSourceBuilder(new LhsBuilder(value));
+                    this.sourceBuilders.add( action.getSourceBuilder() );
+                } else if (action.type == ActionType.ACTION) {                    
+                    action.setSourceBuilder(new RhsBuilder(value));
+                    this.sourceBuilders.add( action.getSourceBuilder() );
+                }
+            } else {
+                ActionType startOfMergeAction = getActionForColumn( row, mergedColStart );
+                action.setSourceBuilder( startOfMergeAction.getSourceBuilder() );
+            }
+            
+        }
+    }
+    
     private void codeRow(final int row,
                          final int column,
                          final String value) {
-        final ActionType actionType = getActionForColumn( row,
-                                                    column );
-
+        final ActionType actionType = getActionForColumn( row, column );
+        if (actionType.getSourceBuilder() == null) {
+            if (actionType.type == ActionType.CONDITION) {
+                actionType.setSourceBuilder( new LhsBuilder(null) );
+                this.sourceBuilders.add( actionType.getSourceBuilder() );
+            } else if (actionType.type == ActionType.ACTION) {
+                actionType.setSourceBuilder( new RhsBuilder(null) );
+                this.sourceBuilders.add( actionType.getSourceBuilder() );
+            }
+        }
         if ( value.trim().equals( "" ) && (actionType.type == ActionType.ACTION || actionType.type == ActionType.CONDITION) ) {
             throw new DecisionTableParseException( "Code description - row:" + (row + 1) + " cell number:" + (column + 1) + " - does not contain any code specification. It should !" );
         }
 
-        actionType.value = value;
+        actionType.addTemplate(column, value);
     }
 
     private void labelRow(final int row,
@@ -312,7 +415,7 @@
         return actionType;
     }
 
-    private void nextRule(final int row,
+    private void nextDataCell(final int row,
                           final int column,
                           final String value) {
         final ActionType actionType = getActionForColumn( row,
@@ -392,20 +495,15 @@
             createDuration( column,
                             value,
                             actionType );
-        } else if ( actionType.type == ActionType.CONDITION ) {
-            createCondition( column,
-                             value,
-                             actionType );
-        } else if ( actionType.type == ActionType.ACTION ) {
-            createConsequence( column,
-                               value,
-                               actionType );
+        } else if ( actionType.type == ActionType.CONDITION || actionType.type == ActionType.ACTION ) {
+            actionType.addCellValue( column, value );
         }
 
     }
 
     private Rule createNewRuleForRow(final int row) {
 
+        
         Integer salience = null;
         if ( this._currentSequentialFlag ) {
             salience = new Integer( Rule.calcSalience( row ) );
@@ -418,24 +516,11 @@
         rule.setComment( "From row number: " + (spreadsheetRow) );
 
         return rule;
+        
     }
 
-    private void createCondition(final int column,
-                                 final String value,
-                                 final ActionType actionType) {
 
-        final Condition cond = new Condition();
-        cond.setSnippet( actionType.getSnippet( value ) );
-        cond.setComment( cellComment( column ) );
-        this._currentRule.addCondition( cond );
-    }
-
-    // 08 - 16 - 2005 RIK: This function creates a new DURATION TAG if apply.
-    // The value in the cell must be made with the first character of the
-    // parameter and the value next to it, separated by ":" character
-    // Examples: w1:d3:h4 mean weeks="1" days="3" hours="4", m=1:s=45 means
-    // minutes="1" seconds="45"
-
+    // 08 - 16 - 2005 RIK: This function creates a new DURATION 
     private void createDuration(final int column,
                                 final String value,
                                 final ActionType actionType) {
@@ -446,16 +531,7 @@
         this._currentRule.setDuration( dur );
     }
 
-    private void createConsequence(final int column,
-                                   final String value,
-                                   final ActionType actionType) {
 
-        final Consequence cons = new Consequence();
-        cons.setSnippet( actionType.getSnippet( value ) );
-        cons.setComment( cellComment( column ) );
-        this._currentRule.addConsequence( cons );
-    }
-
     private boolean isCellValueEmpty(final String value) {
         return value == null || "".equals( value.trim() );
     }

Modified: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SheetListener.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SheetListener.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SheetListener.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -22,6 +22,8 @@
  * Callback interface for scanning an spreadsheet.
  */
 public interface SheetListener {
+	
+    public static final int NON_MERGED = -1;
 
     /**
      * Start a new sheet
@@ -61,9 +63,12 @@
      *            the column alpha character label
      * @param value
      *            the string value of the cell
+     * @param mergedCol
+     *            the "source" column if it is merged. -1 otherwise.           
      */
     public void newCell(int row,
                         int column,
-                        String value);
+                        String value,
+                        int mergedColStart);
 
 }
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SourceBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SourceBuilder.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SourceBuilder.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,13 @@
+package org.drools.decisiontable.parser;
+
+/**
+ * This is for building up LHS and RHS code for a rule row.
+ * @author Michael Neale
+ */
+public interface SourceBuilder {
+    String getResult();
+    void addTemplate(int col, String content);
+    void addCellValue(int col, String value);
+    void clearValues();
+    boolean hasValues();
+}


Property changes on: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SourceBuilder.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvParser.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvParser.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvParser.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -31,6 +31,13 @@
  * This implementation removes empty "cells" at the end of each line.
  * Different CSV tools may or may not put heaps of empty cells in.
  * 
+ * Csv format is almost identical to XLS, with the one limitation:
+ * Merged cells are not supported. To allow constraints to span across cells for the 
+ * one column, this is achieved by using "..." at the end of a cell value.
+ * If a cell value ends with "..." then it will be taken as spanned from the previous cell.
+ * 
+ * 
+ * 
  * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a>
  */
 public class CsvParser
@@ -70,18 +77,46 @@
             this._listener.newRow( row,
                               cells.size() );
 
+            int startMergeCol = SheetListener.NON_MERGED;
             for ( int col = 0; col < cells.size(); col++ ) {
-                final String cell = (String) cells.get( col );
+                String cell = (String) cells.get( col );
 
+                startMergeCol = calcStartMerge( startMergeCol,
+                                                col,
+                                                cell );
+                
+                cell = calcCellText( startMergeCol,
+                                     cell );
+                
                 this._listener.newCell( row,
                                    col,
-                                   cell );
+                                   cell, startMergeCol );
             }
             row++;
             line = reader.readLine();
         }
+        _listener.finishSheet();
     }
 
+    String calcCellText(int startMergeCol,
+                                String cell) {
+        if (startMergeCol != SheetListener.NON_MERGED) {
+            cell = cell.substring( 0, cell.length() - 3 );
+        }
+        return cell;
+    }
+
+    int calcStartMerge(int startMergeCol,
+                               int col,
+                               String cell) {
+        if (cell.endsWith( "..." ) && startMergeCol == SheetListener.NON_MERGED) {
+            startMergeCol = col;                    
+        } else if (!cell.endsWith( "..." )) {
+            startMergeCol = SheetListener.NON_MERGED;
+        }
+        return startMergeCol;
+    }
+
     /** remove the trailing empty cells */
     private void trimCells(final List cells) {
         for ( int i = cells.size() - 1; i > 0; i-- ) {

Modified: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/ExcelParser.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/ExcelParser.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/ExcelParser.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -18,68 +18,37 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
-import org.apache.poi.hssf.eventusermodel.HSSFEventFactory;
-import org.apache.poi.hssf.eventusermodel.HSSFListener;
-import org.apache.poi.hssf.eventusermodel.HSSFRequest;
-import org.apache.poi.hssf.record.BOFRecord;
-import org.apache.poi.hssf.record.BoolErrRecord;
-import org.apache.poi.hssf.record.BoundSheetRecord;
-import org.apache.poi.hssf.record.FormulaRecord;
-import org.apache.poi.hssf.record.LabelSSTRecord;
-import org.apache.poi.hssf.record.NumberRecord;
-import org.apache.poi.hssf.record.Record;
-import org.apache.poi.hssf.record.RowRecord;
-import org.apache.poi.hssf.record.SSTRecord;
-import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.Ref3DPtg;
-import org.apache.poi.hssf.usermodel.HSSFCell;
-import org.apache.poi.hssf.usermodel.HSSFRow;
-import org.apache.poi.hssf.usermodel.HSSFSheet;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.poifs.filesystem.POIFSFileSystem;
+import jxl.Cell;
+import jxl.Range;
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.read.biff.BiffException;
+
 import org.drools.decisiontable.parser.DecisionTableParseException;
 import org.drools.decisiontable.parser.DecisionTableParser;
 import org.drools.decisiontable.parser.SheetListener;
 
 /**
- * @author <a href="mailto:shaun.addison at gmail.com"> Shaun Addison </a><a
- *         href="mailto:michael.neale at gmail.com"> Michael Neale </a>
- *         Forumula handling by Pascal Chanteux
- * 
- * Parse an excel spreadsheet using the event model of POI. TODO: can not
- * resolve date format issues as yet.
- * 
+ * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale </a>
+ * Parse an excel spreadsheet, pusing cell info into the SheetListener interface.
  */
 public class ExcelParser
     implements
-    DecisionTableParser,
-    HSSFListener {
+    DecisionTableParser
+    {
 
     public static final String  DEFAULT_RULESHEET_NAME = "Decision Tables";
-
-    private static final String WORKBOOK               = "Workbook";
-
-    public static final String  DATE_TARGET_FORMAT     = "dd-MMM-yyyy";
-
     private Map                 _listners              = new HashMap();
-
     private SheetListener       _currentSheetListener  = new NullSheetListener();
+	private boolean _useFirstSheet;
 
-    private final List                _sheetNames            = new ArrayList();
 
-    private int                 _currentSheetNumber    = 0;
 
-    private SSTRecord           _sstRec                = null;
-
-    private boolean             _useFirstSheet         = false;
-
-    private HSSFWorkbook        _workbook              = null;
-
     /**
      * Define a map of sheet name to listner handlers.
      * 
@@ -94,178 +63,87 @@
         this._listners.put( ExcelParser.DEFAULT_RULESHEET_NAME,
                        listener );
         this._useFirstSheet = true;
+        this._currentSheetListener = listener;
     }
 
-    /**
-     * Initialise a new sheet and complete the previous.
-     * 
-     * @param record
-     *            the new record
-     */
-    private void newSheet(final String sheetName) {
-        this._currentSheetListener.finishSheet();
-        this._currentSheetListener = new NullSheetListener();
+	public void parseFile(InputStream inStream) {
+		try {
+			Workbook workbook = Workbook.getWorkbook(inStream);
+			
+			if (_useFirstSheet) {
+				Sheet sheet = workbook.getSheet(0);
+				processSheet(sheet, _currentSheetListener);
+			} else {
+				Set sheetNames = _listners.keySet();
+				for (Iterator iter = sheetNames.iterator(); iter.hasNext();) {
+					String sheetName = (String) iter.next();
+					Sheet sheet = workbook.getSheet(sheetName);
+					processSheet(sheet, (SheetListener)_listners.get(sheetName));
+					
+				}
+			}
+		} catch (BiffException e) {
+            throw new DecisionTableParseException( "An error occured opening the workbook. ",
+                    e );
+			
+		} catch (IOException e) {
+            throw new DecisionTableParseException( "Failed to open Excel stream, " + "please check that the content is xls97 format.",
+                    e );
+		}
+		
+		
+	}
 
-        if ( this._useFirstSheet && this._currentSheetNumber == 1 ) {
-            this._currentSheetListener = getFirstSheetListener();
-        } else {
-            if ( this._listners.containsKey( sheetName ) ) {
-                this._currentSheetListener = (SheetListener) this._listners.get( sheetName );
-            }
-        }
+	private void processSheet(Sheet sheet, SheetListener listener) {
+		int maxRows = sheet.getRows();
+		
+		Range[] mergedRanges = sheet.getMergedCells();
 
-        this._currentSheetListener.startSheet( sheetName );
-    }
+		
+		for(int i = 0; i < maxRows; i++) {
+			Cell[] row = sheet.getRow(i);
+			listener.newRow(i, row.length);			
+			for (int cellNum = 0; cellNum < row.length; cellNum++) {
+				Cell cell = row[cellNum];
+				
+				Range merged = getRangeIfMerged(cell, mergedRanges);
+											
+				if (merged != null) {
+                    Cell topLeft = merged.getTopLeft();
+					listener.newCell(i, cellNum, topLeft.getContents(), topLeft.getColumn());
+				} else {
+					listener.newCell(i, cellNum, cell.getContents(), SheetListener.NON_MERGED);
+				}
+			}
+		}
+        listener.finishSheet();
+	}
+	
+    Range getRangeIfMerged(Cell cell, Range[] mergedRanges) {
+    	for (int i = 0; i < mergedRanges.length; i++) {
+			Range r = mergedRanges[i];
+			Cell topLeft = r.getTopLeft();
+			Cell bottomRight = r.getBottomRight();
+			if (cell.getRow() >= topLeft.getRow() 
+					&& cell.getRow() <= bottomRight.getRow()
+					&& cell.getColumn() >= topLeft.getColumn()
+					&& cell.getColumn() <= bottomRight.getColumn()
+					) {
+				return r;
+			}
+		}
+		return null;
+	}
 
-    private SheetListener getFirstSheetListener() {
-        final SheetListener listener = (SheetListener) this._listners.values().iterator().next();
-        if ( listener == null ) {
-            throw new IllegalStateException( "No default first sheet listener found !" );
-        }
-        return listener;
-    }
-
-    /**
-     * Implement the HSSFListener method
-     * 
-     * This receives the events for the Excel file format scan. A bunch of
-     * document data OLE style and the sheet content.
-     */
-    public void processRecord(final Record record) {
-
-        switch ( record.getSid() ) {
-            case BoundSheetRecord.sid :
-                final BoundSheetRecord bsr = (BoundSheetRecord) record;
-                this._sheetNames.add( bsr.getSheetname() );
-                break;
-            case BOFRecord.sid :
-                final BOFRecord bof = (BOFRecord) record;
-                if ( bof.getType() == BOFRecord.TYPE_WORKSHEET ) {
-                    newSheet( (String) this._sheetNames.get( this._currentSheetNumber++ ) );
-                }
-                break;
-            case RowRecord.sid :
-                final RowRecord rowRec = (RowRecord) record;
-                this._currentSheetListener.newRow( rowRec.getRowNumber(),
-                                              rowRec.getLastCol() - rowRec.getFirstCol() + 1 );
-                break;
-            case SSTRecord.sid :
-                this._sstRec = (SSTRecord) record;
-                break;
-            case LabelSSTRecord.sid :
-                handleText( record );
-                break;
-
-            case NumberRecord.sid :
-                handleNumber( record );
-                break;
-            case BoolErrRecord.sid :
-                handleBool( record );
-                break;
-
-            case FormulaRecord.sid :
-                handleFormula( record );
-                break;
-
-            default :
-                break;
-        }
-
-    }
-
-    private void handleFormula(final Record record) {
-
-        final FormulaRecord formulaRec = (FormulaRecord) record;
-
-        final Ptg ptg = formulaRec.peekExpressionToken();
-
-        if ( ptg instanceof Ref3DPtg ) {
-
-            final Ref3DPtg ptg3D = (Ref3DPtg) ptg;
-
-            final HSSFSheet sheet = this._workbook.getSheetAt( ptg3D.getExternSheetIndex() + 1 );
-            final HSSFRow row = sheet.getRow( ptg3D.getRow() );
-            final HSSFCell cell = row.getCell( ptg3D.getColumn() );
-
-            this._currentSheetListener.newCell( formulaRec.getRow(),
-                                           formulaRec.getColumn(),
-                                           "" + cell.getStringCellValue() );
-
-        }
-    }
-
-    private void handleBool(final Record record) {
-        final BoolErrRecord boolRec = (BoolErrRecord) record;
-        this._currentSheetListener.newCell( boolRec.getRow(),
-                                       boolRec.getColumn(),
-                                       "" + boolRec.getBooleanValue() );
-    }
-
-    private void handleText(final Record record) {
-        final LabelSSTRecord labelRec = (LabelSSTRecord) record;
-        final String value = this._sstRec.getString( labelRec.getSSTIndex() );
-        this._currentSheetListener.newCell( labelRec.getRow(),
-                                       labelRec.getColumn(),
-                                       value );
-    }
-
-    private void handleNumber(final Record record) {
-        // MN have to do with stupid numbers with ".0" as well as
-        // freaking excel freaking dates freakin.
-        final NumberRecord numRec = (NumberRecord) record;
-
-        String stringVal = null;
-
-        /*
-         * if (numRec.getXFIndex() == DATE_FORMATTED_CELL) { Date date =
-         * HSSFDateUtil.getJavaDate(val); SimpleDateFormat format = new
-         * SimpleDateFormat(DATE_TARGET_FORMAT); stringVal =
-         * format.format(date); } else {
-         */
-        stringVal = "" + numRec.getValue();
-        stringVal = removeTrailingZero( stringVal );
-        /* } */
-        this._currentSheetListener.newCell( numRec.getRow(),
-                                       numRec.getColumn(),
-                                       "" + stringVal );
-    }
-
-    static String removeTrailingZero(String stringVal) {
+	static String removeTrailingZero(String stringVal) {
         if ( stringVal.endsWith( ".0" ) ) {
             stringVal = stringVal.substring( 0,
                                              stringVal.length() - 2 );
         }
         return stringVal;
-    }
+    }	
 
-    /**
-     * Scan an Excel file stream.
-     * 
-     * @param inStream
-     *            the ms-excel data stream
-     */
-    public void parseFile(final InputStream inStream) {
-        InputStream din = null;
-        POIFSFileSystem poifs = null;
 
-        try {
-            poifs = new POIFSFileSystem( inStream );
 
-            // Get the workbook for further references
-            this._workbook = new HSSFWorkbook( poifs );
 
-            // get the Workbook (excel part) stream in a InputStream
-            din = poifs.createDocumentInputStream( ExcelParser.WORKBOOK );
-            final HSSFRequest req = new HSSFRequest();
-            // lazy listen for ALL records with the listener shown above
-            req.addListenerForAllRecords( this );
-            final HSSFEventFactory factory = new HSSFEventFactory();
-            factory.processEvents( req,
-                                   din );
-        } catch ( final IOException ex ) {
-            throw new DecisionTableParseException( "Failed to open Excel stream, " + "please check that the content is xls97 format.",
-                                                   ex );
-        }
-    }
-
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/NullSheetListener.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/NullSheetListener.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/NullSheetListener.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -39,7 +39,8 @@
 
     public void newCell(final int row,
                         final int column,
-                        final String value) {
+                        final String value,
+                        final int mergedColstart) {
     }
 
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/PropertiesSheetListener.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/PropertiesSheetListener.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/PropertiesSheetListener.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -101,7 +101,8 @@
      */
     public void newCell(final int row,
                         final int column,
-                        final String value) {
+                        final String value,
+                        final int mergedColStart) {
         if ( emptyCellValue( value ) ) {
             return;
         }

Added: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Driver.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Driver.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Driver.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,41 @@
+package org.acme.insurance;
+
+/**
+ * This represents obviously a driver who is applying for an insurance Policy.
+ * @author Michael Neale
+ *
+ */
+public class Driver {
+
+	private String name = "Mr Joe Blogs";
+	private Integer age = new Integer(30);
+	private Integer priorClaims = new Integer(0);	
+	private String  locationRiskProfile = "LOW";
+	
+	public Integer getAge() {
+		return age;
+	}
+	public void setAge(Integer age) {
+		this.age = age;
+	}
+	public String getLocationRiskProfile() {
+		return locationRiskProfile;
+	}
+	public void setLocationRiskProfile(String locationRiskProfile) {
+		this.locationRiskProfile = locationRiskProfile;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public Integer getPriorClaims() {
+		return priorClaims;
+	}
+	public void setPriorClaims(Integer priorClaims) {
+		this.priorClaims = priorClaims;
+	}
+	
+	
+}


Property changes on: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Driver.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Policy.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Policy.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Policy.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,49 @@
+package org.acme.insurance;
+
+/**
+ * This represents a policy that a driver is applying for. 
+ * 
+ * Obviously in the real world, there are actuaries to mess things up, but lets just pretend there is
+ * some simple base price and discount that we can calculate with relatively simple rules !
+ * 
+ * @author Michael Neale
+ */
+public class Policy {
+
+	private String type = "COMPREHENSIVE";
+	private boolean approved = false;
+	private int discountPercent = 0;
+	private int basePrice;
+	
+	public boolean isApproved() {
+		return approved;
+	}
+	public void setApproved(boolean approved) {
+		this.approved = approved;
+	}
+	public int getDiscountPercent() {
+		return discountPercent;
+	}
+	public void setDiscountPercent(int discountPercent) {
+		this.discountPercent = discountPercent;
+	}
+	
+	public String getType() {
+		return type;
+	}
+	
+	public void setType(String type) {
+		this.type = type;
+	}
+	
+	public void applyDiscount(int discount) {
+		discountPercent += discount;
+	}
+	public int getBasePrice() {
+		return basePrice;
+	}
+	public void setBasePrice(int basePrice) {
+		this.basePrice = basePrice;
+	}
+	
+}


Property changes on: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/Policy.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/launcher/PricingRuleLauncher.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/launcher/PricingRuleLauncher.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/launcher/PricingRuleLauncher.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,79 @@
+package org.acme.insurance.launcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+
+import org.acme.insurance.Driver;
+import org.acme.insurance.Policy;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.compiler.DroolsParserException;
+import org.drools.compiler.PackageBuilder;
+import org.drools.decisiontable.InputType;
+import org.drools.decisiontable.SpreadsheetCompiler;
+
+/**
+ * This is a sample file to launch a rule package from a rule source file.
+ */
+public class PricingRuleLauncher {
+
+    public static final void main(String[] args) throws Exception {    	
+    	PricingRuleLauncher launcher = new PricingRuleLauncher();
+    	launcher.executeExample();
+    }
+    
+    public int executeExample() throws Exception {
+    	
+    	//first we compile the decision table into a whole lot of rules.
+    	SpreadsheetCompiler compiler = new SpreadsheetCompiler();
+    	String drl = compiler.compile(getSpreadsheetStream(), InputType.XLS);
+
+    	//UNCOMMENT ME TO SEE THE DRL THAT IS GENERATED
+    	//System.out.println(drl);
+
+    	RuleBase ruleBase = buildRuleBase(drl);
+    	
+		WorkingMemory wm = ruleBase.newWorkingMemory();
+		
+		//now create some test data
+		Driver driver = new Driver();
+		Policy policy = new Policy();
+		
+		wm.assertObject(driver);
+		wm.assertObject(policy);
+		
+		wm.fireAllRules();
+		
+		System.out.println("BASE PRICE IS: " + policy.getBasePrice());
+		System.out.println("DISCOUNT IS: " + policy.getDiscountPercent());
+		
+        return policy.getBasePrice();
+    	
+    }
+
+
+    /** Build the rule base from the generated DRL */
+	private RuleBase buildRuleBase(String drl) throws DroolsParserException, IOException, Exception {
+		//now we build the rule package and rulebase, as if they are normal rules
+		PackageBuilder builder = new PackageBuilder();
+		builder.addPackageFromDrl( new StringReader(drl) );
+		
+		//add the package to a rulebase (deploy the rule package).
+		RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+		ruleBase.addPackage( builder.getPackage() );
+		return ruleBase;
+	}
+    
+    
+
+
+    private InputStream getSpreadsheetStream() {
+    	return this.getClass().getResourceAsStream("/data/ExamplePolicyPricing.xls");
+	}
+
+
+
+    
+}


Property changes on: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/acme/insurance/launcher/PricingRuleLauncher.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -17,6 +17,8 @@
  */
 
 import java.io.InputStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import junit.framework.TestCase;
 
@@ -24,6 +26,9 @@
  * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a>
  * 
  * Some basic unit tests for converter utility.
+ * Note that some of this may still use the drools 2.x syntax, as it is not compiled,
+ * only tested that it generates DRL in the correct structure (not that the DRL itself
+ * is correct).
  */
 public class SpreadsheetCompilerUnitTest extends TestCase {
 
@@ -53,21 +58,39 @@
         final String drl = converter.compile( stream,
                                         InputType.CSV );
         assertNotNull( drl );
+        
+        System.out.println(drl);        
+        
         assertTrue( drl.indexOf( "myObject.setIsValid(1, 2)" ) > 0 );
-        assertTrue( drl.indexOf( "myObject.size () > 50" ) > 0 );
-        //System.out.println(drl);
+        assertTrue( drl.indexOf( "myObject.size () > 50" ) > 0 );    
+        
+        assertTrue( drl.indexOf("Foo(myObject.getColour().equals(red), myObject.size () > 1)") > 0);
     }
 
-    public void testLoadBasic() {
+    public void testLoadBasicWithMergedCells() {
         final SpreadsheetCompiler converter = new SpreadsheetCompiler();
         final InputStream stream = this.getClass().getResourceAsStream( "/data/BasicWorkbook.xls" );
         final String drl = converter.compile( stream,
                                         InputType.XLS );
 
         assertNotNull( drl );
+        
+        Pattern p = Pattern.compile(".*setIsValid\\(Y\\).*setIsValid\\(Y\\).*setIsValid\\(Y\\).*",Pattern.DOTALL | Pattern.MULTILINE);
+        Matcher m = p.matcher(drl);
+        assertTrue(m.matches());
+                
         assertTrue( drl.indexOf( "This is a function block" ) > -1 );
         assertTrue( drl.indexOf( "global Class1 obj1;" ) > -1 );
-        //System.out.println(drl);
+        assertTrue( drl.indexOf( "myObject.setIsValid(10-Jul-1974)" ) > -1 );
+        assertTrue( drl.indexOf( "myObject.getColour().equals(blue)" ) > -1 );
+        assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size () > 1)" ) > -1 );
+        
+        assertTrue( drl.indexOf( "b: Bar() eval(myObject.size() < 3)" ) > -1 );
+        assertTrue( drl.indexOf( "b: Bar() eval(myObject.size() < 9)" ) > -1 );
+        
+        assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size () > 1)" ) < 
+                    drl.indexOf( "b: Bar() eval(myObject.size() < 3)" ));
+        
     }
 
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetIntegrationTest.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetIntegrationTest.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetIntegrationTest.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -22,6 +22,7 @@
 
 import junit.framework.TestCase;
 
+import org.acme.insurance.launcher.PricingRuleLauncher;
 import org.drools.RuleBase;
 import org.drools.RuleBaseFactory;
 import org.drools.WorkingMemory;
@@ -68,5 +69,13 @@
                       list.size() );
 
     }
+    
+    /**
+     * A smoke test mainly.
+     */
+    public void testInsuranceExample() throws Exception {
+        PricingRuleLauncher launcher = new PricingRuleLauncher();
+        assertEquals(120, launcher.executeExample());
+    }
 
 }
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/LhsBuilderTest.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/LhsBuilderTest.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/LhsBuilderTest.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,78 @@
+package org.drools.decisiontable.parser;
+
+import org.drools.decisiontable.parser.LhsBuilder.FieldType;
+
+import junit.framework.TestCase;
+
+public class LhsBuilderTest extends TestCase {
+
+	public void testBuildItUp() throws Exception {
+		LhsBuilder builder = new LhsBuilder("Person");
+		
+		builder.addTemplate(1, "age");
+		builder.addTemplate(2, "size != $param");
+		builder.addTemplate(3, "date <");
+		
+		builder.addCellValue(1, "42");
+		builder.addCellValue(2, "20");
+		builder.addCellValue(3, "30");
+		
+		
+		assertEquals("Person(age == \"42\", size != 20, date < \"30\")", builder.getResult());
+        
+        builder.clearValues();
+        
+        builder.addCellValue( 2, "42" );
+        assertEquals("Person(size != 42)", builder.getResult());
+	}
+    
+    public void testEmptyCells() {
+        LhsBuilder builder = new LhsBuilder("Person");
+        assertFalse(builder.hasValues());
+    }
+    
+    public void testClassicMode() {
+        LhsBuilder builder = new LhsBuilder("");
+        builder.addTemplate( 1, "Person(age < $param)");
+        builder.addCellValue( 1, "42" );
+        
+        assertEquals("Person(age < 42)", builder.getResult());
+        
+        builder = new LhsBuilder(null);
+        builder.addTemplate( 3, "Foo(bar == $param)");
+        builder.addTemplate( 4, "eval(true)");
+        
+        builder.addCellValue( 3, "42" );
+        builder.addCellValue( 4, "Y" );
+        
+        assertEquals("Foo(bar == 42)\neval(true)", builder.getResult());
+    }
+    
+    public void testIdentifyFieldTypes() {
+        LhsBuilder builder = new LhsBuilder("");
+        assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("age"));
+        assertEquals(FieldType.OPERATOR_FIELD, builder.calcFieldType("age <"));
+        assertEquals(FieldType.NORMAL_FIELD, builder.calcFieldType("age < $param"));
+        
+        
+    }
+    
+    public void testIdentifyColumnCorrectly() {
+        LhsBuilder builder = new LhsBuilder(null);
+        assertFalse(builder.isMultipleConstraints());
+        
+        //will be added to Foo
+        builder = new LhsBuilder("Foo");
+        assertTrue(builder.isMultipleConstraints());
+        
+        //will be added to eval
+        builder = new LhsBuilder("f:Foo() eval  ");
+        assertTrue(builder.isMultipleConstraints());
+        
+        //will just be verbatim
+        builder = new LhsBuilder("f: Foo()");
+        assertFalse(builder.isMultipleConstraints());
+        
+    }
+	
+}


Property changes on: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/LhsBuilderTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/PropertiesSheetListenerTest.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/PropertiesSheetListenerTest.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/PropertiesSheetListenerTest.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -33,23 +33,23 @@
 
         listener.newCell( 0,
                           0,
-                          "" );
+                          "", SheetListener.NON_MERGED );
 
         listener.newCell( 0,
                           1,
-                          "key1" );
+                          "key1", SheetListener.NON_MERGED );
         listener.newCell( 0,
                           2,
-                          "value1" );
+                          "value1", SheetListener.NON_MERGED );
 
         listener.newRow( 1,
                          4 );
         listener.newCell( 1,
                           1,
-                          "key2" );
+                          "key2", SheetListener.NON_MERGED );
         listener.newCell( 1,
                           3,
-                          "value2" );
+                          "value2", SheetListener.NON_MERGED );
 
         final Properties props = listener.getProperties();
 
@@ -57,7 +57,7 @@
                          4 );
         listener.newCell( 1,
                           1,
-                          "key3" );
+                          "key3", SheetListener.NON_MERGED );
 
         assertEquals( "value1",
                       props.getProperty( "key1" ) );

Added: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RhsBuilderTest.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RhsBuilderTest.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RhsBuilderTest.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,39 @@
+package org.drools.decisiontable.parser;
+
+import junit.framework.TestCase;
+
+public class RhsBuilderTest extends TestCase {
+
+    public void testConsBuilding() {
+        RhsBuilder builder = new RhsBuilder("foo");
+        builder.addTemplate( 1, "setFoo($param)");
+        builder.addCellValue( 1, "42" );
+        
+        
+        assertEquals("foo.setFoo(42);", builder.getResult());
+        
+        builder.clearValues();
+        builder.addCellValue( 1, "33" );
+        assertEquals("foo.setFoo(33);", builder.getResult());
+    }
+    
+    public void testClassicMode() {
+        RhsBuilder builder = new RhsBuilder("");
+        builder.addTemplate( 1, "p.setSomething($param);" );
+        builder.addTemplate( 2, "drools.clearAgenda();" );
+                
+        builder.addCellValue( 1, "42" );       
+        
+        assertEquals("p.setSomething(42);", builder.getResult());
+                
+        builder.addCellValue( 2, "Y" );
+        assertEquals("p.setSomething(42);\ndrools.clearAgenda();", builder.getResult());
+    }
+    
+    public void testEmptyCellData() {
+        RhsBuilder builder = new RhsBuilder("Foo");
+        builder.addTemplate( 1, "p.setSomething($param);" );        
+        assertFalse(builder.hasValues());
+    }
+    
+}


Property changes on: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RhsBuilderTest.java
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseTest.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseTest.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseTest.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -100,12 +100,12 @@
         // check rules
         Rule rule = (Rule) ruleset.getRules().get( 0 );
         Condition cond = (Condition) rule.getConditions().get( 0 );
-        assertEquals( "myObject.getColour().equals(red)",
+        assertEquals( "Foo(myObject.getColour().equals(red), myObject.size () > 1)",
                       cond.getSnippet() );
 
         Consequence cons = (Consequence) rule.getConsequences().get( 0 );
         assertNotNull( cons );
-        assertEquals( "myObject.setIsValid(Y)",
+        assertEquals( "myObject.setIsValid(Y);",
                       cons.getSnippet() );
 
         rule = (Rule) ruleset.getRules().get( 5 );
@@ -141,7 +141,7 @@
         assertEquals( "myObject.setIsValid(1, 2)",
                       cons.getSnippet() );
         final Condition con = (Condition) rule.getConditions().get( 2 );
-        assertEquals( "myObject.size() < 3",
+        assertEquals( "myObject.size() < $3.00",
                       con.getSnippet() );
 
         rule = (Rule) ruleset.getRules().get( 4 );

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvParserTest.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvParserTest.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvParserTest.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -52,6 +52,26 @@
                                         3 ) );
 
     }
+    
+    /**
+     * Test the handling of merged cells.
+     */
+    public void testCellMergeHandling() {
+        CsvParser parser = new CsvParser(null, null);
+        assertEquals(SheetListener.NON_MERGED, parser.calcStartMerge( SheetListener.NON_MERGED, 1, "foo" ));
+        assertEquals(42, parser.calcStartMerge( SheetListener.NON_MERGED, 42, "..." ));
+        
+        assertEquals(42, parser.calcStartMerge( 42, 43, "..." ));
+        
+        assertEquals(SheetListener.NON_MERGED, parser.calcStartMerge( 42, 44, "VanHalen" ));
+        
+        
+        assertEquals("VanHalen", parser.calcCellText( SheetListener.NON_MERGED, "VanHalen" ));
+        assertEquals("VanHalen", parser.calcCellText( 42, "VanHalen..." ));
+        assertEquals("", parser.calcCellText( 42, "..." ));
+        
+        
+    }
 
     static class MockSheetListener
         implements
@@ -78,7 +98,8 @@
 
         public void newCell(final int row,
                             final int column,
-                            final String value) {
+                            final String value,
+                            final int mergeCellStart) {
 
             this.data.put( cellKey( row,
                                column ),

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls/ExcelParserTest.java
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls/ExcelParserTest.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls/ExcelParserTest.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -16,7 +16,14 @@
  * limitations under the License.
  */
 
+import java.util.Map;
+
 import junit.framework.TestCase;
+import jxl.Cell;
+//import jxl.CellFeatures;
+import jxl.CellType;
+import jxl.Range;
+import jxl.format.CellFormat;
 
 /**
  * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a>
@@ -40,5 +47,102 @@
                       ExcelParser.removeTrailingZero( test ) );
 
     }
+    
+    /**
+     * This should test to see if a cell is in a certain range or not. 
+     * If it is in a merged range, then it should return the top left cell.
+     * @throws Exception
+     */
+    public void testCellMerge() throws Exception {
+    	ExcelParser parser = new ExcelParser((Map) null);
+    	
+    	Range[] ranges = new Range[1];
+    	
+    	MockRange r1 = new MockRange();
+    	ranges[0] = r1;
+    	r1.topLeft = new MockCell();
+    	r1.topLeft.row = 2;
+    	r1.topLeft.column = 2;
+    	r1.topLeft.contents = "first";
+    	
 
+    	
+    	r1.bottomRight = new MockCell();
+    	r1.bottomRight.column = 5;
+    	r1.bottomRight.row = 7;
+    	r1.bottomRight.contents = "last";
+    	
+    	
+    	MockCell cell = new MockCell();
+    	cell.contents = "test";
+    	cell.row = 1;
+    	cell.column = 1;
+    	
+    	assertNull(parser.getRangeIfMerged( cell, ranges));
+    	
+    	cell = new MockCell();
+    	cell.contents = "wrong";
+    	cell.row = 2;
+    	cell.column = 5;
+    	
+    	assertEquals("first", parser.getRangeIfMerged( cell, ranges).getTopLeft().getContents());
+    	
+    }
+    
+    static class MockCell implements Cell {
+
+    	int column;
+    	int row;
+    	String contents;
+    	
+
+		public CellFormat getCellFormat() {
+			return null;
+		}
+
+		public int getColumn() {
+			return column;
+		}
+
+		public String getContents() {
+			return contents;
+		}
+
+		public int getRow() {
+			return row;
+		}
+
+		public CellType getType() {
+			return null;
+		}
+
+		public boolean isHidden() {
+			return false;
+		}
+    	
+    }
+    
+    static class MockRange implements Range {
+
+    	MockCell bottomRight;
+		MockCell topLeft;
+    	
+		public Cell getBottomRight() {
+			return bottomRight;
+		}
+
+		public int getFirstSheetIndex() {
+			return 0;
+		}
+
+		public int getLastSheetIndex() {
+			return 0;
+		}
+
+		public Cell getTopLeft() {
+			return topLeft;
+		}
+    	
+    }
+
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/BasicWorkbook.xls
===================================================================
(Binary files differ)

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/ComplexWorkbook.csv
===================================================================
--- labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/ComplexWorkbook.csv	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/ComplexWorkbook.csv	2006-08-02 16:01:15 UTC (rev 5412)
@@ -1,19 +1,21 @@
-,RuleSet,ruleSetName,,,
+,"RuleSet","ruleSetName",,,
 ,,,,,
 ,,,,,
-
-,RuleTable - Mine,,,,
-,C,C,C,A,A
-,myObject.getColour().equals($param),myObject.size () > $param,myObject.size() < $param,myObject.setIsValid($param),"myObject.setIsValid($1, $2)"
-,Colour Type,Object size,Object size,Valid Object,Valid Object
-some stuff,red,1,$3.00,TRUE,"1,2"
-more to ignore,yellow,2,6,FALSE,"1,2"
-,blue,7,9,N,N
-
-RuleTable - freddy2,,,,,
-C,C,C,A,,
-myObject.getColour().equals($param),myObject.size () > $param,myObject.size() < $param,myObject.setIsValid($param),,
-Colour Type,Object size,Object size,Valid Object,,
-red,10,20,Y
-yellow, ,,Y
-,50,60,Y
+,,,,,
+,"RuleTable - Mine",,,,
+,"C","C","C","A","A"
+,"Foo...","Foo...",,,
+,"myObject.getColour().equals($param)","myObject.size () > $param","myObject.size() < $param","myObject.setIsValid($param)","myObject.setIsValid($1, $2)"
+,"Colour Type","Object size","Object size","Valid Object","Valid Object"
+"some stuff","red",1,3,TRUE,"1,2"
+"more to ignore","yellow",2,6,FALSE,"1,2"
+,"blue",7,9,"N","N"
+,,,,,
+"RuleTable - freddy2",,,,,
+"C","C","C","A",,
+,,,,,
+"myObject.getColour().equals($param)","myObject.size () > $param","myObject.size() < $param","myObject.setIsValid($param)",,
+"Colour Type","Object size","Object size","Valid Object",,
+"red",10,20,"Y",,
+"yellow"," ",,"Y",,
+,50,60,"Y",,

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/ComplexWorkbook.xls
===================================================================
(Binary files differ)

Deleted: labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/CorruptTeamAllocationExample.xls
===================================================================
(Binary files differ)

Added: labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/ExamplePolicyPricing.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/ExamplePolicyPricing.xls
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/IntegrationExampleTest.xls
===================================================================
(Binary files differ)

Modified: labs/jbossrules/trunk/drools-decisiontables/src/test/resources/data/MultiSheetDST.xls
===================================================================
(Binary files differ)

Added: labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/PricingRuleDTExample.java
===================================================================
--- labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/PricingRuleDTExample.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/PricingRuleDTExample.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,77 @@
+package org.drools.examples;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.compiler.DroolsParserException;
+import org.drools.compiler.PackageBuilder;
+import org.drools.decisiontable.InputType;
+import org.drools.decisiontable.SpreadsheetCompiler;
+import org.drools.examples.decisiontable.Driver;
+import org.drools.examples.decisiontable.Policy;
+
+/**
+ * This shows off a decision table.
+ */
+public class PricingRuleDTExample {
+
+    public static final void main(String[] args) throws Exception {    	
+    	PricingRuleDTExample launcher = new PricingRuleDTExample();
+    	launcher.executeExample();
+    }
+    
+    public int executeExample() throws Exception {
+    	
+    	//first we compile the decision table into a whole lot of rules.
+    	SpreadsheetCompiler compiler = new SpreadsheetCompiler();
+    	String drl = compiler.compile(getSpreadsheetStream(), InputType.XLS);
+
+    	//UNCOMMENT ME TO SEE THE DRL THAT IS GENERATED
+    	//System.out.println(drl);
+
+    	RuleBase ruleBase = buildRuleBase(drl);
+    	
+		WorkingMemory wm = ruleBase.newWorkingMemory();
+		
+		//now create some test data
+		Driver driver = new Driver();
+		Policy policy = new Policy();
+		
+		wm.assertObject(driver);
+		wm.assertObject(policy);
+		
+		wm.fireAllRules();
+		
+		System.out.println("BASE PRICE IS: " + policy.getBasePrice());
+		System.out.println("DISCOUNT IS: " + policy.getDiscountPercent());
+		
+        return policy.getBasePrice();
+    	
+    }
+
+
+    /** Build the rule base from the generated DRL */
+	private RuleBase buildRuleBase(String drl) throws DroolsParserException, IOException, Exception {
+		//now we build the rule package and rulebase, as if they are normal rules
+		PackageBuilder builder = new PackageBuilder();
+		builder.addPackageFromDrl( new StringReader(drl) );
+		
+		//add the package to a rulebase (deploy the rule package).
+		RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+		ruleBase.addPackage( builder.getPackage() );
+		return ruleBase;
+	}
+    
+
+    private InputStream getSpreadsheetStream() {
+    	return this.getClass().getResourceAsStream("ExamplePolicyPricing.xls");
+	}
+
+
+
+    
+}


Property changes on: labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/PricingRuleDTExample.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Driver.java
===================================================================
--- labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Driver.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Driver.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,41 @@
+package org.drools.examples.decisiontable;
+
+/**
+ * This represents obviously a driver who is applying for an insurance Policy.
+ * @author Michael Neale
+ *
+ */
+public class Driver {
+
+	private String name = "Mr Joe Blogs";
+	private Integer age = new Integer(30);
+	private Integer priorClaims = new Integer(0);	
+	private String  locationRiskProfile = "LOW";
+	
+	public Integer getAge() {
+		return age;
+	}
+	public void setAge(Integer age) {
+		this.age = age;
+	}
+	public String getLocationRiskProfile() {
+		return locationRiskProfile;
+	}
+	public void setLocationRiskProfile(String locationRiskProfile) {
+		this.locationRiskProfile = locationRiskProfile;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public Integer getPriorClaims() {
+		return priorClaims;
+	}
+	public void setPriorClaims(Integer priorClaims) {
+		this.priorClaims = priorClaims;
+	}
+	
+	
+}


Property changes on: labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Driver.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Policy.java
===================================================================
--- labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Policy.java	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Policy.java	2006-08-02 16:01:15 UTC (rev 5412)
@@ -0,0 +1,49 @@
+package org.drools.examples.decisiontable;
+
+/**
+ * This represents a policy that a driver is applying for. 
+ * 
+ * Obviously in the real world, there are actuaries to mess things up, but lets just pretend there is
+ * some simple base price and discount that we can calculate with relatively simple rules !
+ * 
+ * @author Michael Neale
+ */
+public class Policy {
+
+	private String type = "COMPREHENSIVE";
+	private boolean approved = false;
+	private int discountPercent = 0;
+	private int basePrice;
+	
+	public boolean isApproved() {
+		return approved;
+	}
+	public void setApproved(boolean approved) {
+		this.approved = approved;
+	}
+	public int getDiscountPercent() {
+		return discountPercent;
+	}
+	public void setDiscountPercent(int discountPercent) {
+		this.discountPercent = discountPercent;
+	}
+	
+	public String getType() {
+		return type;
+	}
+	
+	public void setType(String type) {
+		this.type = type;
+	}
+	
+	public void applyDiscount(int discount) {
+		discountPercent += discount;
+	}
+	public int getBasePrice() {
+		return basePrice;
+	}
+	public void setBasePrice(int basePrice) {
+		this.basePrice = basePrice;
+	}
+	
+}


Property changes on: labs/jbossrules/trunk/drools-examples/src/main/java/org/drools/examples/decisiontable/Policy.java
___________________________________________________________________
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-examples/src/main/rules/org/drools/examples/ExamplePolicyPricing.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/trunk/drools-examples/src/main/rules/org/drools/examples/ExamplePolicyPricing.xls
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: labs/jbossrules/trunk/drools-ide/src/main/java/org/drools/ide/wizard/decisiontable/template.xls
===================================================================
(Binary files differ)

Modified: labs/jbossrules/trunk/drools-ide/src/main/java/org/drools/ide/wizard/project/Sample.drl.template
===================================================================
--- labs/jbossrules/trunk/drools-ide/src/main/java/org/drools/ide/wizard/project/Sample.drl.template	2006-08-02 15:57:15 UTC (rev 5411)
+++ labs/jbossrules/trunk/drools-ide/src/main/java/org/drools/ide/wizard/project/Sample.drl.template	2006-08-02 16:01:15 UTC (rev 5412)
@@ -19,4 +19,5 @@
 	then
 		System.out.println( message ); 
 		m.setMessage( message );
+		
 end
\ No newline at end of file




More information about the jboss-svn-commits mailing list