[jboss-svn-commits] JBL Code SVN: r36699 - in labs/jbossrules/tags/5.2.0.M1: drools-decisiontables and 33 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Feb 24 10:37:23 EST 2011


Author: ge0ffrey
Date: 2011-02-24 10:37:22 -0500 (Thu, 24 Feb 2011)
New Revision: 36699

Added:
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/.gitignore
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/build.properties
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/pom.xml
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/DecisionTableProviderImpl.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/ExternalSpreadsheetCompiler.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/InputType.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/SourcePackageProvider.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/SpreadsheetCompiler.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/ActionType.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DecisionTableParser.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DefaultRuleSheetListener.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/LhsBuilder.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RhsBuilder.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleMatrixSheetListener.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetParserUtil.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SourceBuilder.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvLineParser.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvParser.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/ExcelParser.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/NullSheetListener.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/PropertiesSheetListener.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/osgi/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/osgi/decisiontables/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/osgi/decisiontables/Activator.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/org/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/org/drools/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/org/drools/decisiontable/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/org/drools/decisiontable/package.html
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/Example.xls
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/README.txt
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/pydt.py
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/pydt_test.py
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/Driver.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/Policy.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/launcher/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/launcher/PricingRuleLauncher.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ChangeSetTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/Cheese.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ExternalSpreadsheetCompilerIntegrationTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ExternalSpreadsheetCompilerUnitTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/Person.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SourcePackageProviderTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetIntegrationTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/ActionTypeTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/ColumnFactoryTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/LhsBuilderTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/PropertiesSheetListenerTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RhsBuilderTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleSheetParserUtilTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseLargeTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RulesheetUtil.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvLineParserTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvParserTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls/ExcelParserTest.java
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/BasicWorkbook.xls
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/ComplexWorkbook.csv
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/ComplexWorkbook.xls
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/CustomWorkbook.xls
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/ExamplePolicyPricing.xls
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/IntegrationExampleTest.xls
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/MultiSheetDST.xls
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/TeamAllocationExample_TYPICAL_EXAMPLE.xls
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/TestCsv.csv
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/VeryLargeWorkbook.xls
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset1Test.drl
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset1Test.xml
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset2Test.drl
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_integration.drl
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_pricing1.drl
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_pricing2.drl
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template1.drl
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template2.drl
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template3.drl
   labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template4.drl
