[jboss-svn-commits] JBL Code SVN: r8528 - in labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java: . builder

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Dec 21 15:43:10 EST 2006


Author: tirelli
Date: 2006-12-21 15:43:00 -0500 (Thu, 21 Dec 2006)
New Revision: 8528

Added:
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/AccumulateBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildContext.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildUtils.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/CollectBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ColumnBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConditionalElementBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConsequenceBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/EvalBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/FromBuilder.java
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/RuleClassBuilder.java
Modified:
   labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java
Log:
JBRULES-218: Refactoring RuleBuilder to make it easy to maintain

Modified: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/RuleBuilder.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -16,41 +16,13 @@
  * limitations under the License.
  */
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
-import org.antlr.runtime.ANTLRStringStream;
-import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.TokenStream;
-import org.antlr.stringtemplate.StringTemplate;
-import org.antlr.stringtemplate.StringTemplateGroup;
-import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
 import org.codehaus.jfdi.interpreter.TypeResolver;
-import org.codehaus.jfdi.parser.JFDILexer;
-import org.codehaus.jfdi.parser.JFDIParser;
-import org.drools.RuntimeDroolsException;
 import org.drools.base.ClassFieldExtractorCache;
-import org.drools.base.ClassObjectType;
-import org.drools.base.DroolsJFDIFactory;
-import org.drools.base.FieldFactory;
-import org.drools.base.ShadowProxyFactory;
-import org.drools.base.ValueType;
-import org.drools.base.dataproviders.JFDIDataProvider;
-import org.drools.base.evaluators.Operator;
-import org.drools.compiler.RuleError;
-import org.drools.facttemplates.FactTemplate;
-import org.drools.facttemplates.FactTemplateFieldExtractor;
-import org.drools.facttemplates.FactTemplateObjectType;
-import org.drools.lang.descr.AccessorDescr;
 import org.drools.lang.descr.AccumulateDescr;
 import org.drools.lang.descr.AndDescr;
 import org.drools.lang.descr.AttributeDescr;
@@ -60,47 +32,27 @@
 import org.drools.lang.descr.ConditionalElementDescr;
 import org.drools.lang.descr.EvalDescr;
 import org.drools.lang.descr.ExistsDescr;
-import org.drools.lang.descr.FieldBindingDescr;
-import org.drools.lang.descr.FieldConstraintDescr;
 import org.drools.lang.descr.FromDescr;
-import org.drools.lang.descr.LiteralRestrictionDescr;
 import org.drools.lang.descr.NotDescr;
 import org.drools.lang.descr.OrDescr;
-import org.drools.lang.descr.PredicateDescr;
 import org.drools.lang.descr.QueryDescr;
-import org.drools.lang.descr.RestrictionConnectiveDescr;
-import org.drools.lang.descr.RestrictionDescr;
-import org.drools.lang.descr.ReturnValueRestrictionDescr;
 import org.drools.lang.descr.RuleDescr;
-import org.drools.lang.descr.VariableRestrictionDescr;
-import org.drools.rule.Accumulate;
-import org.drools.rule.AndCompositeRestriction;
-import org.drools.rule.Collect;
 import org.drools.rule.Column;
-import org.drools.rule.Declaration;
-import org.drools.rule.EvalCondition;
-import org.drools.rule.From;
+import org.drools.rule.ConditionalElement;
 import org.drools.rule.GroupElement;
 import org.drools.rule.GroupElementFactory;
-import org.drools.rule.LiteralConstraint;
-import org.drools.rule.LiteralRestriction;
-import org.drools.rule.MultiRestrictionFieldConstraint;
-import org.drools.rule.OrCompositeRestriction;
 import org.drools.rule.Package;
-import org.drools.rule.PredicateConstraint;
-import org.drools.rule.Query;
-import org.drools.rule.ReturnValueConstraint;
-import org.drools.rule.ReturnValueRestriction;
 import org.drools.rule.Rule;
-import org.drools.rule.VariableConstraint;
-import org.drools.rule.VariableRestriction;
-import org.drools.spi.AvailableVariables;
-import org.drools.spi.DataProvider;
-import org.drools.spi.Evaluator;
-import org.drools.spi.FieldExtractor;
-import org.drools.spi.FieldValue;
-import org.drools.spi.ObjectType;
-import org.drools.spi.Restriction;
+import org.drools.semantics.java.builder.AccumulateBuilder;
+import org.drools.semantics.java.builder.BuildContext;
+import org.drools.semantics.java.builder.BuildUtils;
+import org.drools.semantics.java.builder.CollectBuilder;
+import org.drools.semantics.java.builder.ColumnBuilder;
+import org.drools.semantics.java.builder.ConditionalElementBuilder;
+import org.drools.semantics.java.builder.ConsequenceBuilder;
+import org.drools.semantics.java.builder.EvalBuilder;
+import org.drools.semantics.java.builder.FromBuilder;
+import org.drools.semantics.java.builder.RuleClassBuilder;
 
 /**
  * This builds the rule structure from an AST.
@@ -108,150 +60,103 @@
  * This is an internal API.
  */
 public class RuleBuilder {
-    private Package                           pkg;
-    private Rule                              rule;
-    private RuleDescr                         ruleDescr;
 
-    public String                             ruleClass;
-    public List                               methods;
-    public Map                                invokers;
+    // the current build context
+    private BuildContext       context;
 
-    private Map                               invokerLookups;
+    // the current build utils
+    private BuildUtils         utils;
 
-    private Map                               descrLookups;
+    // a map of registered builders
+    private Map                builders;
 
-    private Map                               declarations;
+    // the builder for columns
+    private ColumnBuilder      columnBuilder;
 
-    private int                               counter;
-
-    private ColumnCounter                     columnCounter;
-
-    private int                               columnOffset;
-
-    private List                              errors;
-
-    private final TypeResolver                typeResolver;
-
-    private Map                               innerDeclarations;
-
-    private static final StringTemplateGroup  ruleGroup            = new StringTemplateGroup( new InputStreamReader( RuleBuilder.class.getResourceAsStream( "javaRule.stg" ) ),
-                                                                                              AngleBracketTemplateLexer.class );
-
-    private static final StringTemplateGroup  invokerGroup         = new StringTemplateGroup( new InputStreamReader( RuleBuilder.class.getResourceAsStream( "javaInvokers.stg" ) ),
-                                                                                              AngleBracketTemplateLexer.class );
-
-    private static final KnowledgeHelperFixer knowledgeHelperFixer = new KnowledgeHelperFixer();
-
-    private final FunctionFixer               functionFixer;
+    private ConsequenceBuilder consequenceBuilder;
     
-    private AvailableVariables          variables;
+    private RuleClassBuilder   classBuilder;
 
-    // @todo move to an interface so it can work as a decorator
-    private final JavaExprAnalyzer            analyzer             = new JavaExprAnalyzer();
-    private ClassFieldExtractorCache          classFieldExtractorCache;
-
     public RuleBuilder(final TypeResolver typeResolver,
                        final FunctionFixer functionFixer,
                        final ClassFieldExtractorCache cache) {
-        this.classFieldExtractorCache = cache;
-        this.typeResolver = typeResolver;
-        this.functionFixer = functionFixer;
-        this.errors = new ArrayList();
+        this.utils = new BuildUtils( functionFixer,
+                                     new KnowledgeHelperFixer(),
+                                     new JavaExprAnalyzer(),
+                                     typeResolver,
+                                     cache );
+
+        this.columnBuilder = new ColumnBuilder();
+
+        this.consequenceBuilder = new ConsequenceBuilder();
+        
+        this.classBuilder = new RuleClassBuilder();
+
+        // statically adding all builders to the map
+        // but in the future we can move that to a configuration
+        // if we want to
+        this.builders = new HashMap();
+        builders.put( EvalDescr.class,
+                      new EvalBuilder() );
+        builders.put( FromDescr.class,
+                      new FromBuilder() );
+        builders.put( CollectDescr.class,
+                      new CollectBuilder() );
+        builders.put( AccumulateDescr.class,
+                      new AccumulateBuilder() );
+
     }
 
     public Map getInvokers() {
-        return this.invokers;
+        return (this.context == null) ? null : this.context.getInvokers();
     }
 
     public Map getDescrLookups() {
-        return this.descrLookups;
+        return (this.context == null) ? null : this.context.getDescrLookups();
     }
 
     public String getRuleClass() {
-        return this.ruleClass;
+        return (this.context == null) ? null : this.context.getRuleClass();
     }
 
     public Map getInvokerLookups() {
-        return this.invokerLookups;
+        return (this.context == null) ? null : this.context.getInvokerLookups();
     }
 
     public List getErrors() {
-        return this.errors;
+        return (this.context == null) ? null : this.context.getErrors();
     }
 
     public Rule getRule() {
-        if ( !this.errors.isEmpty() ) {
-            this.rule.setSemanticallyValid( false );
+        if ( this.context == null ) {
+            return null;
         }
-        return this.rule;
+        if ( !this.context.getErrors().isEmpty() ) {
+            this.context.getRule().setSemanticallyValid( false );
+        }
+        return this.context.getRule();
     }
 
     public Package getPackage() {
-        return this.pkg;
+        return this.context.getPkg();
     }
 
     public synchronized Rule build(final Package pkg,
                                    final RuleDescr ruleDescr) {
-        this.pkg = pkg;
-        this.methods = new ArrayList();
-        this.invokers = new HashMap();
-        this.invokerLookups = new HashMap();
-        this.declarations = new HashMap();
-        this.descrLookups = new HashMap();
-        this.columnCounter = new ColumnCounter();
-        this.variables = new AvailableVariables( new Map[] { this.declarations, this.pkg.getGlobals() } );
+        this.context = new BuildContext( pkg,
+                                         ruleDescr );
 
-        this.ruleDescr = ruleDescr;
-
-        if ( ruleDescr instanceof QueryDescr ) {
-            this.rule = new Query( ruleDescr.getName() );
-        } else {
-            this.rule = new Rule( ruleDescr.getName() );
-        }
-
         // Assign attributes
-        setAttributes( this.rule,
+        setAttributes( this.context.getRule(),
                        ruleDescr.getAttributes() );
 
         // Build the left hand side
-        // generate invoker, s
+        // generate invokers
         build( ruleDescr );
 
-        return this.rule;
+        return this.context.getRule();
     }
 
-    private void setAttributes(final Rule rule,
-                               final List attributes) {
-        for ( final Iterator it = attributes.iterator(); it.hasNext(); ) {
-            final AttributeDescr attributeDescr = (AttributeDescr) it.next();
-            final String name = attributeDescr.getName();
-            if ( name.equals( "salience" ) ) {
-                rule.setSalience( Integer.parseInt( attributeDescr.getValue() ) );
-            } else if ( name.equals( "no-loop" ) ) {
-                if ( attributeDescr.getValue() == null ) {
-                    rule.setNoLoop( true );
-                } else {
-                    rule.setNoLoop( Boolean.valueOf( attributeDescr.getValue() ).booleanValue() );
-                }
-            } else if ( name.equals( "auto-focus" ) ) {
-                if ( attributeDescr.getValue() == null ) {
-                    rule.setAutoFocus( true );
-                } else {
-                    rule.setAutoFocus( Boolean.valueOf( attributeDescr.getValue() ).booleanValue() );
-                }
-            } else if ( name.equals( "agenda-group" ) ) {
-                rule.setAgendaGroup( attributeDescr.getValue() );
-            } else if ( name.equals( "activation-group" ) ) {
-                rule.setXorGroup( attributeDescr.getValue() );
-            } else if ( name.equals( "duration" ) ) {
-                rule.setDuration( Long.parseLong( attributeDescr.getValue() ) );
-                rule.setAgendaGroup( "" );
-            } else if ( name.equals( "language" ) ) {
-                //@todo: we don't currently  support multiple languages
-            }
-        }
-    }
-
     private void build(final RuleDescr ruleDescr) {
 
         for ( final Iterator it = ruleDescr.getLhs().getDescrs().iterator(); it.hasNext(); ) {
@@ -259,79 +164,70 @@
             if ( object instanceof ConditionalElementDescr ) {
                 if ( object.getClass() == AndDescr.class ) {
                     final GroupElement and = GroupElementFactory.newAndInstance();
-                    build( this.rule,
+                    build( this.context.getRule(),
                            (ConditionalElementDescr) object,
                            and,
                            false, // do not decrement offset
                            false ); // do not decrement first offset
-                    this.rule.addPattern( and );
+                    this.context.getRule().addPattern( and );
                 } else if ( object.getClass() == OrDescr.class ) {
                     final GroupElement or = GroupElementFactory.newOrInstance();
-                    build( this.rule,
+                    build( this.context.getRule(),
                            (ConditionalElementDescr) object,
                            or,
                            true, // when OR is used, offset MUST be decremented
                            false ); // do not decrement first offset
-                    this.rule.addPattern( or );
+                    this.context.getRule().addPattern( or );
                 } else if ( object.getClass() == NotDescr.class ) {
                     // We cannot have declarations created inside a not visible outside it, so track no declarations so they can be removed
-                    this.innerDeclarations = new HashMap();
+                    context.setInnerDeclarations( new HashMap() );
                     final GroupElement not = GroupElementFactory.newNotInstance();
-                    build( this.rule,
+                    build( this.context.getRule(),
                            (ConditionalElementDescr) object,
                            not,
                            true, // when NOT is used, offset MUST be decremented
                            true ); // when NOT is used, offset MUST be decremented for first column
-                    this.rule.addPattern( not );
+                    this.context.getRule().addPattern( not );
 
                     // remove declarations bound inside not node
-                    for ( final Iterator notIt = this.innerDeclarations.keySet().iterator(); notIt.hasNext(); ) {
-                        this.declarations.remove( notIt.next() );
+                    for ( final Iterator notIt = context.getInnerDeclarations().keySet().iterator(); notIt.hasNext(); ) {
+                        context.getDeclarations().remove( notIt.next() );
                     }
 
-                    this.innerDeclarations = null;
+                    context.setInnerDeclarations( null );
                 } else if ( object.getClass() == ExistsDescr.class ) {
                     // We cannot have declarations created inside exists visible outside it, 
                     // so track declarations in a way they can be removed
-                    this.innerDeclarations = new HashMap();
+                    context.setInnerDeclarations( new HashMap() );
                     final GroupElement exists = GroupElementFactory.newExistsInstance();
-                    build( this.rule,
+                    build( this.context.getRule(),
                            (ConditionalElementDescr) object,
                            exists,
                            true, // when EXIST is used, offset MUST be decremented
                            true ); // when EXIST is used, offset MUST be decremented for first column
                     // remove declarations bound inside not node
-                    for ( final Iterator notIt = this.innerDeclarations.keySet().iterator(); notIt.hasNext(); ) {
-                        this.declarations.remove( notIt.next() );
+                    for ( final Iterator notIt = context.getInnerDeclarations().keySet().iterator(); notIt.hasNext(); ) {
+                        context.getDeclarations().remove( notIt.next() );
                     }
 
-                    this.innerDeclarations = null;
-                    this.rule.addPattern( exists );
-                } else if ( object.getClass() == EvalDescr.class ) {
-                    final EvalCondition eval = build( (EvalDescr) object );
-                    if ( eval != null ) {
-                        this.rule.addPattern( eval );
+                    context.setInnerDeclarations( null );
+                    this.context.getRule().addPattern( exists );
+                } else {
+                    ConditionalElementBuilder builder = (ConditionalElementBuilder) this.builders.get( object.getClass() );
+                    ConditionalElement ce = builder.build( this.context,
+                                                           this.utils,
+                                                           this.columnBuilder,
+                                                           (BaseDescr) object );
+                    if ( ce != null ) {
+                        this.context.getRule().addPattern( ce );
                     }
-                } else if ( object.getClass() == FromDescr.class ) {
-                    final From from = build( (FromDescr) object );
-                    if( from != null ) {
-                        this.rule.addPattern( from );
-                    }
-                } else if ( object.getClass() == AccumulateDescr.class ) {
-                    final Accumulate accumulate = build( (AccumulateDescr) object );
-                    if( accumulate != null ) {
-                        this.rule.addPattern( accumulate );
-                    }
-                } else if ( object.getClass() == CollectDescr.class ) {
-                    final Collect collect = build( (CollectDescr) object );
-                    if( collect != null ) {
-                        this.rule.addPattern( collect );
-                    }
                 }
             } else if ( object.getClass() == ColumnDescr.class ) {
-                final Column column = build( (ColumnDescr) object );
+                final Column column = this.columnBuilder.build( this.context,
+                                                                this.utils,
+                                                                (ColumnDescr) object );
                 if ( column != null ) {
-                    this.rule.addPattern( column );
+                    this.context.getRule().addPattern( column );
                 }
             }
         }
@@ -340,14 +236,16 @@
         // generate the main rule from the previously generated s.
         if ( !(ruleDescr instanceof QueryDescr) ) {
             // do not build the consequence if we have a query
-            buildConsequence( ruleDescr );
+            this.consequenceBuilder.buildConsequence( this.context,
+                                                      this.utils,
+                                                      ruleDescr );
         }
-        buildRule( ruleDescr );
+        this.classBuilder.buildRule( this.context, this.utils, ruleDescr );
     }
 
     private void build(final Rule rule,
                        final ConditionalElementDescr descr,
-                       final GroupElement ce,
+                       final GroupElement group,
                        final boolean decrementOffset,
                        boolean decrementFirst) {
         for ( final Iterator it = descr.getDescrs().iterator(); it.hasNext(); ) {
@@ -360,7 +258,7 @@
                            and,
                            false, // do not decrement offset
                            false ); // do not decrement first offset
-                    ce.addChild( and );
+                    group.addChild( and );
                 } else if ( object.getClass() == OrDescr.class ) {
                     final GroupElement or = GroupElementFactory.newOrInstance();
                     build( rule,
@@ -368,7 +266,7 @@
                            or,
                            true, // when OR is used, offset MUST be decremented
                            false ); // do not decrement first offset
-                    ce.addChild( or );
+                    group.addChild( or );
                 } else if ( object.getClass() == NotDescr.class ) {
                     final GroupElement not = GroupElementFactory.newNotInstance();
                     build( rule,
@@ -376,7 +274,7 @@
                            not,
                            true, // when NOT is used, offset MUST be decremented
                            true ); // when NOT is used, offset MUST be decremented for first column
-                    ce.addChild( not );
+                    group.addChild( not );
                 } else if ( object.getClass() == ExistsDescr.class ) {
                     final GroupElement exists = GroupElementFactory.newExistsInstance();
                     build( rule,
@@ -384,1216 +282,61 @@
                            exists,
                            true, // when EXIST is used, offset MUST be decremented
                            true ); // when EXIST is used, offset MUST be decremented for first column
-                    ce.addChild( exists );
-                } else if ( object.getClass() == EvalDescr.class ) {
-                    final EvalCondition eval = build( (EvalDescr) object );
-                    if ( eval != null ) {
-                        ce.addChild( eval );
+                    group.addChild( exists );
+                } else {
+                    ConditionalElementBuilder builder = (ConditionalElementBuilder) this.builders.get( object.getClass() );
+                    ConditionalElement ce = builder.build( this.context,
+                                                           this.utils,
+                                                           this.columnBuilder,
+                                                           (BaseDescr) object );
+                    if ( ce != null ) {
+                        this.context.getRule().addPattern( ce );
                     }
-                } else if ( object.getClass() == FromDescr.class ) {
-                    final From from = build( (FromDescr) object );
-                    this.rule.addPattern( from );
-                } else if ( object.getClass() == AccumulateDescr.class ) {
-                    final Accumulate accumulate = build( (AccumulateDescr) object );
-                    this.rule.addPattern( accumulate );
-                } else if ( object.getClass() == CollectDescr.class ) {
-                    final Collect collect = build( (CollectDescr) object );
-                    this.rule.addPattern( collect );
                 }
             } else if ( object.getClass() == ColumnDescr.class ) {
                 if ( decrementOffset && decrementFirst ) {
-                    this.columnOffset--;
+                    this.context.setColumnOffset( this.context.getColumnOffset() - 1 );
                 } else {
                     decrementFirst = true;
                 }
-                final Column column = build( (ColumnDescr) object );
+                final Column column = this.columnBuilder.build( this.context, this.utils, (ColumnDescr) object );
                 if ( column != null ) {
-                    ce.addChild( column );
+                    group.addChild( column );
                 }
             }
         }
     }
 
-    private Column build(final ColumnDescr columnDescr) {
-        if ( columnDescr.getObjectType() == null || columnDescr.getObjectType().equals( "" ) ) {
-            this.errors.add( new RuleError( this.rule,
-                                            columnDescr,
-                                            null,
-                                            "ObjectType not correctly defined" ) );
-            return null;
-        }
-
-        ObjectType objectType = null;
-
-        final FactTemplate factTemplate = this.pkg.getFactTemplate( columnDescr.getObjectType() );
-
-        if ( factTemplate != null ) {
-            objectType = new FactTemplateObjectType( factTemplate );
-        } else {
-            try {
-                Class userProvidedClass = this.typeResolver.resolveType( columnDescr.getObjectType() );
-                String shadowProxyName = ShadowProxyFactory.getProxyClassNameForClass( userProvidedClass );
-                Class shadowClass = null;
-                try {
-                    // if already loaded
-                    shadowClass = this.pkg.getPackageCompilationData().getClassLoader().loadClass( shadowProxyName );                    
-                } catch( ClassNotFoundException cnfe ) {
-                    // otherwise, create and load
-                    byte[] proxyBytes = ShadowProxyFactory.getProxyBytes( userProvidedClass );
-                    if( proxyBytes != null ) {
-                        this.pkg.getPackageCompilationData().write( shadowProxyName, 
-                                                                    proxyBytes );
-                        shadowClass = this.pkg.getPackageCompilationData().getClassLoader().loadClass( shadowProxyName );
-                    }
-                    
-                }
-                objectType = new ClassObjectType( userProvidedClass, shadowClass );
-            } catch ( final ClassNotFoundException e ) {
-                this.errors.add( new RuleError( this.rule,
-                                                columnDescr,
-                                                null,
-                                                "Unable to resolve ObjectType '" + columnDescr.getObjectType() + "'" ) );
-                return null;
-            }
-        }
-
-        Column column;
-        if ( columnDescr.getIdentifier() != null && !columnDescr.getIdentifier().equals( "" ) ) {
-            column = new Column( this.columnCounter.getNext(),
-                                 this.columnOffset,
-                                 objectType,
-                                 columnDescr.getIdentifier() );
-            this.declarations.put( column.getDeclaration().getIdentifier(),
-                                   column.getDeclaration() );
-
-            if ( this.innerDeclarations != null ) {
-                this.innerDeclarations.put( column.getDeclaration().getIdentifier(),
-                                            column.getDeclaration() );
-            }
-        } else {
-            column = new Column( this.columnCounter.getNext(),
-                                 this.columnOffset,
-                                 objectType,
-                                 null );
-        }
-
-        for ( final Iterator it = columnDescr.getDescrs().iterator(); it.hasNext(); ) {
-            final Object object = it.next();
-            if ( object instanceof FieldBindingDescr ) {
-                build( column,
-                       (FieldBindingDescr) object );
-            } else if ( object instanceof FieldConstraintDescr ) {
-                build( column,
-                       (FieldConstraintDescr) object );
-            } else if ( object instanceof PredicateDescr ) {
-                build( column,
-                       (PredicateDescr) object );
-            }
-        }
-        return column;
-    }
-
-    private void build(final Column column,
-                       final FieldConstraintDescr fieldConstraintDescr) {
-
-        final FieldExtractor extractor = getFieldExtractor( fieldConstraintDescr,
-                                                            column.getObjectType(),
-                                                            fieldConstraintDescr.getFieldName() );
-        if ( extractor == null ) {
-            // @todo log error
-            return;
-        }
-
-        if ( fieldConstraintDescr.getRestrictions().size() == 1 ) {
-            final Object object = fieldConstraintDescr.getRestrictions().get( 0 );
-
-            final Restriction restriction = buildRestriction( column, 
-                                                              extractor,
-                                                              fieldConstraintDescr,
-                                                              (RestrictionDescr) object );
-            if ( restriction == null ) {
-                // @todo log errors
-                return;
-            }
-
-            if ( object instanceof LiteralRestrictionDescr ) {
-                column.addConstraint( new LiteralConstraint( extractor,
-                                                             (LiteralRestriction) restriction ) );
-            } else if ( object instanceof VariableRestrictionDescr ) {
-                column.addConstraint( new VariableConstraint( extractor,
-                                                              (VariableRestriction) restriction ) );
-            } else if ( object instanceof ReturnValueRestrictionDescr ) {
-                column.addConstraint( new ReturnValueConstraint( extractor,
-                                                                 (ReturnValueRestriction) restriction ) );
-            }
-
-            return;
-        }
-
-        final List orList = new ArrayList();
-        List andList = null;
-
-        RestrictionDescr currentRestriction = null;
-        RestrictionDescr previousRestriction = null;
-
-        List currentList = null;
-        List previousList = null;
-
-        for ( final Iterator it = fieldConstraintDescr.getRestrictions().iterator(); it.hasNext(); ) {
-            final Object object = it.next();
-
-            // Process an and/or connective 
-            if ( object instanceof RestrictionConnectiveDescr ) {
-
-                // is the connective an 'and'?
-                if ( ((RestrictionConnectiveDescr) object).getConnective() == RestrictionConnectiveDescr.AND ) {
-                    // if andList is null, then we know its the first
-                    if ( andList == null ) {
-                        andList = new ArrayList();
-                    }
-                    previousList = currentList;
-                    currentList = andList;
+    private void setAttributes(final Rule rule,
+                               final List attributes) {
+        for ( final Iterator it = attributes.iterator(); it.hasNext(); ) {
+            final AttributeDescr attributeDescr = (AttributeDescr) it.next();
+            final String name = attributeDescr.getName();
+            if ( name.equals( "salience" ) ) {
+                rule.setSalience( Integer.parseInt( attributeDescr.getValue() ) );
+            } else if ( name.equals( "no-loop" ) ) {
+                if ( attributeDescr.getValue() == null ) {
+                    rule.setNoLoop( true );
                 } else {
-                    previousList = currentList;
-                    currentList = orList;
+                    rule.setNoLoop( Boolean.valueOf( attributeDescr.getValue() ).booleanValue() );
                 }
-            } else {
-                Restriction restriction = null;
-                if ( currentList != null ) {
-                    // Are we are at the first operator? if so treat differently
-                    if ( previousList == null ) {
-                        restriction = buildRestriction( column,
-                                                        extractor,
-                                                        fieldConstraintDescr,
-                                                        previousRestriction );
-                        if ( currentList == andList ) {
-                            andList.add( restriction );
-                        } else {
-                            orList.add( restriction );
-                        }
-                    } else {
-                        restriction = buildRestriction( column,
-                                                        extractor,
-                                                        fieldConstraintDescr,
-                                                        previousRestriction );
-
-                        if ( previousList == andList && currentList == orList ) {
-                            andList.add( restriction );
-                            if ( andList.size() == 1 ) {
-                                // Can't have an 'and' connective with one child, so add directly to the or list
-                                orList.add( andList.get( 0 ) );
-                            } else {
-                                final Restriction restrictions = new AndCompositeRestriction( (Restriction[]) andList.toArray( new Restriction[andList.size()] ) );
-                                orList.add( restrictions );
-                            }
-                            andList = null;
-                        } else if ( previousList == andList && currentList == andList ) {
-                            andList.add( restriction );
-                        } else if ( previousList == orList && currentList == andList ) {
-                            andList.add( restriction );
-                        } else if ( previousList == orList && currentList == orList ) {
-                            orList.add( restriction );
-                        }
-                    }
-                }
-            }
-            previousRestriction = currentRestriction;
-            currentRestriction = (RestrictionDescr) object;
-        }
-
-        final Restriction restriction = buildRestriction( column, 
-                                                          extractor,
-                                                          fieldConstraintDescr,
-                                                          currentRestriction );
-        currentList.add( restriction );
-
-        Restriction restrictions = null;
-        if ( currentList == andList && !orList.isEmpty() ) {
-            // Check if it finished with an and, and process it
-            if ( andList != null ) {
-                if ( andList.size() == 1 ) {
-                    // Can't have an 'and' connective with one child, so add directly to the or list
-                    orList.add( andList.get( 0 ) );
+            } else if ( name.equals( "auto-focus" ) ) {
+                if ( attributeDescr.getValue() == null ) {
+                    rule.setAutoFocus( true );
                 } else {
-                    orList.add( new AndCompositeRestriction( (Restriction[]) andList.toArray( new Restriction[andList.size()] ) ) );
+                    rule.setAutoFocus( Boolean.valueOf( attributeDescr.getValue() ).booleanValue() );
                 }
-                andList = null;
+            } else if ( name.equals( "agenda-group" ) ) {
+                rule.setAgendaGroup( attributeDescr.getValue() );
+            } else if ( name.equals( "activation-group" ) ) {
+                rule.setXorGroup( attributeDescr.getValue() );
+            } else if ( name.equals( "duration" ) ) {
+                rule.setDuration( Long.parseLong( attributeDescr.getValue() ) );
+                rule.setAgendaGroup( "" );
+            } else if ( name.equals( "language" ) ) {
+                //@todo: we don't currently  support multiple languages
             }
         }
-
-        if ( !orList.isEmpty() ) {
-            restrictions = new OrCompositeRestriction( (Restriction[]) orList.toArray( new Restriction[orList.size()] ) );
-        } else if ( andList != null && !andList.isEmpty() ) {
-            restrictions = new AndCompositeRestriction( (Restriction[]) andList.toArray( new Restriction[andList.size()] ) );
-        } else {
-            // @todo throw error
-        }
-
-        column.addConstraint( new MultiRestrictionFieldConstraint( extractor,
-                                                                   restrictions ) );
     }
 
-    private Restriction buildRestriction(final Column column,
-                                         final FieldExtractor extractor,
-                                         final FieldConstraintDescr fieldConstraintDescr,
-                                         final RestrictionDescr restrictionDescr) {
-        Restriction restriction = null;
-        if ( restrictionDescr instanceof LiteralRestrictionDescr ) {
-            restriction = buildRestriction( extractor,
-                                            fieldConstraintDescr,
-                                            (LiteralRestrictionDescr) restrictionDescr );
-        } else if ( restrictionDescr instanceof VariableRestrictionDescr ) {
-            restriction = buildRestriction( extractor,
-                                            fieldConstraintDescr,
-                                            (VariableRestrictionDescr) restrictionDescr );
-        } else if ( restrictionDescr instanceof ReturnValueRestrictionDescr ) {
-            restriction = buildRestriction( column,
-                                            extractor,
-                                            fieldConstraintDescr,
-                                            (ReturnValueRestrictionDescr) restrictionDescr );
-
-        }
-
-        return restriction;
-    }
-
-    private void build(final Column column,
-                       final FieldBindingDescr fieldBindingDescr) {
-        Declaration declaration = (Declaration) this.declarations.get( fieldBindingDescr.getIdentifier() );
-        if ( declaration != null ) {
-            // This declaration already  exists, so throw an Exception
-            this.errors.add( new RuleError( this.rule,
-                                            fieldBindingDescr,
-                                            null,
-                                            "Duplicate declaration for variable '" + fieldBindingDescr.getIdentifier() + "' in the rule '" + this.rule.getName() + "'" ) );
-            return;
-        }
-
-        final FieldExtractor extractor = getFieldExtractor( fieldBindingDescr,
-                                                            column.getObjectType(),
-                                                            fieldBindingDescr.getFieldName() );
-        if ( extractor == null ) {
-            return;
-        }
-
-        declaration = column.addDeclaration( fieldBindingDescr.getIdentifier(),
-                                             extractor );
-
-        this.declarations.put( declaration.getIdentifier(),
-                               declaration );
-
-        if ( this.innerDeclarations != null ) {
-            this.innerDeclarations.put( declaration.getIdentifier(),
-                                        declaration );
-        }
-    }
-
-    private VariableRestriction buildRestriction(final FieldExtractor extractor,
-                                                 final FieldConstraintDescr fieldConstraintDescr,
-                                                 final VariableRestrictionDescr variableRestrictionDescr) {
-        if ( variableRestrictionDescr.getIdentifier() == null || variableRestrictionDescr.getIdentifier().equals( "" ) ) {
-            this.errors.add( new RuleError( this.rule,
-                                            variableRestrictionDescr,
-                                            null,
-                                            "Identifier not defined for binding field '" + fieldConstraintDescr.getFieldName() + "'" ) );
-            return null;
-        }
-
-        final Declaration declaration = (Declaration) this.declarations.get( variableRestrictionDescr.getIdentifier() );
-
-        if ( declaration == null ) {
-            this.errors.add( new RuleError( this.rule,
-                                            variableRestrictionDescr,
-                                            null,
-                                            "Unable to return Declaration for identifier '" + variableRestrictionDescr.getIdentifier() + "'" ) );
-            return null;
-        }
-
-        final Evaluator evaluator = getEvaluator( variableRestrictionDescr,
-                                                  extractor.getValueType(),
-                                                  variableRestrictionDescr.getEvaluator() );
-        if ( evaluator == null ) {
-            return null;
-        }
-
-        return new VariableRestriction( extractor, 
-                                        declaration,
-                                        evaluator );
-    }
-
-    private LiteralRestriction buildRestriction(final FieldExtractor extractor,
-                                                final FieldConstraintDescr fieldConstraintDescr,
-                                                final LiteralRestrictionDescr literalRestrictionDescr) {
-        FieldValue field = null;
-        if ( literalRestrictionDescr.isStaticFieldValue() ) {
-            final int lastDot = literalRestrictionDescr.getText().lastIndexOf( '.' );
-            final String className = literalRestrictionDescr.getText().substring( 0,
-                                                                                  lastDot );
-            final String fieldName = literalRestrictionDescr.getText().substring( lastDot + 1 );
-            try {
-                final Class staticClass = this.typeResolver.resolveType( className );
-                field = FieldFactory.getFieldValue( staticClass.getField( fieldName ).get( null ).toString(), extractor.getValueType() );
-            } catch ( final ClassNotFoundException e ) {
-                this.errors.add( new RuleError( this.rule,
-                                                literalRestrictionDescr,
-                                                e,
-                                                e.getMessage() ) );
-            } catch ( final Exception e ) {
-                this.errors.add( new RuleError( this.rule,
-                                                literalRestrictionDescr,
-                                                e,
-                                                "Unable to create a Field value of type  '" + extractor.getValueType() + "' and value '" + literalRestrictionDescr.getText() + "'" ) );
-            }
-
-        } else {
-            try {
-                field = FieldFactory.getFieldValue( literalRestrictionDescr.getText(),
-                                                    extractor.getValueType() );
-            } catch ( final Exception e ) {
-                this.errors.add( new RuleError( this.rule,
-                                                literalRestrictionDescr,
-                                                e,
-                                                "Unable to create a Field value of type  '" + extractor.getValueType() + "' and value '" + literalRestrictionDescr.getText() + "'" ) );
-            }
-        }
-
-        final Evaluator evaluator = getEvaluator( literalRestrictionDescr,
-                                                  extractor.getValueType(),
-                                                  literalRestrictionDescr.getEvaluator() );
-        if ( evaluator == null ) {
-            return null;
-        }
-
-        return new LiteralRestriction( field,
-                                       evaluator,
-                                       extractor );
-    }
-
-    private ReturnValueRestriction buildRestriction(final Column column,
-                                                    final FieldExtractor extractor,
-                                                    final FieldConstraintDescr fieldConstraintDescr,
-                                                    final ReturnValueRestrictionDescr returnValueRestrictionDescr) {
-        final String className = "returnValue" + this.counter++;
-        returnValueRestrictionDescr.setClassMethodName( className );
-
-        final List[] usedIdentifiers = getUsedIdentifiers( returnValueRestrictionDescr,
-                                                           returnValueRestrictionDescr.getText() );
-
-        final List tupleDeclarations = new ArrayList();
-        final List factDeclarations = new ArrayList();
-        for ( int i = 0, size = usedIdentifiers[0].size(); i < size; i++ ) {
-            Declaration declaration = (Declaration) this.declarations.get( (String) usedIdentifiers[0].get( i ) );
-            if( declaration.getColumn() == column ) {
-                factDeclarations.add( declaration );
-            } else {
-                tupleDeclarations.add( declaration );
-            }
-        }
-
-        final Evaluator evaluator = getEvaluator( returnValueRestrictionDescr,
-                                                  extractor.getValueType(),
-                                                  returnValueRestrictionDescr.getEvaluator() );
-        if ( evaluator == null ) {
-            return null;
-        }
-
-        Declaration[] previousDeclarations = (Declaration[]) tupleDeclarations.toArray( new Declaration[tupleDeclarations.size()] );
-        Declaration[] localDeclarations = (Declaration[]) factDeclarations.toArray( new Declaration[factDeclarations.size()] );
-        final ReturnValueRestriction returnValueRestriction = new ReturnValueRestriction( extractor,
-                                                                                          previousDeclarations,
-                                                                                          localDeclarations,
-                                                                                          evaluator );
-
-        StringTemplate st = RuleBuilder.ruleGroup.getInstanceOf( "returnValueMethod" );
-
-        setStringTemplateAttributes( st,
-                                     previousDeclarations,
-                                     (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ),
-                                     returnValueRestrictionDescr.getText() );
-
-        final String[] localDeclarationTypes = new String[localDeclarations.length];
-        for ( int i = 0, size = localDeclarations.length; i < size; i++ ) {
-            localDeclarationTypes[i] = localDeclarations[i].getExtractor().getExtractToClass().getName().replace( '$',
-                                                                                                        '.' );
-        }
-
-        st.setAttribute( "localDeclarations",
-                         localDeclarations );
-        st.setAttribute( "localDeclarationTypes",
-                         localDeclarationTypes );
-
-        st.setAttribute( "methodName",
-                         className );
-
-        final String returnValueText = this.functionFixer.fix( returnValueRestrictionDescr.getText(), variables );
-        st.setAttribute( "text",
-                         returnValueText );
-
-        this.methods.add( st.toString() );
-
-        st = RuleBuilder.invokerGroup.getInstanceOf( "returnValueInvoker" );
-
-        st.setAttribute( "package",
-                         this.pkg.getName() );
-        st.setAttribute( "ruleClassName",
-                         ucFirst( this.ruleDescr.getClassName() ) );
-        st.setAttribute( "invokerClassName",
-                         this.ruleDescr.getClassName() + ucFirst( className ) + "Invoker" );
-        st.setAttribute( "methodName",
-                         className );
-
-        setStringTemplateAttributes( st,
-                                     previousDeclarations,
-                                     (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ),
-                                     returnValueRestrictionDescr.getText() );
-
-        st.setAttribute( "localDeclarations",
-                         localDeclarations );
-        st.setAttribute( "localDeclarationTypes",
-                         localDeclarationTypes );
-
-        st.setAttribute( "hashCode",
-                         returnValueText.hashCode() );
-
-        final String invokerClassName = this.pkg.getName() + "." + this.ruleDescr.getClassName() + ucFirst( className ) + "Invoker";
-        this.invokers.put( invokerClassName,
-                           st.toString() );
-        this.invokerLookups.put( invokerClassName,
-                                 returnValueRestriction );
-        this.descrLookups.put( invokerClassName,
-                               returnValueRestrictionDescr );
-
-        return returnValueRestriction;
-    }
-
-    private void build(final Column column,
-                       final PredicateDescr predicateDescr) {
-        // generate 
-        // generate Invoker
-        final String className = "predicate" + this.counter++;
-        predicateDescr.setClassMethodName( className );
-
-        final FieldExtractor extractor = getFieldExtractor( predicateDescr,
-                                                            column.getObjectType(),
-                                                            predicateDescr.getFieldName() );
-        if ( extractor == null ) {
-            return;
-        }
-
-        final Declaration declaration = column.addDeclaration( predicateDescr.getDeclaration(),
-                                                               extractor );
-
-        this.declarations.put( declaration.getIdentifier(),
-                               declaration );
-
-        if ( this.innerDeclarations != null ) {
-            this.innerDeclarations.put( declaration.getIdentifier(),
-                                        declaration );
-        }
-
-        final List[] usedIdentifiers = getUsedIdentifiers( predicateDescr,
-                                                           predicateDescr.getText() );
-        // Don't include the focus declaration, that hasn't been merged into the tuple yet.
-        usedIdentifiers[0].remove( predicateDescr.getDeclaration() );
-
-        final List tupleDeclarations = new ArrayList();
-        final List factDeclarations = new ArrayList();
-        for ( int i = 0, size = usedIdentifiers[0].size(); i < size; i++ ) {
-            Declaration decl = (Declaration) this.declarations.get( (String) usedIdentifiers[0].get( i ) );
-            if( decl.getColumn() == column ) {
-                factDeclarations.add( decl );
-            } else {
-                tupleDeclarations.add( decl );
-            }
-        }
-        Declaration[] previousDeclarations = (Declaration[]) tupleDeclarations.toArray( new Declaration[tupleDeclarations.size()] );
-        Declaration[] localDeclarations = (Declaration[]) factDeclarations.toArray( new Declaration[factDeclarations.size()] );
-
-        final PredicateConstraint predicateConstraint = new PredicateConstraint( declaration,
-                                                                                 previousDeclarations,
-                                                                                 localDeclarations );
-        column.addConstraint( predicateConstraint );
-
-        StringTemplate st = RuleBuilder.ruleGroup.getInstanceOf( "predicateMethod" );
-
-        st.setAttribute( "declaration",
-                         declaration );
-
-        st.setAttribute( "declarationType",
-                         declaration.getExtractor().getExtractToClass().getName().replace( '$',
-                                                                                           '.' ) );
-
-        setStringTemplateAttributes( st,
-                                     previousDeclarations,
-                                     (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ),
-                                     predicateDescr.getText() );
-
-        final String[] localDeclarationTypes = new String[localDeclarations.length];
-        for ( int i = 0, size = localDeclarations.length; i < size; i++ ) {
-            localDeclarationTypes[i] = localDeclarations[i].getExtractor().getExtractToClass().getName().replace( '$',
-                                                                                                        '.' );
-        }
-
-        st.setAttribute( "localDeclarations",
-                         localDeclarations );
-        st.setAttribute( "localDeclarationTypes",
-                         localDeclarationTypes );
-
-        st.setAttribute( "methodName",
-                         className );
-
-        final String predicateText = this.functionFixer.fix( predicateDescr.getText(), variables );
-        st.setAttribute( "text",
-                         predicateText );
-
-        this.methods.add( st.toString() );
-
-        st = RuleBuilder.invokerGroup.getInstanceOf( "predicateInvoker" );
-
-        st.setAttribute( "package",
-                         this.pkg.getName() );
-        st.setAttribute( "ruleClassName",
-                         ucFirst( this.ruleDescr.getClassName() ) );
-        st.setAttribute( "invokerClassName",
-                         this.ruleDescr.getClassName() + ucFirst( className ) + "Invoker" );
-        st.setAttribute( "methodName",
-                         className );
-
-        st.setAttribute( "declaration",
-                         declaration );
-        st.setAttribute( "declarationType",
-                         declaration.getExtractor().getExtractToClass().getName().replace( '$',
-                                                                                           '.' ) );
-
-        setStringTemplateAttributes( st,
-                                     previousDeclarations,
-                                     (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ),
-                                     predicateDescr.getText() );
-
-        st.setAttribute( "localDeclarations",
-                         localDeclarations );
-        st.setAttribute( "localDeclarationTypes",
-                         localDeclarationTypes );
-
-        st.setAttribute( "hashCode",
-                         predicateText.hashCode() );
-
-        final String invokerClassName = this.pkg.getName() + "." + this.ruleDescr.getClassName() + ucFirst( className ) + "Invoker";
-        this.invokers.put( invokerClassName,
-                           st.toString() );
-        this.invokerLookups.put( invokerClassName,
-                                 predicateConstraint );
-        this.descrLookups.put( invokerClassName,
-                               predicateDescr );
-    }
-
-    private From build(final FromDescr fromDescr) {
-      final Column column = build( fromDescr.getReturnedColumn() );
-      
-      if( column == null ) {
-          return null;
-      }
-      
-      AccessorDescr accessor = (AccessorDescr) fromDescr.getDataSource();      
-      DataProvider dataProvider = null;      
-      try {                    
-          JFDIParser parser = createParser(  accessor.toString() );
-          DroolsJFDIFactory factory = new DroolsJFDIFactory( this.typeResolver );
-          factory.setDeclarationMap( this.declarations );
-          factory.setGlobalsMap( this.pkg.getGlobals() );          
-          parser.setValueHandlerFactory( factory );
-          
-          dataProvider = new JFDIDataProvider(parser.expr(), factory);
-      } catch ( final Exception e ) {
-          this.errors.add( new RuleError( this.rule,
-                                          fromDescr,
-                                          null,
-                                          "Unable to build expression for 'from' node '" + accessor.toString() + "'" ) );
-          return null;
-      }
-      
-      
-      return new From( column,
-                       dataProvider );		        
-    }
-    
-//    private From build(final FromDescr fromDescr) {
-//    	return null;
-    	// @todo: waiting for JFDI so we can impl this properly
-//        final Column column = build( fromDescr.getReturnedColumn() );
-//
-//        final DeclarativeInvokerDescr invokerDescr = fromDescr.getDataSource();
-//
-//        DataProvider dataProvider = null;
-//
-//        if ( invokerDescr.getClass() == MethodAccessDescr.class ) {
-//            final MethodAccessDescr methodAccessor = (MethodAccessDescr) invokerDescr;
-//
-//            ValueHandler instanceValueHandler = null;
-//            final String variableName = methodAccessor.getVariableName();
-//            if ( this.declarations.containsKey( variableName ) ) {
-//                instanceValueHandler = new DeclarationVariable( (Declaration) this.declarations.get( variableName ) );
-//            } else if ( this.pkg.getGlobals().containsKey( variableName ) ) {
-//                instanceValueHandler = new GlobalVariable( variableName,
-//                                                           (Class) this.pkg.getGlobals().get( variableName ) );
-//            } else {
-//                throw new IllegalArgumentException( "The variable name [" + variableName + "] was not a global or declaration." );
-//            }
-//
-//            final List arguments = ((MethodAccessDescr) invokerDescr).getArguments();
-//            final List valueHandlers = new ArrayList();
-//
-//            for ( final Iterator iter = arguments.iterator(); iter.hasNext(); ) {
-//                valueHandlers.add( buildValueHandler( (ArgumentValueDescr) iter.next() ) );
-//            }
-//
-//            final MethodInvoker invoker = new MethodInvoker( methodAccessor.getMethodName(),
-//                                                             instanceValueHandler,
-//                                                             (ValueHandler[]) valueHandlers.toArray( new ValueHandler[valueHandlers.size()] ) );
-//            dataProvider = new MethodDataProvider( invoker );
-//        } else if ( invokerDescr.getClass() == FieldAccessDescr.class ) {
-//            final FieldAccessDescr fieldAccessor = (FieldAccessDescr) invokerDescr;
-//
-//            ValueHandler instanceValueHandler = null;
-//            final String variableName = fieldAccessor.getVariableName();
-//            if ( this.declarations.containsKey( variableName ) ) {
-//                instanceValueHandler = new DeclarationVariable( (Declaration) this.declarations.get( variableName ) );
-//            } else if ( this.pkg.getGlobals().containsKey( variableName ) ) {
-//                instanceValueHandler = new GlobalVariable( variableName,
-//                                                           (Class) this.pkg.getGlobals().get( variableName ) );
-//            } else {
-//                throw new IllegalArgumentException( "The variable name [" + variableName + "] was not a global or declaration." );
-//            }
-//            ArgumentValueDescr arg = ((FieldAccessDescr) invokerDescr).getArgument();
-//            ValueHandler valueHandler = null;
-//            if ( arg != null ) {
-//                valueHandler = buildValueHandler( arg );
-//            }
-//
-//            final FieldGetter getter = new FieldGetter( fieldAccessor.getFieldName(),
-//                                                        instanceValueHandler,
-//                                                        valueHandler );
-//            dataProvider = new MethodDataProvider( getter );
-//        }
-//
-//        return new From( column,
-//                         dataProvider );
-
-//    }
-
-//    private ValueHandler buildValueHandler(final ArgumentValueDescr descr) {
-//        ValueHandler valueHandler = null;
-//        if ( descr.getType() == ArgumentValueDescr.VARIABLE ) {
-//            if ( this.declarations.containsKey( descr.getValue() ) ) {
-//                valueHandler = new DeclarationVariable( (Declaration) this.declarations.get( descr.getValue() ) );
-//            } else if ( this.pkg.getGlobals().containsKey( descr.getValue() ) ) {
-//                valueHandler = new GlobalVariable( (String) descr.getValue(),
-//                                                   (Class) this.pkg.getGlobals().get( descr.getValue() ) );
-//            } else {
-//                throw new IllegalArgumentException( "Uknown variable: " + descr.getValue() );
-//            }
-//        } else if ( descr.getType() == ArgumentValueDescr.MAP ) {
-//            final ArgumentValueDescr.KeyValuePairDescr[] pairs = (ArgumentValueDescr.KeyValuePairDescr[]) descr.getValue();
-//            final List list = new ArrayList( pairs.length );
-//            for ( int i = 0, length = pairs.length; i < length; i++ ) {
-//                list.add( new MapValue.KeyValuePair( buildValueHandler( pairs[i].getKey() ),
-//                                                     buildValueHandler( pairs[i].getValue() ) ) );
-//            }
-//
-//            valueHandler = new MapValue( (MapValue.KeyValuePair[]) list.toArray( new MapValue.KeyValuePair[pairs.length] ) );
-//        } else if ( descr.getType() == ArgumentValueDescr.LIST ) {
-//            final List args = (List) descr.getValue();
-//            final List handlers = new ArrayList( args.size() );
-//            for ( final Iterator iter = args.iterator(); iter.hasNext(); ) {
-//                final ArgumentValueDescr arg = (ArgumentValueDescr) iter.next();
-//                handlers.add( buildValueHandler( arg ) );
-//            }
-//            valueHandler = new ListValue( handlers );
-//        } else if ( descr.getType() == ArgumentValueDescr.BOOLEAN ) {
-//            // handling a literal
-//            valueHandler = new LiteralValue( new Boolean ( (String) descr.getValue() ) );
-//        } else if ( descr.getType() == ArgumentValueDescr.INTEGRAL ) {
-//            String text = (String) descr.getValue();
-//            char c = text.charAt( text.length() - 1 );
-//            if ( Character.getType( c ) != Character.DECIMAL_DIGIT_NUMBER ) {
-//                switch ( c ) {
-//                    case 'l' :
-//                    case 'L' :
-//                        valueHandler = new LiteralValue( new Long( (String) descr.getValue() ) );                        
-//                        break;
-//                    case 'f' :
-//                    case 'F' :
-//                        valueHandler = new LiteralValue( new Float( (String) descr.getValue() ) );                          
-//                        break;
-//                    case 'd' :
-//                    case 'D' :
-//                        valueHandler = new LiteralValue( new Double( (String) descr.getValue() ) );                        
-//                        break;
-//                    default :
-//                        throw new IllegalArgumentException( "invalid type identifier '" + c + "' used with number [" + text + "]" );
-//                }
-//            } else {
-//                valueHandler = new LiteralValue( new Integer( (String) descr.getValue() ) );                
-//            }
-//            
-//        } else if ( descr.getType() == ArgumentValueDescr.DECIMAL ) {
-//            String text = (String) descr.getValue();
-//            char c = text.charAt( text.length() - 1 );
-//            if ( Character.getType( c ) != Character.DECIMAL_DIGIT_NUMBER ) {
-//                switch ( c ) {
-//                    case 'l' :
-//                    case 'L' :
-//                        throw new IllegalArgumentException( "invalid type identifier '" + c + "' used with number [" + text + "]" );                      
-//                    case 'f' :
-//                    case 'F' :
-//                        valueHandler = new LiteralValue( new Float( (String) descr.getValue() ) );                          
-//                        break;
-//                    case 'd' :
-//                    case 'D' :
-//                        valueHandler = new LiteralValue( new Double( (String) descr.getValue() ) );                        
-//                        break;
-//                    default :
-//                        throw new IllegalArgumentException( "invalid type identifier '" + c + "' used with number [" + text + "]" );
-//                }
-//            } else {
-//                valueHandler = new LiteralValue( new Float( (String) descr.getValue() ) );                
-//            }
-//        } else if ( descr.getType() == ArgumentValueDescr.STRING ) {
-//            // handling a literal
-//            valueHandler = new LiteralValue( (String) descr.getValue() );
-//        } else {
-//            // This should never happen
-//            throw new IllegalArgumentException( "Unable to determine type for argument [" + descr.getType() + "]" );
-//        }
-//        return valueHandler;
-//    }
-
-	protected JFDIParser createParser(String text) throws IOException {
-		JFDIParser parser = new JFDIParser( createTokenStream( text ) );
-        DroolsJFDIFactory factory = new DroolsJFDIFactory( this.typeResolver );
-        parser.setValueHandlerFactory( factory );
-		return parser;
-	}
-	
-	private TokenStream createTokenStream(String text) throws IOException {
-		return new CommonTokenStream( createLexer( text ) );
-	}
-	
-	private JFDILexer createLexer(String text) throws IOException {
-		JFDILexer lexer = new JFDILexer(  new ANTLRStringStream( text ) );
-		return lexer;
-	}
-	
-	private Reader createReader(String text) {
-		InputStream in = getClass().getResourceAsStream( text );
-		return new InputStreamReader( in );
-	}    
-    
-    private EvalCondition build(final EvalDescr evalDescr) {
-
-        final String className = "eval" + this.counter++;
-        evalDescr.setClassMethodName( className );
-
-        final List[] usedIdentifiers = getUsedIdentifiers( evalDescr,
-                                                           evalDescr.getText() );
-
-        final Declaration[] declarations = new Declaration[usedIdentifiers[0].size()];
-        for ( int i = 0, size = usedIdentifiers[0].size(); i < size; i++ ) {
-            declarations[i] = (Declaration) this.declarations.get( (String) usedIdentifiers[0].get( i ) );
-        }
-
-        final EvalCondition eval = new EvalCondition( declarations );
-
-        StringTemplate st = RuleBuilder.ruleGroup.getInstanceOf( "evalMethod" );
-
-        setStringTemplateAttributes( st,
-                                     declarations,
-                                     (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ),
-                                     evalDescr.getText() );
-
-        st.setAttribute( "methodName",
-                         className );
-
-        final String evalText = this.functionFixer.fix( evalDescr.getText(), variables );
-        st.setAttribute( "text",
-                         evalText );
-
-        this.methods.add( st.toString() );
-
-        st = RuleBuilder.invokerGroup.getInstanceOf( "evalInvoker" );
-
-        st.setAttribute( "package",
-                         this.pkg.getName() );
-        st.setAttribute( "ruleClassName",
-                         ucFirst( this.ruleDescr.getClassName() ) );
-        st.setAttribute( "invokerClassName",
-                         this.ruleDescr.getClassName() + ucFirst( className ) + "Invoker" );
-        st.setAttribute( "methodName",
-                         className );
-
-        setStringTemplateAttributes( st,
-                                     declarations,
-                                     (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ),
-                                     evalDescr.getText() );
-
-        st.setAttribute( "hashCode",
-                         evalText.hashCode() );
-
-        final String invokerClassName = this.pkg.getName() + "." + this.ruleDescr.getClassName() + ucFirst( className ) + "Invoker";
-        this.invokers.put( invokerClassName,
-                           st.toString() );
-        this.invokerLookups.put( invokerClassName,
-                                 eval );
-        this.descrLookups.put( invokerClassName,
-                               evalDescr );
-        return eval;
-    }
-
-    private Accumulate build(final AccumulateDescr accumDescr) {
-        this.innerDeclarations = new HashMap();
-
-        Column sourceColumn = build( accumDescr.getSourceColumn() );
-        
-        if( sourceColumn == null ) {
-            return null;
-        }
-        // remove declarations bound inside source column
-        this.declarations.keySet().removeAll( this.innerDeclarations.keySet() );
-        Map sourceDeclarations = this.innerDeclarations;
-        this.innerDeclarations = null;
-
-        // decrementing offset as accumulate fills only one column
-        this.columnOffset--;
-        Column resultColumn = build( accumDescr.getResultColumn() );
-
-        final String className = "accumulate" + this.counter++;
-        accumDescr.setClassMethodName( className );
-
-        final List[] usedIdentifiers1 = getUsedIdentifiers( accumDescr,
-                                                            accumDescr.getInitCode() );
-        final List[] usedIdentifiers2 = getUsedIdentifiers( accumDescr,
-                                                            accumDescr.getActionCode() );
-        final List[] usedIdentifiers3 = getUsedIdentifiers( accumDescr,
-                                                            accumDescr.getResultCode() );
-
-        final List requiredDeclarations = new ArrayList( usedIdentifiers1[0] );
-        requiredDeclarations.addAll( usedIdentifiers2[0] );
-        requiredDeclarations.addAll( usedIdentifiers3[0] );
-
-        final List requiredGlobals = new ArrayList( usedIdentifiers1[1] );
-        requiredGlobals.addAll( usedIdentifiers2[1] );
-        requiredGlobals.addAll( usedIdentifiers3[1] );
-
-        final Declaration[] declarations = new Declaration[requiredDeclarations.size()];
-        for ( int i = 0, size = requiredDeclarations.size(); i < size; i++ ) {
-            declarations[i] = (Declaration) this.declarations.get( (String) requiredDeclarations.get( i ) );
-        }
-        final Declaration[] sourceDeclArr = (Declaration[]) sourceDeclarations.values().toArray( new Declaration[sourceDeclarations.size()] );
-
-        final String[] globals = (String[]) requiredGlobals.toArray( new String[requiredGlobals.size()] );
-
-        StringTemplate st = RuleBuilder.ruleGroup.getInstanceOf( "accumulateMethod" );
-
-        setStringTemplateAttributes( st,
-                                     declarations,
-                                     globals,
-                                     null );
-
-        st.setAttribute( "innerDeclarations",
-                         sourceDeclArr );
-        st.setAttribute( "methodName",
-                         className );
-
-        final String initCode = this.functionFixer.fix( accumDescr.getInitCode() );
-        final String actionCode = this.functionFixer.fix( accumDescr.getActionCode() );
-        final String resultCode = this.functionFixer.fix( accumDescr.getResultCode() );
-        st.setAttribute( "initCode",
-                         initCode );
-        st.setAttribute( "actionCode",
-                         actionCode );
-        st.setAttribute( "resultCode",
-                         resultCode );
-
-        String resultType = null;
-        // TODO: Need to change this... 
-        if ( resultColumn.getObjectType() instanceof ClassObjectType ) {
-            resultType = ((ClassObjectType) resultColumn.getObjectType()).getClassType().getName();
-        } else {
-            resultType = resultColumn.getObjectType().getValueType().getClassType().getName();
-        }
-
-        st.setAttribute( "resultType",
-                         resultType );
-
-        this.methods.add( st.toString() );
-
-        st = RuleBuilder.invokerGroup.getInstanceOf( "accumulateInvoker" );
-
-        st.setAttribute( "package",
-                         this.pkg.getName() );
-        st.setAttribute( "ruleClassName",
-                         ucFirst( this.ruleDescr.getClassName() ) );
-        st.setAttribute( "invokerClassName",
-                         this.ruleDescr.getClassName() + ucFirst( className ) + "Invoker" );
-        st.setAttribute( "methodName",
-                         className );
-
-        setStringTemplateAttributes( st,
-                                     declarations,
-                                     (String[]) requiredGlobals.toArray( new String[requiredGlobals.size()] ),
-                                     null );
-
-        st.setAttribute( "hashCode",
-                         actionCode.hashCode() );
-
-        Accumulate accumulate = new Accumulate( sourceColumn,
-                                                resultColumn,
-                                                declarations,
-                                                sourceDeclArr );
-        final String invokerClassName = this.pkg.getName() + "." + this.ruleDescr.getClassName() + ucFirst( className ) + "Invoker";
-        this.invokers.put( invokerClassName,
-                           st.toString() );
-        this.invokerLookups.put( invokerClassName,
-                                 accumulate );
-        this.descrLookups.put( invokerClassName,
-                               accumDescr );
-        return accumulate;
-    }
-
-    private Collect build(final CollectDescr collectDescr) {
-        this.innerDeclarations = new HashMap();
-        Column sourceColumn = build( collectDescr.getSourceColumn() );
-
-        if( sourceColumn == null ) {
-            return null;
-        }
-      
-        // remove declarations bound inside source column
-        this.declarations.keySet().removeAll( this.innerDeclarations.keySet() );
-        this.innerDeclarations = null;
-
-        // decrementing offset as collect fills only one column
-        this.columnOffset--;
-        Column resultColumn = build( collectDescr.getResultColumn() );
-
-        final String className = "collect" + this.counter++;
-        collectDescr.setClassMethodName( className );
-
-        Collect collect = new Collect( sourceColumn,
-                                       resultColumn );
-        return collect;
-    }
-
-    private void buildConsequence(final RuleDescr ruleDescr) {
-        // generate 
-        // generate Invoker
-        final String className = "consequence";
-
-        StringTemplate st = RuleBuilder.ruleGroup.getInstanceOf( "consequenceMethod" );
-
-        st.setAttribute( "methodName",
-                         className );
-
-        final List[] usedIdentifiers = getUsedCIdentifiers( ruleDescr,
-                                                            ruleDescr.getConsequence() );
-
-        final Declaration[] declarations = new Declaration[usedIdentifiers[0].size()];
-        for ( int i = 0, size = usedIdentifiers[0].size(); i < size; i++ ) {
-            declarations[i] = (Declaration) this.declarations.get( (String) usedIdentifiers[0].get( i ) );
-        }
-
-        setStringTemplateAttributes( st,
-                                     declarations,
-                                     (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ),
-                                     ruleDescr.getConsequence() );
-        st.setAttribute( "text",
-                         this.functionFixer.fix( RuleBuilder.knowledgeHelperFixer.fix( ruleDescr.getConsequence() ), variables ) );
-
-        this.methods.add( st.toString() );
-
-        st = RuleBuilder.invokerGroup.getInstanceOf( "consequenceInvoker" );
-
-        st.setAttribute( "package",
-                         this.pkg.getName() );
-        st.setAttribute( "ruleClassName",
-                         ucFirst( this.ruleDescr.getClassName() ) );
-        st.setAttribute( "invokerClassName",
-                         ruleDescr.getClassName() + ucFirst( className ) + "Invoker" );
-        st.setAttribute( "methodName",
-                         className );
-
-        setStringTemplateAttributes( st,
-                                     declarations,
-                                     (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ),
-                                     ruleDescr.getConsequence() );
-
-        // Must use the rule declarations, so we use the same order as used in the generated invoker
-        final List list = Arrays.asList( this.rule.getDeclarations() );
-
-        final int[] indexes = new int[declarations.length];
-        for ( int i = 0, length = declarations.length; i < length; i++ ) {
-            indexes[i] = list.indexOf( declarations[i] );
-            if ( indexes[i] == -1 ) {
-                // some defensive code, this should never happen
-                throw new RuntimeDroolsException( "Unable to find declaration in list while generating the consequence invoker" );
-            }
-        }
-
-        st.setAttribute( "indexes",
-                         indexes );
-
-        st.setAttribute( "text",
-                         ruleDescr.getConsequence() );
-
-        final String invokerClassName = this.pkg.getName() + "." + ruleDescr.getClassName() + ucFirst( className ) + "Invoker";
-        this.invokers.put( invokerClassName,
-                           st.toString() );
-        this.invokerLookups.put( invokerClassName,
-                                 this.rule );
-        this.descrLookups.put( invokerClassName,
-                               ruleDescr );
-    }
-
-    private void buildRule(final RuleDescr ruleDescr) {
-        // If there is no compiled code, return
-        if ( this.methods.isEmpty() ) {
-            this.ruleClass = null;
-            return;
-        }
-        final String lineSeparator = System.getProperty( "line.separator" );
-
-        final StringBuffer buffer = new StringBuffer();
-        buffer.append( "package " + this.pkg.getName() + ";" + lineSeparator );
-
-        for ( final Iterator it = this.pkg.getImports().iterator(); it.hasNext(); ) {
-            buffer.append( "import " + it.next() + ";" + lineSeparator );
-        }
-
-        buffer.append( "public class " + ucFirst( this.ruleDescr.getClassName() ) + " {" + lineSeparator );
-        buffer.append( "    private static final long serialVersionUID  = 320L;" + lineSeparator );
-
-        for ( int i = 0, size = this.methods.size() - 1; i < size; i++ ) {
-            buffer.append( this.methods.get( i ) + lineSeparator );
-        }
-
-        final String[] lines = buffer.toString().split( lineSeparator );
-
-        this.ruleDescr.setConsequenceOffset( lines.length + 1 );
-
-        buffer.append( this.methods.get( this.methods.size() - 1 ) + lineSeparator );
-        buffer.append( "}" );
-
-        this.ruleClass = buffer.toString();
-    }
-
-    private void setStringTemplateAttributes(final StringTemplate st,
-                                             final Declaration[] declarations,
-                                             final String[] globals,
-                                             final String text) {
-        final String[] declarationTypes = new String[declarations.length];
-        for ( int i = 0, size = declarations.length; i < size; i++ ) {
-            declarationTypes[i] = declarations[i].getExtractor().getExtractToClass().getName().replace( '$',
-                                                                                                        '.' );
-        }
-
-        final List globalTypes = new ArrayList( globals.length );
-        for ( int i = 0, length = globals.length; i < length; i++ ) {
-            globalTypes.add( ((Class) this.pkg.getGlobals().get( globals[i] )).getName().replace( '$',
-                                                                                                  '.' ) );
-        }
-
-        st.setAttribute( "declarations",
-                         declarations );
-        st.setAttribute( "declarationTypes",
-                         declarationTypes );
-
-        st.setAttribute( "globals",
-                         globals );
-        st.setAttribute( "globalTypes",
-                         globalTypes );
-    }
-
-    private String ucFirst(final String name) {
-        return name.toUpperCase().charAt( 0 ) + name.substring( 1 );
-    }
-
-    private FieldExtractor getFieldExtractor(final BaseDescr descr,
-                                             final ObjectType objectType,
-                                             final String fieldName) {
-        FieldExtractor extractor = null;
-
-        if ( objectType.getValueType() == ValueType.FACTTEMPLATE_TYPE ) {
-            //@todo use extractor cache            
-            final FactTemplate factTemplate = ((FactTemplateObjectType) objectType).getFactTemplate();
-            extractor = new FactTemplateFieldExtractor( factTemplate,
-                                                        factTemplate.getFieldTemplateIndex( fieldName ) );
-        } else {
-            try {
-                extractor = this.classFieldExtractorCache.getExtractor( ((ClassObjectType) objectType).getClassType(),
-                                                                        fieldName );
-            } catch ( final RuntimeDroolsException e ) {
-                this.errors.add( new RuleError( this.rule,
-                                                descr,
-                                                e,
-                                                "Unable to create Field Extractor for '" + fieldName + "'" ) );
-            }
-        }
-
-        return extractor;
-    }
-
-    private Evaluator getEvaluator(final BaseDescr descr,
-                                   final ValueType valueType,
-                                   final String evaluatorString) {
-
-        final Evaluator evaluator = valueType.getEvaluator( Operator.determineOperator( evaluatorString ) );
-
-        if ( evaluator == null ) {
-            this.errors.add( new RuleError( this.rule,
-                                            descr,
-                                            null,
-                                            "Unable to determine the Evaluator for  '" + valueType + "' and '" + evaluatorString + "'" ) );
-        }
-
-        return evaluator;
-    }
-
-    private List[] getUsedIdentifiers(final BaseDescr descr,
-                                      final String text) {
-        List[] usedIdentifiers = null;
-        try {
-            usedIdentifiers = this.analyzer.analyzeExpression( text,
-                                                               new Set[]{this.declarations.keySet(), this.pkg.getGlobals().keySet()} );
-        } catch ( final Exception e ) {
-            this.errors.add( new RuleError( this.rule,
-                                            descr,
-                                            null,
-                                            "Unable to determine the used declarations" ) );
-        }
-        return usedIdentifiers;
-    }
-
-    private List[] getUsedCIdentifiers(final BaseDescr descr,
-                                       final String text) {
-        List[] usedIdentifiers = null;
-        try {
-            usedIdentifiers = this.analyzer.analyzeBlock( text,
-                                                          new Set[]{this.declarations.keySet(), this.pkg.getGlobals().keySet()} );
-        } catch ( final Exception e ) {
-            this.errors.add( new RuleError( this.rule,
-                                            descr,
-                                            null,
-                                            "Unable to determine the used declarations" ) );
-        }
-        return usedIdentifiers;
-    }
-
-    static class ColumnCounter {
-        // we start with -1 so that we can ++this.value - otherwise the first element has a lower value than the second in an 'or'
-        private int value = -1;
-
-        public int getNext() {
-            return ++this.value;
-        }
-    }
 }
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/AccumulateBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/AccumulateBuilder.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/AccumulateBuilder.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.antlr.stringtemplate.StringTemplate;
+import org.drools.base.ClassObjectType;
+import org.drools.lang.descr.AccumulateDescr;
+import org.drools.lang.descr.BaseDescr;
+import org.drools.rule.Accumulate;
+import org.drools.rule.Column;
+import org.drools.rule.ConditionalElement;
+import org.drools.rule.Declaration;
+
+/**
+ * @author etirelli
+ *
+ */
+public class AccumulateBuilder
+    implements
+    ConditionalElementBuilder {
+
+    /* (non-Javadoc)
+     * @see org.drools.semantics.java.builder.ConditionalElementBuilder#build(org.drools.semantics.java.builder.BuildContext, org.drools.semantics.java.builder.BuildUtils, org.drools.semantics.java.builder.ColumnBuilder, org.drools.lang.descr.BaseDescr)
+     */
+    public ConditionalElement build(BuildContext context,
+                                    BuildUtils utils,
+                                    ColumnBuilder columnBuilder,
+                                    BaseDescr descr) {
+
+        AccumulateDescr accumDescr = (AccumulateDescr) descr;
+
+        context.setInnerDeclarations( new HashMap() );
+
+        Column sourceColumn = columnBuilder.build( context,
+                                                   utils,
+                                                   accumDescr.getSourceColumn() );
+
+        if ( sourceColumn == null ) {
+            return null;
+        }
+        // remove declarations bound inside source column
+        context.getDeclarations().keySet().removeAll( context.getInnerDeclarations().keySet() );
+        Map sourceDeclarations = context.getInnerDeclarations();
+        context.setInnerDeclarations( null );
+
+        // decrementing offset as accumulate fills only one column
+        context.setColumnOffset( context.getColumnOffset() - 1 );
+        Column resultColumn = columnBuilder.build( context,
+                                                   utils,
+                                                   accumDescr.getResultColumn() );
+
+        final String className = "accumulate" + context.getNextId();
+        accumDescr.setClassMethodName( className );
+
+        final List[] usedIdentifiers1 = utils.getUsedIdentifiers( context,
+                                                                  accumDescr,
+                                                                  accumDescr.getInitCode() );
+        final List[] usedIdentifiers2 = utils.getUsedIdentifiers( context,
+                                                                  accumDescr,
+                                                                  accumDescr.getActionCode() );
+        final List[] usedIdentifiers3 = utils.getUsedIdentifiers( context,
+                                                                  accumDescr,
+                                                                  accumDescr.getResultCode() );
+
+        final List requiredDeclarations = new ArrayList( usedIdentifiers1[0] );
+        requiredDeclarations.addAll( usedIdentifiers2[0] );
+        requiredDeclarations.addAll( usedIdentifiers3[0] );
+
+        final List requiredGlobals = new ArrayList( usedIdentifiers1[1] );
+        requiredGlobals.addAll( usedIdentifiers2[1] );
+        requiredGlobals.addAll( usedIdentifiers3[1] );
+
+        final Declaration[] declarations = new Declaration[requiredDeclarations.size()];
+        for ( int i = 0, size = requiredDeclarations.size(); i < size; i++ ) {
+            declarations[i] = (Declaration) context.getDeclarations().get( (String) requiredDeclarations.get( i ) );
+        }
+        final Declaration[] sourceDeclArr = (Declaration[]) sourceDeclarations.values().toArray( new Declaration[sourceDeclarations.size()] );
+
+        final String[] globals = (String[]) requiredGlobals.toArray( new String[requiredGlobals.size()] );
+
+        StringTemplate st = utils.getRuleGroup().getInstanceOf( "accumulateMethod" );
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           declarations,
+                                           globals );
+
+        st.setAttribute( "innerDeclarations",
+                         sourceDeclArr );
+        st.setAttribute( "methodName",
+                         className );
+
+        final String initCode = utils.getFunctionFixer().fix( accumDescr.getInitCode() );
+        final String actionCode = utils.getFunctionFixer().fix( accumDescr.getActionCode() );
+        final String resultCode = utils.getFunctionFixer().fix( accumDescr.getResultCode() );
+        st.setAttribute( "initCode",
+                         initCode );
+        st.setAttribute( "actionCode",
+                         actionCode );
+        st.setAttribute( "resultCode",
+                         resultCode );
+
+        String resultType = null;
+        // TODO: Need to change this... 
+        if ( resultColumn.getObjectType() instanceof ClassObjectType ) {
+            resultType = ((ClassObjectType) resultColumn.getObjectType()).getClassType().getName();
+        } else {
+            resultType = resultColumn.getObjectType().getValueType().getClassType().getName();
+        }
+
+        st.setAttribute( "resultType",
+                         resultType );
+
+        context.getMethods().add( st.toString() );
+
+        st = utils.getInvokerGroup().getInstanceOf( "accumulateInvoker" );
+
+        st.setAttribute( "package",
+                         context.getPkg().getName() );
+        st.setAttribute( "ruleClassName",
+                         utils.ucFirst( context.getRuleDescr().getClassName() ) );
+        st.setAttribute( "invokerClassName",
+                         context.getRuleDescr().getClassName() + utils.ucFirst( className ) + "Invoker" );
+        st.setAttribute( "methodName",
+                         className );
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           declarations,
+                                           (String[]) requiredGlobals.toArray( new String[requiredGlobals.size()] ) );
+
+        st.setAttribute( "hashCode",
+                         actionCode.hashCode() );
+
+        Accumulate accumulate = new Accumulate( sourceColumn,
+                                                resultColumn,
+                                                declarations,
+                                                sourceDeclArr );
+        final String invokerClassName = context.getPkg().getName() + "." + context.getRuleDescr().getClassName() + utils.ucFirst( className ) + "Invoker";
+        context.getInvokers().put( invokerClassName,
+                                   st.toString() );
+        context.getInvokerLookups().put( invokerClassName,
+                                         accumulate );
+        context.getDescrLookups().put( invokerClassName,
+                                       accumDescr );
+        return accumulate;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/AccumulateBuilder.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildContext.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildContext.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildContext.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.lang.descr.QueryDescr;
+import org.drools.lang.descr.RuleDescr;
+import org.drools.rule.Package;
+import org.drools.rule.Query;
+import org.drools.rule.Rule;
+import org.drools.spi.AvailableVariables;
+
+/**
+ * A context for the current build
+ * 
+ * @author etirelli
+ */
+public class BuildContext {
+
+    // current package
+    private Package            pkg;
+
+    // current rule
+    private Rule               rule;
+
+    // current Rule descriptor
+    private RuleDescr          ruleDescr;
+
+    // the class name for the rule
+    private String             ruleClass;
+
+    // declarations made in the current context
+    private Map                declarations;
+
+    // helper map for inner declarations
+    private Map                innerDeclarations;
+
+    // available variables 
+    private AvailableVariables variables;
+
+    // errors found when building the current context
+    private List               errors;
+
+    // list of generated methods
+    private List               methods;
+
+    // map<String invokerClassName, String invokerCode> of generated invokers
+    private Map                invokers;
+
+    // map<String invokerClassName, ConditionalElement ce> of generated invoker lookups
+    private Map                invokerLookups;
+
+    // map<String invokerClassName, BaseDescr descr> of descriptor lookups
+    private Map                descrLookups;
+
+    // a simple counter for generated names
+    private int                counter;
+
+    // a simple counter for columns
+    private int                columnCounter;
+
+    // an offset counter for columns
+    private int                columnOffset;
+
+    /**
+     * Default constructor
+     */
+    public BuildContext(final Package pkg,
+                        final RuleDescr ruleDescr) {
+        this.pkg = pkg;
+
+        this.methods = new ArrayList();
+        this.invokers = new HashMap();
+        this.invokerLookups = new HashMap();
+        this.declarations = new HashMap();
+        this.descrLookups = new HashMap();
+        this.declarations = new HashMap();
+        this.errors = new ArrayList();
+        this.variables = new AvailableVariables( new Map[]{this.declarations, this.pkg.getGlobals()} );
+        this.ruleDescr = ruleDescr;
+
+        if ( ruleDescr instanceof QueryDescr ) {
+            this.rule = new Query( ruleDescr.getName() );
+        } else {
+            this.rule = new Rule( ruleDescr.getName() );
+        }
+
+    }
+
+    /**
+     * Returns the map of declarations for the current context
+     * @return
+     */
+    public Map getDeclarations() {
+        return declarations;
+    }
+
+    /**
+     * Returns the list of errors found while building the current context
+     * @return
+     */
+    public List getErrors() {
+        return errors;
+    }
+
+    /**
+     * Returns the current package being built
+     * @return
+     */
+    public Package getPkg() {
+        return pkg;
+    }
+
+    /**
+     * Returns the current Rule being built
+     * @return
+     */
+    public Rule getRule() {
+        return rule;
+    }
+
+    /**
+     * Returns the current RuleDescriptor
+     * @return
+     */
+    public RuleDescr getRuleDescr() {
+        return ruleDescr;
+    }
+
+    /**
+     * Returns the available variables instance
+     * @return
+     */
+    public AvailableVariables getVariables() {
+        return variables;
+    }
+
+    /**
+     * Sets the available variables instance
+     * @param variables
+     */
+    public void setVariables(AvailableVariables variables) {
+        this.variables = variables;
+    }
+
+    /**
+     * Returns the Map<String invokerClassName, BaseDescr descr> of descriptor lookups
+     * @return
+     */
+    public Map getDescrLookups() {
+        return descrLookups;
+    }
+
+    public void setDescrLookups(Map descrLookups) {
+        this.descrLookups = descrLookups;
+    }
+
+    /**
+     * Returns the Map<String invokerClassName, ConditionalElement ce> of generated invoker lookups
+     * @return
+     */
+    public Map getInvokerLookups() {
+        return invokerLookups;
+    }
+
+    public void setInvokerLookups(Map invokerLookups) {
+        this.invokerLookups = invokerLookups;
+    }
+
+    /**
+     * Returns the Map<String invokerClassName, String invokerCode> of generated invokers
+     * @return
+     */
+    public Map getInvokers() {
+        return invokers;
+    }
+
+    public void setInvokers(Map invokers) {
+        this.invokers = invokers;
+    }
+
+    /**
+     * Returns the list of generated methods
+     * @return
+     */
+    public List getMethods() {
+        return methods;
+    }
+
+    public void setMethods(List methods) {
+        this.methods = methods;
+    }
+
+    /**
+     * Returns current counter value for generated method names
+     * @return
+     */
+    public int getCurrentId() {
+        return counter;
+    }
+
+    public int getNextId() {
+        return counter++;
+    }
+
+    public int getCurrentColumnId() {
+        return columnCounter;
+    }
+
+    public int getNextColumnId() {
+        return columnCounter++;
+    }
+
+    public int getColumnOffset() {
+        return columnOffset;
+    }
+
+    public void setColumnOffset( int offset ) {
+        this.columnOffset = offset;
+    }
+
+    public Map getInnerDeclarations() {
+        return innerDeclarations;
+    }
+
+    public void setInnerDeclarations(Map innerDeclarations) {
+        this.innerDeclarations = innerDeclarations;
+    }
+
+    public String getRuleClass() {
+        return ruleClass;
+    }
+
+    public void setRuleClass(String ruleClass) {
+        this.ruleClass = ruleClass;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildContext.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildUtils.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildUtils.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildUtils.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.antlr.stringtemplate.StringTemplate;
+import org.antlr.stringtemplate.StringTemplateGroup;
+import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
+import org.codehaus.jfdi.interpreter.TypeResolver;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.compiler.RuleError;
+import org.drools.lang.descr.BaseDescr;
+import org.drools.rule.Declaration;
+import org.drools.semantics.java.FunctionFixer;
+import org.drools.semantics.java.JavaExprAnalyzer;
+import org.drools.semantics.java.KnowledgeHelperFixer;
+import org.drools.semantics.java.RuleBuilder;
+
+/**
+ * A holder class for utility functions
+ * 
+ * @author etirelli
+ */
+public class BuildUtils {
+
+    // the string template groups
+    private final StringTemplateGroup      ruleGroup    = new StringTemplateGroup( new InputStreamReader( RuleBuilder.class.getResourceAsStream( "javaRule.stg" ) ),
+                                                                                   AngleBracketTemplateLexer.class );
+
+    private final StringTemplateGroup      invokerGroup = new StringTemplateGroup( new InputStreamReader( RuleBuilder.class.getResourceAsStream( "javaInvokers.stg" ) ),
+                                                                                   AngleBracketTemplateLexer.class );
+
+    private final KnowledgeHelperFixer     knowledgeHelperFixer;
+
+    private final FunctionFixer            functionFixer;
+
+    private final JavaExprAnalyzer         analyzer;
+
+    private final TypeResolver             typeResolver;
+
+    private final ClassFieldExtractorCache classFieldExtractorCache;
+
+    public BuildUtils(final FunctionFixer functionFixer,
+                      final KnowledgeHelperFixer knowledgeHelperFixer,
+                      final JavaExprAnalyzer analyzer,
+                      final TypeResolver typeResolver,
+                      final ClassFieldExtractorCache classFieldExtractorCache) {
+        this.functionFixer = functionFixer;
+        this.knowledgeHelperFixer = knowledgeHelperFixer;
+        this.analyzer = analyzer;
+        this.typeResolver = typeResolver;
+        this.classFieldExtractorCache = classFieldExtractorCache;
+    }
+
+    public List[] getUsedIdentifiers(final BuildContext context,
+                                     final BaseDescr descr,
+                                     final String text) {
+        List[] usedIdentifiers = null;
+        try {
+            usedIdentifiers = this.analyzer.analyzeExpression( text,
+                                                               new Set[]{context.getDeclarations().keySet(), context.getPkg().getGlobals().keySet()} );
+        } catch ( final Exception e ) {
+            context.getErrors().add( new RuleError( context.getRule(),
+                                                    descr,
+                                                    null,
+                                                    "Unable to determine the used declarations" ) );
+        }
+        return usedIdentifiers;
+    }
+
+    public List[] getUsedCIdentifiers(final BuildContext context,
+                                      final BaseDescr descr,
+                                      final String text) {
+        List[] usedIdentifiers = null;
+        try {
+            usedIdentifiers = this.analyzer.analyzeBlock( text,
+                                                          new Set[]{context.getDeclarations().keySet(), context.getPkg().getGlobals().keySet()} );
+        } catch ( final Exception e ) {
+            context.getErrors().add( new RuleError( context.getRule(),
+                                                    descr,
+                                                    null,
+                                                    "Unable to determine the used declarations" ) );
+        }
+        return usedIdentifiers;
+    }
+
+    /**
+     * Sets usual string template attributes:
+     * 
+     * <li> list of declarations and declaration types</li>
+     * <li> list of globals and global types</li>
+     *
+     * @param context the current build context
+     * @param st the string template whose attributes will be set 
+     * @param declarations array of declarations to set
+     * @param globals array of globals to set
+     */
+    public void setStringTemplateAttributes(final BuildContext context,
+                                            final StringTemplate st,
+                                            final Declaration[] declarations,
+                                            final String[] globals) {
+        final String[] declarationTypes = new String[declarations.length];
+        for ( int i = 0, size = declarations.length; i < size; i++ ) {
+            declarationTypes[i] = declarations[i].getExtractor().getExtractToClass().getName().replace( '$',
+                                                                                                        '.' );
+        }
+
+        final List globalTypes = new ArrayList( globals.length );
+        for ( int i = 0, length = globals.length; i < length; i++ ) {
+            globalTypes.add( ((Class) context.getPkg().getGlobals().get( globals[i] )).getName().replace( '$',
+                                                                                                          '.' ) );
+        }
+
+        st.setAttribute( "declarations",
+                         declarations );
+        st.setAttribute( "declarationTypes",
+                         declarationTypes );
+
+        st.setAttribute( "globals",
+                         globals );
+        st.setAttribute( "globalTypes",
+                         globalTypes );
+    }
+
+    /**
+     * Upper case the first letter of "name"
+     * 
+     * @param name
+     * @return
+     */
+    public String ucFirst(final String name) {
+        return name.toUpperCase().charAt( 0 ) + name.substring( 1 );
+    }
+
+    /**
+     * Returns the string template group of invokers
+     * @return
+     */
+    public StringTemplateGroup getInvokerGroup() {
+        return invokerGroup;
+    }
+
+    /**
+     * Returns the string template group of actual rule templates
+     * @return
+     */
+    public StringTemplateGroup getRuleGroup() {
+        return ruleGroup;
+    }
+
+    /**
+     * Returns the Knowledge Helper Fixer
+     * @return
+     */
+    public KnowledgeHelperFixer getKnowledgeHelperFixer() {
+        return knowledgeHelperFixer;
+    }
+
+    /**
+     * Returns the function fixer instance
+     * @return
+     */
+    public FunctionFixer getFunctionFixer() {
+        return functionFixer;
+    }
+
+    /**
+     * Returns the current type resolver instance
+     * @return
+     */
+    public TypeResolver getTypeResolver() {
+        return this.typeResolver;
+    }
+
+    /**
+     * Returns the cache of field extractors
+     * @return
+     */
+    public ClassFieldExtractorCache getClassFieldExtractorCache() {
+        return classFieldExtractorCache;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/BuildUtils.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/CollectBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/CollectBuilder.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/CollectBuilder.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import java.util.HashMap;
+
+import org.drools.lang.descr.BaseDescr;
+import org.drools.lang.descr.CollectDescr;
+import org.drools.rule.Collect;
+import org.drools.rule.Column;
+import org.drools.rule.ConditionalElement;
+
+/**
+ * @author etirelli
+ *
+ */
+public class CollectBuilder
+    implements
+    ConditionalElementBuilder {
+
+    /* (non-Javadoc)
+     * @see org.drools.semantics.java.builder.ConditionalElementBuilder#build(org.drools.semantics.java.builder.BuildContext, org.drools.semantics.java.builder.BuildUtils, org.drools.semantics.java.builder.ColumnBuilder, org.drools.lang.descr.BaseDescr)
+     */
+    public ConditionalElement build(BuildContext context,
+                                    BuildUtils utils,
+                                    ColumnBuilder columnBuilder,
+                                    BaseDescr descr) {
+        
+        CollectDescr collectDescr = (CollectDescr) descr;
+        
+        context.setInnerDeclarations( new HashMap() );
+        Column sourceColumn = columnBuilder.build( context, utils, collectDescr.getSourceColumn() );
+
+        if ( sourceColumn == null ) {
+            return null;
+        }
+
+        // remove declarations bound inside source column
+        context.getDeclarations().keySet().removeAll( context.getInnerDeclarations().keySet() );
+        context.setInnerDeclarations( null );
+
+        // decrementing offset as collect fills only one column
+        context.setColumnOffset( context.getColumnOffset() - 1 );
+        Column resultColumn = columnBuilder.build( context, utils, collectDescr.getResultColumn() );
+
+        final String className = "collect" + context.getNextId();
+        collectDescr.setClassMethodName( className );
+
+        Collect collect = new Collect( sourceColumn,
+                                       resultColumn );
+        return collect;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/CollectBuilder.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ColumnBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ColumnBuilder.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ColumnBuilder.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,746 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.antlr.stringtemplate.StringTemplate;
+import org.drools.RuntimeDroolsException;
+import org.drools.base.ClassObjectType;
+import org.drools.base.FieldFactory;
+import org.drools.base.ShadowProxyFactory;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.compiler.RuleError;
+import org.drools.facttemplates.FactTemplate;
+import org.drools.facttemplates.FactTemplateFieldExtractor;
+import org.drools.facttemplates.FactTemplateObjectType;
+import org.drools.lang.descr.BaseDescr;
+import org.drools.lang.descr.ColumnDescr;
+import org.drools.lang.descr.FieldBindingDescr;
+import org.drools.lang.descr.FieldConstraintDescr;
+import org.drools.lang.descr.LiteralRestrictionDescr;
+import org.drools.lang.descr.PredicateDescr;
+import org.drools.lang.descr.RestrictionConnectiveDescr;
+import org.drools.lang.descr.RestrictionDescr;
+import org.drools.lang.descr.ReturnValueRestrictionDescr;
+import org.drools.lang.descr.VariableRestrictionDescr;
+import org.drools.rule.AndCompositeRestriction;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.LiteralRestriction;
+import org.drools.rule.MultiRestrictionFieldConstraint;
+import org.drools.rule.OrCompositeRestriction;
+import org.drools.rule.PredicateConstraint;
+import org.drools.rule.ReturnValueConstraint;
+import org.drools.rule.ReturnValueRestriction;
+import org.drools.rule.VariableConstraint;
+import org.drools.rule.VariableRestriction;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.ObjectType;
+import org.drools.spi.Restriction;
+
+/**
+ * A builder for columns
+ * 
+ * @author etirelli
+ */
+public class ColumnBuilder {
+
+    /**
+     * Build a column for the given descriptor in the current 
+     * context and using the given utils object
+     * 
+     * @param context
+     * @param utils
+     * @param columnDescr
+     * @return
+     */
+    public Column build(final BuildContext context,
+                        final BuildUtils utils,
+                        final ColumnDescr columnDescr) {
+
+        if ( columnDescr.getObjectType() == null || columnDescr.getObjectType().equals( "" ) ) {
+            context.getErrors().add( new RuleError( context.getRule(),
+                                                    columnDescr,
+                                                    null,
+                                                    "ObjectType not correctly defined" ) );
+            return null;
+        }
+
+        ObjectType objectType = null;
+
+        final FactTemplate factTemplate = context.getPkg().getFactTemplate( columnDescr.getObjectType() );
+
+        if ( factTemplate != null ) {
+            objectType = new FactTemplateObjectType( factTemplate );
+        } else {
+            try {
+                Class userProvidedClass = utils.getTypeResolver().resolveType( columnDescr.getObjectType() );
+                String shadowProxyName = ShadowProxyFactory.getProxyClassNameForClass( userProvidedClass );
+                Class shadowClass = null;
+                try {
+                    // if already loaded
+                    shadowClass = context.getPkg().getPackageCompilationData().getClassLoader().loadClass( shadowProxyName );
+                } catch ( ClassNotFoundException cnfe ) {
+                    // otherwise, create and load
+                    byte[] proxyBytes = ShadowProxyFactory.getProxyBytes( userProvidedClass );
+                    if ( proxyBytes != null ) {
+                        context.getPkg().getPackageCompilationData().write( shadowProxyName,
+                                                                            proxyBytes );
+                        shadowClass = context.getPkg().getPackageCompilationData().getClassLoader().loadClass( shadowProxyName );
+                    }
+
+                }
+                objectType = new ClassObjectType( userProvidedClass,
+                                                  shadowClass );
+            } catch ( final ClassNotFoundException e ) {
+                context.getErrors().add( new RuleError( context.getRule(),
+                                                        columnDescr,
+                                                        null,
+                                                        "Unable to resolve ObjectType '" + columnDescr.getObjectType() + "'" ) );
+                return null;
+            }
+        }
+
+        Column column;
+        if ( columnDescr.getIdentifier() != null && !columnDescr.getIdentifier().equals( "" ) ) {
+            column = new Column( context.getNextColumnId(),
+                                 context.getColumnOffset(),
+                                 objectType,
+                                 columnDescr.getIdentifier() );
+            context.getDeclarations().put( column.getDeclaration().getIdentifier(),
+                                           column.getDeclaration() );
+
+            if ( context.getInnerDeclarations() != null ) {
+                context.getInnerDeclarations().put( column.getDeclaration().getIdentifier(),
+                                                    column.getDeclaration() );
+            }
+        } else {
+            column = new Column( context.getNextColumnId(),
+                                 context.getColumnOffset(),
+                                 objectType,
+                                 null );
+        }
+
+        for ( final Iterator it = columnDescr.getDescrs().iterator(); it.hasNext(); ) {
+            final Object object = it.next();
+            if ( object instanceof FieldBindingDescr ) {
+                build( context,
+                       utils,
+                       column,
+                       (FieldBindingDescr) object );
+            } else if ( object instanceof FieldConstraintDescr ) {
+                build( context,
+                       utils,
+                       column,
+                       (FieldConstraintDescr) object );
+            } else if ( object instanceof PredicateDescr ) {
+                build( context,
+                       utils,
+                       column,
+                       (PredicateDescr) object );
+            }
+        }
+        return column;
+    }
+
+    private void build(final BuildContext context,
+                       final BuildUtils utils,
+                       final Column column,
+                       final FieldConstraintDescr fieldConstraintDescr) {
+
+        final FieldExtractor extractor = getFieldExtractor( context,
+                                                            utils,
+                                                            fieldConstraintDescr,
+                                                            column.getObjectType(),
+                                                            fieldConstraintDescr.getFieldName() );
+        if ( extractor == null ) {
+            // @todo log error
+            return;
+        }
+
+        if ( fieldConstraintDescr.getRestrictions().size() == 1 ) {
+            final Object object = fieldConstraintDescr.getRestrictions().get( 0 );
+
+            final Restriction restriction = buildRestriction( context,
+                                                              utils,
+                                                              column,
+                                                              extractor,
+                                                              fieldConstraintDescr,
+                                                              (RestrictionDescr) object );
+            if ( restriction == null ) {
+                // @todo log errors
+                return;
+            }
+
+            if ( object instanceof LiteralRestrictionDescr ) {
+                column.addConstraint( new LiteralConstraint( extractor,
+                                                             (LiteralRestriction) restriction ) );
+            } else if ( object instanceof VariableRestrictionDescr ) {
+                column.addConstraint( new VariableConstraint( extractor,
+                                                              (VariableRestriction) restriction ) );
+            } else if ( object instanceof ReturnValueRestrictionDescr ) {
+                column.addConstraint( new ReturnValueConstraint( extractor,
+                                                                 (ReturnValueRestriction) restriction ) );
+            }
+
+            return;
+        }
+
+        final List orList = new ArrayList();
+        List andList = null;
+
+        RestrictionDescr currentRestriction = null;
+        RestrictionDescr previousRestriction = null;
+
+        List currentList = null;
+        List previousList = null;
+
+        for ( final Iterator it = fieldConstraintDescr.getRestrictions().iterator(); it.hasNext(); ) {
+            final Object object = it.next();
+
+            // Process an and/or connective 
+            if ( object instanceof RestrictionConnectiveDescr ) {
+
+                // is the connective an 'and'?
+                if ( ((RestrictionConnectiveDescr) object).getConnective() == RestrictionConnectiveDescr.AND ) {
+                    // if andList is null, then we know its the first
+                    if ( andList == null ) {
+                        andList = new ArrayList();
+                    }
+                    previousList = currentList;
+                    currentList = andList;
+                } else {
+                    previousList = currentList;
+                    currentList = orList;
+                }
+            } else {
+                Restriction restriction = null;
+                if ( currentList != null ) {
+                    // Are we are at the first operator? if so treat differently
+                    if ( previousList == null ) {
+                        restriction = buildRestriction( context,
+                                                        utils,
+                                                        column,
+                                                        extractor,
+                                                        fieldConstraintDescr,
+                                                        previousRestriction );
+                        if ( currentList == andList ) {
+                            andList.add( restriction );
+                        } else {
+                            orList.add( restriction );
+                        }
+                    } else {
+                        restriction = buildRestriction( context,
+                                                        utils,
+                                                        column,
+                                                        extractor,
+                                                        fieldConstraintDescr,
+                                                        previousRestriction );
+
+                        if ( previousList == andList && currentList == orList ) {
+                            andList.add( restriction );
+                            if ( andList.size() == 1 ) {
+                                // Can't have an 'and' connective with one child, so add directly to the or list
+                                orList.add( andList.get( 0 ) );
+                            } else {
+                                final Restriction restrictions = new AndCompositeRestriction( (Restriction[]) andList.toArray( new Restriction[andList.size()] ) );
+                                orList.add( restrictions );
+                            }
+                            andList = null;
+                        } else if ( previousList == andList && currentList == andList ) {
+                            andList.add( restriction );
+                        } else if ( previousList == orList && currentList == andList ) {
+                            andList.add( restriction );
+                        } else if ( previousList == orList && currentList == orList ) {
+                            orList.add( restriction );
+                        }
+                    }
+                }
+            }
+            previousRestriction = currentRestriction;
+            currentRestriction = (RestrictionDescr) object;
+        }
+
+        final Restriction restriction = buildRestriction( context,
+                                                          utils,
+                                                          column,
+                                                          extractor,
+                                                          fieldConstraintDescr,
+                                                          currentRestriction );
+        currentList.add( restriction );
+
+        Restriction restrictions = null;
+        if ( currentList == andList && !orList.isEmpty() ) {
+            // Check if it finished with an and, and process it
+            if ( andList != null ) {
+                if ( andList.size() == 1 ) {
+                    // Can't have an 'and' connective with one child, so add directly to the or list
+                    orList.add( andList.get( 0 ) );
+                } else {
+                    orList.add( new AndCompositeRestriction( (Restriction[]) andList.toArray( new Restriction[andList.size()] ) ) );
+                }
+                andList = null;
+            }
+        }
+
+        if ( !orList.isEmpty() ) {
+            restrictions = new OrCompositeRestriction( (Restriction[]) orList.toArray( new Restriction[orList.size()] ) );
+        } else if ( andList != null && !andList.isEmpty() ) {
+            restrictions = new AndCompositeRestriction( (Restriction[]) andList.toArray( new Restriction[andList.size()] ) );
+        } else {
+            // @todo throw error
+        }
+
+        column.addConstraint( new MultiRestrictionFieldConstraint( extractor,
+                                                                   restrictions ) );
+    }
+
+    private void build(final BuildContext context,
+                       final BuildUtils utils,
+                       final Column column,
+                       final FieldBindingDescr fieldBindingDescr) {
+
+        Declaration declaration = (Declaration) context.getDeclarations().get( fieldBindingDescr.getIdentifier() );
+        if ( declaration != null ) {
+            // This declaration already  exists, so throw an Exception
+            context.getErrors().add( new RuleError( context.getRule(),
+                                                    fieldBindingDescr,
+                                                    null,
+                                                    "Duplicate declaration for variable '" + fieldBindingDescr.getIdentifier() + "' in the rule '" + context.getRule().getName() + "'" ) );
+            return;
+        }
+
+        final FieldExtractor extractor = getFieldExtractor( context,
+                                                            utils,
+                                                            fieldBindingDescr,
+                                                            column.getObjectType(),
+                                                            fieldBindingDescr.getFieldName() );
+        if ( extractor == null ) {
+            return;
+        }
+
+        declaration = column.addDeclaration( fieldBindingDescr.getIdentifier(),
+                                             extractor );
+
+        context.getDeclarations().put( declaration.getIdentifier(),
+                                       declaration );
+
+        if ( context.getInnerDeclarations() != null ) {
+            context.getInnerDeclarations().put( declaration.getIdentifier(),
+                                                declaration );
+        }
+    }
+
+    private void build(final BuildContext context,
+                       final BuildUtils utils,
+                       final Column column,
+                       final PredicateDescr predicateDescr) {
+        // generate 
+        // generate Invoker
+        final String className = "predicate" + context.getNextId();
+        predicateDescr.setClassMethodName( className );
+
+        final FieldExtractor extractor = getFieldExtractor( context,
+                                                            utils,
+                                                            predicateDescr,
+                                                            column.getObjectType(),
+                                                            predicateDescr.getFieldName() );
+        if ( extractor == null ) {
+            return;
+        }
+
+        final Declaration declaration = column.addDeclaration( predicateDescr.getDeclaration(),
+                                                               extractor );
+
+        context.getDeclarations().put( declaration.getIdentifier(),
+                                       declaration );
+
+        if ( context.getInnerDeclarations() != null ) {
+            context.getInnerDeclarations().put( declaration.getIdentifier(),
+                                                declaration );
+        }
+
+        final List[] usedIdentifiers = utils.getUsedIdentifiers( context,
+                                                                 predicateDescr,
+                                                                 predicateDescr.getText() );
+        // Don't include the focus declaration, that hasn't been merged into the tuple yet.
+        usedIdentifiers[0].remove( predicateDescr.getDeclaration() );
+
+        final List tupleDeclarations = new ArrayList();
+        final List factDeclarations = new ArrayList();
+        for ( int i = 0, size = usedIdentifiers[0].size(); i < size; i++ ) {
+            Declaration decl = (Declaration) context.getDeclarations().get( (String) usedIdentifiers[0].get( i ) );
+            if ( decl.getColumn() == column ) {
+                factDeclarations.add( decl );
+            } else {
+                tupleDeclarations.add( decl );
+            }
+        }
+        Declaration[] previousDeclarations = (Declaration[]) tupleDeclarations.toArray( new Declaration[tupleDeclarations.size()] );
+        Declaration[] localDeclarations = (Declaration[]) factDeclarations.toArray( new Declaration[factDeclarations.size()] );
+
+        final PredicateConstraint predicateConstraint = new PredicateConstraint( declaration,
+                                                                                 previousDeclarations,
+                                                                                 localDeclarations );
+        column.addConstraint( predicateConstraint );
+
+        StringTemplate st = utils.getRuleGroup().getInstanceOf( "predicateMethod" );
+
+        st.setAttribute( "declaration",
+                         declaration );
+
+        st.setAttribute( "declarationType",
+                         declaration.getExtractor().getExtractToClass().getName().replace( '$',
+                                                                                           '.' ) );
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           previousDeclarations,
+                                           (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ) );
+
+        final String[] localDeclarationTypes = new String[localDeclarations.length];
+        for ( int i = 0, size = localDeclarations.length; i < size; i++ ) {
+            localDeclarationTypes[i] = localDeclarations[i].getExtractor().getExtractToClass().getName().replace( '$',
+                                                                                                                  '.' );
+        }
+
+        st.setAttribute( "localDeclarations",
+                         localDeclarations );
+        st.setAttribute( "localDeclarationTypes",
+                         localDeclarationTypes );
+
+        st.setAttribute( "methodName",
+                         className );
+
+        final String predicateText = utils.getFunctionFixer().fix( predicateDescr.getText(),
+                                                                   context.getVariables() );
+        st.setAttribute( "text",
+                         predicateText );
+
+        context.getMethods().add( st.toString() );
+
+        st = utils.getInvokerGroup().getInstanceOf( "predicateInvoker" );
+
+        st.setAttribute( "package",
+                         context.getPkg().getName() );
+        st.setAttribute( "ruleClassName",
+                         utils.ucFirst( context.getRuleDescr().getClassName() ) );
+        st.setAttribute( "invokerClassName",
+                         context.getRuleDescr().getClassName() + utils.ucFirst( className ) + "Invoker" );
+        st.setAttribute( "methodName",
+                         className );
+
+        st.setAttribute( "declaration",
+                         declaration );
+        st.setAttribute( "declarationType",
+                         declaration.getExtractor().getExtractToClass().getName().replace( '$',
+                                                                                           '.' ) );
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           previousDeclarations,
+                                           (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ) );
+
+        st.setAttribute( "localDeclarations",
+                         localDeclarations );
+        st.setAttribute( "localDeclarationTypes",
+                         localDeclarationTypes );
+
+        st.setAttribute( "hashCode",
+                         predicateText.hashCode() );
+
+        final String invokerClassName = context.getPkg().getName() + "." + context.getRuleDescr().getClassName() + utils.ucFirst( className ) + "Invoker";
+        context.getInvokers().put( invokerClassName,
+                                   st.toString() );
+        context.getInvokerLookups().put( invokerClassName,
+                                         predicateConstraint );
+        context.getDescrLookups().put( invokerClassName,
+                                       predicateDescr );
+    }
+
+    private Restriction buildRestriction(final BuildContext context,
+                                         final BuildUtils utils,
+                                         final Column column,
+                                         final FieldExtractor extractor,
+                                         final FieldConstraintDescr fieldConstraintDescr,
+                                         final RestrictionDescr restrictionDescr) {
+        Restriction restriction = null;
+        if ( restrictionDescr instanceof LiteralRestrictionDescr ) {
+            restriction = buildRestriction( context,
+                                            utils,
+                                            extractor,
+                                            fieldConstraintDescr,
+                                            (LiteralRestrictionDescr) restrictionDescr );
+        } else if ( restrictionDescr instanceof VariableRestrictionDescr ) {
+            restriction = buildRestriction( context,
+                                            extractor,
+                                            fieldConstraintDescr,
+                                            (VariableRestrictionDescr) restrictionDescr );
+        } else if ( restrictionDescr instanceof ReturnValueRestrictionDescr ) {
+            restriction = buildRestriction( context,
+                                            utils,
+                                            column,
+                                            extractor,
+                                            fieldConstraintDescr,
+                                            (ReturnValueRestrictionDescr) restrictionDescr );
+
+        }
+
+        return restriction;
+    }
+
+    private VariableRestriction buildRestriction(final BuildContext context,
+                                                 final FieldExtractor extractor,
+                                                 final FieldConstraintDescr fieldConstraintDescr,
+                                                 final VariableRestrictionDescr variableRestrictionDescr) {
+        if ( variableRestrictionDescr.getIdentifier() == null || variableRestrictionDescr.getIdentifier().equals( "" ) ) {
+            context.getErrors().add( new RuleError( context.getRule(),
+                                                    variableRestrictionDescr,
+                                                    null,
+                                                    "Identifier not defined for binding field '" + fieldConstraintDescr.getFieldName() + "'" ) );
+            return null;
+        }
+
+        final Declaration declaration = (Declaration) context.getDeclarations().get( variableRestrictionDescr.getIdentifier() );
+
+        if ( declaration == null ) {
+            context.getErrors().add( new RuleError( context.getRule(),
+                                                    variableRestrictionDescr,
+                                                    null,
+                                                    "Unable to return Declaration for identifier '" + variableRestrictionDescr.getIdentifier() + "'" ) );
+            return null;
+        }
+
+        final Evaluator evaluator = getEvaluator( context,
+                                                  variableRestrictionDescr,
+                                                  extractor.getValueType(),
+                                                  variableRestrictionDescr.getEvaluator() );
+        if ( evaluator == null ) {
+            return null;
+        }
+
+        return new VariableRestriction( extractor,
+                                        declaration,
+                                        evaluator );
+    }
+
+    private LiteralRestriction buildRestriction(final BuildContext context,
+                                                final BuildUtils utils,
+                                                final FieldExtractor extractor,
+                                                final FieldConstraintDescr fieldConstraintDescr,
+                                                final LiteralRestrictionDescr literalRestrictionDescr) {
+        FieldValue field = null;
+        if ( literalRestrictionDescr.isStaticFieldValue() ) {
+            final int lastDot = literalRestrictionDescr.getText().lastIndexOf( '.' );
+            final String className = literalRestrictionDescr.getText().substring( 0,
+                                                                                  lastDot );
+            final String fieldName = literalRestrictionDescr.getText().substring( lastDot + 1 );
+            try {
+                final Class staticClass = utils.getTypeResolver().resolveType( className );
+                field = FieldFactory.getFieldValue( staticClass.getField( fieldName ).get( null ).toString(),
+                                                    extractor.getValueType() );
+            } catch ( final ClassNotFoundException e ) {
+                context.getErrors().add( new RuleError( context.getRule(),
+                                                        literalRestrictionDescr,
+                                                        e,
+                                                        e.getMessage() ) );
+            } catch ( final Exception e ) {
+                context.getErrors().add( new RuleError( context.getRule(),
+                                                        literalRestrictionDescr,
+                                                        e,
+                                                        "Unable to create a Field value of type  '" + extractor.getValueType() + "' and value '" + literalRestrictionDescr.getText() + "'" ) );
+            }
+
+        } else {
+            try {
+                field = FieldFactory.getFieldValue( literalRestrictionDescr.getText(),
+                                                    extractor.getValueType() );
+            } catch ( final Exception e ) {
+                context.getErrors().add( new RuleError( context.getRule(),
+                                                        literalRestrictionDescr,
+                                                        e,
+                                                        "Unable to create a Field value of type  '" + extractor.getValueType() + "' and value '" + literalRestrictionDescr.getText() + "'" ) );
+            }
+        }
+
+        final Evaluator evaluator = getEvaluator( context,
+                                                  literalRestrictionDescr,
+                                                  extractor.getValueType(),
+                                                  literalRestrictionDescr.getEvaluator() );
+        if ( evaluator == null ) {
+            return null;
+        }
+
+        return new LiteralRestriction( field,
+                                       evaluator,
+                                       extractor );
+    }
+
+    private ReturnValueRestriction buildRestriction(final BuildContext context,
+                                                    final BuildUtils utils,
+                                                    final Column column,
+                                                    final FieldExtractor extractor,
+                                                    final FieldConstraintDescr fieldConstraintDescr,
+                                                    final ReturnValueRestrictionDescr returnValueRestrictionDescr) {
+        final String className = "returnValue" + context.getNextId();
+        returnValueRestrictionDescr.setClassMethodName( className );
+
+        final List[] usedIdentifiers = utils.getUsedIdentifiers( context,
+                                                                 returnValueRestrictionDescr,
+                                                                 returnValueRestrictionDescr.getText() );
+
+        final List tupleDeclarations = new ArrayList();
+        final List factDeclarations = new ArrayList();
+        for ( int i = 0, size = usedIdentifiers[0].size(); i < size; i++ ) {
+            Declaration declaration = (Declaration) context.getDeclarations().get( (String) usedIdentifiers[0].get( i ) );
+            if ( declaration.getColumn() == column ) {
+                factDeclarations.add( declaration );
+            } else {
+                tupleDeclarations.add( declaration );
+            }
+        }
+
+        final Evaluator evaluator = getEvaluator( context,
+                                                  returnValueRestrictionDescr,
+                                                  extractor.getValueType(),
+                                                  returnValueRestrictionDescr.getEvaluator() );
+        if ( evaluator == null ) {
+            return null;
+        }
+
+        Declaration[] previousDeclarations = (Declaration[]) tupleDeclarations.toArray( new Declaration[tupleDeclarations.size()] );
+        Declaration[] localDeclarations = (Declaration[]) factDeclarations.toArray( new Declaration[factDeclarations.size()] );
+        final ReturnValueRestriction returnValueRestriction = new ReturnValueRestriction( extractor,
+                                                                                          previousDeclarations,
+                                                                                          localDeclarations,
+                                                                                          evaluator );
+
+        StringTemplate st = utils.getRuleGroup().getInstanceOf( "returnValueMethod" );
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           previousDeclarations,
+                                           (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ) );
+
+        final String[] localDeclarationTypes = new String[localDeclarations.length];
+        for ( int i = 0, size = localDeclarations.length; i < size; i++ ) {
+            localDeclarationTypes[i] = localDeclarations[i].getExtractor().getExtractToClass().getName().replace( '$',
+                                                                                                                  '.' );
+        }
+
+        st.setAttribute( "localDeclarations",
+                         localDeclarations );
+        st.setAttribute( "localDeclarationTypes",
+                         localDeclarationTypes );
+
+        st.setAttribute( "methodName",
+                         className );
+
+        final String returnValueText = utils.getFunctionFixer().fix( returnValueRestrictionDescr.getText(),
+                                                                     context.getVariables() );
+        st.setAttribute( "text",
+                         returnValueText );
+
+        context.getMethods().add( st.toString() );
+
+        st = utils.getInvokerGroup().getInstanceOf( "returnValueInvoker" );
+
+        st.setAttribute( "package",
+                         context.getPkg().getName() );
+        st.setAttribute( "ruleClassName",
+                         utils.ucFirst( context.getRuleDescr().getClassName() ) );
+        st.setAttribute( "invokerClassName",
+                         context.getRuleDescr().getClassName() + utils.ucFirst( className ) + "Invoker" );
+        st.setAttribute( "methodName",
+                         className );
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           previousDeclarations,
+                                           (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ) );
+
+        st.setAttribute( "localDeclarations",
+                         localDeclarations );
+        st.setAttribute( "localDeclarationTypes",
+                         localDeclarationTypes );
+
+        st.setAttribute( "hashCode",
+                         returnValueText.hashCode() );
+
+        final String invokerClassName = context.getPkg().getName() + "." + context.getRuleDescr().getClassName() + utils.ucFirst( className ) + "Invoker";
+        context.getInvokers().put( invokerClassName,
+                                   st.toString() );
+        context.getInvokerLookups().put( invokerClassName,
+                                         returnValueRestriction );
+        context.getDescrLookups().put( invokerClassName,
+                                       returnValueRestrictionDescr );
+
+        return returnValueRestriction;
+    }
+
+    private FieldExtractor getFieldExtractor(final BuildContext context,
+                                             final BuildUtils utils,
+                                             final BaseDescr descr,
+                                             final ObjectType objectType,
+                                             final String fieldName) {
+        FieldExtractor extractor = null;
+
+        if ( objectType.getValueType() == ValueType.FACTTEMPLATE_TYPE ) {
+            //@todo use extractor cache            
+            final FactTemplate factTemplate = ((FactTemplateObjectType) objectType).getFactTemplate();
+            extractor = new FactTemplateFieldExtractor( factTemplate,
+                                                        factTemplate.getFieldTemplateIndex( fieldName ) );
+        } else {
+            try {
+                extractor = utils.getClassFieldExtractorCache().getExtractor( ((ClassObjectType) objectType).getClassType(),
+                                                                              fieldName );
+            } catch ( final RuntimeDroolsException e ) {
+                context.getErrors().add( new RuleError( context.getRule(),
+                                                        descr,
+                                                        e,
+                                                        "Unable to create Field Extractor for '" + fieldName + "'" ) );
+            }
+        }
+
+        return extractor;
+    }
+
+    private Evaluator getEvaluator(final BuildContext context,
+                                   final BaseDescr descr,
+                                   final ValueType valueType,
+                                   final String evaluatorString) {
+
+        final Evaluator evaluator = valueType.getEvaluator( Operator.determineOperator( evaluatorString ) );
+
+        if ( evaluator == null ) {
+            context.getErrors().add( new RuleError( context.getRule(),
+                                                    descr,
+                                                    null,
+                                                    "Unable to determine the Evaluator for  '" + valueType + "' and '" + evaluatorString + "'" ) );
+        }
+
+        return evaluator;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ColumnBuilder.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConditionalElementBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConditionalElementBuilder.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConditionalElementBuilder.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import org.drools.lang.descr.BaseDescr;
+import org.drools.rule.ConditionalElement;
+
+/**
+ * An interface to define classes capable of building
+ * specific conditional elements.
+ * 
+ * @author etirelli
+ */
+public interface ConditionalElementBuilder {
+
+    public ConditionalElement build(final BuildContext context,
+                                    final BuildUtils utils, 
+                                    final ColumnBuilder columnBuilder,
+                                    final BaseDescr descr);
+
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConditionalElementBuilder.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConsequenceBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConsequenceBuilder.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConsequenceBuilder.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.antlr.stringtemplate.StringTemplate;
+import org.drools.RuntimeDroolsException;
+import org.drools.lang.descr.RuleDescr;
+import org.drools.rule.Declaration;
+
+/**
+ * @author etirelli
+ *
+ */
+public class ConsequenceBuilder {
+
+    public void buildConsequence(final BuildContext context,
+                                 final BuildUtils utils,
+                                 final RuleDescr ruleDescr) {
+        // generate 
+        // generate Invoker
+        final String className = "consequence";
+
+        StringTemplate st = utils.getRuleGroup().getInstanceOf( "consequenceMethod" );
+
+        st.setAttribute( "methodName",
+                         className );
+
+        final List[] usedIdentifiers = utils.getUsedCIdentifiers( context,
+                                                                  ruleDescr,
+                                                                  ruleDescr.getConsequence() );
+
+        final Declaration[] declarations = new Declaration[usedIdentifiers[0].size()];
+        for ( int i = 0, size = usedIdentifiers[0].size(); i < size; i++ ) {
+            declarations[i] = (Declaration) context.getDeclarations().get( (String) usedIdentifiers[0].get( i ) );
+        }
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           declarations,
+                                           (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ) );
+        st.setAttribute( "text",
+                         utils.getFunctionFixer().fix( utils.getKnowledgeHelperFixer().fix( ruleDescr.getConsequence() ),
+                                                       context.getVariables() ) );
+
+        context.getMethods().add( st.toString() );
+
+        st = utils.getInvokerGroup().getInstanceOf( "consequenceInvoker" );
+
+        st.setAttribute( "package",
+                         context.getPkg().getName() );
+        st.setAttribute( "ruleClassName",
+                         utils.ucFirst( context.getRuleDescr().getClassName() ) );
+        st.setAttribute( "invokerClassName",
+                         ruleDescr.getClassName() + utils.ucFirst( className ) + "Invoker" );
+        st.setAttribute( "methodName",
+                         className );
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           declarations,
+                                           (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ) );
+
+        // Must use the rule declarations, so we use the same order as used in the generated invoker
+        final List list = Arrays.asList( context.getRule().getDeclarations() );
+
+        final int[] indexes = new int[declarations.length];
+        for ( int i = 0, length = declarations.length; i < length; i++ ) {
+            indexes[i] = list.indexOf( declarations[i] );
+            if ( indexes[i] == -1 ) {
+                // some defensive code, this should never happen
+                throw new RuntimeDroolsException( "Unable to find declaration in list while generating the consequence invoker" );
+            }
+        }
+
+        st.setAttribute( "indexes",
+                         indexes );
+
+        st.setAttribute( "text",
+                         ruleDescr.getConsequence() );
+
+        final String invokerClassName = context.getPkg().getName() + "." + ruleDescr.getClassName() + utils.ucFirst( className ) + "Invoker";
+        context.getInvokers().put( invokerClassName,
+                                   st.toString() );
+        context.getInvokerLookups().put( invokerClassName,
+                                         context.getRule() );
+        context.getDescrLookups().put( invokerClassName,
+                                       ruleDescr );
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/ConsequenceBuilder.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/EvalBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/EvalBuilder.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/EvalBuilder.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import java.util.List;
+
+import org.antlr.stringtemplate.StringTemplate;
+import org.drools.lang.descr.BaseDescr;
+import org.drools.lang.descr.EvalDescr;
+import org.drools.rule.ConditionalElement;
+import org.drools.rule.Declaration;
+import org.drools.rule.EvalCondition;
+
+/**
+ * @author etirelli
+ *
+ */
+public class EvalBuilder
+    implements
+    ConditionalElementBuilder {
+
+    /**
+     * Builds and returns an Eval Conditional Element
+     * 
+     * @param context The current build context
+     * @param utils The current build utils instance
+     * @param columnBuilder not used by EvalBuilder
+     * @param descr The Eval Descriptor to build the eval conditional element from
+     * 
+     * @return the Eval Conditional Element
+     */
+    public ConditionalElement build(final BuildContext context,
+                                    final BuildUtils utils,
+                                    final ColumnBuilder columnBuilder,
+                                    final BaseDescr descr) {
+        // it must be an EvalDescr
+        EvalDescr evalDescr = (EvalDescr) descr;
+
+        final String className = "eval" + context.getNextId();
+        
+        evalDescr.setClassMethodName( className );
+
+        final List[] usedIdentifiers = utils.getUsedIdentifiers( context,
+                                                                 evalDescr,
+                                                                 evalDescr.getText() );
+
+        final Declaration[] declarations = new Declaration[usedIdentifiers[0].size()];
+        for ( int i = 0, size = usedIdentifiers[0].size(); i < size; i++ ) {
+            declarations[i] = (Declaration) context.getDeclarations().get( (String) usedIdentifiers[0].get( i ) );
+        }
+
+        final EvalCondition eval = new EvalCondition( declarations );
+
+        StringTemplate st = utils.getRuleGroup().getInstanceOf( "evalMethod" );
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           declarations,
+                                           (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ) );
+
+        st.setAttribute( "methodName",
+                         className );
+
+        final String evalText = utils.getFunctionFixer().fix( evalDescr.getText(),
+                                                              context.getVariables() );
+        st.setAttribute( "text",
+                         evalText );
+
+        context.getMethods().add( st.toString() );
+
+        st = utils.getInvokerGroup().getInstanceOf( "evalInvoker" );
+
+        st.setAttribute( "package",
+                         context.getPkg().getName() );
+        st.setAttribute( "ruleClassName",
+                         utils.ucFirst( context.getRuleDescr().getClassName() ) );
+        st.setAttribute( "invokerClassName",
+                         context.getRuleDescr().getClassName() + utils.ucFirst( className ) + "Invoker" );
+        st.setAttribute( "methodName",
+                         className );
+
+        utils.setStringTemplateAttributes( context,
+                                           st,
+                                           declarations,
+                                           (String[]) usedIdentifiers[1].toArray( new String[usedIdentifiers[1].size()] ) );
+
+        st.setAttribute( "hashCode",
+                         evalText.hashCode() );
+
+        final String invokerClassName = context.getPkg().getName() + "." + context.getRuleDescr().getClassName() + utils.ucFirst( className ) + "Invoker";
+        context.getInvokers().put( invokerClassName,
+                                   st.toString() );
+        context.getInvokerLookups().put( invokerClassName,
+                                         eval );
+        context.getDescrLookups().put( invokerClassName,
+                                       evalDescr );
+        return eval;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/EvalBuilder.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/FromBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/FromBuilder.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/FromBuilder.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import java.io.IOException;
+
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.TokenStream;
+import org.codehaus.jfdi.parser.JFDILexer;
+import org.codehaus.jfdi.parser.JFDIParser;
+import org.drools.base.DroolsJFDIFactory;
+import org.drools.base.dataproviders.JFDIDataProvider;
+import org.drools.compiler.RuleError;
+import org.drools.lang.descr.AccessorDescr;
+import org.drools.lang.descr.BaseDescr;
+import org.drools.lang.descr.FromDescr;
+import org.drools.rule.Column;
+import org.drools.rule.ConditionalElement;
+import org.drools.rule.From;
+import org.drools.spi.DataProvider;
+
+/**
+ * A builder for "from" conditional element
+ * 
+ * @author etirelli
+ */
+public class FromBuilder
+    implements
+    ConditionalElementBuilder {
+
+    /**
+     * @inheritDoc
+     */
+    public ConditionalElement build(final BuildContext context,
+                                    final BuildUtils utils,
+                                    final ColumnBuilder columnBuilder,
+                                    final BaseDescr descr) {
+        FromDescr fromDescr = (FromDescr) descr;
+
+        final Column column = columnBuilder.build( context,
+                                                   utils,
+                                                   fromDescr.getReturnedColumn() );
+
+        if ( column == null ) {
+            return null;
+        }
+
+        AccessorDescr accessor = (AccessorDescr) fromDescr.getDataSource();
+        DataProvider dataProvider = null;
+        try {
+            JFDIParser parser = createParser( utils,
+                                              accessor.toString() );
+            DroolsJFDIFactory factory = new DroolsJFDIFactory( utils.getTypeResolver() );
+            factory.setDeclarationMap( context.getDeclarations() );
+            factory.setGlobalsMap( context.getPkg().getGlobals() );
+            parser.setValueHandlerFactory( factory );
+
+            dataProvider = new JFDIDataProvider( parser.expr(),
+                                                 factory );
+        } catch ( final Exception e ) {
+            context.getErrors().add( new RuleError( context.getRule(),
+                                                    fromDescr,
+                                                    null,
+                                                    "Unable to build expression for 'from' node '" + accessor.toString() + "'" ) );
+            return null;
+        }
+
+        return new From( column,
+                         dataProvider );
+    }
+
+    protected JFDIParser createParser(BuildUtils utils,
+                                      String text) throws IOException {
+        JFDIParser parser = new JFDIParser( createTokenStream( text ) );
+        DroolsJFDIFactory factory = new DroolsJFDIFactory( utils.getTypeResolver() );
+        parser.setValueHandlerFactory( factory );
+        return parser;
+    }
+
+    private TokenStream createTokenStream(String text) throws IOException {
+        return new CommonTokenStream( createLexer( text ) );
+    }
+
+    private JFDILexer createLexer(String text) throws IOException {
+        JFDILexer lexer = new JFDILexer( new ANTLRStringStream( text ) );
+        return lexer;
+    }
+
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/FromBuilder.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native

Added: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/RuleClassBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/RuleClassBuilder.java	2006-12-21 20:34:34 UTC (rev 8527)
+++ labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/RuleClassBuilder.java	2006-12-21 20:43:00 UTC (rev 8528)
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 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.semantics.java.builder;
+
+import java.util.Iterator;
+
+import org.drools.lang.descr.RuleDescr;
+
+/**
+ * @author etirelli
+ *
+ */
+public class RuleClassBuilder {
+
+    public void buildRule(final BuildContext context,
+                           final BuildUtils utils,
+                           final RuleDescr ruleDescr) {
+        // If there is no compiled code, return
+        if ( context.getMethods().isEmpty() ) {
+            context.setRuleClass( null );
+            return;
+        }
+        final String lineSeparator = System.getProperty( "line.separator" );
+
+        final StringBuffer buffer = new StringBuffer();
+        buffer.append( "package " + context.getPkg().getName() + ";" + lineSeparator );
+
+        for ( final Iterator it = context.getPkg().getImports().iterator(); it.hasNext(); ) {
+            buffer.append( "import " + it.next() + ";" + lineSeparator );
+        }
+
+        buffer.append( "public class " + utils.ucFirst( ruleDescr.getClassName() ) + " {" + lineSeparator );
+        buffer.append( "    private static final long serialVersionUID  = 320L;" + lineSeparator );
+
+        for ( int i = 0, size = context.getMethods().size() - 1; i < size; i++ ) {
+            buffer.append( context.getMethods().get( i ) + lineSeparator );
+        }
+
+        final String[] lines = buffer.toString().split( lineSeparator );
+
+        ruleDescr.setConsequenceOffset( lines.length + 1 );
+
+        buffer.append( context.getMethods().get( context.getMethods().size() - 1 ) + lineSeparator );
+        buffer.append( "}" );
+
+        context.setRuleClass( buffer.toString() );
+    }
+}


Property changes on: labs/jbossrules/trunk/drools-compiler/src/main/java/org/drools/semantics/java/builder/RuleClassBuilder.java
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + id author date revision
Name: svn:eol-style
   + native




More information about the jboss-svn-commits mailing list