Log:
All monolothic build versions (<= 5.2.0.M1) stay in subversion

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/.gitignore
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/.gitignore	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/.gitignore	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,13 @@
+/target
+/local
+
+# Eclipse, Netbeans and IntelliJ files
+/.*
+!.gitignore
+/nbproject
+/*.ipr
+/*.iws
+/*.iml
+
+# The META-INF directory is generated by the maven-felix-plugin
+META-INF

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/build.properties
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/build.properties	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/build.properties	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,12 @@
+src.includes = .,\
+               build.properties,\
+               META-INF/,\
+               src/,\
+               pom.xml
+bin.includes = .,\
+               META-INF/,\
+               build.properties               
+source.. = src/main/java/,\
+           src/main/resources/
+output.. = target/classes/     
+jars.compile.order = .          

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/pom.xml
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/pom.xml	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/pom.xml	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.drools</groupId>
+    <artifactId>drools</artifactId>
+    <version>5.2.0.M1</version>
+  </parent>
+  <artifactId>drools-decisiontables</artifactId>
+  <packaging>jar</packaging>
+  <name>Drools :: Decision Tables</name>
+  
+  <dependencies>
+    <!-- Internal dependencies -->
+    <dependency>
+      <groupId>org.drools</groupId>
+      <artifactId>drools-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.drools</groupId>
+      <artifactId>drools-compiler</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.drools</groupId>
+      <artifactId>drools-templates</artifactId>
+    </dependency>
+    <!-- External dependencies -->
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.osgi.compendium</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>net.sourceforge.jexcelapi</groupId>
+      <artifactId>jxl</artifactId>
+    </dependency>
+
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifestFile>META-INF/MANIFEST.MF</manifestFile>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <executions>
+          <execution>
+            <id>manifest</id>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>manifest</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <manifestLocation>META-INF</manifestLocation>
+          <instructions>
+            <Bundle-SymbolicName>org.drools.decisiontables;singleton:=true</Bundle-SymbolicName>
+            <_removeheaders>Ignore-Package</_removeheaders>
+            <Require-Bundle>org.drools.core;bundle-version="5.2.0.M1"</Require-Bundle>
+            <Import-Package>!org.drools.*, *</Import-Package>
+            <Export-Package>org.drools.*</Export-Package>
+            <DynamicImport-Package>org.drools.*</DynamicImport-Package>
+            <Bundle-Activator>org.drools.osgi.decisiontables.Activator</Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/DecisionTableProviderImpl.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/DecisionTableProviderImpl.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/DecisionTableProviderImpl.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,238 @@
+package org.drools.decisiontable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import org.drools.builder.DecisionTableConfiguration;
+import org.drools.compiler.DecisionTableProvider;
+import org.drools.core.util.StringUtils;
+
+public class DecisionTableProviderImpl
+    implements
+    DecisionTableProvider {
+
+    public String loadFromInputStream(InputStream is,
+                                      DecisionTableConfiguration configuration) {
+
+        return compileStream( is,
+                              configuration );
+    }
+    
+    private String compileStream(InputStream is,
+                                 DecisionTableConfiguration configuration) {
+        SpreadsheetCompiler compiler = new SpreadsheetCompiler();
+        switch ( configuration.getInputType() ) {
+            case XLS : {
+                if ( StringUtils.isEmpty( configuration.getWorksheetName() ) ) {
+                    return compiler.compile( is,
+                                             InputType.XLS );
+                } else {
+                    return compiler.compile( is,
+                                             configuration.getWorksheetName() );
+                }
+            }
+            case CSV : {
+                return compiler.compile( is,
+                                         InputType.CSV );
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Adapts a <code>Reader</code> as an <code>InputStream</code>.
+     * Adapted from <CODE>StringInputStream</CODE>.
+     *
+     */
+    public static class ReaderInputStream extends InputStream {
+
+        /** Source Reader */
+        private Reader in;
+
+        private String encoding = System.getProperty( "file.encoding" );
+
+        private byte[] slack;
+
+        private int    begin;
+
+        /**
+         * Construct a <CODE>ReaderInputStream</CODE>
+         * for the specified <CODE>Reader</CODE>.
+         *
+         * @param reader   <CODE>Reader</CODE>.  Must not be <code>null</code>.
+         */
+        public ReaderInputStream(Reader reader) {
+            in = reader;
+        }
+
+        /**
+         * Construct a <CODE>ReaderInputStream</CODE>
+         * for the specified <CODE>Reader</CODE>,
+         * with the specified encoding.
+         *
+         * @param reader     non-null <CODE>Reader</CODE>.
+         * @param encoding   non-null <CODE>String</CODE> encoding.
+         */
+        public ReaderInputStream(Reader reader,
+                                 String encoding) {
+            this( reader );
+            if ( encoding == null ) {
+                throw new IllegalArgumentException( "encoding must not be null" );
+            } else {
+                this.encoding = encoding;
+            }
+        }
+
+        /**
+         * Reads from the <CODE>Reader</CODE>, returning the same value.
+         *
+         * @return the value of the next character in the <CODE>Reader</CODE>.
+         *
+         * @exception IOException if the original <code>Reader</code> fails to be read
+         */
+        public synchronized int read() throws IOException {
+            if ( in == null ) {
+                throw new IOException( "Stream Closed" );
+            }
+
+            byte result;
+            if ( slack != null && begin < slack.length ) {
+                result = slack[begin];
+                if ( ++begin == slack.length ) {
+                    slack = null;
+                }
+            } else {
+                byte[] buf = new byte[1];
+                if ( read( buf,
+                           0,
+                           1 ) <= 0 ) {
+                    result = -1;
+                }
+                result = buf[0];
+            }
+
+            if ( result < -1 ) {
+                result += 256;
+            }
+
+            return result;
+        }
+
+        /**
+         * Reads from the <code>Reader</code> into a byte array
+         *
+         * @param b  the byte array to read into
+         * @param off the offset in the byte array
+         * @param len the length in the byte array to fill
+         * @return the actual number read into the byte array, -1 at
+         *         the end of the stream
+         * @exception IOException if an error occurs
+         */
+        public synchronized int read(byte[] b,
+                                     int off,
+                                     int len) throws IOException {
+            if ( in == null ) {
+                throw new IOException( "Stream Closed" );
+            }
+
+            while ( slack == null ) {
+                char[] buf = new char[len]; // might read too much
+                int n = in.read( buf );
+                if ( n == -1 ) {
+                    return -1;
+                }
+                if ( n > 0 ) {
+                    slack = new String( buf,
+                                        0,
+                                        n ).getBytes( encoding );
+                    begin = 0;
+                }
+            }
+
+            if ( len > slack.length - begin ) {
+                len = slack.length - begin;
+            }
+
+            System.arraycopy( slack,
+                              begin,
+                              b,
+                              off,
+                              len );
+
+            if ( (begin += len) >= slack.length ) {
+                slack = null;
+            }
+
+            return len;
+        }
+
+        /**
+         * Marks the read limit of the StringReader.
+         *
+         * @param limit the maximum limit of bytes that can be read before the
+         *              mark position becomes invalid
+         */
+        public synchronized void mark(final int limit) {
+            try {
+                in.mark( limit );
+            } catch ( IOException ioe ) {
+                throw new RuntimeException( ioe.getMessage() );
+            }
+        }
+
+        /**
+         * @return   the current number of bytes ready for reading
+         * @exception IOException if an error occurs
+         */
+        public synchronized int available() throws IOException {
+            if ( in == null ) {
+                throw new IOException( "Stream Closed" );
+            }
+            if ( slack != null ) {
+                return slack.length - begin;
+            }
+            if ( in.ready() ) {
+                return 1;
+            } else {
+                return 0;
+            }
+        }
+
+        /**
+         * @return false - mark is not supported
+         */
+        public boolean markSupported() {
+            return false; // would be imprecise
+        }
+
+        /**
+         * Resets the StringReader.
+         *
+         * @exception IOException if the StringReader fails to be reset
+         */
+        public synchronized void reset() throws IOException {
+            if ( in == null ) {
+                throw new IOException( "Stream Closed" );
+            }
+            slack = null;
+            in.reset();
+        }
+
+        /**
+         * Closes the Stringreader.
+         *
+         * @exception IOException if the original StringReader fails to be closed
+         */
+        public synchronized void close() throws IOException {
+            if ( in != null ) {
+                in.close();
+                slack = null;
+                in = null;
+            }
+        }
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/ExternalSpreadsheetCompiler.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/ExternalSpreadsheetCompiler.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/ExternalSpreadsheetCompiler.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.decisiontable.parser.DecisionTableParser;
+import org.drools.decisiontable.parser.xls.ExcelParser;
+import org.drools.template.parser.DataListener;
+import org.drools.template.parser.DefaultTemplateContainer;
+import org.drools.template.parser.TemplateContainer;
+import org.drools.template.parser.TemplateDataListener;
+
+public class ExternalSpreadsheetCompiler {
+
+    public String compile(final String xls,
+                          final String template,
+                          int startRow,
+                          int startCol) {
+        return compile( xls,
+                        template,
+                        InputType.XLS,
+                        startRow,
+                        startCol );
+
+    }
+
+    public String compile(final String xls,
+                          final String template,
+                          InputType type,
+                          int startRow,
+                          int startCol) {
+        final InputStream xlsStream = this.getClass().getResourceAsStream( xls );
+        final InputStream templateStream = this.getClass().getResourceAsStream( template );
+        return compile( xlsStream,
+                        templateStream,
+                        type,
+                        startRow,
+                        startCol );
+
+    }
+
+    public String compile(final String xls,
+                          final String worksheetName,
+                          final String template,
+                          int startRow,
+                          int startCol) {
+        final InputStream xlsStream = this.getClass().getResourceAsStream( xls );
+        final InputStream templateStream = this.getClass().getResourceAsStream( template );
+        return compile( xlsStream,
+                        worksheetName,
+                        templateStream,
+                        startRow,
+                        startCol );
+
+    }
+
+    public String compile(final InputStream xlsStream,
+                          final InputStream templateStream,
+                          int startRow,
+                          int startCol) {
+        return compile( xlsStream,
+                        templateStream,
+                        InputType.XLS,
+                        startRow,
+                        startCol );
+    }
+
+    public String compile(final InputStream xlsStream,
+                          final InputStream templateStream,
+                          InputType type,
+                          int startRow,
+                          int startCol) {
+        TemplateContainer tc = new DefaultTemplateContainer( templateStream );
+        closeStream( templateStream );
+        return compile( xlsStream,
+                        type,
+                        new TemplateDataListener( startRow,
+                                                  startCol,
+                                                  tc ) );
+    }
+
+    public String compile(final InputStream xlsStream,
+                          final String worksheetName,
+                          final InputStream templateStream,
+                          int startRow,
+                          int startCol) {
+        TemplateContainer tc = new DefaultTemplateContainer( templateStream );
+        closeStream( templateStream );
+        return compile( xlsStream,
+                        worksheetName,
+                        new TemplateDataListener( startRow,
+                                                  startCol,
+                                                  tc ) );
+    }
+
+    public void compile(final String xls,
+                        InputType type,
+                        final List<DataListener> listeners) {
+        final InputStream xlsStream = this.getClass().getResourceAsStream( xls );
+        compile( xlsStream,
+                 type,
+                 listeners );
+    }
+
+    public void compile(final String xls,
+                        final Map<String, List<DataListener>> listeners) {
+        final InputStream xlsStream = this.getClass().getResourceAsStream( xls );
+        compile( xlsStream,
+                 listeners );
+    }
+
+    public void compile(final InputStream xlsStream,
+                        InputType type,
+                        final List<DataListener> listeners) {
+        final DecisionTableParser parser = type.createParser( listeners );
+        parser.parseFile( xlsStream );
+        closeStream( xlsStream );
+    }
+
+    public void compile(final InputStream xlsStream,
+                        final Map<String, List<DataListener>> listeners) {
+        final DecisionTableParser parser = new ExcelParser( listeners );
+        parser.parseFile( xlsStream );
+        closeStream( xlsStream );
+    }
+
+    /**
+     * Generates DRL from the input stream containing the spreadsheet.
+     * 
+     * @param xlsStream
+     *            The stream to the spreadsheet. Uses the first worksheet found
+     *            for the decision tables, ignores others.
+     * @param type
+     *            The type of the file - InputType.CSV or InputType.XLS
+     * @param listener
+     * @return DRL xml, ready for use in drools.
+     * @throws IOException
+     */
+    public String compile(final InputStream xlsStream,
+                          final InputType type,
+                          final TemplateDataListener listener) {
+        ArrayList<DataListener> listeners = new ArrayList<DataListener>();
+        listeners.add( listener );
+        compile( xlsStream,
+                 type,
+                 listeners );
+        return listener.renderDRL();
+    }
+
+    public String compile(final InputStream xlsStream,
+                          final String worksheetName,
+                          final TemplateDataListener listener) {
+        Map<String, List<DataListener>> listeners = new HashMap<String, List<DataListener>>();
+        List<DataListener> l = new ArrayList<DataListener>();
+        l.add( listener );
+        listeners.put( worksheetName,
+                       l );
+        compile( xlsStream,
+                 listeners );
+        return listener.renderDRL();
+    }
+
+    private void closeStream(final InputStream stream) {
+        try {
+            stream.close();
+        } catch ( final Exception e ) {
+            System.err.print( "WARNING: Wasn't able to " + "correctly close stream for decision table. " + e.getMessage() );
+        }
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/InputType.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/InputType.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/InputType.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable;
+
+import java.util.List;
+
+import org.drools.decisiontable.parser.DecisionTableParser;
+import org.drools.decisiontable.parser.csv.CsvLineParser;
+import org.drools.decisiontable.parser.csv.CsvParser;
+import org.drools.decisiontable.parser.xls.ExcelParser;
+import org.drools.template.parser.DataListener;
+
+/**
+ * Provides valid input types for decision tables.
+ * (which also serve as parser factories).
+ * 
+ * @author Michael Neale
+ */
+public abstract class InputType {
+    public static final InputType XLS = new XlsInput();
+    public static final InputType CSV = new CsvInput();
+
+    protected InputType() {
+
+    }
+
+    /**
+     * @param listener
+     * @return The appropriate Parser. 
+     */
+    public abstract DecisionTableParser createParser(DataListener listener);
+    public abstract DecisionTableParser createParser(List<DataListener> listeners);
+
+}
+
+class XlsInput extends InputType {
+
+    public DecisionTableParser createParser(final DataListener listener) {
+        return new ExcelParser( listener );
+    }
+    public DecisionTableParser createParser(final List<DataListener> listeners) {
+    	return new ExcelParser( listeners );
+    }
+
+}
+
+class CsvInput extends InputType {
+
+    public DecisionTableParser createParser(final DataListener listener) {
+        return new CsvParser( listener,
+                              new CsvLineParser() );
+    }
+
+    public DecisionTableParser createParser(final List<DataListener> listeners) {
+    	return new CsvParser( listeners,
+    			new CsvLineParser() );
+    }
+    
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/SourcePackageProvider.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/SourcePackageProvider.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/SourcePackageProvider.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,48 @@
+package org.drools.decisiontable;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.agent.FileLoader;
+import org.drools.compiler.DroolsParserException;
+import org.drools.compiler.PackageBuilder;
+import org.drools.rule.Package;
+
+/**
+ * This is used by the agent when a source file is encountered.
+ * 
+ * @author Toni Rikkola
+ *
+ */
+public class SourcePackageProvider
+    implements
+    FileLoader {
+
+    public Package loadPackage(File rm) throws IOException {
+        final FileInputStream fin = new FileInputStream( rm );
+
+        final SpreadsheetCompiler converter = new SpreadsheetCompiler();
+        String drl = converter.compile( fin,
+                                        InputType.XLS );
+
+        fin.close();
+        
+        PackageBuilder b = new PackageBuilder();
+        try {
+            b.addPackageFromDrl( new StringReader( drl ) );
+            if ( b.hasErrors() ) {
+                throw new RuntimeDroolsException( "Error building rules from source: " + b.getErrors() );
+            } else {
+                return b.getPackage();
+            }
+        } catch ( DroolsParserException e ) {
+            throw new RuntimeException( e );
+        }
+
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/SpreadsheetCompiler.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/SpreadsheetCompiler.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/SpreadsheetCompiler.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.decisiontable.parser.DecisionTableParser;
+import org.drools.decisiontable.parser.DefaultRuleSheetListener;
+import org.drools.decisiontable.parser.RuleSheetListener;
+import org.drools.decisiontable.parser.xls.ExcelParser;
+import org.drools.template.model.DRLOutput;
+import org.drools.template.model.Package;
+import org.drools.template.parser.DataListener;
+
+/**
+ * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale </a>
+ *
+ * This class handles the input XLS and CSV and extracts the rule DRL, ready for
+ * pumping into drools.
+ */
+public class SpreadsheetCompiler {
+
+    /**
+     * Generates DRL from the input stream containing the spreadsheet.
+     *
+     * @param showPackage
+     *            tells it to print or not print any package statements in the spreadsheet.
+     * @param xlsStream
+     *            The stream to the spreadsheet. Uses the first worksheet found
+     *            for the decision tables, ignores others.
+     * @return DRL xml, ready for use in drools.
+     */
+    public String compile(boolean showPackage,
+                          final InputStream xlsStream,
+                          final InputType type) {
+        return compile( xlsStream,
+                        type,
+                        new DefaultRuleSheetListener( showPackage ) );
+    }
+
+    /**
+     * Generates DRL from the input stream containing the spreadsheet.
+     *
+     * @param xlsStream
+     *            The stream to the spreadsheet. Uses the first worksheet found
+     *            for the decision tables, ignores others.
+     * @return DRL xml, ready for use in drools.
+     */
+    public String compile(final InputStream xlsStream,
+                          final InputType type) {
+        return compile( xlsStream,
+                        type,
+                        new DefaultRuleSheetListener() );
+    }
+
+    /**
+     * Generates DRL from the input stream containing the spreadsheet.
+     *
+     * @param xlsStream
+     *            The stream to the spreadsheet. Uses the first worksheet found
+     *            for the decision tables, ignores others.
+     * @param type
+     *            The type of the file - InputType.CSV or InputType.XLS
+     * @param listener
+     *
+     * @return DRL xml, ready for use in drools.
+     */
+    public String compile(final InputStream xlsStream,
+                          final InputType type,
+                          final RuleSheetListener listener) {
+        final DecisionTableParser parser = type.createParser( listener );
+        parser.parseFile( xlsStream );
+        final Package rulePackage = listener.getRuleSet();
+        final DRLOutput out = new DRLOutput();
+        rulePackage.renderDRL( out );
+        return out.getDRL();
+    }
+
+    /**
+     * Convenience implementation, taking rules from the classpath. It is
+     * recommended to use the stream version, as you can then change rules
+     * dynamically. (that is a lot of the benefit of rule engines !).
+     *
+     * @param classPathResource
+     *            full class path to the spreadsheet you wish to convert to DRL.
+     *            Uses the first worksheet for the decision tables.
+     * @return DRL.
+     */
+    public String compile(final String classPathResource,
+                          final InputType inputType) {
+        final InputStream stream = this.getClass().getResourceAsStream( classPathResource );
+        try {
+            final String drl = compile( stream,
+                                        inputType );
+            return drl;
+        } finally {
+            closeStream( stream );
+        }
+    }
+
+    /**
+     * Looks for a named worksheet to find the decision tables on. Only works
+     * with XLS format spreadsheets (as they have multiple worksheets).
+     *
+     * @param stream
+     *            The stream of the decision tables (spreadsheet) IN XLS format !!
+     * @param worksheetName
+     *            The name of the worksheet that the decision tables live on.
+     * @return DRL, ready to go.
+     */
+    public String compile(final InputStream stream,
+                          final String worksheetName) {
+        final RuleSheetListener listener = getRuleSheetListener( stream,
+                                                                 worksheetName );
+        final Package rulePackage = listener.getRuleSet();
+        final DRLOutput out = new DRLOutput();
+        rulePackage.renderDRL( out );
+        return out.getDRL();
+    }
+
+    private RuleSheetListener getRuleSheetListener(final InputStream stream,
+                                                   final String worksheetName) {
+        final RuleSheetListener listener = new DefaultRuleSheetListener();
+        final Map<String, List<DataListener>> sheetListeners = new HashMap<String, List<DataListener>>();
+        final List<DataListener> listeners = new ArrayList<DataListener>();
+        listeners.add(listener);
+        sheetListeners.put( worksheetName,
+                       listeners );
+        final ExcelParser parser = new ExcelParser( sheetListeners );
+        parser.parseFile( stream );
+        return listener;
+    }
+
+    private void closeStream(final InputStream stream) {
+        try {
+            stream.close();
+        } catch ( final Exception e ) {
+            System.err.print( "WARNING: Wasn't able to " + "correctly close stream for decision table. " + e.getMessage() );
+        }
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/ActionType.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/ActionType.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/ActionType.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.template.parser.DecisionTableParseException;
+
+/**
+ * Simple holder class identifying a condition, action or attribute column, also
+ * including the rule name and a comment (called "description").
+ * Its objects are stored in a map in the main listener class, to track what type of values
+ * you can expect to see in the rows directly below the column header, identified
+ * by an ActionType.Code.
+ * 
+ * @author Michael Neale
+ */
+public class ActionType {
+
+    public enum Code {
+        CONDITION(       "CONDITION",        "C" ),
+        ACTION(          "ACTION",           "A" ),
+        NAME(            "NAME",             "N", 1 ),
+        DESCRIPTION(     "DESCRIPTION",      "I" ),
+        SALIENCE(        "PRIORITY",         "P", 1 ),
+        DURATION(        "DURATION",         "D", 1 ),
+        NOLOOP(          "NO-LOOP",          "U", 1 ),
+        LOCKONACTIVE(    "LOCK-ON-ACTIVE",   "L", 1 ),
+        AUTOFOCUS(       "AUTO-FOCUS",       "F", 1 ),
+        ACTIVATIONGROUP( "ACTIVATION-GROUP", "X", 1 ),
+        AGENDAGROUP(     "AGENDA-GROUP",     "G", 1 ),
+        RULEFLOWGROUP(   "RULEFLOW-GROUP",   "R", 1 ),
+        METADATA(        "METADATA",         "@" );
+                
+        private String colHeader;
+        private String colShort;
+        private int    maxCount;
+        
+        /**
+         * Constructor.
+         * @param colHeader the column header
+         * @param colShort  a single letter, recognized as initial
+         * @param maxCount  maximum number of permitted columns
+         */
+        Code( String colHeader, String colShort, int maxCount ){
+            this.colHeader = colHeader;
+            this.colShort = colShort;
+            this.maxCount = maxCount;
+        }
+        
+        
+        Code( String colHeader, String colShort ){
+        	this( colHeader, colShort, Integer.MAX_VALUE );
+        }
+        
+        public String getColHeader(){
+            return colHeader;
+        }
+        public String getColShort(){
+            return colShort;
+        }
+		public int getMaxCount() {
+			return maxCount;
+		}
+    }
+
+    public static final EnumSet<Code> ATTRIBUTE_CODE_SET = EnumSet.range( Code.SALIENCE, Code.RULEFLOWGROUP );
+
+    private static final Map<String,Code> tag2code = new HashMap<String,Code>();
+    static {
+        for( Code code: EnumSet.allOf( Code.class ) ){
+        	tag2code.put( code.colHeader, code );
+        	tag2code.put( code.colShort, code );
+        }
+    }
+
+    private Code code;
+    private SourceBuilder sourceBuilder  = null;
+
+    /**
+     * Constructor.
+     * @param actionTypeCode code identifying the column
+     */
+    ActionType( Code actionTypeCode) {
+        this.code = actionTypeCode;
+    }
+
+    public static EnumSet<Code> getAttributeCodeSet() {
+		return ATTRIBUTE_CODE_SET;
+	}
+
+	public static Map<String, Code> getTag2code() {
+		return tag2code;
+	}
+
+	/**
+     * Retrieves the code.
+     * @return an enum Code value
+     */
+    public Code getCode(){
+    	return this.code;
+    }
+
+    /**
+     * This is only set for LHS or RHS building.
+     */
+    public void setSourceBuilder(SourceBuilder src) {
+        this.sourceBuilder = src;
+    }
+
+    public SourceBuilder getSourceBuilder() {
+        return this.sourceBuilder;
+    }
+
+    /**
+     * Create a new action type that matches this cell, and add it to the map,
+     * keyed on that column.
+     */
+    public static void addNewActionType(final Map<Integer, ActionType> actionTypeMap,
+                                        final String value,
+                                        final int column, final int row) {
+        final String ucValue = value.toUpperCase();  
+
+        Code code = tag2code.get( ucValue );
+        if( code == null ) code = tag2code.get( ucValue.substring( 0, 1 ) );
+        if( code != null ){
+        	
+        	int count = 0;
+        	for( ActionType at: actionTypeMap.values() ){
+        		if( at.getCode() == code ) count++;
+        	}
+        	if( count >= code.getMaxCount() ){
+        		throw new DecisionTableParseException( "Maximum number of " +
+        				code.getColHeader() + "/" + code.getColShort() + " columns is " +
+        				code.getMaxCount() + ", in cell " + RuleSheetParserUtil.rc2name(row, column) );
+        	}
+            actionTypeMap.put( new Integer( column ), new ActionType( code ) );
+        } else {
+            throw new DecisionTableParseException(
+                    "Invalid column header: " + value + ", should be CONDITION, ACTION or attribute, " +
+                    "in cell " + RuleSheetParserUtil.rc2name(row, column) );
+        }
+    }
+
+    /**
+     * This is where a code snippet template is added.
+     */
+    public void addTemplate(int row, int column, String content) {
+    	if( this.sourceBuilder == null ){
+    		throw new DecisionTableParseException(
+                    "Unexpected content \"" + content + "\" in cell " +
+                    RuleSheetParserUtil.rc2name(row, column) + ", leave this cell blank" );
+    	}
+        this.sourceBuilder.addTemplate( row, column, 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 row, int column, String content) {
+        //Michael Neale:
+        // For single standard quotes we escape them - eg they may mean "inches" 
+        // as in "I want a Stonehenge replica 19" tall"
+        int idx = content.indexOf("\"");
+        if (idx > 0 && content.indexOf("\"", idx) > -1) {
+            content = content.replace("\"", "\\\"");
+        }
+//        if( this.sourceBuilder != null ){
+        this.sourceBuilder.addCellValue( row, column, content );
+//        }
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DecisionTableParser.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DecisionTableParser.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DecisionTableParser.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.io.InputStream;
+
+/**
+ * Generic interface for all input parsers.
+ * 
+ * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a>
+ *
+ */
+public interface DecisionTableParser {
+    /**
+     * Parse an input stream, store the resulting rulebase.
+     */
+    public void parseFile(InputStream inStream);
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DefaultRuleSheetListener.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DefaultRuleSheetListener.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/DefaultRuleSheetListener.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,631 @@
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.decisiontable.parser.xls.PropertiesSheetListener;
+import org.drools.decisiontable.parser.xls.PropertiesSheetListener.CaseInsensitiveMap;
+import org.drools.template.model.Condition;
+import org.drools.template.model.Consequence;
+import org.drools.template.model.Global;
+import org.drools.template.model.Import;
+import org.drools.template.model.Package;
+import org.drools.template.model.Rule;
+import org.drools.template.parser.DecisionTableParseException;
+import static org.drools.decisiontable.parser.ActionType.Code;
+
+/**
+ * An object of this class is prepared to receive calls passing it the
+ * contents of a spreadsheet containing one or more decision tables.
+ * Each of these tables is then expanded into a set of similar rules,
+ * varying to a degree with respect to the patterns and actions.
+ * 
+ * A "rule set" starts with some overall definitions such as imports,
+ * globals, functions and queries.
+ * 
+ * A table is identifed by a cell beginning with the text "RuleTable". The first
+ * row after the table identifier defines the column type: either a pattern of
+ * the condition or an action for the consequence, or an attribute.
+ * 
+ * The second row contains optional pattern type declarations. If cells in
+ * this row are merged, then all snippets below the merged stretch become part of
+ * the same pattern, as separate constraints.
+ *
+ * The third row identifies the java code block associated with the condition
+ * or consequence. This code block should include one or more parameter markers
+ * for the insertion of values defined in cells of that column.
+ * 
+ * The third row is available for comments on the purpose of the column.
+ *
+ * All subsequent rows identify rules with the set, providing values to be
+ * inserted where there are markers in the code snippets defined in the third
+ * row, or for the attribute identified by the column header.
+ * 
+ * @author <a href="mailto:shaun.addison at gmail.com"> Shaun Addison </a><a
+ *         href="mailto:michael.neale at gmail.com"> Michael Neale </a>
+ */
+public class DefaultRuleSheetListener
+implements RuleSheetListener {
+
+	//keywords
+	public static final String            QUERIES_TAG            = "Queries";
+	public static final String            FUNCTIONS_TAG          = "Functions";
+	public static final String            IMPORT_TAG             = "Import";
+	public static final String            SEQUENTIAL_FLAG        = "Sequential";
+	public static final String            VARIABLES_TAG          = "Variables";
+	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              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;
+	private int                           _ruleRow;
+	private int                           _ruleStartColumn;
+	private int                           _ruleStartRow;
+	private Rule                          _currentRule;
+	private String                        _currentRulePrefix;
+	private boolean                       _currentSequentialFlag = false;                        // indicates that we are in sequential mode
+
+	//accumulated output
+	private Map<Integer, ActionType>       _actions;
+	private final HashMap<Integer, String> _cellComments          = new HashMap<Integer, String>();
+	private final List<Rule>               _ruleList              = new LinkedList<Rule>();
+
+	//need to keep an ordered list of this to make conditions appear in the right order
+	private List<SourceBuilder>            sourceBuilders         = new ArrayList<SourceBuilder>();
+
+	private final PropertiesSheetListener _propertiesListener     = new PropertiesSheetListener();
+
+	private boolean showPackage;
+
+	/**
+	 * Constructor.
+	 */
+	public DefaultRuleSheetListener() {
+		this( true );
+	}
+
+	/**
+	 * Constructor.
+	 * @param showPackage if true, the rule set name is passed to the resulting package
+	 */
+	public DefaultRuleSheetListener(boolean showPackage) {
+		this.showPackage = showPackage;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.drools.decisiontable.parser.RuleSheetListener#getProperties()
+	 */
+	public CaseInsensitiveMap getProperties() {
+		return this._propertiesListener.getProperties();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.drools.decisiontable.parser.RuleSheetListener#getRuleSet()
+	 */
+	public Package getRuleSet() {
+		if ( this._ruleList.isEmpty() ) {
+			throw new DecisionTableParseException( "No RuleTable cells in spreadsheet." );
+		}
+		final Package ruleset = buildRuleSet();
+		return ruleset;
+	}
+
+	/**
+	 * Add a new rule to the current list of rules
+	 * @param rule
+	 */
+	protected void addRule(final Rule newRule) {
+		this._ruleList.add( newRule );
+	}
+
+	private Package buildRuleSet() {
+		final String defaultPackageName = "rule_table";
+		final String rulesetName =
+			getProperties().getSingleProperty( RULESET_TAG, defaultPackageName );
+
+		final Package ruleset = new Package( (showPackage) ? rulesetName : null );
+		for ( Rule rule : this._ruleList ) {
+			ruleset.addRule( rule );
+		}
+
+		final List<Import> importList = RuleSheetParserUtil.getImportList( getProperties().getProperty( IMPORT_TAG ) );
+		for ( Import import1 : importList ) {
+			ruleset.addImport( import1 );
+		}
+
+		final List<Global> variableList = RuleSheetParserUtil.getVariableList( getProperties().getProperty( VARIABLES_TAG ) );
+		for ( Global global : variableList ) {
+			ruleset.addVariable( global );
+		}
+
+		final List<String> functions = getProperties().getProperty( FUNCTIONS_TAG );
+		if( functions != null ){
+			for( String function: functions ){
+				ruleset.addFunctions( function );
+			}
+		}
+
+		final List<String> queries = getProperties().getProperty( QUERIES_TAG );
+		if( queries != null ){
+			for( String query: queries ){
+				ruleset.addQueries( query );
+			}
+		}
+
+		for( Code code: ActionType.ATTRIBUTE_CODE_SET ){
+			List<String> values = getProperties().getProperty( code.getColHeader() );
+			if( values != null ){
+				if( values.size() > 1 ){
+					List<String> cells = getProperties().getPropertyCells( code.getColHeader() );					
+					throw new DecisionTableParseException( "Multiple values for " + code.getColHeader() +
+							" in cells " + cells.toString() );
+				}
+				String value = values.get( 0 );
+				switch( code ){
+				case SALIENCE:
+					try {
+						ruleset.setSalience( new Integer( value ) );
+					} catch( NumberFormatException nfe ){
+						throw new DecisionTableParseException( "Priority is not an integer literal, in cell " + 
+								getProperties().getSinglePropertyCell( code.getColHeader() ) );
+					}
+                    break;
+				case DURATION:
+					try {
+						ruleset.setDuration( new Long( value ) );
+					} catch( NumberFormatException nfe ){
+						throw new DecisionTableParseException( "Duration is not an integer literal, in cell " + 
+								getProperties().getSinglePropertyCell( code.getColHeader() )  );
+					}
+					break;
+				case NOLOOP:
+					ruleset.setNoLoop( RuleSheetParserUtil.isStringMeaningTrue( value ) );
+					break;
+				case LOCKONACTIVE:
+					ruleset.setLockOnActive( RuleSheetParserUtil.isStringMeaningTrue( value ) );
+					break;
+				case AUTOFOCUS:
+					ruleset.setAutoFocus( RuleSheetParserUtil.isStringMeaningTrue( value ) );
+					break;
+				case ACTIVATIONGROUP:
+					ruleset.setActivationGroup( value );
+					break;
+				case AGENDAGROUP:
+					ruleset.setAgendaGroup( value );
+					break;
+				case RULEFLOWGROUP:
+					ruleset.setRuleFlowGroup( value );
+					break;
+				}
+			}
+		}
+
+		return ruleset;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see my.hssf.util.SheetListener#startSheet(java.lang.String)
+	 */
+	public void startSheet(final String name) {
+		// nothing to see here... move along..
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see my.hssf.util.SheetListener#finishSheet()
+	 */
+	public void finishSheet() {
+		this._propertiesListener.finishSheet();
+		finishRuleTable();
+		flushRule();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see my.hssf.util.SheetListener#newRow()
+	 */
+	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<SourceBuilder> iter = sourceBuilders.iterator(); iter.hasNext(); ) {
+			SourceBuilder src = iter.next();
+			if ( src.hasValues() ) {
+				switch( src.getActionTypeCode() ){
+				case CONDITION:
+					Condition cond = new Condition();
+					cond.setSnippet( src.getResult() );
+					_currentRule.addCondition( cond );
+					break;
+				case ACTION:
+					Consequence cons = new Consequence();
+					cons.setSnippet( src.getResult() );
+					_currentRule.addConsequence( cons );
+					break;
+				case METADATA:
+					_currentRule.addMetadata( src.getResult() );
+					break;
+				}
+				src.clearValues();
+			}
+		}
+
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see my.hssf.util.SheetListener#newCell(int, int, java.lang.String)
+	 */
+	public void newCell(final int row,
+			final int column,
+			final String value,
+			int mergedColStart) {
+		if ( isCellValueEmpty( value ) ) {
+			return;
+		}
+		if ( _isInRuleTable && row == this._ruleStartRow ) {
+			return;
+		}
+		if ( this._isInRuleTable ) {
+			processRuleCell( row, column, value, mergedColStart );
+		} else {
+			processNonRuleCell( row, column, value );
+		}
+	}
+
+	/**
+	 * This gets called each time a "new" rule table is found.
+	 */
+	private void initRuleTable(final int row,
+			final int column,
+			final String value) {
+		preInitRuleTable( row, column, value );
+		this._isInRuleTable = true;
+		this._actions = new HashMap<Integer, ActionType>();
+		this.sourceBuilders = new ArrayList<SourceBuilder>();
+		this._ruleStartColumn = column;
+		this._ruleStartRow = row;
+		this._ruleRow = row + LABEL_ROW + 1;
+
+		// setup stuff for the rules to come.. (the order of these steps are
+		// important !)
+		this._currentRulePrefix = RuleSheetParserUtil.getRuleName( value );
+		this._currentSequentialFlag = getSequentialFlag();
+
+		String headCell = RuleSheetParserUtil.rc2name( this._ruleStartRow, this._ruleStartColumn );
+		String ruleCell = RuleSheetParserUtil.rc2name( this._ruleRow, this._ruleStartColumn );
+		this._currentRule = createNewRuleForRow( this._ruleRow, headCell, ruleCell );
+
+		this._ruleList.add( this._currentRule );
+		postInitRuleTable( row, column, value );
+
+	}
+
+	/**
+	 * Called before rule table initialisation. Subclasses may
+	 * override this method to do additional processing.
+	 */
+	protected void preInitRuleTable(int row,
+			int column,
+			String value) {
+	}
+
+	protected Rule getCurrentRule() {
+		return _currentRule;
+	}
+
+	/**
+	 * Called after rule table initialisation. Subclasses may
+	 * override this method to do additional processing.
+	 */
+	protected void postInitRuleTable(int row,
+			int column,
+			String value) {
+	}
+
+	private boolean getSequentialFlag() {
+		final String seqFlag = getProperties().getSingleProperty( SEQUENTIAL_FLAG, "false" );
+		return RuleSheetParserUtil.isStringMeaningTrue( seqFlag );
+	}
+
+	private void finishRuleTable() {
+		if ( this._isInRuleTable ) {
+			this._currentSequentialFlag = false;
+			this._isInRuleTable = false;
+
+		}
+	}
+
+	private void processNonRuleCell(final int row,
+			final int column,
+			final String value) {
+		String testVal = value.trim().toLowerCase();
+		if ( testVal.startsWith( RULE_TABLE_TAG ) ) {
+			initRuleTable( row, column, value.trim() );
+		} else {
+			this._propertiesListener.newCell( row, column, value, RuleSheetListener.NON_MERGED );
+		}
+	}
+
+	private void processRuleCell(final int row,
+			final int column,
+			final String value,
+			final int mergedColStart) {
+		String trimVal = value.trim();
+		String testVal = trimVal.toLowerCase();
+		if ( testVal.startsWith( RULE_TABLE_TAG ) ) {
+			finishRuleTable();
+			initRuleTable( row, column, trimVal );
+			return;
+		}
+
+		// Ignore any comments cells preceding the first rule table column
+		if ( column < this._ruleStartColumn ) {
+			return;
+		}
+
+		// Ignore any further cells from the rule def row
+		if ( row == this._ruleStartRow ) {
+			return;
+		}
+
+		switch ( row - this._ruleStartRow ) {
+		case ACTION_ROW :
+			ActionType.addNewActionType( this._actions, trimVal, column, row );
+			break;
+
+		case OBJECT_TYPE_ROW :
+			objectTypeRow( row, column, trimVal, mergedColStart );
+			break;
+
+		case CODE_ROW :
+			codeRow( row, column, trimVal );
+			break;
+
+		case LABEL_ROW :
+			labelRow( row, column, trimVal );
+			break;
+
+		default :
+			nextDataCell( row, column, trimVal );
+			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 object declarations." + " Please insert an additional row before the snippets, " + 
+					"at cell " + RuleSheetParserUtil.rc2name( row, column ) );
+		}
+		ActionType action = getActionForColumn( row, column );
+		if ( mergedColStart == RuleSheetListener.NON_MERGED ) {
+			if ( action.getCode() == Code.CONDITION ) {
+				SourceBuilder src = new LhsBuilder( row-1, column, value );
+				action.setSourceBuilder( src );
+				this.sourceBuilders.add( src );
+
+			} else if ( action.getCode() == Code.ACTION ) {
+				SourceBuilder src = new RhsBuilder( Code.ACTION, row-1, column, value );
+				action.setSourceBuilder( src );
+				this.sourceBuilders.add( src );
+			}
+		} else {
+			if ( column == mergedColStart ) {
+				if ( action.getCode() == Code.CONDITION ) {
+					action.setSourceBuilder( new LhsBuilder( row-1, column, value ) );
+					this.sourceBuilders.add( action.getSourceBuilder() );
+				} else if ( action.getCode() == Code.ACTION ) {
+					action.setSourceBuilder( new RhsBuilder( Code.ACTION, row-1, column, 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 );
+		if ( actionType.getSourceBuilder() == null ) {
+			if ( actionType.getCode() == Code.CONDITION ) {
+				actionType.setSourceBuilder( new LhsBuilder( row-2, column, null ) );
+				this.sourceBuilders.add( actionType.getSourceBuilder() );
+			} else if ( actionType.getCode() == Code.ACTION ) {
+				actionType.setSourceBuilder( new RhsBuilder( Code.ACTION, row-2, column, null ) );
+				this.sourceBuilders.add( actionType.getSourceBuilder() );
+			} else if ( actionType.getCode() == Code.SALIENCE ) {
+				actionType.setSourceBuilder( new LhsBuilder( row-2, column, null ) );
+				this.sourceBuilders.add( actionType.getSourceBuilder() );
+			} else if ( actionType.getCode() == Code.METADATA ) {
+				actionType.setSourceBuilder( new RhsBuilder( Code.METADATA, row-2, column, null ) );
+				this.sourceBuilders.add( actionType.getSourceBuilder() );
+			}
+		}
+
+		if ( value.trim().equals( "" ) &&
+			(actionType.getCode() == Code.ACTION ||
+			 actionType.getCode() == Code.CONDITION ||
+			 actionType.getCode() == Code.METADATA) ) {
+			throw new DecisionTableParseException( "Code description in cell " +
+					RuleSheetParserUtil.rc2name( row, column ) +
+			" does not contain any code specification. It should!" );
+		}
+
+		actionType.addTemplate( row, column, value );
+	}
+
+	private void labelRow(final int row,
+			final int column,
+			final String value) {
+		final ActionType actionType = getActionForColumn( row, column );
+
+		if ( ! value.trim().equals( "" ) && (actionType.getCode() == Code.ACTION ||
+				actionType.getCode() == Code.CONDITION) ) {
+			this._cellComments.put( new Integer( column ), value );
+		} else {
+			this._cellComments.put( new Integer( column ),
+					"From cell: " + RuleSheetParserUtil.rc2name( row, column ) );
+		}
+	}
+
+	private ActionType getActionForColumn(final int row,
+			final int column) {
+		final ActionType actionType = this._actions.get( new Integer( column ) );
+
+		if ( actionType == null ) {
+			throw new DecisionTableParseException( "Code description in cell " + 
+					RuleSheetParserUtil.rc2name( row, column ) +
+			" does not have an 'ACTION' or 'CONDITION' column header." );
+		}
+
+		return actionType;
+	}
+
+	private void nextDataCell(final int row,
+			final int column,
+			final String value) {
+		final ActionType actionType = getActionForColumn( row, column );
+
+		if ( row - this._ruleRow > 1 ) {
+			// Encountered a row gap from the last rule.
+			// This is not part of the ruleset.
+			finishRuleTable();
+			processNonRuleCell( row, column, value );
+			return;
+		}
+
+		if ( row > this._ruleRow ) {
+			// In a new row/rule
+			String headCell = RuleSheetParserUtil.rc2name( this._ruleStartRow, this._ruleStartColumn );
+			String ruleCell = RuleSheetParserUtil.rc2name( row, this._ruleStartColumn );
+			this._currentRule = createNewRuleForRow( row, headCell, ruleCell );
+			this._ruleList.add( this._currentRule );
+			this._ruleRow++;
+		}
+
+		switch( actionType.getCode() ){
+		case CONDITION:
+		case ACTION:
+		case METADATA:
+			actionType.addCellValue( row, column, value );
+			break;        
+		case SALIENCE:
+			// Only if rule set is not sequential!
+			if( ! this._currentSequentialFlag ){
+				if( value.startsWith( "(" ) && value.endsWith( ")" ) ){
+					this._currentRule.setSalience( value );
+				} else {
+					try {
+						this._currentRule.setSalience( new Integer( value ) );
+					} catch( NumberFormatException nfe ){
+						throw new DecisionTableParseException( "Priority is not an integer literal, in cell " + 
+								RuleSheetParserUtil.rc2name( row, column ) );
+					}
+				}
+			}
+			break;
+		case NAME:
+			this._currentRule.setName( value );
+			break;
+		case DESCRIPTION:
+			this._currentRule.setDescription( value );
+			break;
+		case ACTIVATIONGROUP:
+			this._currentRule.setActivationGroup( value );
+			break;
+		case AGENDAGROUP:
+			this._currentRule.setAgendaGroup( value );
+			break;
+		case RULEFLOWGROUP:
+			this._currentRule.setRuleFlowGroup( value );
+			break;
+		case NOLOOP:
+			this._currentRule.setNoLoop( RuleSheetParserUtil.isStringMeaningTrue( value ) );
+			break;
+		case LOCKONACTIVE:
+			this._currentRule.setLockOnActive( RuleSheetParserUtil.isStringMeaningTrue( value ) );
+			break;
+		case AUTOFOCUS:
+			this._currentRule.setLockOnActive( RuleSheetParserUtil.isStringMeaningTrue( value ) );
+			break;
+		case DURATION:
+			try {
+				this._currentRule.setDuration( new Long( value ) );
+			} catch( NumberFormatException nfe ){
+				throw new DecisionTableParseException( "Duration is not an integer literal, in cell " + 
+						RuleSheetParserUtil.rc2name( row, column ) );
+			}
+			break;
+		}
+	}
+
+	private Rule createNewRuleForRow(final int row, final String headCell, final String ruleCell ) {
+		Integer salience = null;
+		if ( this._currentSequentialFlag ) {
+			salience = new Integer( Rule.calcSalience( row ) );
+		}
+		final int spreadsheetRow = row + 1;
+		final String name = this._currentRulePrefix + "_" + spreadsheetRow;
+		final Rule rule = new Rule( name, salience, spreadsheetRow );
+		rule.setComment( " rule values at " + ruleCell + ", header at " + headCell );
+
+		return rule;
+	}
+
+	private boolean isCellValueEmpty(final String value) {
+		return value == null || "".equals( value.trim() );
+	}
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/LhsBuilder.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/LhsBuilder.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/LhsBuilder.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,219 @@
+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 java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.drools.template.model.SnippetBuilder;
+import org.drools.template.parser.DecisionTableParseException;
+
+/**
+ * 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 int headerRow;
+	private int headerCol;
+    private String colDefPrefix;
+    private String colDefSuffix;
+    private boolean multiple;
+    private String andop;
+    private Map<Integer, String> constraints;
+    private List<String> values;
+    private boolean hasValues;
+    private static Set<String> operators;
+
+    static {
+        operators = new HashSet<String>();
+        operators.add( "==" );
+        operators.add( "=" );
+        operators.add( "!=" );
+        operators.add( "<" );
+        operators.add( ">" );
+        operators.add( "<=" );
+        operators.add( ">=" );
+        operators.add( "contains" );
+        operators.add( "matches" );
+        operators.add( "memberOf" );
+        operators.add( "str[startsWith]" );
+        operators.add( "str[endsWith]" );
+        operators.add( "str[length]" );
+    }
+    
+    private static final Pattern patParFrm = Pattern.compile( "\\(\\s*\\)\\s*from\\b" );
+    private static final Pattern patFrm    = Pattern.compile( "\\s+from\\s+" );
+    private static final Pattern patPar    = Pattern.compile( "\\(\\s*\\)" );
+    private static final Pattern patEval   = Pattern.compile( "\\beval\\s*(?:\\(\\s*\\)\\s*)?$" );
+    
+    
+    /**
+     * @param colDefinition The initial column definition that is shared via merged cells.
+     */
+    public LhsBuilder( int row, int column, String colDefinition ) {
+    	this.headerRow = row;
+    	this.headerCol = column;
+        this.constraints = new HashMap<Integer, String>();
+        this.values = new ArrayList<String>();
+
+        String colDef = colDefinition == null ? "" : colDefinition;
+        if( "".equals( colDef ) ){
+        	colDefPrefix = colDefSuffix = "";
+        	multiple = false;
+        	andop = "";
+        	return;
+        }
+        multiple = true;
+        
+        // ...eval
+        Matcher matEval = patEval.matcher( colDef );
+        if( matEval.find() ){
+            colDefPrefix = colDef.substring( 0, matEval.start() ) + "eval(";
+        	colDefSuffix = ")";
+        	andop = " && ";
+        	return;
+        }
+    	andop = ", ";
+
+        // ...(<b> ) from...
+        Matcher matParFrm = patParFrm.matcher( colDef );
+        if( matParFrm.find() ){
+        	colDefPrefix = colDef.substring( 0, matParFrm.start() ) + '(';
+        	colDefSuffix = ") from" + colDef.substring( matParFrm.end() );
+        	return;
+        }
+
+        // ...from...
+        Matcher matFrm = patFrm.matcher( colDef );
+        if( matFrm.find() ){
+        	colDefPrefix = colDef.substring( 0, matFrm.start() ) + "(";
+        	colDefSuffix = ") from " + colDef.substring( matFrm.end() );
+        	return;
+        }
+        
+        // ...(<b> )...
+        Matcher matPar = patPar.matcher( colDef );
+        if( matPar.find() ){
+        	colDefPrefix = colDef.substring( 0, matPar.start() ) + '(';
+        	colDefSuffix = ")" + colDef.substring( matPar.end() );
+        	return;
+        }
+        
+        // <a>
+        colDefPrefix = colDef + '(';
+        colDefSuffix = ")";
+    }
+
+	public ActionType.Code getActionTypeCode(){
+		return ActionType.Code.CONDITION;
+	}
+
+    public void addTemplate(int row, 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 + " == \"" + SnippetBuilder.PARAM_STRING + "\"" );
+        } else if (fieldType == FieldType.OPERATOR_FIELD) {
+            constraints.put( key, content + " \"" + SnippetBuilder.PARAM_STRING + "\"" );
+        }
+    }
+    
+    public void clearValues() {
+        this.hasValues = false;
+        this.values.clear();
+    }
+
+    public void addCellValue(int row, int column, String value) {
+        this.hasValues = true;
+        Integer key = new Integer( column );
+        String content = (String) this.constraints.get( key );
+        if( content == null ){
+        	throw new DecisionTableParseException( "No code snippet for CONDITION in cell " +
+        		RuleSheetParserUtil.rc2name( this.headerRow + 2, this.headerCol ) );
+        }
+        SnippetBuilder snip = new SnippetBuilder( content );
+        String result = snip.build( value );
+        this.values.add( result );
+    }
+
+    public String getResult() {
+        StringBuffer buf = new StringBuffer();
+        if ( ! isMultipleConstraints() ) {
+        	String nl = "";
+        	for( String content: values ){
+                buf.append( nl ).append( content );
+                nl = "\n";
+            }
+            return buf.toString();
+        } else {
+            buf.append( this.colDefPrefix );
+            String sep = "";
+            for( String constraint: values ) {
+                buf.append( sep ).append( constraint );
+                sep = this.andop;
+            }
+            buf.append( colDefSuffix );
+            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() {
+    	return multiple;
+    }
+
+    /**
+     * Work out the type of "field" that is being specified, 
+     * as in :
+     * age 
+     * age <
+     * age == $param
+     * age == $1 || age == $2
+     * forall{age < $}{,}
+     * 
+     * etc. as we treat them all differently.
+     */
+	public FieldType calcFieldType(String content) {
+		if (!SnippetBuilder.getType(content).equals(
+				SnippetBuilder.SnippetType.SINGLE)) {
+			return FieldType.NORMAL_FIELD;
+		}
+       for ( String op : operators ) {
+            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;
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RhsBuilder.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RhsBuilder.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RhsBuilder.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,92 @@
+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.template.model.SnippetBuilder;
+import org.drools.template.parser.DecisionTableParseException;
+
+/**
+ * Builds up a consequence entry.
+ * @author Michael Neale
+ *
+ */
+public class RhsBuilder implements SourceBuilder {
+
+	private int headerRow;
+	private int headerCol;
+	private ActionType.Code actionTypeCode;
+    private Map<Integer, String> templates;
+    private String variable;
+    private List<String> 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( ActionType.Code code, int row, int column, String boundVariable ) {
+    	this.actionTypeCode = code;
+    	this.headerRow = row;
+    	this.headerCol = column;
+        this.variable = boundVariable == null ? "" : boundVariable.trim();
+        this.templates = new HashMap<Integer, String>();
+        this.values = new ArrayList<String>();
+    }
+
+    
+	public ActionType.Code getActionTypeCode(){
+		return this.actionTypeCode;
+	}
+
+    
+    public void addTemplate(int row, int column, String content) {
+        Integer key = new Integer( column );
+        content = content.trim();
+        if ( isBoundVar() ) {
+            content = variable + "." + content + ";";
+        }
+        this.templates.put( key, content );
+    }
+
+    private boolean isBoundVar() {
+        return !("".equals( variable ));
+    }
+
+    public void addCellValue(int row, int column, String value) {
+    	hasValues = true;
+    	String template = (String) this.templates.get( new Integer( column ) );
+    	if( template == null ){
+    		throw new DecisionTableParseException( "No code snippet for " + 
+    				this.actionTypeCode + ", above cell " +
+    				RuleSheetParserUtil.rc2name( this.headerRow + 2, this.headerCol ) );
+    	}
+    	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<String> iter = this.values.iterator(); iter.hasNext(); ) {            
+            buf.append( iter.next() );
+            if (iter.hasNext()) {
+                buf.append( '\n' );
+            }
+        }
+        return buf.toString();
+    }
+
+    public boolean hasValues() {
+        return hasValues;
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleMatrixSheetListener.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleMatrixSheetListener.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleMatrixSheetListener.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.core.util.StringUtils;
+import org.drools.decisiontable.parser.DefaultRuleSheetListener;
+import org.drools.template.model.Condition;
+import org.drools.template.model.Consequence;
+import org.drools.template.model.Rule;
+import org.drools.template.model.SnippetBuilder;
+
+/**
+ * @author <a href="mailto:stevearoonie at gmail.com"> Steven Williams </a><a
+ *         href="mailto:michael.neale at gmail.com"> Michael Neale </a>
+ * 
+ * Define a ruleset spreadsheet which contains a matrix style decision tables.
+ * 
+ * This is an example of a custom RuleSheetListener. It differs from the standard
+ * decision table in the following ways:
+ *    - AgendaGroup property so that all rules fall within the same agenda-group
+ *    - Precondition property which specifies a condition that is always included 
+ *      if a rule is being generated
+ *    - Action property. Each cell within the decision table causes this action
+ *      to be triggered
+ *    - HorizontalCondition property. Each column header in the matrix
+ *      applies this condition
+ *    - VerticalCondition property. Each row header in the matrix applies this
+ *      condition 
+ * 
+ * A table is identifed by a cell beginning with the text "RuleTable". 
+ * The cells after RuleTable in the same row identify the Horizontal Conditions.
+ * The cells after RuleTable in the same column identify the Vertical Conditions.
+ * The cells with the matrix identify the actions.
+ * Wherever an action cell exists for a Vertical/Horizontal condition intersection
+ * the following rule is created:
+ * rule "rule_row_col"
+ *    agenda-group AgendaGroup
+ *    when
+ *       Precondition
+ *       VerticalCondition
+ *       HorizontalCondition
+ *    then
+ *       Action
+ * end
+ */
+public class RuleMatrixSheetListener extends DefaultRuleSheetListener {
+
+	//keywords
+	public static final String AGENDAGROUP_TAG         = "AgendaGroup";
+	public static final String PRECONDITION_TAG        = "Precondition";
+	public static final String ACTION_TAG              = "Action";
+	public static final String HORIZONTALCONDITION_TAG = "HorizontalCondition";
+	public static final String VERTICALCONDITION_TAG   = "VerticalCondition";
+
+	//state machine variables for this parser
+	private int                ruleTableRow;
+	private int                ruleTableColumn;
+	private String             _currentAgendaGroup;
+	private Condition          _currentPrecondition;
+	private String             _action;
+	private String             _horizontalCondition;
+	private String             _verticalCondition;
+	private List<Condition>    _horizontalConditions   = new ArrayList<Condition>();
+	private Condition          _currentVerticalCondition;
+	private boolean            isInRuleTable;
+	private Rule               firstRule;
+
+	public void newCell(final int row,
+			final int column,
+			final String value,
+			final int mergedColStart) {
+		// if we aren't in the rule table just use the default handling
+		// (add a property)
+		if ( ! isInRuleTable ) {
+			super.newCell( row, column, value, mergedColStart );
+			return;
+		}
+		// ignore empty cells
+		if ( StringUtils.isEmpty( value ) ) {
+			return;
+		}
+
+		//Horizontal header column
+		//Create a new condition using HorizontalCondition as the template
+		//and save it for later use
+		if ( row == (ruleTableRow) && column > ruleTableColumn ) {
+			_horizontalConditions.add( createCondition( value, _horizontalCondition ) );
+		}
+		//Vertical header column
+		//Create a new condition using VerticalCondition as the template
+		//and set it as the current condition
+		else if ( row > (ruleTableRow) && column == ruleTableColumn ) {
+			_currentVerticalCondition = createCondition( value, _verticalCondition );
+		}
+		//Intersection column
+		//Create a new Consequence
+		else if ( row > (ruleTableRow) && column > ruleTableColumn ) {
+			createRule( row, column, value );
+		}
+	}
+
+	private void createRule(final int row,
+			final int column,
+			final String value) {
+		final Consequence consequence = createConsequence( value );
+
+		Rule rule = firstRule;
+		if ( rule == null ) {
+			rule = new Rule( "rule_" + row + "_" + column,
+					null,
+					row );
+			addRule( rule );
+		} else {
+			firstRule = null;
+			rule.setName( "rule_" + row + "_" + column );
+		}
+		rule.setAgendaGroup( this._currentAgendaGroup );
+		rule.addCondition( this._currentPrecondition );
+		rule.addCondition( _currentVerticalCondition );
+		rule.addCondition( (Condition) _horizontalConditions.get( column - (ruleTableColumn + 1) ) );
+		rule.addConsequence( consequence );
+	}
+
+	private Consequence createConsequence(final String value) {
+		final SnippetBuilder snip = new SnippetBuilder( _action );
+		final String result = snip.build( value );
+		final Consequence consequence = new Consequence();
+		consequence.setSnippet( result );
+		return consequence;
+	}
+
+	private Condition createCondition(final String value,
+			final String conditionTemplate) {
+		SnippetBuilder snip = new SnippetBuilder( conditionTemplate );
+		String result = snip.build( value );
+		Condition condition = new Condition();
+		condition.setSnippet( result );
+		return condition;
+	}
+
+	public void newRow(int rowNumber,
+			int columns) {
+		// nothing to do here
+	}
+
+	public void finishSheet() {
+		// nothing to do here
+	}
+
+	protected void postInitRuleTable(int row,
+			int column,
+			String value) {
+		this.firstRule = getCurrentRule();
+	}
+
+	/**
+	 * This gets called each time a "new" rule table is found.
+	 */
+	protected void preInitRuleTable(final int row,
+			final int column,
+			final String value) {
+		this.ruleTableColumn = column;
+		this.ruleTableRow = row;
+		this.isInRuleTable = true;
+		this._currentAgendaGroup  = getProperties().getSingleProperty( AGENDAGROUP_TAG );
+		this._action              = getProperties().getSingleProperty( ACTION_TAG );
+		this._horizontalCondition = getProperties().getSingleProperty( HORIZONTALCONDITION_TAG );
+		this._verticalCondition   = getProperties().getSingleProperty( VERTICALCONDITION_TAG );
+		String precondition       = getProperties().getSingleProperty( PRECONDITION_TAG );
+		if ( precondition != null ) {
+			this._currentPrecondition = new Condition();
+			this._currentPrecondition.setSnippet( precondition );
+		}
+	}
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetListener.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.util.Properties;
+
+import org.drools.decisiontable.parser.xls.PropertiesSheetListener.CaseInsensitiveMap;
+import org.drools.template.model.Package;
+import org.drools.template.parser.DataListener;
+
+/**
+ * @author <a href="mailto:stevearoonie at gmail.com"> Steven Williams</a>
+ * 
+ * SheetListener used for creating rules
+ */
+public interface RuleSheetListener extends DataListener {
+
+	/**
+	 * Return the rule sheet properties
+	 */
+	public abstract CaseInsensitiveMap getProperties();
+
+	/**
+	 * Build the final ruleset as parsed.
+	 */
+	public abstract Package getRuleSet();
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetParserUtil.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetParserUtil.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/RuleSheetParserUtil.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.drools.template.model.Global;
+import org.drools.template.model.Import;
+import org.drools.template.parser.DecisionTableParseException;
+
+/**
+ * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale </a>
+ * 
+ * Parking lot for utility methods that don't belong anywhere else.
+ */
+public class RuleSheetParserUtil {
+
+	private RuleSheetParserUtil() {
+		// strictly util
+	}
+
+	public static String getRuleName(final String ruleRow) {
+		String testVal = ruleRow.toLowerCase();
+		final int left = testVal.indexOf( DefaultRuleSheetListener.RULE_TABLE_TAG );
+		return ruleRow.substring( left + DefaultRuleSheetListener.RULE_TABLE_TAG.length() ).trim();
+	}
+
+	private static void invalidRuleTableDef(final String ruleRow) {
+		throw new IllegalArgumentException( "Invalid rule table header cell. Should be in the format of 'RuleTable YourRuleName'. " + "It was: \n [" + ruleRow + "] \n" );
+	}
+
+	/**
+	 * Create a list of Import model objects from cell contents.
+	 * @param importCells The cells containing text for all the classes to import.
+	 * @return A list of Import classes, which can be added to the ruleset.
+	 */
+	public static List<Import> getImportList(final List<String> importCells) {
+		final List<Import> importList = new ArrayList<Import>();
+		if ( importCells == null ) return importList;
+
+		for( String importCell: importCells ){
+			final StringTokenizer tokens = new StringTokenizer( importCell, "," );
+			while ( tokens.hasMoreTokens() ) {
+				final Import imp = new Import();
+				imp.setClassName( tokens.nextToken().trim() );
+				importList.add( imp );
+			}
+		}
+		return importList;
+	}
+
+	/**
+	 * Create a list of Global model objects from cell contents. 
+	 * @param variableCella The cells containing text for all the global variables to set.
+	 * @return A list of Variable classes, which can be added to the ruleset.
+	 */
+	public static List<Global> getVariableList( final List<String> variableCells ){
+		final List<Global> variableList = new ArrayList<Global>();
+		if ( variableCells == null ) return variableList;
+
+		for( String variableCell: variableCells ){
+			final StringTokenizer tokens = new StringTokenizer( variableCell, "," );
+			while ( tokens.hasMoreTokens() ) {
+				final String token = tokens.nextToken();
+				final Global vars = new Global();
+				final StringTokenizer paramTokens = new StringTokenizer( token, " " );
+				vars.setClassName( paramTokens.nextToken() );
+				if ( !paramTokens.hasMoreTokens() ) {
+					throw new DecisionTableParseException( "The format for global variables is incorrect. " + "It should be: [Class name, Class otherName]. But it was: [" + variableCell + "]" );
+				}
+				vars.setIdentifier( paramTokens.nextToken() );
+				variableList.add( vars );
+			}
+		}
+		return variableList;
+	}
+
+	/**
+	 * @return true is the String could possibly mean true. False otherwise !
+	 */
+	public static boolean isStringMeaningTrue(String property) {
+		if ( property == null ) {
+			return false;
+		} else {
+			property = property.trim();
+			if ( property.equalsIgnoreCase( "true" ) ) {
+				return true;
+			} else if ( property.startsWith( "Y" ) ) {
+				return true;
+			} else if ( property.startsWith( "y" ) ) {
+				return true;
+			} else if ( property.equalsIgnoreCase( "on" ) ) {
+				return true;
+			} else {
+				return false;
+			}
+		}
+	}
+
+	/**
+	 * Convert spreadsheet row, column numbers to a cell name.
+	 * @param row  row number
+	 * @param col  the column number. Start with zero.
+	 * @return The spreadsheet name for this cell, "A" to "ZZZ".
+	 */
+	public static String rc2name( int row, int col ){
+		StringBuilder sb = new StringBuilder();
+		int b = 26;
+		int p = 1;
+		if( col >= b  ){
+			col -= b;
+			p *= b;
+		}
+		if( col >= b*b ){
+			col -= b*b;
+			p *= b;
+		}
+		while( p > 0 ){
+			sb.append( (char)(col/p + (int)'A') );
+			col %= p;
+			p /= b;
+		}
+		sb.append( row + 1 );
+		return sb.toString();
+	}
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SourceBuilder.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SourceBuilder.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/SourceBuilder.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,14 @@
+package org.drools.decisiontable.parser;
+
+/**
+ * This is for building up LHS and RHS code for a rule row.
+ * @author Michael Neale
+ */
+public interface SourceBuilder {
+	ActionType.Code getActionTypeCode();
+    String getResult();
+    void addTemplate(int row, int col, String content);
+    void addCellValue(int row, int col, String value);
+    void clearValues();
+    boolean hasValues();
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvLineParser.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvLineParser.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvLineParser.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser.csv;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 
+ * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a> Break up
+ *         a CSV line, with all the normal CSV features.
+ */
+public class CsvLineParser {
+    private ICsvParser lineParser;
+
+    public CsvLineParser() {
+        this.lineParser = new CsvParserImpl();
+    }
+
+    /**
+     * Use the current lineParser implementation to return a CSV line as a List
+     * of cells. (Strings).
+     */
+    public List<String> parse(final CharSequence line) {
+        return this.lineParser.parse( line.toString() );
+    }
+
+    /**
+     * This is insurance incase I need to replace it with more complex Csv
+     * handlers in the future.
+     */
+    static interface ICsvParser {
+        public List<String> parse(String line);
+    }
+
+    /**
+     * Parse comma-separated values (CSV), a common Windows file format. Sample
+     * input: "LU",86.25,"11/4/1998","2:19PM",+4.0625
+     * <p>
+     * Inner logic adapted from a C++ original that was Copyright (C) 1999
+     * Lucent Technologies Excerpted from 'The Practice of Programming' by Brian
+     * W. Kernighan and Rob Pike.
+     * <p>
+     * Included by permission of the http://tpop.awl.com/ web site, which says:
+     * "You may use this code for any purpose, as long as you leave the
+     * copyright notice and book citation attached." I have done so.
+     * 
+     * @author Brian W. Kernighan and Rob Pike (C++ original)
+     * @author Ian F. Darwin (translation into Java and removal of I/O)
+     * @author Ben Ballard (rewrote advQuoted to handle '""' and for
+     *         readability)
+     */
+    static class CsvParserImpl
+        implements
+        ICsvParser {
+
+        public static final char DEFAULT_SEP = ',';
+
+        /** Construct a CSV parser, with the default separator (','). */
+        public CsvParserImpl() {
+            this( CsvParserImpl.DEFAULT_SEP );
+        }
+
+        /**
+         * Construct a CSV parser with a given separator.
+         * 
+         * @param sep
+         *            The single char for the separator (not a list of separator
+         *            characters)
+         */
+        public CsvParserImpl(final char sep) {
+            this.fieldSep = sep;
+        }
+
+        /** The fields in the current String */
+        protected List<String> list = new ArrayList<String>();
+
+        /** the separator char for this parser */
+        protected char fieldSep;
+
+        /**
+         * parse: break the input String into fields
+         * 
+         * @return java.util.Iterator containing each field from the original as
+         *         a String, in order.
+         */
+        public List<String> parse(final String line) {
+            final StringBuffer sb = new StringBuffer();
+            this.list.clear(); // recycle to initial state
+            int i = 0;
+
+            if ( line.length() == 0 ) {
+                this.list.add( line );
+                return this.list;
+            }
+
+            do {
+                sb.setLength( 0 );
+                if ( i < line.length() && line.charAt( i ) == '"' ) {
+                    i = advQuoted( line,
+                                                                                       sb,
+                                                                                       ++i ); // skip
+                } else {
+                    i = advPlain( line,
+                                       sb,
+                                       i );
+                }
+                this.list.add( sb.toString() );
+                i++;
+            } while ( i < line.length() );
+
+            return this.list;
+        }
+
+        /** advQuoted: quoted field; return index of next separator */
+        protected int advQuoted(final String s,
+                                final StringBuffer sb,
+                                final int i) {
+            int j;
+            final int len = s.length();
+            for ( j = i; j < len; j++ ) {
+                if ( s.charAt( j ) == '"' && j + 1 < len ) {
+                    if ( s.charAt( j + 1 ) == '"' ) {
+                        j++; // skip escape char
+                    } else if ( s.charAt( j + 1 ) == this.fieldSep ) { // next delimeter
+                        j++; // skip end quotes
+                        break;
+                    }
+                } else if ( s.charAt( j ) == '"' && j + 1 == len ) { // end quotes at end of line
+                    break; // done
+                }
+                sb.append( s.charAt( j ) ); // regular character.
+            }
+            return j;
+        }
+
+        /** advPlain: unquoted field; return index of next separator */
+        protected int advPlain(final String s,
+                               final StringBuffer sb,
+                               final int i) {
+            int j;
+
+            j = s.indexOf( this.fieldSep,
+                           i ); // look for separator
+            if ( j == -1 ) { // none found
+                sb.append( s.substring( i ) );
+                return s.length();
+            } else {
+                sb.append( s.substring( i,
+                                        j ) );
+                return j;
+            }
+        }
+
+    }
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvParser.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvParser.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/csv/CsvParser.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser.csv;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.decisiontable.parser.DecisionTableParser;
+import org.drools.template.parser.DataListener;
+import org.drools.template.parser.DecisionTableParseException;
+
+/**
+ * Csv implementation. 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 implements DecisionTableParser {
+
+	private List<DataListener> _listeners;
+
+	private CsvLineParser _lineParser;
+
+	public CsvParser(final DataListener listener,
+			final CsvLineParser lineParser) {
+		_listeners = new ArrayList<DataListener>();
+		_listeners.add(listener);
+		this._lineParser = lineParser;
+	}
+
+	public CsvParser(final List<DataListener> listeners, final CsvLineParser lineParser) {
+		this._listeners = listeners;
+		this._lineParser = lineParser;
+	}
+
+	public void parseFile(final InputStream inStream) {
+		final BufferedReader reader = new BufferedReader(new InputStreamReader(
+				inStream));
+		try {
+			startSheet();
+			processRows(reader);
+			finishSheet();
+		} catch (final IOException e) {
+			throw new DecisionTableParseException(
+					"An error occurred reading the CSV data.", e);
+		}
+	}
+
+	private void startSheet() {
+	    for ( DataListener listener : _listeners ) {
+			listener.startSheet("csv");
+		}
+	}
+
+	private void finishSheet() {
+        for ( DataListener listener : _listeners ) {
+			listener.finishSheet();
+		}
+	}
+
+	private void newRow(final int row, final int numCells) {
+        for ( DataListener listener : _listeners ) {
+			listener.newRow(row, numCells);
+		}
+	}
+
+	private void newCell(final int row, final int column, final String value,
+			final int mergedColStart) {
+        for ( DataListener listener : _listeners ) {
+			listener.newCell(row, column, value, mergedColStart);
+		}
+	}
+
+	private void processRows(final BufferedReader reader) throws IOException {
+		String line = reader.readLine();
+
+		int row = 0;
+		while (line != null) {
+
+			final List<String> cells = this._lineParser.parse(line);
+			// remove the trailing empty "cells" which some tools smatter around
+			// trimCells(cells);
+			newRow(row, cells.size());
+
+			int startMergeCol = DataListener.NON_MERGED;
+			for (int col = 0; col < cells.size(); col++) {
+				String cell = (String) cells.get(col);
+
+				startMergeCol = calcStartMerge(startMergeCol, col, cell);
+
+				cell = calcCellText(startMergeCol, cell);
+
+				newCell(row, col, cell, startMergeCol);
+			}
+			row++;
+			line = reader.readLine();
+		}
+		finishSheet();
+	}
+
+	String calcCellText(int startMergeCol, String cell) {
+		if (startMergeCol != DataListener.NON_MERGED) {
+			cell = cell.substring(0, cell.length() - 3);
+		}
+		return cell;
+	}
+
+	int calcStartMerge(int startMergeCol, int col, String cell) {
+		if (cell.endsWith("...") && startMergeCol == DataListener.NON_MERGED) {
+			startMergeCol = col;
+		} else if (!cell.endsWith("...")) {
+			startMergeCol = DataListener.NON_MERGED;
+		}
+		return startMergeCol;
+	}
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/ExcelParser.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/ExcelParser.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/ExcelParser.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser.xls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import jxl.Cell;
+import jxl.Range;
+import jxl.Sheet;
+import jxl.Workbook;
+import jxl.read.biff.BiffException;
+
+import org.drools.decisiontable.parser.DecisionTableParser;
+import org.drools.template.parser.DataListener;
+import org.drools.template.parser.DecisionTableParseException;
+
+/**
+ * @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 {
+
+    public static final String              DEFAULT_RULESHEET_NAME = "Decision Tables";
+    private Map<String, List<DataListener>> _listeners = new HashMap<String, List<DataListener>>();
+    private boolean                         _useFirstSheet;
+
+    /**
+     * Define a map of sheet name to listner handlers.
+     * 
+     * @param sheetListeners
+     *            map of String to SheetListener
+     */
+    public ExcelParser(final Map<String, List<DataListener>> sheetListeners) {
+        this._listeners = sheetListeners;
+    }
+
+    public ExcelParser(final List<DataListener> sheetListeners) {
+        this._listeners.put( ExcelParser.DEFAULT_RULESHEET_NAME,
+                            sheetListeners );
+        this._useFirstSheet = true;
+    }
+
+    public ExcelParser(final DataListener listener) {
+        List<DataListener> listeners = new ArrayList<DataListener>();
+        listeners.add( listener );
+        this._listeners.put( ExcelParser.DEFAULT_RULESHEET_NAME,
+                            listeners );
+        this._useFirstSheet = true;
+    }
+
+    public void parseFile(InputStream inStream) {
+        try {
+            Workbook workbook = Workbook.getWorkbook( inStream );
+
+            if ( _useFirstSheet ) {
+                Sheet sheet = workbook.getSheet( 0 );
+                processSheet( sheet,
+                              _listeners.get( DEFAULT_RULESHEET_NAME ) );
+            } else {
+                for ( String sheetName : _listeners.keySet() ) {
+                    Sheet sheet = workbook.getSheet( sheetName );
+                    processSheet( sheet,
+                                  _listeners.get( sheetName ) );
+
+                }
+            }
+        } catch ( BiffException e ) {
+            throw new DecisionTableParseException( "An error occured opening the workbook. It is possible that the encoding of the document did not match the encoding of the reader.",
+                                                   e );
+
+        } catch ( IOException e ) {
+            throw new DecisionTableParseException( "Failed to open Excel stream, " + "please check that the content is xls97 format.",
+                                                   e );
+        }
+
+    }
+
+    private void processSheet(Sheet sheet,
+                              List< ? extends DataListener> listeners) {
+        int maxRows = sheet.getRows();
+
+        Range[] mergedRanges = sheet.getMergedCells();
+
+        for ( int i = 0; i < maxRows; i++ ) {
+            Cell[] row = sheet.getRow( i );
+            newRow( listeners,
+                    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();
+                    newCell( listeners,
+                             i,
+                             cellNum,
+                             topLeft.getContents(),
+                             topLeft.getColumn() );
+                } else {
+                    newCell( listeners,
+                             i,
+                             cellNum,
+                             cell.getContents(),
+                             DataListener.NON_MERGED );
+                }
+            }
+        }
+        finishSheet( listeners );
+    }
+
+    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;
+    }
+
+    static String removeTrailingZero(String stringVal) {
+        if ( stringVal.endsWith( ".0" ) ) {
+            stringVal = stringVal.substring( 0,
+                                             stringVal.length() - 2 );
+        }
+        return stringVal;
+    }
+
+    private void finishSheet(List< ? extends DataListener> listeners) {
+        for ( DataListener listener : listeners ) {
+            listener.finishSheet();
+        }
+    }
+
+    private void newRow(List< ? extends DataListener> listeners,
+                        int row,
+                        int cols) {
+        for ( DataListener listener : listeners ) {
+            listener.newRow( row,
+                             cols );
+        }
+    }
+
+    public void newCell(List< ? extends DataListener> listeners,
+                        int row,
+                        int column,
+                        String value,
+                        int mergedColStart) {
+        for ( DataListener listener : listeners ) {
+            listener.newCell( row,
+                              column,
+                              value,
+                              mergedColStart );
+        }
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/NullSheetListener.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/NullSheetListener.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/NullSheetListener.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser.xls;
+
+import org.drools.template.parser.DataListener;
+
+/**
+ * @author <a href="mailto:shaun.addison at gmail.com"> Shaun Addison </a>
+ * 
+ * Null listner.
+ */
+public class NullSheetListener
+    implements
+    DataListener {
+
+    public void startSheet(final String name) {
+    }
+
+    public void finishSheet() {
+    }
+
+    public void newRow(final int rowNumber,
+                       final int columns) {
+    }
+
+    public void newCell(final int row,
+                        final int column,
+                        final String value,
+                        final int mergedColstart) {
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/PropertiesSheetListener.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/PropertiesSheetListener.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/decisiontable/parser/xls/PropertiesSheetListener.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser.xls;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.decisiontable.parser.RuleSheetParserUtil;
+import org.drools.template.parser.DataListener;
+
+/**
+ * Reads an Excel sheet as key-value properties.
+ *
+ * Treats the first non-empty cell on a row as a key and any subsequent
+ * non-empty cell as a value. Any cells defined after the second cell are
+ * ignored as comments.
+ *
+ * Could be easily adapted to accept multiple values per key but the semantics
+ * were kept in line with Properties.
+ *
+ * @author <a href="mailto:shaun.addison at gmail.com"> Shaun Addison </a>
+ *
+ */
+public class PropertiesSheetListener implements DataListener {
+
+	private static final String EMPTY_STRING   = "";
+
+	private final Map<Integer, String[]> _rowProperties = new HashMap<Integer, String[]>();
+
+	private final CaseInsensitiveMap _properties = new CaseInsensitiveMap();
+
+	/**
+	 * Return the key value pairs. If this is called before the sheet is
+	 * finished, then it will build the properties map with what is known.
+	 * Subsequent calls will update the properties map.
+	 *
+	 * @return properties
+	 */
+	public CaseInsensitiveMap getProperties() {
+		finishSheet(); // MN allows this to be called before the sheet is
+		// finished, as
+		// some properties are used whilst the sheet is being parsed.
+		return this._properties;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see my.hssf.util.SheetListener#startSheet(java.lang.String)
+	 */
+	public void startSheet(final String name) {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see my.hssf.util.SheetListener#finishSheet()
+	 */
+	public void finishSheet() {
+		for ( String[] keyValue : _rowProperties.values() ) {
+			this._properties.addProperty( keyValue[0], new String[]{ keyValue[1], keyValue[2] } );
+		}
+		// Discard to avoid repeated addition of properties,
+		// since finishSheet may be called more than once.
+		_rowProperties.clear();
+	}
+
+	/**
+	 * Enter a new row. This is ignored.
+	 *
+	 * @param rowNumber
+	 *            The row number.
+	 * @param columns
+	 *            The Colum number.
+	 */
+	public void newRow(final int rowNumber,
+			final int columns) {
+		// nothing to do.
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see my.hssf.util.SheetListener#newCell(int, int, java.lang.String)
+	 */
+	public void newCell(final int row,
+			final int column,
+			final String value,
+			final int mergedColStart) {
+		if ( emptyCellValue( value ) ) {
+			return;
+		}
+		final Integer rowInt = new Integer( row );
+		if ( this._rowProperties.containsKey( rowInt ) ) {
+			final String[] keyValue = (String[]) this._rowProperties.get( rowInt );
+			if ( keyValue[1] == PropertiesSheetListener.EMPTY_STRING ) {
+				keyValue[1] = value;
+				keyValue[2] = RuleSheetParserUtil.rc2name(row, column);
+			}
+		} else {
+			final String[] keyValue = {value, PropertiesSheetListener.EMPTY_STRING, RuleSheetParserUtil.rc2name(row, column+1) };
+			this._rowProperties.put( rowInt, keyValue );
+		}
+	}
+
+	private boolean emptyCellValue(final String value) {
+		return value == null || value.trim().equals( "" );
+	}
+
+	@SuppressWarnings("serial")
+	public static class CaseInsensitiveMap extends HashMap<String,List<String[]>> {
+
+		private List<String[]> getPropertyCell(String key) {
+			return super.get( key.toLowerCase() );
+		}
+
+		public void addProperty( String key, String[] value ){
+			key = key.toLowerCase(); 
+			List<String[]> r  = getPropertyCell( key );
+			if( r == null ){
+				r = new ArrayList<String[]>();    			
+			}
+			r.add( value );
+			super.put( key, r );
+		}
+
+		private List<String> getList( String key, int index ) {
+			List<String[]> pcList  = getPropertyCell( key );
+            if( pcList == null ) return null;
+			List<String> r = new ArrayList<String>();
+			for( String[] pc: pcList ){
+				r.add( pc[index] );
+			}
+			return r;
+		}
+
+		public List<String> getProperty(String key) {
+			return getList( key, 0 );
+		}
+
+		public List<String> getPropertyCells(String key) {
+			return getList( key, 1 );
+		}
+
+		private String getSingle( String key, int index ){
+			List<String[]> r  = getPropertyCell( key );
+			if( r == null || r.size() == 0 ) return null;
+			return r.get( 0 )[index];			
+		}
+
+		public String getSingleProperty( String key ){
+			return getSingle( key, 0 );
+		}
+
+		public String getSinglePropertyCell( String key ){
+			return getSingle( key, 1 );
+		}
+
+		public String getSingleProperty( String key, String defaultValue ){
+			String r = getSingleProperty( key );
+			if( r == null || r == "" ) r = defaultValue;
+			return r;
+		}
+
+	}
+}
+

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/osgi/decisiontables/Activator.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/osgi/decisiontables/Activator.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/java/org/drools/osgi/decisiontables/Activator.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,35 @@
+package org.drools.osgi.decisiontables;
+
+import java.util.Hashtable;
+
+
+//import org.drools.KnowledgeBaseFactoryService;
+//import org.drools.builder.KnowledgeBuilderFactoryService;
+//import org.drools.builder.impl.KnowledgeBuilderFactoryServiceImpl;
+//import org.drools.impl.KnowledgeBaseFactoryServiceImpl;
+//import org.drools.io.ResourceFactoryService;
+//import org.drools.io.impl.ResourceFactoryServiceImpl;
+import org.drools.Service;
+import org.drools.compiler.DecisionTableProvider;
+import org.drools.decisiontable.DecisionTableProviderImpl;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class Activator
+    implements
+    BundleActivator {
+    private ServiceRegistration kdtableReg;
+
+    public void start(BundleContext bc) throws Exception {
+    	System.out.println( "registering decision tables drools services" );
+        this.kdtableReg = bc.registerService(  new String[]{ DecisionTableProvider.class.getName(), Service.class.getName()},
+                                               new DecisionTableProviderImpl(),
+                                               new Hashtable() );
+        System.out.println( "drools decision tables services registered" );
+    }
+
+    public void stop(BundleContext bc) throws Exception {
+        this.kdtableReg.unregister();
+    }
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/org/drools/decisiontable/package.html
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/org/drools/decisiontable/package.html	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/org/drools/decisiontable/package.html	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,3 @@
+<body>
+	This it a utility for using spreadsheets to manage rules. Use SpreasheetCompiler.
+</body>
\ No newline at end of file

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/Example.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/Example.xls
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/README.txt
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/README.txt	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/README.txt	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,8 @@
+-- Python decision tables --
+
+To use XLS format, the xlrd module is required to be available/installed. 
+You can get this from:http://www.lexicon.net/sjmachin/xlrd.htm 
+To install, you will unzip the xlrd package, and then run pythong setup.py install. 
+
+Michael Neale
+www.michaelneale.net

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/pydt.py
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/pydt.py	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/pydt.py	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,95 @@
+#this is PyDT - Python Decision Tables
+# (c) 2007 Michael Neale (michael at michaelneale.net)
+# Use entirely at your own risk !
+# 
+#  Copyright 2005 JBoss Inc
+#  
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#  
+#       http://www.apache.org/licenses/LICENSE-2.0
+#  
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+
+
+#this is the actual "engine" if you can call it that.
+def process_dt(fact, table) :
+	def make_header(hdr) :
+	    splut = hdr[1].split(' ')
+	    if len(splut) > 1 :
+	    #if hdr[1].contains(' ') :
+	        #itms = hdr[1].split(' ')
+	        return [hdr[0], fact[splut[0]] + ' ' + splut[1]]
+	    else :
+	        return [hdr[0], fact[hdr[1]]]
+	#calc the headers
+	headers = map(make_header, table['condition_headers'])
+	#lets try a map based approach
+	def eval_table(row) :
+	    #go through all the conditions, evaluating
+	    def check_condition(condition) :
+	    #for condition in headers :
+	        col_index = condition[0]
+	        if not row.has_key(col_index) :
+	            return False
+	        cell_value = row[col_index]
+	        predicate = str(condition[1]) + str(cell_value)
+	        return not eval(predicate)
+	    size = len(filter(check_condition,headers))
+	    if size == 0 :
+	        #for action in table['action_headers'] :
+	        def apply_actions(action) :
+	            col_label = action[0]
+	            if (row.has_key(col_label)) :
+	                fact[action[1]] = row[col_label]
+	        map(apply_actions, table['action_headers'])
+	map(eval_table, table['data'])
+
+
+
+
+# Load a XLS into a decision table structure for processing
+def load_xls(file_name) :
+	import xlrd
+	book = xlrd.open_workbook(file_name)
+	sh = book.sheet_by_index(0)	
+        condition_headers, action_headers, data = [],[],[]
+	for rx in range(sh.nrows):
+		if rx == 0 :		
+			divider = 0
+			for cx in range(sh.ncols):
+				cv = sh.cell_value(rowx=rx, colx=cx)				
+				if cv == "" : 
+					continue
+				if cv == "*" or cv == 'actions:' :
+					divider = cx
+				else:
+					if divider == 0 : #we are in conditions
+						condition_headers.append([cx, cv])
+					else: #we are in actions
+						action_headers.append([cx, cv])
+		else:	
+			data_row = {}
+			#print condition_headers
+			for cx in range(sh.ncols):
+				cv = sh.cell_value(rowx=rx, colx=cx)
+				if cv != "":
+					data_row[cx] = cv
+			if len(data_row) > 0 :
+				data.append(data_row)
+	return {
+		"condition_headers" : condition_headers,
+		"action_headers" : action_headers,
+		"data" : data
+		}
+
+
+
+
+

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/pydt_test.py
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/pydt_test.py	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/main/resources/python-dt/pydt_test.py	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,44 @@
+import pydt
+
+test_fact = { "Age" : 42, "Risk" : "'HIGH'", "PolicyType" : "'COMPREHENSIVE'" }
+
+test_table = {
+    "condition_headers" : [ ["A" , "Age"], ["B", "Risk =="], ["C", "PolicyType =="]],
+    "action_headers" : [ ["F","Premium"], ["G","Log"]],
+
+
+    "data" : [
+        {"row" : 2, "A" : "> 2", "B" : "'HIGH'", "C": "'COMPREHENSIVE'",  "F" : "245"},
+        {"row" : 3, "A" : "< 25 ", "B" : "'LOW'", "F" : "390"}
+        ]
+
+}
+
+
+#and now some crude test code
+pydt.process_dt(test_fact, test_table)
+print "RESULT: " + str(test_fact)
+if not test_fact.has_key("Premium") :
+	print("ERROR: no premium was calculated")
+if  test_fact["Premium"] == '245' :
+	print("PASSED STEP 1")
+else :
+	print("FAILED STEP 1: Premium was " + test_fact["Premium"])
+
+#some simple test
+tbl = pydt.load_xls("Example.xls")
+if tbl['condition_headers'][0][1] == "Age" :
+	print "PASSED STEP 2"
+else:
+	print "FAILED STEP 2"
+
+#now test it all, end to end
+test_fact = { "Age" : 42, "Risk" : "'HIGH'", "PolicyType" : "'COMPREHENSIVE'" }
+pydt.process_dt(test_fact, tbl)
+if not test_fact.has_key("Premium") :
+	print("ERROR: no premium was calculated")
+premium = test_fact["Premium"]
+if premium == 245 :
+	print("PASSED STEP 3")
+else :
+	print("FAILED STEP 3: Premium was " + test_fact["Premium"])

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/Driver.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/Driver.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/Driver.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -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;
+	}
+	
+	
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/Policy.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/Policy.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/Policy.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -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;
+	}
+	
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/launcher/PricingRuleLauncher.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/launcher/PricingRuleLauncher.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/acme/insurance/launcher/PricingRuleLauncher.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,92 @@
+package org.acme.insurance.launcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringReader;
+
+import org.acme.insurance.Driver;
+import org.acme.insurance.Policy;
+import org.drools.KnowledgeBase;
+import org.drools.KnowledgeBaseFactory;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.builder.DecisionTableConfiguration;
+import org.drools.builder.DecisionTableInputType;
+import org.drools.builder.KnowledgeBuilder;
+import org.drools.builder.KnowledgeBuilderFactory;
+import org.drools.builder.ResourceType;
+import org.drools.compiler.DroolsParserException;
+import org.drools.compiler.PackageBuilder;
+import org.drools.decisiontable.InputType;
+import org.drools.decisiontable.SpreadsheetCompiler;
+import org.drools.io.ResourceFactory;
+import org.drools.runtime.StatefulKnowledgeSession;
+
+/**
+ * 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 {
+        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+
+        DecisionTableConfiguration dtconf = KnowledgeBuilderFactory.newDecisionTableConfiguration();
+        dtconf.setInputType( DecisionTableInputType.XLS );
+
+        kbuilder.add( ResourceFactory.newClassPathResource( "/data/ExamplePolicyPricing.xls", getClass() ),
+                              ResourceType.DTABLE,
+                              dtconf );
+
+        if ( kbuilder.hasErrors() ) {
+            throw new RuntimeException( kbuilder.getErrors().toString() );
+        }
+
+        //BUILD RULEBASE
+        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+
+        //NEW WORKING MEMORY
+        final StatefulKnowledgeSession session = kbase.newStatefulKnowledgeSession();
+
+        //now create some test data
+        Driver driver = new Driver();
+        Policy policy = new Policy();
+
+        session.insert( driver );
+        session.insert( policy );
+
+        session.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" );
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ChangeSetTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ChangeSetTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ChangeSetTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,80 @@
+package org.drools.decisiontable;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import org.drools.KnowledgeBase;
+import org.drools.KnowledgeBaseFactory;
+import org.drools.builder.DecisionTableConfiguration;
+import org.drools.builder.DecisionTableInputType;
+import org.drools.builder.KnowledgeBuilder;
+import org.drools.builder.KnowledgeBuilderFactory;
+import org.drools.builder.ResourceType;
+import org.drools.compiler.PackageBuilderConfiguration;
+import org.drools.core.util.FileManager;
+import org.drools.io.ResourceFactory;
+import org.drools.io.impl.ClassPathResource;
+import org.drools.io.impl.KnowledgeResource;
+import org.drools.runtime.StatefulKnowledgeSession;
+import org.drools.xml.XmlChangeSetReader;
+import org.xml.sax.SAXException;
+
+public class ChangeSetTest {
+    
+    FileManager fileManager;
+    
+    @Before
+    public void setUp() throws Exception {
+        fileManager = new FileManager();
+        fileManager.setUp();
+        ResourceFactory.getResourceChangeNotifierService().start();
+        ResourceFactory.getResourceChangeScannerService().start();
+    }
+    
+
+    @After
+    public void tearDown() throws Exception {
+        fileManager.tearDown();
+        ResourceFactory.getResourceChangeNotifierService().stop();
+        ResourceFactory.getResourceChangeScannerService().stop();
+    }
+    
+    @Test
+    public void testIntegregation() {
+        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+        kbuilder.add( ResourceFactory.newClassPathResource( "changeset1Test.xml", getClass()), ResourceType.CHANGE_SET );
+        assertFalse( kbuilder.hasErrors() );
+        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+        StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
+        List list = new ArrayList();
+        ksession.setGlobal( "list", list );
+        
+        ksession.insert( new Cheese( "cheddar",
+                                    42 ) );
+        ksession.insert( new Person( "michael",
+                                    "stilton",
+                                    25 ) );
+        
+        ksession.fireAllRules();
+        ksession.dispose();
+        
+        assertEquals( 3, list.size() );
+  
+        assertEquals( "Young man cheddar",
+                      list.get( 0 ) );
+        
+        assertEquals( "rule1",
+                      list.get( 1 ) );
+        assertEquals( "rule2",
+                      list.get( 2 ) );
+    }
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/Cheese.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/Cheese.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/Cheese.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable;
+
+public class Cheese {
+    private String type;
+    private int    price;
+
+    public Cheese() {
+    	
+    }
+    public Cheese(final String type,
+                  final int price) {
+        super();
+        this.type = type;
+        this.price = price;
+    }
+
+    public int getPrice() {
+        return this.price;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public void setPrice(final int price) {
+        this.price = price;
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ExternalSpreadsheetCompilerIntegrationTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ExternalSpreadsheetCompilerIntegrationTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ExternalSpreadsheetCompilerIntegrationTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+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.DroolsError;
+import org.drools.compiler.PackageBuilder;
+import org.drools.rule.Package;
+import org.drools.template.parser.DataListener;
+import org.drools.template.parser.TemplateDataListener;
+
+/**
+ * @author <a href="mailto:stevearoonie at gmail.com">Steven Williams</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 ExternalSpreadsheetCompilerIntegrationTest {
+    @Test
+    public void testIntegration() throws Exception
+    {
+        final ExternalSpreadsheetCompiler converter = new ExternalSpreadsheetCompiler();
+        final String drl = converter.compile("/data/IntegrationExampleTest.xls", "/templates/test_integration.drl", 18, 3);
+        //COMPILE
+        System.out.println( drl );
+        final PackageBuilder builder = new PackageBuilder();
+        builder.addPackageFromDrl( new StringReader( drl ) );
+
+        final Package pkg = builder.getPackage();
+        assertNotNull( pkg );
+        assertEquals( 0,
+                      builder.getErrors().getErrors().length );
+
+        //BUILD RULEBASE
+        final RuleBase rb = RuleBaseFactory.newRuleBase();
+        rb.addPackage( pkg );
+
+        //NEW WORKING MEMORY
+        final WorkingMemory wm = rb.newStatefulSession();
+
+        //ASSERT AND FIRE
+        wm.insert( new Cheese( "stilton",
+                                     42 ) );
+        wm.insert( new Person( "michael",
+                                     "stilton",
+                                     42 ) );
+        final List<String> list = new ArrayList<String>();
+        wm.setGlobal( "list",
+                      list );
+        wm.fireAllRules();
+        assertEquals( 1,
+                      list.size() );
+
+        
+    }
+    
+    @Test
+    public void testPricing() throws Exception
+    {
+        final ExternalSpreadsheetCompiler converter = new ExternalSpreadsheetCompiler();
+        final List<DataListener> listeners = new ArrayList<DataListener>();
+        TemplateDataListener l1 = new TemplateDataListener(10, 3, "/templates/test_pricing1.drl");
+		listeners.add(l1);
+        TemplateDataListener l2 = new TemplateDataListener(30, 3, "/templates/test_pricing2.drl");
+		listeners.add(l2);
+		converter.compile("/data/ExamplePolicyPricing.xls", InputType.XLS, listeners);
+        //COMPILE
+        final PackageBuilder builder = new PackageBuilder();
+        builder.addPackageFromDrl( new StringReader( l1.renderDRL() ) );
+        builder.addPackageFromDrl( new StringReader( l2.renderDRL() ) );
+
+        final Package pkg = builder.getPackage();
+        assertNotNull( pkg );
+        DroolsError[] errors = builder.getErrors().getErrors();
+//		for (int i = 0; i < errors.length; i++) {
+//			DroolsError error = errors[i];
+//			System.out.println(error.getMessage());
+//		}
+        assertEquals( 0,
+                      errors.length );
+
+        //BUILD RULEBASE
+        final RuleBase rb = RuleBaseFactory.newRuleBase();
+        rb.addPackage( pkg );
+
+        WorkingMemory wm = rb.newStatefulSession();
+        
+        //now create some test data
+        Driver driver = new Driver();
+        Policy policy = new Policy();
+        
+        wm.insert(driver);
+        wm.insert(policy);
+        
+        wm.fireAllRules();
+        
+        System.out.println("BASE PRICE IS: " + policy.getBasePrice());
+        System.out.println("DISCOUNT IS: " + policy.getDiscountPercent());
+        
+        int basePrice = policy.getBasePrice();
+        assertEquals(120, basePrice);
+
+        
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ExternalSpreadsheetCompilerUnitTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ExternalSpreadsheetCompilerUnitTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/ExternalSpreadsheetCompilerUnitTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * @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 ExternalSpreadsheetCompilerUnitTest {
+    @Test
+    public void testLoadFromClassPath() {
+        final ExternalSpreadsheetCompiler converter = new ExternalSpreadsheetCompiler();
+        final String drl = converter.compile( "/data/MultiSheetDST.xls",
+                                              "/templates/test_template1.drl",
+                                              11,
+                                              2 );
+        assertNotNull( drl );
+
+        //		System.out.println(drl);
+
+        assertTrue( drl.indexOf( "rule \"How cool is Shaun 12\"" ) > 0 );
+        assertTrue( drl.indexOf( "rule \"How cool is Kumar 11\"" ) > 0 );
+        assertTrue( drl.indexOf( "import example.model.User;" ) > -1 );
+        assertTrue( drl.indexOf( "import example.model.Car;" ) > -1 );
+    }
+
+    @Test
+    public void testLoadSpecificWorksheet() {
+        final ExternalSpreadsheetCompiler converter = new ExternalSpreadsheetCompiler();
+        final String drl = converter.compile( "/data/MultiSheetDST.xls",
+                                              "Another Sheet",
+                                              "/templates/test_template1.drl",
+                                              11,
+                                              2 );
+        //		System.out.println(drl);
+        assertNotNull( drl );
+    }
+
+    @Test
+    public void testLoadCsv() {
+        final ExternalSpreadsheetCompiler converter = new ExternalSpreadsheetCompiler();
+        final String drl = converter.compile( "/data/ComplexWorkbook.csv",
+                                              "/templates/test_template2.drl",
+                                              InputType.CSV,
+                                              10,
+                                              2 );
+        assertNotNull( drl );
+
+        assertTrue( drl.indexOf( "myObject.setIsValid(1, 2)" ) > 0 );
+        assertTrue( drl.indexOf( "myObject.size () > 2" ) > 0 );
+
+        assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red),\n\t\tmyObject.size () > 1" ) > 0 );
+    }
+
+    @Test
+    public void testLoadBasicWithMergedCells() {
+        final ExternalSpreadsheetCompiler converter = new ExternalSpreadsheetCompiler();
+        final String drl = converter.compile( "/data/BasicWorkbook.xls",
+                                              "/templates/test_template3.drl",
+                                              InputType.XLS,
+                                              10,
+                                              2 );
+
+        final String drl1 = converter.compile( "/data/BasicWorkbook.xls",
+                                               "/templates/test_template3.drl",
+                                               InputType.XLS,
+                                               21,
+                                               2 );
+
+        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 );
+        assertTrue( drl1.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() > 12\")" ) > -1 );
+
+        assertTrue( drl.indexOf( "b: Bar()\n\t\teval(myObject.size() < 3)" ) > -1 );
+        assertTrue( drl.indexOf( "b: Bar()\n\t\teval(myObject.size() < 9)" ) > -1 );
+
+        assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size() > 1)" ) < drl.indexOf( "b: Bar()\n\t\teval(myObject.size() < 3)" ) );
+
+    }
+
+    @Test
+    public void testLoadBasicWithExtraCells() {
+        final ExternalSpreadsheetCompiler compiler = new ExternalSpreadsheetCompiler();
+        final String drl = compiler.compile( "/data/BasicWorkbook.xls",
+                                             "/templates/test_template4.drl",
+                                             InputType.XLS,
+                                             10,
+                                             2 );
+        assertNotNull( drl );
+
+        assertTrue( drl.indexOf( "This is a function block" ) > -1 );
+        assertTrue( drl.indexOf( "global Class1 obj1;" ) > -1 );
+        assertTrue( drl.indexOf( "myObject.getColour().equals(blue)" ) > -1 );
+        assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size() > 12\")" ) > -1 );
+
+        assertTrue( drl.indexOf( "b: Bar()\n\t\teval(myObject.size() < 3)" ) > -1 );
+        assertTrue( drl.indexOf( "b: Bar()\n\t\teval(myObject.size() < 9)" ) > -1 );
+
+        assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size() > 1)" ) < drl.indexOf( "b: Bar()\n\t\teval(myObject.size() < 3)" ) );
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/Person.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/Person.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/Person.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable;
+
+public class Person {
+    private String name;
+    private String likes;
+    private int    age;
+
+    private char         sex;
+
+    private boolean      alive;
+
+    private String       status;
+
+    public Person() {
+    	
+    }
+    public Person(final String name) {
+        this( name,
+              "",
+              0 );
+    }
+
+    public Person(final String name,
+                  final String likes) {
+        this( name,
+              likes,
+              0 );
+    }
+
+    public Person(final String name,
+                  final String likes,
+                  final int age) {
+        this.name = name;
+        this.likes = likes;
+        this.age = age;
+    }
+
+    public String getStatus() {
+        return this.status;
+    }
+
+    public void setStatus(final String status) {
+        this.status = status;
+    }
+
+    public String getLikes() {
+        return this.likes;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public int getAge() {
+        return this.age;
+    }
+
+    public boolean isAlive() {
+        return this.alive;
+    }
+
+    public void setAlive(final boolean alive) {
+        this.alive = alive;
+    }
+
+    public char getSex() {
+        return this.sex;
+    }
+
+    public void setSex(final char sex) {
+        this.sex = sex;
+    }
+
+    public String toString() {
+        return "[Person name='" + this.name + "']";
+    }
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SourcePackageProviderTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SourcePackageProviderTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SourcePackageProviderTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,92 @@
+package org.drools.decisiontable;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Properties;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import org.drools.RuleBase;
+import org.drools.agent.RuleAgent;
+
+public class SourcePackageProviderTest {
+
+    @Test
+    public void testSourceProvider() throws Exception {
+        new SourcePackageProvider();
+
+        File dir = getTempDirectory();
+
+        InputStream in = this.getClass().getResourceAsStream( "/data/ExamplePolicyPricing.xls" );
+
+        File target = new File( dir,
+                                "Something.xls" );
+
+        OutputStream out = new FileOutputStream( target );
+
+        byte[] buf = new byte[1024];
+        int len;
+        while ( (len = in.read( buf )) > 0 ) {
+            out.write( buf,
+                       0,
+                       len );
+        }
+        in.close();
+        out.close();
+
+        Properties config = new Properties();
+        config.setProperty( RuleAgent.FILES,
+                            target.getPath() );
+
+        RuleAgent ag = RuleAgent.newRuleAgent( config );
+
+        assertNotNull( ag );
+
+        RuleBase rb = ag.getRuleBase();
+        assertNotNull( rb );
+    }
+
+    public static File getTempDirectory() {
+        File f = tempDir();
+        if ( f.exists() ) {
+            if ( f.isFile() ) {
+                throw new IllegalStateException( "The temp directory exists as a file. Nuke it now !" );
+            }
+            deleteDir( f );
+            f.mkdir();
+        } else {
+            f.mkdir();
+        }
+        return f;
+    }
+
+    private static File tempDir() {
+        File tmp = new File( System.getProperty( "java.io.tmpdir" ) );
+
+        return new File( tmp,
+                         "__temp_test_drools_packages" );
+    }
+
+    public static boolean deleteDir(File dir) {
+
+        if ( dir.isDirectory() ) {
+            String[] children = dir.list();
+            for ( int i = 0; i < children.length; i++ ) {
+                boolean success = deleteDir( new File( dir,
+                                                       children[i] ) );
+                if ( !success ) {
+                    //throw new RuntimeException("Unable to delete !");
+                    return false;
+                }
+            }
+        }
+
+        // The directory is now empty so delete it
+        return dir.delete();
+    }
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetCompilerUnitTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable;
+
+import java.io.InputStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import org.drools.decisiontable.parser.RuleMatrixSheetListener;
+
+/**
+ * @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 {
+
+    @Test
+    public void testLoadFromClassPath() {
+        final SpreadsheetCompiler converter = new SpreadsheetCompiler();
+        String drl = converter.compile( "/data/MultiSheetDST.xls",
+                                              InputType.XLS );
+
+        assertNotNull( drl );
+
+        assertTrue( drl.indexOf( "rule \"How cool am I_12\"" ) > drl.indexOf( "rule \"How cool am I_11\"" ) );
+        assertTrue( drl.indexOf( "import example.model.User;" ) > -1 );
+        assertTrue( drl.indexOf( "import example.model.Car;" ) > -1 );
+        assertTrue( drl.indexOf("package ") > -1);
+        InputStream ins = this.getClass().getResourceAsStream("/data/MultiSheetDST.xls");
+
+        drl = converter.compile( false, ins,
+                InputType.XLS );
+
+        assertNotNull( drl );
+
+        assertTrue( drl.indexOf( "rule \"How cool am I_12\"" ) > 0 );
+        assertTrue( drl.indexOf( "import example.model.User;" ) > -1 );
+        assertTrue( drl.indexOf( "import example.model.Car;" ) > -1 );
+        assertTrue( drl.indexOf("package ") == -1);
+
+    }
+
+    @Test
+    public void testLoadSpecificWorksheet() {
+        final SpreadsheetCompiler converter = new SpreadsheetCompiler();
+        final InputStream stream = this.getClass().getResourceAsStream( "/data/MultiSheetDST.xls" );
+        final String drl = converter.compile( stream,
+                                              "Another Sheet" );
+        assertNotNull( drl );
+    }
+
+    @Test
+    public void testLoadCustomListener() {
+        final SpreadsheetCompiler converter = new SpreadsheetCompiler();
+        final InputStream stream = this.getClass().getResourceAsStream( "/data/CustomWorkbook.xls" );
+        final String drl = converter.compile( stream,
+                                              InputType.XLS,
+                                              new RuleMatrixSheetListener() );
+        assertNotNull( drl );
+        assertTrue( drl.indexOf( "\"matrix\"" ) != -1 );
+        assertTrue( drl.indexOf( "$v : FundVisibility" ) != -1 );
+        assertTrue( drl.indexOf( "FundType" ) != -1 );
+        assertTrue( drl.indexOf( "Role" ) != -1 );
+    }
+
+    @Test
+    public void testLoadCsv() {
+        final SpreadsheetCompiler converter = new SpreadsheetCompiler();
+        final InputStream stream = this.getClass().getResourceAsStream( "/data/ComplexWorkbook.csv" );
+        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 );
+
+        assertTrue( drl.indexOf( "Foo(myObject.getColour().equals(red), myObject.size () > 1)" ) > 0 );
+    }
+
+    @Test
+    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 );
+
+        System.out.println(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 );
+        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 () > 12\\\")" ) > -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)" ) );
+
+
+        assertTrue( drl.indexOf( "myObject.setIsValid(\"19-Jul-1992\")" ) > -1 );
+
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetIntegrationTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetIntegrationTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/SpreadsheetIntegrationTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable;
+
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import org.acme.insurance.launcher.PricingRuleLauncher;
+import org.drools.KnowledgeBase;
+import org.drools.KnowledgeBaseFactory;
+import org.drools.builder.DecisionTableConfiguration;
+import org.drools.builder.DecisionTableInputType;
+import org.drools.builder.KnowledgeBuilder;
+import org.drools.builder.KnowledgeBuilderFactory;
+import org.drools.builder.ResourceType;
+import org.drools.io.ResourceFactory;
+import org.drools.runtime.StatefulKnowledgeSession;
+
+public class SpreadsheetIntegrationTest {
+
+    @Test
+    public void testExecute() throws Exception {
+        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+
+        DecisionTableConfiguration dtconf = KnowledgeBuilderFactory.newDecisionTableConfiguration();
+        dtconf.setInputType( DecisionTableInputType.XLS );
+
+        kbuilder.add( ResourceFactory.newClassPathResource( "/data/IntegrationExampleTest.xls", getClass() ),
+                              ResourceType.DTABLE,
+                              dtconf );
+
+        assertFalse( kbuilder.hasErrors() );
+
+        //BUILD RULEBASE
+        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+
+        //NEW WORKING MEMORY
+        final StatefulKnowledgeSession session = kbase.newStatefulKnowledgeSession();
+
+        //ASSERT AND FIRE
+        session.insert( new Cheese( "stilton",
+                                    42 ) );
+        session.insert( new Person( "michael",
+                                    "stilton",
+                                    42 ) );
+        final List<String> list = new ArrayList<String>();
+        session.setGlobal( "list",
+                           list );
+        session.fireAllRules();
+        assertEquals( 1,
+                      list.size() );
+        assertEquals( "Old man stilton",
+                      list.get( 0 ) );
+    }
+
+    @Test
+    public void testNamedWorksheet() throws Exception {
+        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
+
+        DecisionTableConfiguration dtconf = KnowledgeBuilderFactory.newDecisionTableConfiguration();
+        dtconf.setInputType( DecisionTableInputType.XLS );
+        dtconf.setWorksheetName( "Tables_2" );
+
+        kbuilder.add( ResourceFactory.newClassPathResource( "/data/IntegrationExampleTest.xls", getClass() ),
+                              ResourceType.DTABLE,
+                              dtconf );
+
+        assertFalse( kbuilder.hasErrors() );
+
+        //BUILD RULEBASE
+        KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
+        kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
+
+        //NEW WORKING MEMORY
+        final StatefulKnowledgeSession session = kbase.newStatefulKnowledgeSession();
+
+        //ASSERT AND FIRE
+        session.insert( new Cheese( "cheddar",
+                                    42 ) );
+        session.insert( new Person( "michael",
+                                    "stilton",
+                                    25 ) );
+        final List<String> list = new ArrayList<String>();
+        session.setGlobal( "list",
+                           list );
+        session.fireAllRules();
+        assertEquals( 1,
+                      list.size() );
+        assertEquals( "Young man cheddar",
+                      list.get( 0 ) );
+    }
+
+    /**
+     * A smoke test mainly.
+     */
+    @Test
+    public void testInsuranceExample() throws Exception {
+        PricingRuleLauncher launcher = new PricingRuleLauncher();
+        assertEquals( 120,
+                      launcher.executeExample() );
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/ActionTypeTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/ActionTypeTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/ActionTypeTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,51 @@
+package org.drools.decisiontable.parser;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import org.drools.decisiontable.parser.ActionType;
+import static org.drools.decisiontable.parser.ActionType.Code;
+
+public class ActionTypeTest {
+
+    @Test
+    public void testChooseActionType() {
+        Map<Integer, ActionType> actionTypeMap = new HashMap<Integer, ActionType>();
+        ActionType.addNewActionType( actionTypeMap, "C", 0, 1 );
+        
+        ActionType type = (ActionType) actionTypeMap.get( new Integer(0) );
+        assertEquals( Code.CONDITION, type.getCode() );
+        
+        
+        actionTypeMap = new HashMap<Integer, ActionType>();
+        ActionType.addNewActionType( actionTypeMap, "A", 0, 1 );
+        type = (ActionType) actionTypeMap.get( new Integer(0) );
+        assertEquals(Code.ACTION, type.getCode());
+        
+        actionTypeMap = new HashMap<Integer, ActionType>();
+        ActionType.addNewActionType( actionTypeMap, "X", 0, 1 );
+        type = (ActionType) actionTypeMap.get( new Integer(0) );
+        assertEquals(Code.ACTIVATIONGROUP, type.getCode());
+        
+        actionTypeMap = new HashMap<Integer, ActionType>();
+        ActionType.addNewActionType( actionTypeMap, "ACTIVATION-GROUP", 0, 1 );
+        type = (ActionType) actionTypeMap.get( new Integer(0) );
+        assertEquals(Code.ACTIVATIONGROUP, type.getCode());
+        
+        actionTypeMap = new HashMap<Integer, ActionType>();
+        ActionType.addNewActionType( actionTypeMap, "NO-LOOP", 0, 1 );
+        type = (ActionType) actionTypeMap.get( new Integer(0) );
+        assertEquals(Code.NOLOOP, type.getCode());
+        
+        actionTypeMap = new HashMap<Integer, ActionType>();
+        ActionType.addNewActionType( actionTypeMap, "RULEFLOW-GROUP", 0, 1 );
+        type = (ActionType) actionTypeMap.get( new Integer(0) );
+        assertEquals(Code.RULEFLOWGROUP, type.getCode());
+    }
+    
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/ColumnFactoryTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/ColumnFactoryTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/ColumnFactoryTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,71 @@
+package org.drools.decisiontable.parser;
+
+import org.drools.template.parser.ArrayColumn;
+import org.drools.template.parser.Column;
+import org.drools.template.parser.ColumnFactory;
+import org.drools.template.parser.LongColumn;
+import org.drools.template.parser.StringColumn;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class ColumnFactoryTest {
+
+    @Test
+    public void testGetColumn() {
+		ColumnFactory f = new ColumnFactory();
+		Column column = f.getColumn("column");
+		assertTrue(column instanceof StringColumn);
+		assertEquals("column", column.getName());
+	}
+
+    @Test
+    public void testGetStringArrayColumn() {
+		ColumnFactory f = new ColumnFactory();
+		Column column = f.getColumn("column: String[]");
+		assertTrue(column instanceof ArrayColumn);
+		assertEquals("column", column.getName());
+		assertEquals("StringCell", ((ArrayColumn)column).getCellType());
+	}
+	
+    @Test
+    public void testGetLongArrayColumn() {
+		ColumnFactory f = new ColumnFactory();
+		Column column = f.getColumn("column: Long[]");
+		assertTrue(column instanceof ArrayColumn);
+		assertEquals("column", column.getName());
+		assertEquals("LongCell", ((ArrayColumn)column).getCellType());
+	}
+	
+    @Test
+    public void testGetArrayColumnSimple() {
+		ColumnFactory f = new ColumnFactory();
+		Column column = f.getColumn("column[]");
+		assertTrue(column instanceof ArrayColumn);
+		assertEquals("column", column.getName());
+		assertEquals("StringCell", ((ArrayColumn)column).getCellType());
+		
+	}
+
+    @Test
+    public void testGetLongColumn() {
+		ColumnFactory f = new ColumnFactory();
+		Column column = f.getColumn("column: Long");
+		assertTrue(column instanceof LongColumn);
+		assertEquals("column", column.getName());
+	}
+
+    @Test
+    public void testInvalidGetColumn() {
+		try {
+			ColumnFactory f = new ColumnFactory();
+			f.getColumn("column$");
+			fail("IllegalArgumentException expected");
+		} catch (IllegalArgumentException expected) {
+
+		}
+	}
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/LhsBuilderTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/LhsBuilderTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/LhsBuilderTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,223 @@
+package org.drools.decisiontable.parser;
+
+import org.drools.decisiontable.parser.LhsBuilder.FieldType;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class LhsBuilderTest {
+
+	@Test
+	public void testBuildItUp() throws Exception {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Person" );
+
+		builder.addTemplate(10, 1, "age");
+		builder.addTemplate(10, 2, "size != $param");
+		builder.addTemplate(10, 3, "date <");
+
+		builder.addCellValue(11, 1, "42");
+		builder.addCellValue(11, 2, "20");
+		builder.addCellValue(11, 3, "30");
+
+
+		assertEquals("Person(age == \"42\", size != 20, date < \"30\")", builder.getResult());
+
+		builder.clearValues();
+
+		builder.addCellValue(12, 2, "42" );
+		assertEquals("Person(size != 42)", builder.getResult());
+	}
+
+	@Test
+	public void testEmptyCells() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Person" );
+		assertFalse(builder.hasValues());
+	}
+
+	@Test
+	public void testClassicMode() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "" );
+		builder.addTemplate( 10, 1, "Person(age < $param)");
+		builder.addCellValue( 11, 1, "42" );
+
+		assertEquals("Person(age < 42)", builder.getResult());
+
+		builder = new LhsBuilder( 9, 3, null );
+		builder.addTemplate( 10, 3, "Foo(bar == $param)");
+		builder.addTemplate( 10, 4, "eval(true)");
+
+		builder.addCellValue( 11, 3, "42" );
+		builder.addCellValue( 11, 4, "Y" );
+
+		assertEquals("Foo(bar == 42)\neval(true)", builder.getResult());
+	}
+
+	@Test
+	public void testForAllAndFucntion() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "" );
+		builder.addTemplate( 10, 1, "forall(&&){Foo(bar != $)}");
+		builder.addCellValue( 11, 1, "42,43");
+		assertEquals("Foo(bar != 42) && Foo(bar != 43)", builder.getResult());
+	}
+
+	@Test
+	public void testForAllOr() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Person" );
+		builder.addTemplate( 10, 1, "forall(||){age < $}");
+		builder.addCellValue( 11, 1, "42");
+		assertEquals("Person(age < 42)", builder.getResult());
+	}
+
+	@Test
+	public void testForAllOrPrefix() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Person" );
+		builder.addTemplate( 10, 1, "age < 10 && forall(||){age < $}");
+		builder.addCellValue( 11, 1, "42");
+		assertEquals("Person(age < 10 && age < 42)", builder.getResult());
+	}
+
+	@Test
+	public void testForAllOrCSV() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Person" );
+		builder.addTemplate( 10, 1, "forall(||){age < $}");
+		builder.addCellValue( 11, 1, "42, 43, 44");
+		assertEquals("Person(age < 42 || age < 43 || age < 44)", builder.getResult());
+	}
+
+	@Test
+	public void testForAllAnd() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Person" );
+		builder.addTemplate(10, 1, "forall(&&){age < $}");
+		builder.addCellValue(11, 1, "42");
+		assertEquals("Person(age < 42)", builder.getResult());
+	}
+
+	@Test
+	public void testForAllAndCSV() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Person" );
+		builder.addTemplate(10, 1, "forall(&&){age < $}");
+		builder.addCellValue(11, 1, "42, 43, 44");
+		assertEquals("Person(age < 42 && age < 43 && age < 44)", builder
+				.getResult());
+	}
+
+	@Test
+	public void testForAllAndForAllOrCSVMultiple() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Person" );
+		builder.addTemplate(10, 1, "forall(&&){age < $ || age == $}");
+		builder.addCellValue(11, 1, "42, 43, 44");
+		assertEquals(
+				"Person(age < 42 || age == 42 && age < 43 || age == 43 && age < 44 || age == 44)",
+				builder.getResult());
+	}
+
+	@Test
+	public void testForAllsAndForAllOrCSVMultiple() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Person" );
+		builder.addTemplate(10, 1, "forall(&&){age < $ || age == $} && forall(&&){age < $ || age == $}");
+		builder.addCellValue(11, 1, "42, 43, 44");
+		assertEquals(
+				"Person(age < 42 || age == 42 && age < 43 || age == 43 && age < 44 || age == 44 && age < 42 || age == 42 && age < 43 || age == 43 && age < 44 || age == 44)",
+				builder.getResult());
+	}
+
+	@Test
+	public void testIdentifyFieldTypes() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "" );
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("age"));
+		assertEquals(FieldType.OPERATOR_FIELD, builder.calcFieldType("age <"));
+		assertEquals(FieldType.NORMAL_FIELD, builder.calcFieldType("age < $param"));
+		assertEquals(FieldType.NORMAL_FIELD, builder.calcFieldType("forall(||){age < $}"));
+		assertEquals(FieldType.NORMAL_FIELD, builder.calcFieldType("forall(&&){age < $}"));
+		assertEquals(FieldType.NORMAL_FIELD, builder.calcFieldType("forall(,){age < $}"));
+		assertEquals(FieldType.NORMAL_FIELD, builder.calcFieldType("forall(){age < $}"));
+		assertEquals(FieldType.NORMAL_FIELD, builder.calcFieldType("forall(){age < $} && forall(){age == $}"));
+		assertEquals(FieldType.NORMAL_FIELD, builder.calcFieldType("x && forall(){age < $} && forall(){age == $}"));
+		assertEquals(FieldType.NORMAL_FIELD, builder.calcFieldType("x && forall(){age < $} && forall(){age == $} && y"));
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("age < $para"));
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("forall{||}{age < $}"));
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("forall(){}"));
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("forall(){age < $"));
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("forall(){,"));
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("forall({})"));
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("forall({}){test})"));
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("forall(&&){{}})"));
+		assertEquals(FieldType.SINGLE_FIELD, builder.calcFieldType("forall(&&){{})"));
+	}
+
+	@Test
+	public void testIdentifyColumnCorrectly() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, null );
+		assertFalse(builder.isMultipleConstraints());
+
+		//will be added to Foo
+		builder = new LhsBuilder( 9, 1, "Foo" );
+		assertTrue(builder.isMultipleConstraints());
+
+		//will be added to eval
+		builder = new LhsBuilder( 9, 1, "f:Foo() eval  " );
+		assertTrue(builder.isMultipleConstraints());
+
+		// will just be verbatim
+		builder = new LhsBuilder( 9, 1, "f: Foo()" );
+		assertTrue(builder.isMultipleConstraints());
+	}
+	
+	@Test
+	public void testTypeConst3() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Type" );
+		builder.addTemplate( 10, 1, "flda");
+		builder.addTemplate( 10, 2, "fldb >");
+		builder.addTemplate( 10, 3, "fldc str[startsWith]");
+		builder.addCellValue( 11, 1, "good");
+		builder.addCellValue( 11, 2, "42");
+		builder.addCellValue( 11, 3, "abc");
+		assertEquals("Type(flda == \"good\", fldb > \"42\", fldc str[startsWith] \"abc\")", builder.getResult());
+	}
+
+	@Test
+	public void testTypeParConst2() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Type()" );
+		builder.addTemplate( 10, 1, "flda");
+		builder.addTemplate( 10, 2, "fldb >");
+		builder.addCellValue( 11, 1, "good");
+		builder.addCellValue( 11, 2, "42");
+		assertEquals("Type(flda == \"good\", fldb > \"42\")", builder.getResult());
+	}
+
+	@Test
+	public void testTypeConstFrom() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Type from $west" );
+		builder.addTemplate( 10, 1, "flda");
+		builder.addCellValue( 11, 1, "good");
+		assertEquals("Type(flda == \"good\") from $west", builder.getResult());
+	}
+
+	@Test
+	public void testTypeEvalExp2() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "Type($a:a,$b:b) eval" );
+		builder.addTemplate( 10, 1, "$a > $param");
+		builder.addTemplate( 10, 2, "$b < $param");
+		builder.addCellValue( 11, 1, "1");
+		builder.addCellValue( 11, 2, "99");
+		assertEquals("Type($a:a,$b:b) eval($a > 1 && $b < 99)", builder.getResult());
+	}
+	
+	@Test
+	public void testEvalExp2() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, "eval()" );
+		builder.addTemplate( 10, 1, "$a > $param");
+		builder.addTemplate( 10, 2, "$b < $param");
+		builder.addCellValue( 11, 1, "1");
+		builder.addCellValue( 11, 2, "99");
+		assertEquals("eval($a > 1 && $b < 99)", builder.getResult());
+	}
+	
+	@Test
+	public void testTypeParPlain() {
+		LhsBuilder builder = new LhsBuilder( 9, 1, null );
+		builder.addTemplate( 10, 1, "Type()");
+		builder.addCellValue( 11, 1, "x");
+		assertEquals("Type()", builder.getResult());
+	}
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/PropertiesSheetListenerTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/PropertiesSheetListenerTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/PropertiesSheetListenerTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.util.Properties;
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import org.drools.decisiontable.parser.xls.PropertiesSheetListener;
+import org.drools.decisiontable.parser.xls.PropertiesSheetListener.CaseInsensitiveMap;
+import org.drools.template.parser.DataListener;
+
+public class PropertiesSheetListenerTest {
+
+    @Test
+    public void testProperties() {
+        final PropertiesSheetListener listener = new PropertiesSheetListener();
+        listener.startSheet( "test" );
+
+        listener.newRow( 0, 4 );
+
+        listener.newCell( 0, 0,
+                          "", DataListener.NON_MERGED );
+
+        listener.newCell( 0, 1,
+                          "key1", DataListener.NON_MERGED );
+        listener.newCell( 0, 2,
+                          "value1", DataListener.NON_MERGED );
+
+        listener.newRow( 1, 4 );
+        listener.newCell( 1, 1,
+                          "key2", DataListener.NON_MERGED );
+        listener.newCell( 1, 3,
+                          "value2", DataListener.NON_MERGED );
+
+        final CaseInsensitiveMap props = listener.getProperties();
+
+        listener.newRow( 2, 4 );
+        listener.newCell( 1, 1,
+                          "key3", DataListener.NON_MERGED );
+
+        assertEquals( "value1", props.getSingleProperty( "Key1" ) );
+        assertEquals( "value2", props.getSingleProperty( "key2" ) );
+        
+    }
+
+    @Test
+    public void testCaseInsensitive() {
+    	CaseInsensitiveMap map = new PropertiesSheetListener.CaseInsensitiveMap();
+    	map.addProperty("x3", new String[]{ "hey", "B2" } );
+    	map.addProperty("x4", new String[]{ "wHee", "C3" } );
+    	map.addProperty("XXx", new String[]{ "hey2", "D4" } );
+
+    	assertNull( map.getProperty("x") );
+    	assertEquals("hey", map.getSingleProperty("x3"));
+    	assertEquals("hey", map.getSingleProperty("X3"));
+    	assertEquals("wHee", map.getSingleProperty("x4"));
+    	assertEquals("hey2", map.getSingleProperty("xxx"));
+    	assertEquals("hey2", map.getSingleProperty("XXX"));
+    	assertEquals("hey2", map.getSingleProperty("XXx"));
+
+    	assertEquals("Whee2", map.getSingleProperty("x", "Whee2"));
+
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RhsBuilderTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RhsBuilderTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RhsBuilderTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,58 @@
+package org.drools.decisiontable.parser;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class RhsBuilderTest {
+
+    @Test
+    public void testConsBuilding() {
+        RhsBuilder builder = new RhsBuilder( ActionType.Code.ACTION, 9, 1, "foo");
+        builder.addTemplate( 10, 1, "setFoo($param)");
+        builder.addCellValue( 10,1, "42" );
+        
+        
+        assertEquals("foo.setFoo(42);", builder.getResult());
+        
+        builder.clearValues();
+        builder.addCellValue( 10, 1, "33" );
+        assertEquals("foo.setFoo(33);", builder.getResult());
+    }
+    
+    @Test
+    public void testClassicMode() {
+        RhsBuilder builder = new RhsBuilder( ActionType.Code.ACTION, 9, 1, "");
+        builder.addTemplate( 10, 1, "p.setSomething($param);" );
+        builder.addTemplate( 10, 2, "drools.clearAgenda();" );
+                
+        builder.addCellValue( 12, 1, "42" );       
+        
+        assertEquals("p.setSomething(42);", builder.getResult());
+                
+        builder.addCellValue( 12, 2, "Y" );
+        assertEquals("p.setSomething(42);\ndrools.clearAgenda();", builder.getResult());
+    }
+
+    @Test
+    public void testMetadata() {
+        RhsBuilder builder = new RhsBuilder( ActionType.Code.METADATA, 9, 1, "");
+        builder.addTemplate( 10, 1, "Author($param)" );
+                
+        builder.addCellValue( 12, 1, "A. U. Thor" );       
+        assertEquals("Author(A. U. Thor)", builder.getResult());
+        builder.clearValues();
+        
+        builder.addCellValue( 13, 1, "P. G. Wodehouse" );
+        assertEquals("Author(P. G. Wodehouse)", builder.getResult());
+    }
+
+    @Test
+    public void testEmptyCellData() {
+        RhsBuilder builder = new RhsBuilder( ActionType.Code.ACTION, 9, 1, "Foo");
+        builder.addTemplate( 10, 1, "p.setSomething($param);" );        
+        assertFalse(builder.hasValues());
+    }
+    
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleSheetParserUtilTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleSheetParserUtilTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleSheetParserUtilTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.template.model.Global;
+import org.drools.template.model.Import;
+import org.drools.template.parser.DecisionTableParseException;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a>
+ * 
+ * Nuff said...
+ */
+public class RuleSheetParserUtilTest {
+
+	@Test
+	public void testRuleName() {
+		final String row = "  RuleTable       This is my rule name";
+		final String result = RuleSheetParserUtil.getRuleName( row );
+		assertEquals( "This is my rule name",
+				result );
+	}
+
+	/**
+	 * This is here as the old way was to do this.
+	 */
+	@Ignore
+	@Test
+	public void testInvalidRuleName() {
+		final String row = "RuleTable       This is my rule name (type class)";
+		try {
+			final String result = RuleSheetParserUtil.getRuleName( row );
+			fail( "should have failed, but get result: " + result );
+		} catch ( final IllegalArgumentException e ) {
+			assertNotNull( e.getMessage() );
+		}
+	}
+
+	@Test
+	public void testIsStringMeaningTrue() {
+		assertTrue( RuleSheetParserUtil.isStringMeaningTrue( "true" ) );
+		assertTrue( RuleSheetParserUtil.isStringMeaningTrue( "TRUE" ) );
+		assertTrue( RuleSheetParserUtil.isStringMeaningTrue( "yes" ) );
+		assertTrue( RuleSheetParserUtil.isStringMeaningTrue( "oN" ) );
+
+		assertFalse( RuleSheetParserUtil.isStringMeaningTrue( "no" ) );
+		assertFalse( RuleSheetParserUtil.isStringMeaningTrue( "false" ) );
+		assertFalse( RuleSheetParserUtil.isStringMeaningTrue( null ) );
+	}
+
+	@Test
+	public void testListImports() {
+		List<String> cellVals = null;
+
+		List<Import> list = RuleSheetParserUtil.getImportList( cellVals );
+		assertNotNull( list );
+		assertEquals( 0, list.size() );
+
+		cellVals = new ArrayList<String>();
+		cellVals.add( "" );
+		assertEquals( 0, RuleSheetParserUtil.getImportList( cellVals ).size() );
+
+		cellVals.add( 0, "com.something.Yeah, com.something.No,com.something.yeah.*" );
+		list = RuleSheetParserUtil.getImportList( cellVals );
+		assertEquals( 3, list.size() );
+		assertEquals( "com.something.Yeah",   (list.get( 0 )).getClassName() );
+		assertEquals( "com.something.No",     (list.get( 1 )).getClassName() );
+		assertEquals( "com.something.yeah.*", (list.get( 2 )).getClassName() );
+	}
+
+	@Test
+	public void testListVariables() {
+		List<String> varCells = new ArrayList<String>();
+		varCells.add( "Var1 var1, Var2 var2,Var3 var3" );
+		final List<Global> varList = RuleSheetParserUtil.getVariableList( varCells );
+		assertNotNull( varList );
+		assertEquals( 3,
+				varList.size() );
+		Global var = varList.get( 0 );
+		assertEquals( "Var1",
+				var.getClassName() );
+		var = varList.get( 2 );
+		assertEquals( "Var3",
+				var.getClassName() );
+		assertEquals( "var3",
+				var.getIdentifier() );
+	}
+
+	@Test
+	public void testBadVariableFormat() {
+		List<String> varCells = new ArrayList<String>();
+		varCells.add( "class1, object2" );
+		try {
+			RuleSheetParserUtil.getVariableList( varCells );
+			fail( "should not work" );
+		} catch ( final DecisionTableParseException e ) {
+			assertNotNull( e.getMessage() );
+		}
+	}
+
+	@Test
+	public void testRowColumnToCellNAme() {
+		String cellName = RuleSheetParserUtil.rc2name( 0, 0 );
+		assertEquals( "A1", cellName );
+
+		cellName = RuleSheetParserUtil.rc2name( 0, 10 );
+		assertEquals( "K1", cellName );
+
+		cellName = RuleSheetParserUtil.rc2name( 0, 42 );
+		assertEquals( "AQ1", cellName );
+
+		cellName = RuleSheetParserUtil.rc2name( 9, 27 );
+		assertEquals( "AB10", cellName );
+
+		cellName = RuleSheetParserUtil.rc2name( 99, 53 );
+		assertEquals( "BB100", cellName );
+	}
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseLargeTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseLargeTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseLargeTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.io.InputStream;
+
+import org.drools.template.model.Package;
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a>
+ * 
+ * A special test for parsing a large workbook, to see how it scales.
+ * 
+ */
+public class RuleWorksheetParseLargeTest {
+
+	private long startTimer;
+
+	private long endTimer;
+
+	/**
+	 * Tests parsing a large spreadsheet into an in memory ruleset. This doesn't
+	 * really do anything much at present. Takes a shed-load of memory to dump
+	 * out this much XML as a string, so really should think of using a stream
+	 * in some cases... (tried StringWriter, but is still in memory, so doesn't
+	 * help).
+	 * 
+	 * Stream to a temp file would work: return a stream from that file
+	 * (decorate FileInputStream such that when you close it, it deletes the
+	 * temp file).... must be other options.
+	 * 
+	 * @throws Exception
+	 */
+	@Ignore @Test
+	public void testLargeWorkSheetParseToRuleset() throws Exception {
+		//  Test removed until have streaming sorted in future. No one using Uber Tables just yet !        
+		InputStream stream = RuleWorksheetParseLargeTest.class.getResourceAsStream( "/data/VeryLargeWorkbook.xls" );
+
+		startTimer( );
+		RuleSheetListener listener = RuleWorksheetParseTest.getRuleSheetListener( stream );
+		stopTimer( );
+
+		System.out.println( "Time to parse large table : " + getTime() + "ms" );
+		Package ruleset = listener.getRuleSet( );
+		assertNotNull( ruleset );
+
+//		startTimer();
+//		String xml = ...;   // toXml() not in Package any more.
+//		System.out.println( xml );
+//		stopTimer();
+//		System.out.println("Time taken for rendering: " + getTime() + "ms");
+	}
+
+	private void startTimer() {
+		this.startTimer = System.currentTimeMillis();
+	}
+
+
+	private void stopTimer() {
+		this.endTimer = System.currentTimeMillis();
+	}
+
+	private long getTime() {
+		return this.endTimer - this.startTimer;
+	}
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RuleWorksheetParseTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,484 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import static org.junit.Assert.*;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Locale;
+
+
+import org.drools.decisiontable.parser.xls.PropertiesSheetListener.CaseInsensitiveMap;
+import org.drools.template.model.Condition;
+import org.drools.template.model.Consequence;
+import org.drools.template.model.DRLOutput;
+import org.drools.template.model.Import;
+import org.drools.template.model.Package;
+import org.drools.template.model.Rule;
+import org.drools.template.parser.DataListener;
+import org.drools.template.parser.DecisionTableParseException;
+
+/**
+ * @author Shaun Addison, Michael Neale
+ * 
+ * Test an excel file.
+ * 
+ * Assumes it has a sheet called "Decision Tables" with a rule table identified
+ * by a "RuleTable" cell
+ */
+public class RuleWorksheetParseTest {
+
+	@Test
+	public void testBasicWorkbookProperties() throws Exception {
+
+		final InputStream stream = RuleWorksheetParseTest.class.getResourceAsStream( "/data/BasicWorkbook.xls" );
+
+		final RuleSheetListener listener = getRuleSheetListener( stream );
+
+		final CaseInsensitiveMap props = listener.getProperties();
+		assertNotNull( props );
+		assertEquals( "myruleset", props.getSingleProperty( "RuleSet" ) );
+		assertEquals( "someMisc",  props.getSingleProperty( "misc" ) );
+		/*
+		 * System.out.println("Here are the global properties...");
+		 * listener.getProperties().list(System.out);
+		 */
+	}
+
+	@Test
+	public void testComplexWorkbookProperties() throws Exception {
+		final InputStream stream = RuleWorksheetParseTest.class.getResourceAsStream( "/data/ComplexWorkbook.xls" );
+		final RuleSheetListener listener = getRuleSheetListener( stream );
+
+		final CaseInsensitiveMap props = listener.getProperties();
+		assertNotNull( props );
+		final String ruleSetName = props.getSingleProperty( "RuleSet" );
+		assertEquals( "ruleSetName", ruleSetName );
+	}
+
+	@Test
+	public void testWorkbookParse() throws Exception {
+		final InputStream stream = RuleWorksheetParseTest.class.getResourceAsStream( "/data/BasicWorkbook.xls" );
+		final RuleSheetListener listener = getRuleSheetListener( stream );
+
+		final Package ruleset = listener.getRuleSet();
+		assertNotNull( ruleset );
+
+		final Rule firstRule = (Rule) ruleset.getRules().get( 0 );
+		assertNotNull( firstRule.getSalience() );
+		assertTrue( Integer.parseInt( firstRule.getSalience() ) > 0 );
+
+		// System.out.println(ruleset.toXML());
+
+		assertEquals( "myruleset", ruleset.getName() );
+		assertEquals( 3, ruleset.getImports().size() );
+		assertEquals( 6, ruleset.getRules().size() );
+
+		// check imports
+		Import imp = (Import) ruleset.getImports().get( 0 );
+		assertEquals( "blah.class1", imp.getClassName() );
+		imp = (Import) ruleset.getImports().get( 1 );
+		assertEquals( "blah.class2", imp.getClassName() );
+		imp = (Import) ruleset.getImports().get( 2 );
+		assertEquals( "lah.di.dah", imp.getClassName() );
+
+		// check rules
+		Rule rule = (Rule) ruleset.getRules().get( 0 );
+		Condition cond = (Condition) rule.getConditions().get( 0 );
+		assertEquals( "Foo(myObject.getColour().equals(red), myObject.size () > 12\\\")",
+				cond.getSnippet() );
+
+		Consequence cons = (Consequence) rule.getConsequences().get( 0 );
+		assertNotNull( cons );
+		assertEquals( "myObject.setIsValid(Y);", cons.getSnippet() );
+
+		rule = (Rule) ruleset.getRules().get( 5 );
+		cond = (Condition) rule.getConditions().get( 1 );
+		assertEquals( "myObject.size () > 7", cond.getSnippet() );
+		cons = (Consequence) rule.getConsequences().get( 0 );
+		assertEquals( "myObject.setIsValid(10-Jul-1974)", cons.getSnippet() );
+
+	}
+
+	private RuleSheetListener listener;
+	private int row;
+
+	private void makeRuleSet(){
+		listener = new DefaultRuleSheetListener();
+		listener.startSheet( "bad_sheet" );
+		row = 1;
+		listener.newRow( row, 2 );
+		listener.newCell( row, 1, "RuleSet",  DataListener.NON_MERGED );
+		listener.newCell( row, 2, "myRuleSet", DataListener.NON_MERGED );
+	}
+
+	private void makeAttribute( String key, String val){
+		row++;
+		listener.newRow( row, 2 );
+		listener.newCell( row, 1, key,  DataListener.NON_MERGED );
+		listener.newCell( row, 2, val,  DataListener.NON_MERGED );
+	}
+
+	private void makeRuleTable(){
+		listener.newRow( 10, 1 );
+		listener.newCell(10, 1, "RuleTable myRuleTable",  DataListener.NON_MERGED );
+	}	
+
+	private void makeRow( int row, String... values ) throws DecisionTableParseException {
+		listener.newRow( row, values.length );
+		for( int i = 0; i < values.length; i++ ){
+			if( values[i] != null ){
+				listener.newCell( row, i+1, values[i],  DataListener.NON_MERGED );
+			}
+		}
+	}
+
+	/**
+	 * Duplications of several columns are not permitted: NO-LOOP/U.
+	 */
+	@Test
+	public void testTooManyColumnsNoLoop() {
+		try {
+			makeRuleSet();
+			makeRuleTable();
+			makeRow( 11, "C", "C", "A", "U", "U" );
+			listener.finishSheet();
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			String badCell = RuleSheetParserUtil.rc2name( 11, 5 );
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( badCell ) );
+		}
+	}
+
+	/**
+	 * Duplications of several columns are not permitted : PRIORITY/P.
+	 */
+	@Test
+	public void testTooManyColumnsPriority() {
+		try {
+			makeRuleSet();
+			makeRuleTable();
+			makeRow( 11, "C", "C", "A", "PRIORITY", "P" );
+			listener.finishSheet();
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			String badCell = RuleSheetParserUtil.rc2name( 11, 5 );
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( badCell ) );
+		}
+	}
+
+	/**
+	 * Column headers must be valid.
+	 */
+	@Test
+	public void testBadColumnHeader() {
+		try {
+			makeRuleSet();
+			makeRuleTable();
+			makeRow( 11, "Condition", "CONDITION", "A", "BLURB", "P" );
+			listener.finishSheet();
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			String badCell = RuleSheetParserUtil.rc2name( 11, 4 );
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( badCell ) );
+		}
+	}
+
+	/**
+	 * Must have a type for pattern below a condition, not a snippet.
+	 */
+	@Test
+	public void testMissingCondition() {
+		try {
+			makeRuleSet();
+			makeRuleTable();
+			makeRow( 11, "C",   "C", "C",   "A", "A" );
+			makeRow( 12, "attr == $param", "attr == $param", "attr == $param", "action();", "action();" );
+			listener.finishSheet();
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			String badCell = RuleSheetParserUtil.rc2name( 12, 1 );
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( badCell ) );
+		}
+	}
+
+	/**
+	 * Must have a code snippet in a condition.
+	 */
+	@Test
+	public void testMissingCodeSnippetCondition() {
+		try {
+			makeRuleSet();
+			makeRuleTable();
+			makeRow( 11, "C",              "C",              "C",   "A",         "A" );
+			makeRow( 12, "Foo",            "Foo",            "Foo" );
+			makeRow( 13, "attr == $param", "attr == $param", "",    "action();", "action();" );
+			makeRow( 15, "1",              "2",              "3",   "",          "" );
+			listener.finishSheet();
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			String badCell = RuleSheetParserUtil.rc2name( 13, 3 );
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( badCell ) );
+		}
+	}
+
+	/**
+	 * Spurious code snippet.
+	 */
+	@Test
+	public void testSpuriousCodeSnippet() {
+		try {
+			makeRuleSet();
+			makeRuleTable();
+			makeRow( 11, "C",              "C",              "A" );
+			makeRow( 12, "Foo",            "Foo" );
+			makeRow( 13, "attr == $param", "attr == $param", "action();", "attr > $param" );
+			makeRow( 15, "1",              "2",              "" );
+			listener.finishSheet();
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			String badCell = RuleSheetParserUtil.rc2name( 13, 4 );
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( badCell ) );
+		}
+	}
+
+	/**
+	 * Incorrect priority - not numeric
+	 */
+	@Test
+	public void testIncorrectPriority() {
+		try {
+			makeRuleSet();
+			makeRuleTable();
+			makeRow( 11, "C",              "A",         "P" );
+			makeRow( 12, "Foo",            "Foo"            );
+			makeRow( 13, "attr == $param", "x"              );
+			makeRow( 15, "1",              "show()",   "12E" );
+			listener.finishSheet();
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			String badCell = RuleSheetParserUtil.rc2name( 15, 3 );
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( badCell ) );
+		}
+	}
+
+	/**
+	 * Must not have snippet for attribute
+	 */
+	@Test
+	public void testSnippetForAttribute() {
+		try {
+			makeRuleSet();
+			makeRuleTable();
+			makeRow( 11, "C",              "A",         "G" );
+			makeRow( 12, "Foo",            "Foo"            );
+			makeRow( 13, "attr == $param", "x",       "XXX" );
+			makeRow( 15, "1",              "show()",   "10" );
+			listener.finishSheet();
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			String badCell = RuleSheetParserUtil.rc2name( 13, 3 );
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( badCell ) );
+		}
+	}
+
+	/**
+	 * Check correct rendering of string-valued attribute
+	 */
+	@Test
+	public void testRuleAttributeRendering() {
+		makeRuleSet();
+		makeRuleTable();
+		makeRow( 11, "C",              "A",         "G"     );
+		makeRow( 12, "Foo",            "Foo"                );
+		makeRow( 13, "attr == $param", "x"                  );
+		makeRow( 15, "1",              "show()",   "foo bar" );
+		makeRow( 16, "2",              "list()",   "\"10\" group\"" );
+		listener.finishSheet();
+		Package p = listener.getRuleSet();
+		DRLOutput dout = new DRLOutput();
+		p.renderDRL(dout);
+		String drl = dout.getDRL();
+		//		System.out.println( drl );
+		assertTrue( drl.contains( "agenda-group \"foo bar\"" ) );
+		assertTrue( drl.contains( "agenda-group \"10\\\" group\"" ) );
+	}
+
+	/**
+	 * Duplicate package level attribute
+	 */
+	@Test
+	public void testDuplicatePackageAttribute() {
+		try {
+			makeRuleSet();
+			makeAttribute( "agenda-group", "agroup" );  // B3, C3
+			makeAttribute( "agenda-group", "bgroup" );  // B3. B4
+			makeRuleTable();
+			makeRow( 11, "C",              "A",         "P" );
+			makeRow( 12, "Foo",            "Foo"            );
+			makeRow( 13, "attr == $param", "x"              );
+			makeRow( 15, "1",              "show()",   "10" );
+			listener.finishSheet();
+			Package p = listener.getRuleSet();
+			DRLOutput dout = new DRLOutput();
+			p.renderDRL(dout);
+			String drl = dout.getDRL();
+			//			System.out.println( drl );
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( "C3, C4" ) );
+		}
+	}
+
+	/**
+	 * Check correct rendering of package level attributes
+	 */
+	@Test
+	public void testPackageAttributeRendering() {
+		makeRuleSet();
+		makeAttribute( "NO-LOOP", "true" );
+		makeAttribute( "agenda-group", "agroup" );
+		makeRuleTable();
+		makeRow( 11, "C",              "A",         "P"     );
+		makeRow( 12, "foo:Foo",        "foo"                );
+		makeRow( 13, "attr == $param", "x($param)"          );
+		makeRow( 15, "1",              "1",         "100"   );
+		listener.finishSheet();
+		Package p = listener.getRuleSet();
+		DRLOutput dout = new DRLOutput();
+		p.renderDRL(dout);
+		String drl = dout.getDRL();
+		//		System.out.println( drl );
+		assertTrue( drl.contains( "no-loop true" ) );
+		assertTrue( drl.contains( "agenda-group \"agroup\"" ) );
+	}
+
+	/**
+	 * Must have a code snippet in an action.
+	 */
+	@Test
+	public void testMissingCodeSnippetAction() {
+		try {
+			makeRuleSet();
+			makeRuleTable();
+			makeRow( 11, "C",              "A"          );
+			makeRow( 12, "foo: Foo",       "Bar()"          );
+			makeRow( 13, "attr == $param"  );
+			makeRow( 15, "1",              "1"          );
+			makeRow( 16, "2",              "2"          );
+			listener.finishSheet();
+			Package p = listener.getRuleSet();
+			DRLOutput dout = new DRLOutput();
+			p.renderDRL(dout);
+			String drl = dout.getDRL();
+			System.out.println( drl );
+			fail( "should have failed" );
+		} catch( DecisionTableParseException e ) {
+			String badCell = RuleSheetParserUtil.rc2name( 13, 2 );
+			System.err.println( e.getMessage() );
+			assertTrue( e.getMessage().contains( badCell ) );
+		}
+	}
+	
+	@Test
+	public void testMetadata() {
+		makeRuleSet();
+		makeRuleTable();
+		makeRow( 11, "C",              "A",              "@",              "@"  );
+		makeRow( 12, "foo: Foo",       "foo"          );
+		makeRow( 13, "attr == $param", "goaway($param)", "Author($param)", "Version($1-$2)" );
+		makeRow( 15, "1",              "1",              "J.W.Goethe",     "3,14"       );
+		makeRow( 16, "2",              "2",              "",               ""       );
+		listener.finishSheet();
+		Package p = listener.getRuleSet();
+		DRLOutput dout = new DRLOutput();
+		p.renderDRL(dout);
+		String drl = dout.getDRL();
+
+		assertTrue( drl.contains( "@Author(J.W.Goethe)" ) );
+		assertTrue( drl.contains( "@Version(3-14)" ) );
+		assertFalse( drl.contains( "@Author()" ) );
+		assertFalse( drl.contains( "@Version(-)" ) );
+	}
+
+
+	/**
+	 * See if it can cope with odd shaped rule table, including missing
+	 * conditions. Also is not "sequential".
+	 */
+	@Test
+	public void testComplexWorksheetMissingConditionsInLocaleEnUs() throws Exception {
+        Locale originalDefaultLocale = Locale.getDefault();
+        Locale.setDefault(Locale.US);
+        doComplexWorksheetMissingConditions();
+        Locale.setDefault(originalDefaultLocale);
+	}
+
+    @Test @Ignore // TODO JBRULES-2880 TIRELLI: Ignore test while we decide what to do in order to solve i18n issues
+	public void testComplexWorksheetMissingConditionsInLocaleFrFr() throws Exception {
+        Locale originalDefaultLocale = Locale.getDefault();
+        Locale.setDefault(Locale.FRANCE);
+        doComplexWorksheetMissingConditions();
+        Locale.setDefault(originalDefaultLocale);
+    }
+
+    private void doComplexWorksheetMissingConditions() throws IOException {
+        final InputStream stream = RuleWorksheetParseTest.class.getResourceAsStream( "/data/ComplexWorkbook.xls" );
+        final RuleSheetListener listener = getRuleSheetListener( stream );
+
+        final Package ruleset = listener.getRuleSet();
+        assertEquals( 6, ruleset.getRules().size() );
+        assertEquals( 0, ruleset.getImports().size() );
+
+        Rule rule = (Rule) ruleset.getRules().get( 0 );
+        assertEquals( 3, rule.getConditions().size() );
+        assertEquals( 2, rule.getConsequences().size() );
+        final Consequence cons = (Consequence) rule.getConsequences().get( 1 );
+        assertEquals( "myObject.setIsValid(1, 2)", cons.getSnippet() );
+        final Condition con = (Condition) rule.getConditions().get( 2 );
+        assertEquals( "myObject.size() < $3.00", con.getSnippet() );
+
+        rule = (Rule) ruleset.getRules().get( 4 );
+
+        // this should have less conditions
+        assertEquals( 1, rule.getConditions().size() );
+
+        rule = (Rule) ruleset.getRules().get( 5 );
+        assertEquals( 2, rule.getConditions().size() );
+        assertEquals( 1, rule.getConsequences().size() );
+    }
+
+	/**
+	 * Utility method showing how to get a rule sheet listener from a stream.
+	 */
+	public static RuleSheetListener getRuleSheetListener(final InputStream stream) throws IOException {
+		return RulesheetUtil.getRuleSheetListener( stream );
+	}
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RulesheetUtil.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RulesheetUtil.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/RulesheetUtil.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.decisiontable.parser.xls.ExcelParser;
+import org.drools.template.parser.DataListener;
+
+/**
+ * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a>
+ * 
+ */
+public class RulesheetUtil {
+
+    /**
+     * Utility method showing how to get a rule sheet listener from a stream.
+     */
+    public static RuleSheetListener getRuleSheetListener(final InputStream stream) throws IOException {
+        final Map<String, List<DataListener>> sheetListeners = new HashMap<String, List<DataListener>>();
+        final List<DataListener> listeners = new ArrayList<DataListener>(); 
+        final RuleSheetListener listener = new DefaultRuleSheetListener();
+        listeners.add(listener);
+        sheetListeners.put( ExcelParser.DEFAULT_RULESHEET_NAME,
+                      listeners );
+        final ExcelParser parser = new ExcelParser( sheetListeners );
+        try {
+            parser.parseFile( stream );
+        } finally {
+            stream.close();
+        }
+        stream.close();
+        return listener;
+    }
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvLineParserTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvLineParserTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvLineParserTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser.csv;
+
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class CsvLineParserTest {
+
+    @Test
+    public void testSimpleLineParse() {
+        final CsvLineParser parser = new CsvLineParser();
+        final String s = "a,b,c";
+        final List<String> list = parser.parse( s );
+        assertEquals( 3,
+                      list.size() );
+
+        assertEquals( "a",
+                      list.get( 0 ) );
+        assertEquals( "b",
+                      list.get( 1 ) );
+        assertEquals( "c",
+                      list.get( 2 ) );
+    }
+
+    @Test
+    public void testLineParse() {
+        final CsvLineParser parser = new CsvLineParser();
+        final String s = "a,\"b\",c";
+        final List<String> list = parser.parse( s );
+        assertEquals( 3,
+                      list.size() );
+
+        assertEquals( "a",
+                      list.get( 0 ) );
+        assertEquals( "b",
+                      list.get( 1 ) );
+        assertEquals( "c",
+                      list.get( 2 ) );
+    }
+
+    @Test
+    public void testDoubleQuotes() {
+        final CsvLineParser parser = new CsvLineParser();
+        final String s = "a,\"\"\"b\"\"\",c";
+        final List<String> list = parser.parse( s );
+        assertEquals( 3,
+                      list.size() );
+
+        assertEquals( "a",
+                      list.get( 0 ) );
+        assertEquals( "\"b\"",
+                      list.get( 1 ) );
+        assertEquals( "c",
+                      list.get( 2 ) );
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvParserTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvParserTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/csv/CsvParserTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser.csv;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import org.drools.template.parser.DataListener;
+
+public class CsvParserTest {
+
+    @Test
+    public void testCsv() {
+        final MockSheetListener listener = new MockSheetListener();
+        final CsvLineParser lineParser = new CsvLineParser();
+        final CsvParser parser = new CsvParser( listener,
+                                                lineParser );
+
+        parser.parseFile( getClass().getResourceAsStream( "/data/TestCsv.csv" ) );
+        assertEquals( "A",
+                      listener.getCell( 0,
+                                        0 ) );
+        assertEquals( "B",
+                      listener.getCell( 0,
+                                        1 ) );
+        assertEquals( "",
+                      listener.getCell( 2,
+                                        0 ) );
+        assertEquals( "C",
+                      listener.getCell( 1,
+                                        0 ) );
+        assertEquals( "D",
+                      listener.getCell( 1,
+                                        1 ) );
+        assertEquals( "E",
+                      listener.getCell( 1,
+                                        3 ) );
+
+    }
+
+    /**
+     * Test the handling of merged cells.
+     */
+    @Test
+    public void testCellMergeHandling() {
+        CsvParser parser = new CsvParser( (DataListener) null,
+                                          null );
+        assertEquals( DataListener.NON_MERGED,
+                      parser.calcStartMerge( DataListener.NON_MERGED,
+                                             1,
+                                             "foo" ) );
+        assertEquals( 42,
+                      parser.calcStartMerge( DataListener.NON_MERGED,
+                                             42,
+                                             "..." ) );
+
+        assertEquals( 42,
+                      parser.calcStartMerge( 42,
+                                             43,
+                                             "..." ) );
+
+        assertEquals( DataListener.NON_MERGED,
+                      parser.calcStartMerge( 42,
+                                             44,
+                                             "VanHalen" ) );
+
+        assertEquals( "VanHalen",
+                      parser.calcCellText( DataListener.NON_MERGED,
+                                           "VanHalen" ) );
+        assertEquals( "VanHalen",
+                      parser.calcCellText( 42,
+                                           "VanHalen..." ) );
+        assertEquals( "",
+                      parser.calcCellText( 42,
+                                           "..." ) );
+
+    }
+
+    static class MockSheetListener
+        implements
+        DataListener {
+
+        Map<String, String> data = new HashMap<String, String>();
+
+        public String getCell(final int row,
+                              final int col) {
+            return this.data.get( cellKey( row,
+                                           col ) );
+        }
+
+        public void startSheet(final String name) {
+        }
+
+        public void finishSheet() {
+        }
+
+        public void newRow(final int rowNumber,
+                           final int columns) {
+
+        }
+
+        public void newCell(final int row,
+                            final int column,
+                            final String value,
+                            final int mergeCellStart) {
+
+            this.data.put( cellKey( row,
+                                    column ),
+                           value );
+        }
+
+        String cellKey(final int row,
+                       final int column) {
+            return "R" + row + "C" + column;
+        }
+    }
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls/ExcelParserTest.java
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls/ExcelParserTest.java	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/java/org/drools/decisiontable/parser/xls/ExcelParserTest.java	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.drools.decisiontable.parser.xls;
+
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import jxl.Cell;
+import jxl.CellType;
+import jxl.Range;
+import jxl.format.CellFormat;
+
+import org.drools.template.parser.DataListener;
+
+/**
+ * @author <a href="mailto:michael.neale at gmail.com"> Michael Neale</a>
+ * 
+ * Some unit tests for the corners of ExcelParser that are not explicitly
+ * covered by integration tests.
+ */
+public class ExcelParserTest {
+
+    @Test
+    public void testRemoveTrailingZero() {
+        String test = "1.0";
+        assertEquals( "1",
+                      ExcelParser.removeTrailingZero( test ) );
+
+        test = "42.0";
+        assertEquals( "42",
+                      ExcelParser.removeTrailingZero( test ) );
+
+        test = "42";
+        assertEquals( "42",
+                      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
+     */
+    @Test
+    public void testCellMerge() throws Exception {
+    	ExcelParser parser = new ExcelParser((Map<String, List<DataListener>>) 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<CellFeatures> 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;
+		}
+
+        public jxl.CellFeatures getCellFeatures() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+    }
+    
+    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;
+		}
+    	
+    }
+
+}

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/BasicWorkbook.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/BasicWorkbook.xls
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/ComplexWorkbook.csv
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/ComplexWorkbook.csv	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/ComplexWorkbook.csv	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,21 @@
+,"RuleSet","ruleSetName",,,
+,,,,,
+,,,,,
+,,,,,
+,"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","1,3"
+,,,,,
+"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",,

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/ComplexWorkbook.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/ComplexWorkbook.xls
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/CustomWorkbook.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/CustomWorkbook.xls
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

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


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

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/IntegrationExampleTest.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/IntegrationExampleTest.xls
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/MultiSheetDST.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/MultiSheetDST.xls
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/TeamAllocationExample_TYPICAL_EXAMPLE.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/TeamAllocationExample_TYPICAL_EXAMPLE.xls
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/TestCsv.csv
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/TestCsv.csv	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/TestCsv.csv	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,3 @@
+A,B,
+C,D,,E
+,X
\ No newline at end of file

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/VeryLargeWorkbook.xls
===================================================================
(Binary files differ)


Property changes on: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/data/VeryLargeWorkbook.xls
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset1Test.drl
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset1Test.drl	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset1Test.drl	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,10 @@
+package org.drools.test
+
+global java.util.List list;
+
+rule "rule1"
+	salience 10
+when
+then
+    list.add( "rule1" );
+end
\ No newline at end of file

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset1Test.xml
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset1Test.xml	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset1Test.xml	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,13 @@
+<change-set xmlns='http://drools.org/drools-5.0/change-set'
+            xmlns:xs='http://www.w3.org/2001/XMLSchema-instance'
+            xs:schemaLocation='http://drools.org/drools-5.0/change-set http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-api/src/main/resources/change-set-1.0.0.xsd' >
+            
+    <add>
+        
+	    <resource  source='classpath:org/drools/decisiontable/changeset1Test.drl' type='DRL' />
+	    <resource source='classpath:data/IntegrationExampleTest.xls' type="DTABLE">
+	        <decisiontable-conf input-type="XLS" worksheet-name="Tables_2" />
+	    </resource>
+	    <resource source='classpath:org/drools/decisiontable/changeset2Test.drl' type='DRL' />
+    </add>
+</change-set>

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset2Test.drl
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset2Test.drl	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/org/drools/decisiontable/changeset2Test.drl	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,10 @@
+package org.drools.test
+
+global java.util.List list;
+
+rule "rule2"
+	salience 5
+when
+then
+    list.add( "rule2" );
+end
\ No newline at end of file

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_integration.drl
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_integration.drl	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_integration.drl	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,24 @@
+template header
+age: Long
+type
+log
+
+package Some_business_rules;
+#generated from Decision Table
+import org.drools.decisiontable.Cheese;
+import org.drools.decisiontable.Person;
+global java.util.List list;
+
+template "cheesefans"
+age > 21 && < 43
+type
+log
+
+rule "Cheese fans_@{row.rowNumber}"
+	when
+		Person(age == "@{age}")
+		Cheese(type == "@{type}")
+	then
+		list.add("@{log}");
+end
+end template
\ No newline at end of file

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_pricing1.drl
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_pricing1.drl	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_pricing1.drl	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,28 @@
+template header
+age[]
+profile
+priorClaims
+policyType
+base
+reason
+
+package org.acme.insurance;
+
+template "Pricing bracket"
+age
+policyType
+base
+
+rule "Pricing bracket_@{row.rowNumber}"
+	
+	when
+		Driver(age >= @{age0}, age <= @{age1}
+			, priorClaims == "@{priorClaims}"
+			, locationRiskProfile == "@{profile}"
+		)
+		policy: Policy(type == "@{policyType}")
+	then
+		policy.setBasePrice(@{base});
+		System.out.println("@{reason}");
+end
+end template

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_pricing2.drl
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_pricing2.drl	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_pricing2.drl	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,23 @@
+template header
+age[]
+priorClaims
+policyType
+discount
+
+package org.acme.insurance;
+
+template "discounts"
+age
+priorClaims
+policyType
+discount
+
+rule "Discounts_@{row.rowNumber}"
+	
+	when
+		Driver(age >= @{age0}, age <= @{age1}, priorClaims == "@{priorClaims}")
+		policy: Policy(type == "@{policyType}")
+	then
+		policy.applyDiscount(@{discount});
+end
+end template

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template1.drl
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template1.drl	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template1.drl	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,39 @@
+template header
+name
+age[]
+log
+coolness
+
+package This_is_a_ruleset;
+#generated from Decision Table
+import example.model.User;
+import example.model.Car;
+
+template "coolness"
+name
+age
+log
+coolness
+rule "How cool is @{name} @{row.rowNumber}"
+	when
+		user.getName().equals("@{name}")
+		user.getAge() >= @{age0} && user.getAge() <= @{age1}
+	then
+		System.out.println( "@{log}" );
+		user.setCoolness("@{coolness}");
+end
+end template
+template "uncoolness"
+name
+age
+log
+rule "How uncool is @{name} @{row.rowNumber}"
+	when
+		user.getName().equals("@{name}")
+		user.getAge() >= @{age0} && user.getAge() <= @{age1}
+	then
+		System.out.println( "@{log}" );
+		user.setCoolness("Not so cool"); //@{coolness} putting the column in the comments makes the line conditionally display
+end		
+end template
+

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template2.drl
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template2.drl	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template2.drl	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,28 @@
+template header
+colour
+minSize
+maxSize
+valida
+validb[]
+
+package rulesetName;
+#generated from Decision Table
+
+
+template "mine"
+colour
+minSize
+maxSize
+valida
+validb
+rule "some stuff @{row.rowNumber}"
+	when
+		Foo(myObject.getColour().equals(@{colour}),
+		myObject.size () > @{minSize},
+		myObject.size () < @{maxSize})
+	then
+		myObject.setIsValid(@{valida});
+		myObject.setIsValid(@{validb0}, @{validb1});
+end
+end template
+

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template3.drl
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template3.drl	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template3.drl	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,31 @@
+template header
+colour
+minSize
+maxSize
+valid
+
+
+package rulesetName;
+#generated from Decision Table
+import blah.class1
+import blah.class2
+
+global Class1 obj1;
+function test() {
+	This is a function block
+}
+template "This_Is_Rule_Name_Prefix"
+colour
+minSize
+maxSize
+valid
+rule "This_Is_Rule_Name_Prefix @{row.rowNumber}"
+	when
+		Foo(myObject.getColour().equals(@{colour}), myObject.size() > @{minSize})
+		b: Bar()
+		eval(myObject.size() < @{maxSize})
+	then
+		myObject.setIsValid(@{valid});
+end
+end template
+

Added: labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template4.drl
===================================================================
--- labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template4.drl	                        (rev 0)
+++ labs/jbossrules/tags/5.2.0.M1/drools-decisiontables/src/test/resources/templates/test_template4.drl	2011-02-24 15:37:22 UTC (rev 36699)
@@ -0,0 +1,29 @@
+template header
+colour
+minSize
+maxSize
+
+
+package rulesetName;
+#generated from Decision Table
+import blah.class1
+import blah.class2
+
+global Class1 obj1;
+function test() {
+	This is a function block
+}
+template "This_Is_Rule_Name_Prefix"
+colour
+minSize
+maxSize
+rule "This_Is_Rule_Name_Prefix @{row.rowNumber}"
+	when
+		Foo(myObject.getColour().equals(@{colour}), myObject.size() > @{minSize})
+		b: Bar()
+		eval(myObject.size() < @{maxSize})
+	then
+		myObject.setIsValid(true);
+end
+end template
+



More information about the jboss-svn-commits mailing list