[jboss-svn-commits] JBL Code SVN: r8755 - in labs/jbossrules/trunk/drools-core: . src/main/java/org src/main/java/org/codehaus/jfdi src/main/java/org/codehaus/jfdi/interpreter src/main/java/org/drools/base src/main/java/org/drools/base/dataproviders src/main/java/org/mvel src/main/java/org/mvel/compiled src/main/java/org/mvel/conversion src/main/java/org/mvel/integration src/main/java/org/mvel/integration/impl src/main/java/org/mvel/util

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sun Jan 7 15:50:59 EST 2007


Author: mark.proctor at jboss.com
Date: 2007-01-07 15:50:16 -0500 (Sun, 07 Jan 2007)
New Revision: 8755

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELDeclarationVariable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELGlobalVariable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/AccessorNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/BlankLiteral.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/CompileException.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/CompiledExpression.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ConversionException.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ConversionHandler.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/DataConversion.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ENode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ExpressionParser.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/FastTokenIterator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Interpreter.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/MVEL.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/MVELSH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Node.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/NodeType.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Operator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ParseException.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Projection.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/PropertyAccessException.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/PropertyAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Soundex.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TemplateCompiler.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TemplateParser.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Tester.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ThisLiteral.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Token.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenIterator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenMap.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ArrayAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/CompiledAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/Deferral.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/FieldAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/GetterAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/IndexedCharSeqAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ListAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/MapAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/MethodAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/StaticReferenceAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ThisValueAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/VariableAccessor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ArrayCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/BigDecimalCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/BooleanCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ByteCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/CharArrayCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/CharCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/Converter.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/DoubleCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/FloatCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/IntArrayCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/IntegerCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/LongCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ObjectCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/PrimArrayHandler.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/PrimIntArrayCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ShortCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/StringArrayCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/StringCH.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/IndexedProperty.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/VariableResolver.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/VariableResolverFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/BaseVariableResolver.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/ClassImportResolver.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/ClassImportResolverFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/LocalVariableResolverFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/MapVariableResolver.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/MapVariableResolverFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ArrayTools.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ExecutionStack.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/FastExecutionStack.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ParseTools.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/PropertyTools.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ReflectionUtil.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/Sandbox.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ShadowingExecutionStack.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/Stack.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/StackElement.java
Removed:
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/SymbolTable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AbstractValueHandlerFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AnonListValue.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AnonMapValue.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/BigDecimalOverloader.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/Coercion.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/CoercionException.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/DefaultExternalVariable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/DefaultValueHandlerFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ListValue.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/LiteralValue.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/LocalVariable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MapValue.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MethodInvoker.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MethodResolver.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/NotAnLValueException.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ObjectValue.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/OperatorOverloader.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/SymbolTableImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ValueHandler.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ValueHandlerFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/VariableValueHandler.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/operations/
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/types/
   labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/parser/
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIDeclarationVariable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIFactory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIGlobalVariable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/JFDIDataProvider.java
Modified:
   labs/jbossrules/trunk/drools-core/.classpath
Log:
JBRULES-604 integrate MVEL into JBRules intead of JFDI.

Modified: labs/jbossrules/trunk/drools-core/.classpath
===================================================================
--- labs/jbossrules/trunk/drools-core/.classpath	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/.classpath	2007-01-07 20:50:16 UTC (rev 8755)
@@ -9,6 +9,5 @@
 	<classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar"/>
 	<classpathentry kind="var" path="M2_REPO/xstream/xstream/1.1.3/xstream-1.1.3.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/antlr/antlr/3.0b5/antlr-3.0b5.jar"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/mvel"/>
 	<classpathentry kind="output" path="target/classes"/>
 </classpath>

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/SymbolTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/SymbolTable.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/SymbolTable.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,8 +0,0 @@
-package org.codehaus.jfdi;
-
-public interface SymbolTable {
-	
-	Object put(String identifier, Object object);
-	Object get(String identifier);
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AbstractValueHandlerFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AbstractValueHandlerFactory.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AbstractValueHandlerFactory.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,124 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import java.io.Serializable;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This creates value handers to attach to nodes in the AST.
- * This is an abstract factory, of which there will be a Drools implementation 
- * (but could also be a stand alone one).
- * 
- * @author Michael Neale
- */
-public abstract class AbstractValueHandlerFactory
-    implements
-    Serializable,
-    ValueHandlerFactory {
-
-    private static final long    serialVersionUID = 320L;
-
-    protected final TypeResolver typeResolver;    
-    
-    protected  String[] requiredVariables;
-
-    public AbstractValueHandlerFactory(TypeResolver typeResolver) {
-        this.typeResolver = typeResolver;
-    }
-
-    /* (non-Javadoc)
-     * @see org.codehaus.jfdi.interpreter.ValueHandlerFactory#createLiteral(int, java.lang.String)
-     */
-    public ValueHandler createLiteral(Class cls,
-                                      String val) {
-        if ( cls.getClass() == String.class ) {
-            return new LiteralValue( val );
-        } else {
-            Object objectValue = null;
-            try {
-                objectValue = cls.getDeclaredConstructor( new Class[]{String.class} ).newInstance( new Object[]{val} );
-            } catch ( Exception e ) {
-                throw new RuntimeException( e );
-            }
-            return new LiteralValue( objectValue );
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.codehaus.jfdi.interpreter.ValueHandlerFactory#createLocalVariable(java.lang.String, java.lang.String, boolean)
-     */
-    public ValueHandler createLocalVariable(String identifier,
-                                            String type,
-                                            boolean isFinal) {
-        Class clazz = null;
-        try {
-            clazz = this.typeResolver.resolveType( type );
-        } catch ( ClassNotFoundException e ) {
-            throw new RuntimeException( e );
-        }
-
-        return new LocalVariable( identifier,
-                                  clazz,
-                                  isFinal );
-    }
-
-    /* (non-Javadoc)
-     * @see org.codehaus.jfdi.interpreter.ValueHandlerFactory#createExternalVariable(java.lang.String)
-     */
-    public abstract ValueHandler createExternalVariable(String identifier);
-    
-    protected void registerExternalVariable(String identifier) {
-        // Increase the size of the array and add the new variable
-        if ( this.requiredVariables == null ) {
-            this.requiredVariables = new  String[] { identifier  };
-        }  else {
-            String[] newArray = new String[ this.requiredVariables.length + 1];
-            System.arraycopy(this.requiredVariables, 
-                             0, newArray, 0, this.requiredVariables.length );
-            newArray[ newArray.length -1 ] = identifier;
-            this.requiredVariables = newArray;
-        }
-    }    
-        
-    public String[] getRequiredVariables() {
-        return this.requiredVariables;
-    }    
-
-    public static class MapValue {
-
-        private List list;
-
-        public MapValue() {
-            list = new ArrayList();
-        }
-
-        public void add(KeyValuePair pair) {
-            this.list.add( pair );
-        }
-
-        public KeyValuePair[] getKeyValuePairs() {
-            return (KeyValuePair[]) this.list.toArray( new KeyValuePair[this.list.size()] );
-        }
-    }
-
-    public static class KeyValuePair {
-        private ValueHandler key;
-        private ValueHandler value;
-
-        public KeyValuePair(ValueHandler key,
-                            ValueHandler value) {
-            this.key = key;
-            this.value = value;
-        }
-
-        public ValueHandler getKey() {
-            return this.key;
-        }
-
-        public ValueHandler getValue() {
-            return this.value;
-        }
-    }
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AnonListValue.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AnonListValue.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AnonListValue.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,106 +0,0 @@
-/**
- * 
- */
-package org.codehaus.jfdi.interpreter;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
-import org.codehaus.jfdi.interpreter.operations.Expr;
-
-public class AnonListValue implements ValueHandler {
-
-	private static final long serialVersionUID = 320L;
-
-	private final Expr[] values;
-
-	private Object cachedValue = null;
-	
-	public AnonListValue(final List values) {
-		this( (Expr[]) values.toArray( new Expr[ values.size() ] ) );
-	}
-
-	public AnonListValue(final Expr[] values) {
-		this.values = values;
-	}
-
-	public Object getValue() {
-		if (this.cachedValue == null) {
-			final List resolvedList = new ArrayList();
-
-			for (int i = 0; i < values.length; ++i) {
-				resolvedList.add(values[i].getValue());
-			}
-
-			this.cachedValue = resolvedList;
-		}
-		return this.cachedValue;
-	}
-
-	public Class getExtractToClass() {
-		return List.class;
-	}
-
-	public void reset() {
-		this.cachedValue = null;
-	}
-
-	public String toString() {
-		return "[ListValue list=" + Arrays.asList(values) + "]";
-	}
-
-	public int hashCode() {
-		final int PRIME = 31;
-		int result = 1;
-		result = PRIME * result + values.hashCode();
-		return result;
-	}
-
-	public boolean equals(Object object) {
-		if (this == object) {
-			return true;
-		}
-
-		if (object == null || getClass() != object.getClass()) {
-			return false;
-		}
-
-		final AnonListValue other = (AnonListValue) object;
-		
-		if (values.length != other.values.length) {
-			return false;
-		}
-		
-		for ( int i = 0 ; i < values.length ; ++i ) {
-			if ( values[i] != other.values[i] ) {
-				return false;
-			}
-		}
-		
-		return true;
-	}
-
-	public Class getType() {
-		return List.class;
-	}
-
-	public boolean isFinal() {
-		return true;
-	}
-
-	public boolean isLiteral() {
-		return false;
-	}
-
-	public boolean isLocal() {
-		return false;
-	}
-
-	public void setValue(Object variable) {
-		throw new UnsupportedOperationException(
-				"Not allowed to set the value of a list.");
-	}
-
-}
\ No newline at end of file

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AnonMapValue.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AnonMapValue.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/AnonMapValue.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,136 +0,0 @@
-/**
- * 
- */
-package org.codehaus.jfdi.interpreter;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.codehaus.jfdi.interpreter.operations.Expr;
-
-public class AnonMapValue
-    implements
-    ValueHandler {
-    
-    private static final long serialVersionUID = 320L;
-
-    private final KeyValuePair[] pairs;
-    
-    
-    private Object cachedValue = null;    
-
-    public AnonMapValue(final KeyValuePair[] pairs) {
-        this.pairs = pairs;
-    }
-
-    public Object getValue() {
-        if ( this.cachedValue == null ) {            
-            final Map map = new HashMap();
-    
-            for ( int i = 0, length = this.pairs.length; i < length; i++ ) {
-                final Expr key = this.pairs[i].getKey();
-                final Expr value = this.pairs[i].getValue();
-                map.put( key.getValue(  ),
-                         value.getValue( ) );
-            }
-            this.cachedValue = map;
-        }
-
-        return this.cachedValue;
-    }
-    
-    public Class getExtractToClass() {
-        return Map.class;
-    }     
-
-    public void reset() {
-        this.cachedValue = null;
-    }    
-    
-    public static class KeyValuePair implements Serializable {
-        private static final long serialVersionUID = 320L;
-        
-        private Expr key;
-        private Expr value;
-
-        public KeyValuePair(final Expr key,
-                            final Expr value) {
-            this.key = key;
-            this.value = value;
-        }
-
-        /**
-         * 
-         * @return The ValueHandler for the key
-         */
-        public Expr getKey() {
-            return this.key;
-        }
-
-        /**
-         * 
-         * @return The ValueHandler for the value
-         */
-        public Expr getValue() {
-            return this.value;
-        }
-        
-        public String toString() {
-            return this.key + "/" + this.value;
-        }
-
-        public int hashCode() {
-            final int PRIME = 31;
-            int result = 1;
-            result = PRIME * result + this.key.hashCode();
-            result = PRIME * result + this.value.hashCode();
-            return result;
-        }                
-
-        public boolean equals(Object object) {
-            if ( this == object ) {
-                return true;
-            }
-            
-            if ( object == null ||  getClass() != object.getClass() ) {
-                return false;
-            }
-            final KeyValuePair other = (KeyValuePair) object;
-            return this.key.equals( other.key ) && this.value.equals( other.value );
-        }                        
-    }
-    
-    public String toString() {
-        StringBuffer buffer = new StringBuffer();
-        buffer.append( "MapValue pairs=" );
-        for ( int i = 0, length = this.pairs.length; i < length; i++ ) {
-            buffer.append( this.pairs[i] );            
-        }
-        buffer.append( "]" );
-        
-        return buffer.toString();
-    }
-
-
-    public Class getType() {
-        return Map.class;
-    }
-
-    public boolean isFinal() {        
-        return true;
-    }
-
-    public boolean isLiteral() {        
-        return false;
-    }
-
-    public boolean isLocal() {
-        return false;
-    }
-
-    public void setValue(Object variable) {
-        throw new UnsupportedOperationException("You can't change the value of a map (only the contents).");        
-    }
-    
-}
\ No newline at end of file

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/BigDecimalOverloader.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/BigDecimalOverloader.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/BigDecimalOverloader.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,41 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import java.math.BigDecimal;
-
-
-public class BigDecimalOverloader
-    implements
-    OperatorOverloader {
-
-    public Object divide(Object left,
-                         Object right) {
-        BigDecimal l = (BigDecimal) left;        
-        return l.divide( (BigDecimal) right, BigDecimal.ROUND_HALF_UP );        
-    }
-
-    public Class getApplicableType() {        
-        return BigDecimal.class;
-    }
-
-    public Object minus(Object left,
-                        Object right) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public Object multiply(Object left,
-                           Object right) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public Object plus(Object left,
-                       Object right) {
-        BigDecimal l = (BigDecimal) left;
-        BigDecimal r = (BigDecimal) right;
-        
-        //hmmm... should the right allow a string or something else? 
-        return l.add( r );
-    }
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/Coercion.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/Coercion.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/Coercion.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,50 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-public class Coercion {
-	
-	public static boolean toBoolean(Object obj) {
-		if ( obj instanceof Boolean ) {
-			return ((Boolean)obj).booleanValue();
-		}
-		
-		throw new CoercionException( obj, "boolean" );
-	}
-	
-	public static int toInteger(Object obj) {
-		if ( obj instanceof Number ) {
-			return ((Number)obj).intValue();
-		}
-		throw new CoercionException( obj, "integer" );
-	}
-	
-	public static BigInteger toBigInteger(Object object) {
-		if ( object instanceof BigInteger ) {
-			return (BigInteger) object;
-		}
-		
-		if ( object instanceof BigDecimal ) {
-			return ((BigDecimal)object).toBigInteger();
-		}
-		
-		return new BigInteger( object.toString() );
-	}
-	
-	public static double toFloat(Object obj) {
-		if ( obj instanceof Number ) {
-			return ((Number)obj).doubleValue();
-		}
-		throw new CoercionException( obj, "floating-point" );
-	}
-	
-	public static BigDecimal toBigDecimal(Object object) {
-		if ( object instanceof BigDecimal ) {
-			return (BigDecimal) object;
-		}
-		
-		return new BigDecimal( object.toString() );
-	}
-}
-	

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/CoercionException.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/CoercionException.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/CoercionException.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,17 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-public class CoercionException extends RuntimeException {
-	
-	private Object obj;
-	private String type;
-
-	public CoercionException(Object obj, String type) {
-		this.obj = obj;
-		this.type = type;
-	}
-	
-	public String getMessage() {
-		return "Invalid coercion: " + obj.getClass().getName() + " to " + type;
-	}
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/DefaultExternalVariable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/DefaultExternalVariable.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/DefaultExternalVariable.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,52 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import java.util.Map;
-
-public class DefaultExternalVariable
-    implements
-    VariableValueHandler {
-    private Map context;
-    
-    private Object cachedValue;
-    
-    private String identifer;
-    private Class type;
-    
-    public DefaultExternalVariable(String identifier,
-                                   Map context) {
-        this.identifer = identifier;
-        this.context = context;
-    }
-    
-    public String getIdentifier() {
-        return this.identifer;
-    }
-
-    public Class getType() {
-        return getValue().getClass();
-    }
-
-    public Object getValue() {
-        if ( this.cachedValue  ==  null ) {
-            this.cachedValue = this.context.get( this.identifer );
-        }
-        return this.cachedValue;
-    }
-
-    public boolean isFinal() {
-        return true;
-    }
-
-    public boolean isLiteral() {
-        return false;
-    }
-
-    public boolean isLocal() {
-        return false;
-    }
-
-    public void setValue(Object value) {
-        throw new UnsupportedOperationException( "External Variable identifer='" + this.identifer + "' type='" + this.type + "' is final, it cannot be set" );
-    }
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/DefaultValueHandlerFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/DefaultValueHandlerFactory.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/DefaultValueHandlerFactory.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,32 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class DefaultValueHandlerFactory extends AbstractValueHandlerFactory {
-    
-    public Map variables = new HashMap();       
-
-    public DefaultValueHandlerFactory(TypeResolver typeResolver) {
-        super( typeResolver );
-    }
-
-    public void addVariable(String identifier,
-                            Object instance) {
-        this.variables.put( identifier,
-                            instance );
-    }
-
-    public ValueHandler createExternalVariable(String identifier) {        
-        registerExternalVariable( identifier );
-        
-        VariableValueHandler handler = new DefaultExternalVariable( identifier,
-                                                                    this.variables );
-                
-        return handler;
-    }
-
-    public boolean isValidVariable(String identifier) {        
-        return variables.containsKey( identifier );
-    }    
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ListValue.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ListValue.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ListValue.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,21 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import java.util.List;
-
-public class ListValue extends AnonListValue
-    implements
-    VariableValueHandler {
-
-    private final String identifier;
-
-    public ListValue(List list, String identifier) {
-        super( list );
-        this.identifier = identifier;
-        
-    }
-
-    public String getIdentifier() {
-        return identifier;
-    }
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/LiteralValue.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/LiteralValue.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/LiteralValue.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,78 +0,0 @@
-/**
- * 
- */
-package org.codehaus.jfdi.interpreter;
-
-
-public class LiteralValue
-    implements
-    ValueHandler {
-    
-    private static final long serialVersionUID = 320L;
-
-    private final Object value;
-
-    private int id;       
-
-    public LiteralValue(final Object value) {
-        this.value = value;
-    }
-
-    public Object getValue() {
-        return this.value;
-    }
-    
-    public void reset() {
-        // N/A
-    }    
-    
-    public String toString() {
-        return "LiteralValue value=[" + this.value + "]";
-    }
-
-    public int hashCode() {
-        final int PRIME = 31;
-        int result = 1;
-        result = PRIME * this.value.hashCode();
-        return result;
-    }
-
-    public boolean equals(Object object) {
-        if ( this == object ) {
-            return true;
-        }
-        if ( object == null || getClass() != object.getClass()) {
-            return false;
-        }
-        final LiteralValue other = (LiteralValue) object;
-        return this.value.equals( other.value );
-    }
-
-    public int getId() {
-
-        return this.id;
-    }
-
-    public Class getType() {       
-        return this.value.getClass();
-    }
-
-    public boolean isFinal() {
-        return true;
-    }
-
-    public boolean isLiteral() {
-        return true;
-    }
-
-    public boolean isLocal() {
-        return true;
-    }
-
-    public void setValue(Object variable) {
-        throw new UnsupportedOperationException("You can't treat a literal value as a variable.");        
-    }
-    
-    
-
-}
\ No newline at end of file

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/LocalVariable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/LocalVariable.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/LocalVariable.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,51 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-public class LocalVariable implements VariableValueHandler {
-
-    
-    private final Class type;
-    private Object value;
-    private final boolean isFinal;
-    private final String identifier;
-    
-    
-    public LocalVariable(String identifier, 
-                         Class type,
-                         boolean isFinal) {
-        this.type = type;
-        this.isFinal = isFinal;
-        this.identifier = identifier;
-    }    
-
-    public Class getType() {
-        return this.type;
-    }
-
-    public Object getValue() {
-        
-        return this.value;
-    }
-
-    public boolean isFinal() {
-
-        return isFinal;
-    }
-
-    public boolean isLiteral() {
-        return false;
-    }
-
-    public boolean isLocal() {
-        return true;
-    }
-
-    public void setValue(Object variable) {
-        this.value = variable;
-        
-    }
-
-    public String getIdentifier() {
-        return this.identifier;
-    }
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MapValue.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MapValue.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MapValue.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,18 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-
-/** This is a map value that is a variable (still inline, but it has been assigned to something */
-public class MapValue extends AnonMapValue implements VariableValueHandler {
-
-    private final String identifier;
-
-    public MapValue(KeyValuePair[] pairs, String identifier) {
-        super( pairs );
-        this.identifier = identifier;
-    }
-
-    public String getIdentifier() {
-        return identifier;
-    }
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MethodInvoker.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MethodInvoker.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MethodInvoker.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,87 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.Date;
-
-public class MethodInvoker {
-	private Method method;
-
-	private boolean isFunction;
-
-	private final Object[] params;
-
-	private Class[] parameterTypes;
-
-	/**
-	 * Method invoker
-	 */
-	public MethodInvoker(Method method, boolean isFunction, Object[] params) {
-		this.method = method;
-		this.params = params;
-		this.isFunction = isFunction;
-	}
-
-	public Object invoke(Object instance) throws IllegalArgumentException,
-			IllegalAccessException, InvocationTargetException {
-		
-		System.err.println( "invoke ::" + method  + " on " + instance );
-
-		// None static methods cannot have a null instance
-		if (!isFunction && instance == null) {
-			throw new NullPointerException(
-					"Cannot call the non-static method ["
-							+ this.method.getName() + "] on the class ["
-							+ this.method.getDeclaringClass().getName()
-							+ " with a null instance");
-		}
-
-		Object result = null;
-
-		System.err.println("invoke on " + instance);
-		System.err.println("invoke of " + method);
-		System.err.println("invoke with " + Arrays.asList( params ) );
-
-		// now the actual invoking of the method
-		result = this.method.invoke(instance, params);
-
-		return result;
-	}
-
-	/**
-	 * Attempt to convert text to the target class type
-	 */
-	private static Object convert(String text, Class type) {
-		if (type == Integer.class || type == int.class) {
-			return new Integer(text);
-		} else if (text == "null") {
-			return null;
-		} else if (type == Character.class || type == char.class) {
-			return (new Character(text.charAt(0)));
-		} else if (type == Short.class || type == short.class) {
-			return new Short(text);
-		} else if (type == Long.class || type == long.class) {
-			return new Long(text);
-		} else if (type == Float.class || type == float.class) {
-			return new Float(text);
-		} else if (type == Double.class || type == double.class) {
-			return new Double(text);
-		} else if (type == Boolean.class || type == boolean.class) {
-			return new Boolean(text);
-		} else if (type == Date.class) {
-			// return DateFactory.parseDate( text );
-			throw new UnsupportedOperationException(
-					"Whoops ! need to do dates !");
-		} else if (type == BigDecimal.class) {
-			return new BigDecimal(text);
-		} else if (type == BigInteger.class) {
-			return new BigInteger(text);
-		} else {
-			throw new IllegalArgumentException("Unable to convert [" + text
-					+ "] to type: [" + type.getName() + "]");
-		}
-	}
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MethodResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MethodResolver.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/MethodResolver.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,159 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.codehaus.jfdi.interpreter.operations.Expr;
-
-/**
- * Determines the method to call, based on the given values
- * 
- */
-public class MethodResolver {
-
-	private final static MethodResolver instance = new MethodResolver();
-
-	public static MethodResolver getInstance() {
-		return instance;
-	}
-
-	private MethodResolver() {
-	}
-
-	public Method resolveMethod(Class clazz, String name, Object[] params) {
-
-		System.err.println("resolve " + name + " on " + clazz);
-
-		Class[] classes = new Class[params.length];
-		for (int i = 0, length = params.length; i < length; i++) {
-			classes[i] = params[i].getClass();
-		}
-
-		return resolveMethod(clazz, name, classes);
-	}
-
-	public Method resolveMethod(Class clazz, String name, Class[] params) {
-		Method method = null;
-
-		boolean allDefined = true;
-
-		// check for null params, so we know if all the types are defined
-		for (int i = 0, length = params.length; i < length; i++) {
-			System.err.println( "param: " + params[i] );
-			if (params[i] == null) {
-				allDefined = false;
-			}
-		}
-		
-		System.err.println( "clazz: " + clazz );
-		System.err.println( "name: " + name );
-
-		if (allDefined) {
-			method = getMethod(clazz, name, params);
-		} else {
-			// For some reason all the types are not specified, so just match
-			// the first method with the same
-			// number of arguments
-			Method[] methods = getMethods(clazz, name, params.length);
-			if (methods != null && methods.length != 0) {
-				method = methods[0];
-			}
-		}
-
-		// @todo We could potentially output a warning here
-		// if ( (method.getModifiers() & Modifier.PUBLIC) != Modifier.PUBLIC ) {
-		// throw new RuntimeDroolsException( "Unable to call the private method
-		// [" + name + "] on class [" + clazz.getName() + "] for parameters " +
-		// arrayToString( params ) );
-		// }
-		System.err.println( "find " + method );
-		return method;
-	}
-
-	public boolean isStatic(Method method) {
-		return (method != null && (method.getModifiers() & Modifier.STATIC) == Modifier.STATIC);
-	}
-
-	/**
-	 * work out what method we will be calling at runtime, based on the name and
-	 * number of parameters.
-	 */
-	private Method getMethod(Class clazz, String methodName, Class[] args) {
-
-		// Fist get methods with same number of arguments
-		Method[] methods = getMethods(clazz, methodName, args.length);
-		if (methods.length == 0) {
-			return null;
-		}
-
-		// now iterate to find correct method
-		for (int i = 0, length = methods.length; i < length; i++) {
-			if (matchesTypes(methods[i].getParameterTypes(), args)) {
-				return methods[i];
-			}
-		}
-
-		// Casting hasn't worked, so just return the first method with the same
-		// number of params
-		return methods[0];
-	}
-
-	private Method[] getMethods(Class clazz, String methodName, int length) {
-		List list = new ArrayList();
-		Method[] methods = clazz.getMethods();
-		for (int i = 0; i < methods.length; i++) {
-			if (methods[i].getName().equals(methodName)) {
-				System.err.println( "NAME: " + methods[i] );
-				System.err.println( "len: " + length );
-				if (methods[i].getParameterTypes().length == length) {
-					System.err.println( "ADD: " + methods[i] );
-					list.add(methods[i]);
-				}
-			}
-		}
-		return (Method[]) list.toArray(new Method[list.size()]);
-	}
-	
-	private boolean matchesTypes(Class[] methodClasses, Class[] argumentClasses) {
-		for (int i = 0, length = methodClasses.length; i < length; i++) {
-			Class methodClass = methodClasses[i];
-			Class argumentClass = argumentClasses[i];
-			if (methodClasses[i].isPrimitive()) {
-				// try matching to primitive
-				if (methodClass == int.class && argumentClass == Integer.class) {
-					continue;
-				} else if (methodClass == long.class
-						&& argumentClass == Long.class) {
-					continue;
-				} else if (methodClass == float.class
-						&& argumentClass == Float.class) {
-					continue;
-				} else if (methodClass == double.class
-						&& argumentClass == Double.class) {
-					continue;
-				} else {
-					return false;
-				}
-			} else if (methodClasses[i] != argumentClasses[i]) {
-				return false;
-			}
-		}
-		return true;
-	}
-
-	private String arrayToString(Object[] values) {
-		StringBuffer args = new StringBuffer();
-		for (int i = 0, length = values.length; i < length; i++) {
-			args.append("[");
-			args.append(values[i].getClass());
-			args.append("]");
-			if (i < length - 1) {
-				args.append(", ");
-			}
-		}
-		return args.toString();
-	}
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/NotAnLValueException.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/NotAnLValueException.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/NotAnLValueException.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,15 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-public class NotAnLValueException extends RuntimeException {
-	
-	private Object obj;
-
-	public NotAnLValueException(Object obj) {
-		this.obj = obj;
-	}
-	
-	public String getMessage() {
-		return "Not an l-value: " + obj;
-	}
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ObjectValue.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ObjectValue.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ObjectValue.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,37 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-public class ObjectValue implements ValueHandler {
-	
-	private Object value;
-
-	public ObjectValue(Object value) {
-		this.value = value;
-	}
-
-	public void setValue(Object value) {
-		throw new NotAnLValueException( value );
-	}
-
-	public boolean isLocal() {
-		return true;
-	}
-
-	public boolean isFinal() {
-		// TODO Auto-generated method stub
-		return true;
-	}
-
-	public boolean isLiteral() {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public Class getType() {
-		return value.getClass();
-	}
-
-	public Object getValue() {
-		return value;
-	}
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/OperatorOverloader.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/OperatorOverloader.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/OperatorOverloader.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,19 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-/**
- * This interface is to be implemented by users, to provide declarations of operator overloading.
- * The engine can use this to apply operators accordingly when it is registered. 
- * 
- * @author Michael Neale
- */
-public interface OperatorOverloader {
-
-    Object plus(Object left, Object right);
-    Object minus(Object left, Object right);
-    Object multiply(Object left, Object right);
-    Object divide(Object left, Object right);
-    
-    Class getApplicableType();
-    
-    
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/SymbolTableImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/SymbolTableImpl.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/SymbolTableImpl.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,49 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.codehaus.jfdi.SymbolTable;
-
-class SymbolTableImpl implements SymbolTable {
-	
-	private List stackFrames;
-	
-	SymbolTableImpl() {
-		this.stackFrames = new ArrayList();
-	}
-	
-	void pushFrame() {
-		stackFrames.add( new HashMap() );
-	}
-	
-	void popFrame() {
-		stackFrames.remove( stackFrames.size() - 1 );
-	}
-
-	public Object put(String identifier, Object object) {
-		for ( Iterator frameIter = stackFrames.iterator(); frameIter.hasNext(); ) {
-			Map frame = (Map) frameIter.next();
-			if ( frame.containsKey( identifier ) ) {
-				return frame.put( identifier, object );
-			}
-		}
-		
-		Map lastFrame = (Map) stackFrames.get( stackFrames.size() - 1 );
-		return lastFrame.put( identifier, object );
-	}
-
-	public Object get(String identifier) {
-		for ( int i = stackFrames.size(); i >= 0 ; --i ) {
-			Map frame = (Map) stackFrames.get( i );
-			if ( frame.containsKey( identifier ) ) {
-				return frame.get( identifier );
-			}
-		}
-		return null;
-	}
-	
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ValueHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ValueHandler.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ValueHandler.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,16 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-import org.codehaus.jfdi.interpreter.operations.Expr;
-
-/**
- * This specifies a container for a variable that will be used at runtime. 
- * The runtime will call this when executing.
- */
-public interface ValueHandler extends Expr {
-    void setValue(Object value);
-    
-    boolean isLocal();
-    boolean isFinal();
-    boolean isLiteral();
-    
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ValueHandlerFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ValueHandlerFactory.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/ValueHandlerFactory.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,48 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-public interface ValueHandlerFactory {
-
-    /** the type parameter is one of the following constants */
-    /** Obviously if it was in quotes, its a string literal (which could be anything) */
-    public static final int STRING     = 1;
-    /** Means true integer, not Javas interpretation of it */
-    public static final int CHAR       = 2;
-    public static final int INTEGER    = 4;
-    public static final int LONG       = 8;
-    public static final int FLOAT      = 16;
-    public static final int DOUBLE     = 32;
-    public static final int BIGINTEGER = 64;    
-    public static final int BIGDECIMAL = 128;
-    public static final int BOOLEAN    = 256;  
-    public static final int NULL       = 512;    
-    public static final int MAP        = 1024;    
-    public static final int LIST       = 2048;
-
-    /**
-     * This is for creating a literal "value handler"
-     */
-    public ValueHandler createLiteral(Class cls,
-                                               String val);
-
-    /** 
-     * A local variable requires a type of some form (class).
-     */
-    public ValueHandler createLocalVariable(String identifier,
-                                                     String type,
-                                                     boolean isFinal);
-
-    /** 
-     * To be implemented by the concrete factory.
-     * External variables will be provided to the parser ahead of time.
-     */
-    public ValueHandler createExternalVariable(String identifier);
-    
-    /**
-     * return true if the specified external identifier is a variable.
-     */
-    public boolean isValidVariable(String identifier);
-    
-    public String[] getRequiredVariables();
-    
-
-}
\ No newline at end of file

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/VariableValueHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/VariableValueHandler.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/codehaus/jfdi/interpreter/VariableValueHandler.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,8 +0,0 @@
-package org.codehaus.jfdi.interpreter;
-
-public interface VariableValueHandler extends ValueHandler {
-    
-    /** the id of the actual variable in the source. */
-    String getIdentifier();
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIDeclarationVariable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIDeclarationVariable.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIDeclarationVariable.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,51 +0,0 @@
-package org.drools.base;
-
-import java.util.Map;
-
-import org.codehaus.jfdi.interpreter.VariableValueHandler;
-import org.drools.reteoo.ReteTuple;
-import org.drools.rule.Declaration;
-import org.drools.spi.FieldExtractor;
-
-public class DroolsJFDIDeclarationVariable
-    implements
-    VariableValueHandler {
-    
-    private Declaration declaration;
-    private DroolsJFDIFactory factory;
-       
-    public DroolsJFDIDeclarationVariable(Declaration declaration,
-                                      DroolsJFDIFactory factory ) {
-        this.declaration = declaration;
-        this.factory =  factory;
-    }
-    
-    public String getIdentifier() {
-        return this.declaration.getIdentifier();
-    }
-
-    public Class getType() {
-        return declaration.getExtractor().getExtractToClass();
-    }
-
-    public Object getValue() {
-        return declaration.getValue( this.factory.getValue( this.declaration ));
-    }
-
-    public boolean isFinal() {
-        return true;
-    }
-
-    public boolean isLiteral() {
-        return false;
-    }
-
-    public boolean isLocal() {
-        return false;
-    }
-
-    public void setValue(Object value) {
-        throw new UnsupportedOperationException( "External Variable identifer='" + getIdentifier() + "' type='" + getType() + "' is final, it cannot be set" );
-    }
-
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIFactory.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIFactory.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,70 +0,0 @@
-package org.drools.base;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-import org.codehaus.jfdi.interpreter.AbstractValueHandlerFactory;
-import org.codehaus.jfdi.interpreter.TypeResolver;
-import org.codehaus.jfdi.interpreter.ValueHandler;
-import org.drools.WorkingMemory;
-import org.drools.common.InternalWorkingMemory;
-import org.drools.reteoo.ReteTuple;
-import org.drools.rule.Declaration;
-import org.drools.spi.Tuple;
-
-public class DroolsJFDIFactory extends AbstractValueHandlerFactory {    
-    private Tuple tuple;
-    private Map declarations;
-    private Map globals;
-    //private
-    private WorkingMemory workingMemory;
-    
-    public DroolsJFDIFactory(TypeResolver typeResolver) {
-        super( typeResolver );
-    }
-    
-    public void setDeclarationMap(Map declarations) {
-        this.declarations = declarations;
-    }
-    
-    public void setGlobalsMap(Map globals) {
-        this.globals = globals;
-    }
-    
-    public void setContext(Tuple tuple, WorkingMemory workingMemory) {
-        this.tuple = tuple;
-        this.workingMemory = workingMemory;
-    }
-    
-    public Object getValue(Declaration declaration) {
-        return tuple.get( declaration ).getObject();
-    }
-    
-    public Object getValue(String identifier) {
-        return this.workingMemory.getGlobal( identifier );
-    }    
-
-    public ValueHandler createExternalVariable(String identifier) {        
-        registerExternalVariable( identifier );
-        ValueHandler variable;
-        if ( this.declarations.containsKey( identifier )) {
-            variable = new DroolsJFDIDeclarationVariable( (Declaration) this.declarations.get( identifier ), this );
-        } else {
-            variable = new DroolsJFDIGlobalVariable( identifier, (Class) this.globals.get( identifier ), this );
-        }
-        return variable;
-    }
-
-    public boolean isValidVariable(String identifier) {        
-        return this.declarations.containsKey( identifier );
-    }   
-    
-    public Declaration[] getRequiredDeclarations()  {
-        List list = new ArrayList();
-        for (int i  = 0, length  = this.requiredVariables.length; i < length; i++) {
-            list.add( this.declarations.get( this.requiredVariables[i] ) );
-        }
-        return (Declaration[]) list.toArray( new Declaration[list.size()  ]  );
-    }
-}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIGlobalVariable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIGlobalVariable.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsJFDIGlobalVariable.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,54 +0,0 @@
-package org.drools.base;
-
-import java.util.Map;
-
-import org.codehaus.jfdi.interpreter.VariableValueHandler;
-import org.drools.reteoo.ReteTuple;
-import org.drools.rule.Declaration;
-import org.drools.spi.FieldExtractor;
-
-public class DroolsJFDIGlobalVariable
-    implements
-    VariableValueHandler {
-    
-    private String identifier;
-    private Class type;
-    private DroolsJFDIFactory factory;
-       
-    public DroolsJFDIGlobalVariable(String identifier,
-                                    Class type,
-                                    DroolsJFDIFactory factory ) {
-        this.identifier = identifier;
-        this.factory =  factory;
-        this.type = type;
-    }
-    
-    public String getIdentifier() {
-        return this.identifier;
-    }
-
-    public Class getType() {
-        return this.type;
-    }
-
-    public Object getValue() {
-        return this.factory.getValue( this.identifier );
-    }
-
-    public boolean isFinal() {
-        return true;
-    }
-
-    public boolean isLiteral() {
-        return false;
-    }
-
-    public boolean isLocal() {
-        return false;
-    }
-
-    public void setValue(Object value) {
-        throw new UnsupportedOperationException( "External Variable identifer='" + getIdentifier() + "' type='" + getType() + "' is final, it cannot be set" );
-    }
-
-}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELDeclarationVariable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELDeclarationVariable.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELDeclarationVariable.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,39 @@
+package org.drools.base;
+
+import org.drools.rule.Declaration;
+import org.mvel.integration.VariableResolver;
+
+public class DroolsMVELDeclarationVariable
+    implements
+    VariableResolver {
+    
+    private Declaration declaration;
+    private DroolsMVELFactory factory;
+       
+    public DroolsMVELDeclarationVariable(Declaration declaration,
+    		DroolsMVELFactory factory ) {
+        this.declaration = declaration;
+        this.factory =  factory;
+    }        
+    
+    public String getName() {
+        return this.declaration.getIdentifier();
+    }
+
+    public Class getKnownType() {
+        return declaration.getExtractor().getExtractToClass();
+    }
+
+    public Object getValue() {
+        return declaration.getValue( this.factory.getValue( this.declaration ));
+    }
+
+    public void setValue(Object value) {
+        throw new UnsupportedOperationException( "External Variable identifer='" + getName() + "' type='" + getKnownType()+ "' is final, it cannot be set" );
+    }
+    
+    public int getFlags()  {
+    	return 0;
+    }    
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELFactory.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELFactory.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,116 @@
+package org.drools.base;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.WorkingMemory;
+import org.drools.rule.Declaration;
+import org.drools.spi.Tuple;
+import org.mvel.integration.VariableResolver;
+import org.mvel.integration.VariableResolverFactory;
+
+public class DroolsMVELFactory implements VariableResolverFactory {    
+    private Tuple tuple;
+    private Map declarations;
+    private Map globals;
+    
+    private Map resolvers;
+    //private
+    private WorkingMemory workingMemory;
+    
+    public DroolsMVELFactory() {
+    	this.resolvers = Collections.EMPTY_MAP;
+    }
+    
+    public void setDeclarationMap(Map declarations) {
+        this.declarations = declarations;
+    }
+    
+    public void setGlobalsMap(Map globals) {
+        this.globals = globals;
+    }
+    
+    public void setContext(Tuple tuple, WorkingMemory workingMemory) {
+        this.tuple = tuple;
+        this.workingMemory = workingMemory;
+    }
+    
+    public Object getValue(Declaration declaration) {
+        return tuple.get( declaration ).getObject();
+    }
+    
+    public Object getValue(String identifier) {
+        return this.workingMemory.getGlobal( identifier );
+    }
+
+	public VariableResolver createVariable(String name, Object value) {
+		throw new UnsupportedOperationException( "Variables cannot be created here" );
+	}
+
+	public VariableResolverFactory getNextFactory() {
+		return null;
+	}
+
+	public VariableResolverFactory setNextFactory(VariableResolverFactory resolverFactory) {
+		throw new UnsupportedOperationException( "Chained factories are not support for DroolsMVELFactory" );
+	}    	
+	
+	public VariableResolver getVariableResolver(String name) {	 	  
+		return ( VariableResolver ) this.resolvers.get( name );
+	}
+
+	public boolean isResolveable(String name) {
+		 //return this.declarations.containsKey( name ) || this.globals.containsKey( name );
+		  if ( this.resolvers == Collections.EMPTY_MAP) {
+			  this.resolvers = new HashMap();
+		  }
+		  
+		  VariableResolver resolver = (VariableResolver) this.resolvers.get( name );
+		  
+		  if ( resolver != null )  {
+			  return true;
+		  }
+		  
+	      if ( this.declarations.containsKey( name )) {
+	    	  resolver = new DroolsMVELDeclarationVariable( (Declaration) this.declarations.get( name ), this );
+	      } else {
+	    	  resolver = new DroolsMVELGlobalVariable( name, (Class) this.globals.get( name ), this );
+	      }
+	      
+	      if ( resolver != null ) {
+	    	  this.resolvers.put( name,  resolver );
+	    	  return true;
+	      } else {
+	    	  return false;
+	      }	      	
+	}
+
+	public boolean isTarget(String name) {
+		return this.resolvers.containsKey( name  );
+	}    
+    
+//    public ValueHandler createExternalVariable(String identifier) {        
+//        registerExternalVariable( identifier );
+//        ValueHandler variable;
+//        if ( this.declarations.containsKey( identifier )) {
+//            variable = new DroolsMVELDeclarationVariable( (Declaration) this.declarations.get( identifier ), this );
+//        } else {
+//            variable = new DroolsMVELGlobalVariable( identifier, (Class) this.globals.get( identifier ), this );
+//        }
+//        return variable;
+//    	return null;
+//    }
+//
+//    public boolean isValidVariable(String identifier) {        
+//        return this.declarations.containsKey( identifier );
+//    }   
+//    
+//    public Declaration[] getRequiredDeclarations()  {
+//        List list = new ArrayList();
+//        for (int i  = 0, length  = this.requiredVariables.length; i < length; i++) {
+//            list.add( this.declarations.get( this.requiredVariables[i] ) );
+//        }
+//        return (Declaration[]) list.toArray( new Declaration[list.size()  ]  );
+//    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELGlobalVariable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELGlobalVariable.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/DroolsMVELGlobalVariable.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,41 @@
+package org.drools.base;
+
+import org.mvel.integration.VariableResolver;
+
+public class DroolsMVELGlobalVariable
+    implements
+    VariableResolver {
+    
+    private String name;
+    private Class knownType;
+    private DroolsMVELFactory factory;
+       
+    public DroolsMVELGlobalVariable(String identifier,
+                                    Class knownType,
+                                    DroolsMVELFactory factory ) {
+        this.name = identifier;
+        this.factory =  factory;
+        this.knownType = knownType;
+    }
+    
+    public String getName() {
+        return this.name;
+    }
+
+    public Class getKnownType() {
+        return this.knownType;
+    }
+
+    public Object getValue() {
+        return this.factory.getValue( this.name );
+    }
+
+    public void setValue(Object value) {
+        throw new UnsupportedOperationException( "External Variable identifer='" + getName() + "' type='" + getKnownType() + "' is final, it cannot be set" );
+    }
+    
+    public int getFlags()  {
+    	return 0;
+    }        
+
+}

Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/JFDIDataProvider.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/JFDIDataProvider.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/JFDIDataProvider.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -1,46 +0,0 @@
-package org.drools.base.dataproviders;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-
-import org.codehaus.jfdi.interpreter.operations.Expr;
-import org.codehaus.jfdi.parser.JFDIParser;
-import org.drools.WorkingMemory;
-import org.drools.base.DroolsJFDIFactory;
-import org.drools.reteoo.ReteTuple;
-import org.drools.rule.Declaration;
-import org.drools.spi.DataProvider;
-import org.drools.spi.PropagationContext;
-import org.drools.spi.Tuple;
-
-public class JFDIDataProvider
-    implements
-    DataProvider {
-    private final Expr              expression;
-    private final DroolsJFDIFactory factory;
-
-    public JFDIDataProvider(final Expr expression,
-                            final DroolsJFDIFactory factory) {
-        this.expression = expression;
-        this.factory = factory;
-    }
-
-    public Declaration[] getRequiredDeclarations() {
-        return factory.getRequiredDeclarations();
-    }
-
-    public Iterator getResults(final Tuple tuple,
-                               final WorkingMemory wm,
-                               final PropagationContext ctx) {
-        factory.setContext( tuple, wm );
-        Object result = this.expression.getValue();
-        if ( result instanceof Collection ) {
-            return ((Collection) result).iterator();
-        } else if ( result instanceof Iterator ) {
-            return (Iterator) result;
-        } else {
-            return Collections.singletonList( result ).iterator();
-        }
-    }
-}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/base/dataproviders/MVELDataProvider.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,50 @@
+package org.drools.base.dataproviders;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.drools.WorkingMemory;
+import org.drools.base.DroolsMVELFactory;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.Declaration;
+import org.drools.spi.DataProvider;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.mvel.CompiledExpression;
+import org.mvel.ExpressionParser;
+
+public class MVELDataProvider
+    implements
+    DataProvider {
+    //private final Expr              expression;
+    private final CompiledExpression expression;
+    private final DroolsMVELFactory factory;
+
+    public MVELDataProvider(final CompiledExpression expression,
+                            final DroolsMVELFactory factory) {
+        this.expression = expression;
+        this.factory = factory;
+    }
+
+    public Declaration[] getRequiredDeclarations() {
+    	return new Declaration[]  {};
+        //return factory.getRequiredDeclarations();
+    }
+
+    public Iterator getResults(final Tuple tuple,
+                               final WorkingMemory wm,
+                               final PropagationContext ctx) {
+        factory.setContext( tuple, wm );
+                        
+        //this.expression.
+        Object result = ExpressionParser.executeExpression(this.expression, factory);
+        if ( result instanceof Collection ) {
+            return ((Collection) result).iterator();
+        } else if ( result instanceof Iterator ) {
+            return (Iterator) result;
+        } else {
+            return Collections.singletonList( result ).iterator();
+        }
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/AccessorNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/AccessorNode.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/AccessorNode.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,11 @@
+package org.mvel;
+
+import org.mvel.integration.VariableResolverFactory;
+
+import java.util.Map;
+
+public interface AccessorNode {
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory variableFactory) throws Exception;
+    public AccessorNode getNextNode();
+    public AccessorNode setNextNode(AccessorNode accessorNode);
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/BlankLiteral.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/BlankLiteral.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/BlankLiteral.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,26 @@
+package org.mvel;
+
+import static org.mvel.util.PropertyTools.isNumeric;
+
+import static java.lang.String.valueOf;
+import java.util.Collection;
+
+public class BlankLiteral {
+    public static final BlankLiteral INSTANCE = new BlankLiteral();
+
+    public boolean equals(Object obj) {
+        if (obj == null || "".equals(valueOf(obj))) {
+            return true;
+        }
+        else if (isNumeric(obj)) {
+            return "0".equals(valueOf(obj));
+        }
+        else if (obj instanceof Collection) {
+            return ((Collection) obj).size() == 0;
+        }
+        else if (obj.getClass().isArray()) {
+            return ((Object[]) obj).length == 0;
+        }
+        return false;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/CompileException.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/CompileException.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/CompileException.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,46 @@
+package org.mvel;
+
+import static java.lang.String.copyValueOf;
+
+public class CompileException extends RuntimeException {
+    private char[] expr;
+    private int cursor;
+
+    public CompileException() {
+        super();
+    }
+
+    public CompileException(String message) {
+        super(message);
+    }
+
+    public CompileException(String message, char[] expr, int cursor, Exception e) {
+        super("Failed to compile:\n[Error: " + message + "]\n[Near: \"" + showCodeNearError(expr, cursor) + "\"]", e);
+    }
+
+    public CompileException(String message, char[] expr, int cursor) {
+         super("Failed to compile:\n[Error: " + message + "]\n[Near: \"" + showCodeNearError(expr, cursor) + "\"]");
+     }
+
+
+    public CompileException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public CompileException(Throwable cause) {
+        super(cause);
+    }
+
+    private static CharSequence showCodeNearError(char[] expr, int cursor) {
+        int start = cursor - 10;
+        int end = (cursor + 20);
+
+        if (start < 0) {
+            start = 0;
+        }
+        if (end > expr.length) {
+            end = expr.length - 1;
+        }
+        return "'" + copyValueOf(expr, start, end - start) + "'";
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/CompiledExpression.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/CompiledExpression.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/CompiledExpression.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,67 @@
+package org.mvel;                                      
+
+import java.io.Serializable;
+
+public class CompiledExpression implements Serializable {
+    private char[] expression;
+    private TokenIterator tokenMap;
+
+    private Class knownEgressType;
+    private Class knownIngressType;
+
+    private boolean convertableIngressEgress;
+
+    public CompiledExpression(char[] expression, TokenIterator tokenMap) {
+        this.expression = expression;
+        this.tokenMap = new FastTokenIterator(tokenMap);
+    }
+
+    public char[] getExpression() {
+        return expression;
+    }
+
+    public void setExpression(char[] expression) {
+        this.expression = expression;
+    }
+
+    public TokenIterator getTokenMap() {
+        return tokenMap;
+    }
+
+    public void setTokenMap(TokenIterator tokenMap) {
+        this.tokenMap = new FastTokenIterator(tokenMap);
+    }
+
+
+    public Class getKnownEgressType() {
+        return knownEgressType;
+    }
+
+    public void setKnownEgressType(Class knownEgressType) {
+        this.knownEgressType = knownEgressType;
+    }
+
+
+    public Class getKnownIngressType() {
+        return knownIngressType;
+    }
+
+    public void setKnownIngressType(Class knownIngressType) {
+        this.knownIngressType = knownIngressType;
+    }
+
+
+    public boolean isConvertableIngressEgress() {
+        return convertableIngressEgress;
+    }
+
+    public void setConvertableIngressEgress(boolean convertableIngressEgress) {
+        this.convertableIngressEgress = convertableIngressEgress;
+    }
+
+    public void pack() {
+        if (knownIngressType != null && knownEgressType != null) {
+             convertableIngressEgress = knownIngressType.isAssignableFrom(knownEgressType);
+        }
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ConversionException.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ConversionException.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ConversionException.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,20 @@
+package org.mvel;
+
+public class ConversionException extends PropertyAccessException {
+
+    public ConversionException() {
+        super();
+    }
+
+    public ConversionException(String message) {
+        super(message);
+    }
+
+    public ConversionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ConversionException(Throwable cause) {
+        super(cause);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ConversionHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ConversionHandler.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ConversionHandler.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,6 @@
+package org.mvel;
+
+public interface ConversionHandler {
+    public Object convertFrom(Object in);
+    public boolean canConvertFrom(Class cls);
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/DataConversion.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/DataConversion.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/DataConversion.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,74 @@
+package org.mvel;
+
+import java.util.*;
+import java.math.BigDecimal;
+
+import org.mvel.conversion.*;
+
+public class DataConversion {
+    private static final Map<Class, ConversionHandler> CONVERTERS
+            = new HashMap<Class, ConversionHandler>();
+
+    static {
+        ConversionHandler ch;
+
+        CONVERTERS.put(Integer.class, ch = new IntegerCH());
+        CONVERTERS.put(int.class, ch);
+
+        CONVERTERS.put(Short.class, ch = new ShortCH());
+        CONVERTERS.put(short.class, ch);
+
+        CONVERTERS.put(Long.class, ch = new LongCH());
+        CONVERTERS.put(long.class, ch);
+
+        CONVERTERS.put(Character.class, ch = new CharCH());
+        CONVERTERS.put(char.class, ch);
+
+        CONVERTERS.put(Byte.class, ch = new ByteCH());
+        CONVERTERS.put(byte.class, ch);
+
+        CONVERTERS.put(Float.class, ch = new FloatCH());
+        CONVERTERS.put(float.class, ch);
+
+        CONVERTERS.put(Double.class, ch = new DoubleCH());
+        CONVERTERS.put(double.class, ch);
+
+        CONVERTERS.put(Boolean.class, ch = new BooleanCH());
+        CONVERTERS.put(boolean.class, ch);
+
+        CONVERTERS.put(String.class, new StringCH());
+
+        CONVERTERS.put(Object.class, new ObjectCH());
+
+        CONVERTERS.put(char[].class, new CharArrayCH());
+
+        CONVERTERS.put(String[].class, new StringArrayCH());
+
+        CONVERTERS.put(Integer[].class, new IntArrayCH());
+
+        CONVERTERS.put(int[].class, new PrimArrayHandler(int[].class));
+        CONVERTERS.put(long[].class, new PrimArrayHandler(long[].class));
+        CONVERTERS.put(double[].class, new PrimArrayHandler(double[].class));
+        CONVERTERS.put(float[].class, new PrimArrayHandler(float[].class));
+        CONVERTERS.put(short[].class, new PrimArrayHandler(short[].class));
+        CONVERTERS.put(boolean[].class, new PrimArrayHandler(boolean[].class));
+
+        CONVERTERS.put(BigDecimal.class, new BigDecimalCH());
+    }
+
+    public static boolean canConvert(Class toType, Class convertFrom) {
+        return CONVERTERS.containsKey(toType) && CONVERTERS.get(toType).canConvertFrom(convertFrom);
+    }
+
+    public static <T> T convert(Object in, Class<T> toType) {
+        if (in == null) return null;
+        if (toType == in.getClass() || toType.isAssignableFrom(in.getClass())) {
+            return (T) in;
+        }
+        return (T) CONVERTERS.get(toType).convertFrom(in);
+    }
+
+    public static void addConversionHandler(Class type, ConversionHandler handler) {
+        CONVERTERS.put(type, handler);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ENode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ENode.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ENode.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,5 @@
+package org.mvel;
+
+public class ENode {
+  
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ExpressionParser.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ExpressionParser.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ExpressionParser.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,1868 @@
+package org.mvel;
+
+import static org.mvel.DataConversion.canConvert;
+import org.mvel.compiled.GetterAccessor;
+import org.mvel.integration.VariableResolverFactory;
+import org.mvel.integration.impl.LocalVariableResolverFactory;
+import org.mvel.integration.impl.MapVariableResolverFactory;
+import org.mvel.util.ExecutionStack;
+import org.mvel.util.ParseTools;
+import static org.mvel.util.ParseTools.captureContructorAndResidual;
+import static org.mvel.util.ParseTools.containsCheck;
+import org.mvel.util.PropertyTools;
+import static org.mvel.util.PropertyTools.*;
+import org.mvel.util.Stack;
+
+import java.io.Serializable;
+import static java.lang.Character.isWhitespace;
+import static java.lang.Class.forName;
+import static java.lang.String.valueOf;
+import static java.lang.System.arraycopy;
+import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import static java.util.Collections.synchronizedMap;
+import static java.util.regex.Pattern.compile;
+
+public class ExpressionParser {
+    private char[] expr;
+
+    private boolean returnBigDecimal = false;
+
+    private RoundingMode roundingMode = RoundingMode.HALF_DOWN;
+
+    private boolean compileMode = false;
+    private boolean fastExecuteMode = false;
+
+    private int fields;
+    private int cursor;
+    private int length;
+
+    private Object ctx;
+
+    private TokenIterator tokenMap;
+
+    private VariableResolverFactory variableFactory;
+
+    private Stack stk = new ExecutionStack();
+
+    private PropertyAccessor propertyAccessor;
+    private CompiledExpression compiledExpression;
+
+    private static Map<String, char[]> EX_PRECACHE;
+
+
+    static {
+        configureFactory();
+    }
+
+    static void configureFactory() {
+        if (MVEL.THREAD_SAFE) {
+            EX_PRECACHE = synchronizedMap(new WeakHashMap<String, char[]>(10));
+        }
+        else {
+            EX_PRECACHE = new WeakHashMap<String, char[]>(10);
+        }
+    }
+
+    public static Object eval(String expression, Object ctx) {
+        return new ExpressionParser(expression, ctx).parse();
+    }
+
+    public static Object eval(String expression, VariableResolverFactory resolverFactory) {
+        return new ExpressionParser(expression, resolverFactory).parse();
+    }
+
+
+    public static Object eval(String expression, Object ctx, VariableResolverFactory resolverFactory) {
+        return new ExpressionParser(expression, ctx, resolverFactory).parse();
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public static Object eval(String expression, Map tokens) {
+        return new ExpressionParser(expression, null, tokens).parse();
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public static Object eval(String expression, Object ctx, Map tokens) {
+        return new ExpressionParser(expression, ctx, tokens).parse();
+    }
+
+    /**
+     * Compiles an expression and returns a Serializable object containing the compiled
+     * expression.
+     *
+     * @param expression - the expression to be compiled
+     * @return -
+     */
+    public static Serializable compileExpression(String expression) {
+        ExpressionParser parser = new ExpressionParser(expression)
+                .setCompileMode(true);
+
+        parser.parse();
+
+        return new CompiledExpression(parser.getExpressionArray(), parser.tokenMap);
+    }
+
+    /**
+     * Compiles an expression and returns a Serializable object containing the compiled
+     * expression.
+     *
+     * @param expression - the expression to be compiled
+     * @return -
+     */
+    public static Serializable compileExpression(char[] expression) {
+        ExpressionParser parser = new ExpressionParser(expression)
+                .setCompileMode(true);
+
+        parser.parse();
+
+        return new CompiledExpression(parser.getExpressionArray(), parser.tokenMap);
+    }
+
+    public static Object executeExpression(Object compiledExpression) {
+        return new ExpressionParser(compiledExpression).parse();
+    }
+
+    /**
+     * Executes a compiled expression.
+     *
+     * @param compiledExpression -
+     * @param ctx                -
+     * @param vars               -
+     * @return -
+     * @see #compileExpression(String)
+     */
+    @SuppressWarnings({"unchecked"})
+    public static Object executeExpression(final Object compiledExpression, final Object ctx, final Map vars) {
+        return new ExpressionParser(compiledExpression, ctx, vars).parse();
+    }
+
+    public static Object executeExpression(final Object compiledExpression, final Object ctx, final VariableResolverFactory resolverFactory) {
+        return new ExpressionParser(compiledExpression, ctx, resolverFactory).parse();
+    }
+
+    /**
+     * Executes a compiled expression.
+     *
+     * @param compiledExpression -
+     * @param factory            -
+     * @return -
+     * @see #compileExpression(String)
+     */
+    public static Object executeExpression(final Object compiledExpression, final VariableResolverFactory factory) {
+        return new ExpressionParser(compiledExpression, factory).parse();
+    }
+
+    /**
+     * Executes a compiled expression.
+     *
+     * @param compiledExpression -
+     * @param ctx                -
+     * @return -
+     * @see #compileExpression(String)
+     */
+    public static Object executeExpression(final Object compiledExpression, final Object ctx) {
+        return new ExpressionParser(compiledExpression, ctx).parse();
+    }
+
+
+    /**
+     * Executes a compiled expression.
+     *
+     * @param compiledExpression -
+     * @param vars               -
+     * @return -
+     * @see #compileExpression(String)
+     */
+    @SuppressWarnings({"unchecked"})
+    public static Object executeExpression(final Object compiledExpression, final Map vars) {
+        return new ExpressionParser(compiledExpression, null, vars).parse();
+    }
+
+
+    /**
+     * Execute a compiled expression and convert the result to a type
+     *
+     * @param compiledExpression -
+     * @param ctx                -
+     * @param vars               -
+     * @param toType             -
+     * @return -
+     */
+    @SuppressWarnings({"unchecked"})
+    public static <T> T executeExpression(final Object compiledExpression, final Object ctx, final Map vars, Class<T> toType) {
+        return DataConversion.convert(new ExpressionParser(compiledExpression, ctx, vars).parse(), toType);
+    }
+
+    /**
+     * Execute a compiled expression and convert the result to a type
+     *
+     * @param compiledExpression -
+     * @param vars               -
+     * @param toType             -
+     * @return -
+     */
+    @SuppressWarnings({"unchecked"})
+    public static <T> T executeExpression(final Object compiledExpression, Map vars, Class<T> toType) {
+        return DataConversion.convert(new ExpressionParser(compiledExpression, null, vars).parse(), toType);
+    }
+
+
+    /**
+     * Execute a compiled expression and convert the result to a type.
+     *
+     * @param compiledExpression -
+     * @param ctx                -
+     * @param toType             -
+     * @return -
+     */
+    public static <T> T executeExpression(final Object compiledExpression, final Object ctx, Class<T> toType) {
+        return DataConversion.convert(new ExpressionParser(compiledExpression, ctx).parse(), toType);
+    }
+
+
+    public static Object[] executeAllExpression(Serializable[] compiledExpressions, Object ctx, VariableResolverFactory vars) {
+        if (compiledExpressions == null) return GetterAccessor.EMPTY;
+
+        Object[] o = new Object[compiledExpressions.length];
+        for (int i = 0; i < compiledExpressions.length; i++) {
+            o[i] = executeExpression(compiledExpressions[i], ctx, vars);
+        }
+        return o;
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public static <T> T eval(char[] expression, Object ctx, Map vars, Class<T> toType) {
+        return DataConversion.convert(new ExpressionParser(expression, ctx, vars).parse(), toType);
+    }
+
+    public static <T> T eval(char[] expression, Object ctx, Class<T> toType) {
+        return DataConversion.convert(new ExpressionParser(expression, ctx).parse(), toType);
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public static <T> T eval(char[] expression, Map vars, Class<T> toType) {
+        return DataConversion.convert(new ExpressionParser(expression, null, vars).parse(), toType);
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public static Object eval(char[] expression, Object ctx, Map vars) {
+        return new ExpressionParser(expression, ctx, vars).parse();
+    }
+
+    public static String evalToString(String expression, Object ctx) {
+        return valueOf(eval(expression, ctx));
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public static String evalToString(String expression, Map vars) {
+        return valueOf(eval(expression, vars));
+    }
+
+    @SuppressWarnings({"unchecked"})
+    public static String evalToString(String expression, Object ctx, Map vars) {
+        return valueOf(eval(expression, ctx, vars));
+    }
+
+    /**
+     * Evaluate an expression in Boolean-only mode.
+     *
+     * @param expression -
+     * @param ctx        -
+     * @param vars       -
+     * @return -
+     */
+    @SuppressWarnings({"unchecked"})
+    public static Boolean evalToBoolean(String expression, Object ctx, Map vars) {
+        return (Boolean) new ExpressionParser(expression, ctx, vars, true).parse();
+    }
+
+    /**
+     * Evaluate an expression in Boolean-only mode.
+     *
+     * @param expression -
+     * @param ctx        -
+     * @return -
+     */
+    public static Boolean evalToBoolean(String expression, Object ctx) {
+        return evalToBoolean(expression, ctx, null);
+    }
+
+    /**
+     * Evaluate an expression in Boolean-only mode.
+     *
+     * @param expression -
+     * @param vars       -
+     * @return -
+     */
+    public static Boolean evalToBoolean(String expression, Map vars) {
+        return evalToBoolean(expression, null, vars);
+    }
+
+    Object parse() {
+        stk.clear();
+
+        fields = (Token.BOOLEAN_MODE & fields);
+
+        cursor = 0;
+
+        if (fastExecuteMode)
+            parseAndExecuteAccelerated();
+        else
+            parseAndExecuteInterpreted();
+
+        Object result = stk.peek();
+
+        if (isBooleanModeOnly()) {
+            if (result instanceof Boolean) return result;
+            else if (result instanceof Token) {
+                if (((Token) result).getValue() instanceof Boolean) {
+                    return ((Token) result).getValue();
+                }
+                return !BlankLiteral.INSTANCE.equals(((Token) result).getValue());
+            }
+            else if (result instanceof BigDecimal) {
+                return !BlankLiteral.INSTANCE.equals(((BigDecimal) result).floatValue());
+            }
+            throw new CompileException("unknown exception in expression: encountered unknown stack element: " + result);
+        }
+        else if (result instanceof Token) {
+            result = ((Token) result).getValue();
+        }
+
+        if (result instanceof BigDecimal) {
+            if (returnBigDecimal) return result;
+            else if (((BigDecimal) result).scale() > 14) {
+                return ((BigDecimal) result).floatValue();
+            }
+            else if (((BigDecimal) result).scale() > 0) {
+                return ((BigDecimal) result).doubleValue();
+            }
+            else if (((BigDecimal) result).longValue() > Integer.MAX_VALUE) {
+                return ((BigDecimal) result).longValue();
+            }
+            else {
+                return ((BigDecimal) result).intValue();
+            }
+        }
+        else
+            return result;
+
+    }
+
+    /**
+     * This method is called to reduce a binary statement (or junction).  The difference between a binary and
+     * trinary statement, as far as the parser is concerned is that a binary statement has an entrant state,
+     * where-as a trinary statement does not.  Consider: (x && y): in this case, x will be reduced first, and
+     * therefore will have a value on the stack, so the parser will then process the next statement as a binary,
+     * which is (&& y).
+     * <p/>
+     * You can also think of a binary statement in terms of: ({stackvalue} op value)
+     *
+     * @param o - operator
+     * @return int - behaviour code
+     */
+    private int reduceBinary(Operator o) {
+        switch (o) {
+            case AND:
+                if (stk.peek() instanceof Boolean && !((Boolean) valueOnly(stk.peek()))) {
+                    nextToken();
+                    return -1;
+                }
+                break;
+            case OR:
+                if (stk.peek() instanceof Boolean && ((Boolean) valueOnly(stk.peek()))) {
+                    nextToken();
+                    return -1;
+                }
+                break;
+
+            case TERNARY:
+                Token tk;
+                if (!compileMode && (Boolean) valueOnly(stk.peek())) {
+                    stk.discard();
+                    return 1;
+                }
+                else {
+                    fields |= Token.CAPTURE_ONLY;
+                    stk.clear();
+
+                    while ((tk = nextToken()) != null && !(tk.isOperator() && tk.getOperator() == Operator.TERNARY_ELSE)) {
+                        //nothing
+                    }
+
+                    setFieldFalse(Token.CAPTURE_ONLY);
+
+                    return 1;
+                }
+
+
+            case TERNARY_ELSE:
+                return -1;
+
+            case END_OF_STMT:
+                setFieldFalse(Token.LISTCREATE);
+                if (fastExecuteMode) {
+                    if ((fields & Token.ASSIGN) != 0 || !tokenMap.hasMoreTokens()) {
+                        return -1;
+                    }
+                    else {
+                        stk.clear();
+                        return 1;
+                    }
+                }
+
+                if ((fields & Token.ASSIGN) != 0 || cursor == length) {
+                    return -1;
+                }
+                else {
+                    stk.clear();
+                    return 1;
+                }
+
+            case ASSIGN:
+                if (!(tk = (Token) stk.pop()).isValidNameIdentifier())
+                    throw new CompileException("invalid identifier: " + tk.getName());
+
+                fields |= Token.ASSIGN;
+                parseAndExecuteInterpreted();
+                fields ^= Token.ASSIGN;
+
+                //noinspection unchecked
+                finalLocalVariableFactory().createVariable(tk.getName(), stk.pushAndPeek(valueOnly(stk.pop())));
+
+                if (fastExecuteMode) {
+                    if (tokenMap.hasMoreTokens()) {
+                        stk.clear();
+                    }
+                }
+                else if (cursor != length) {
+                    stk.clear();
+                }
+
+                return 1;
+
+            case NEW:
+                stk.discard();
+
+                try {
+                    fields |= Token.CAPTURE_ONLY;
+
+                    String[] name = captureContructorAndResidual(fastExecuteMode ? nextCompiledToken().getName() : nextToken().getName());
+
+                    stk.push(ParseTools.constructObject(name[0], ctx, variableFactory));
+                    setFieldFalse(Token.CAPTURE_ONLY);
+
+                    if (name.length == 2) {
+                        stk.push(PropertyAccessor.get(name[1], stk.pop()));
+                    }
+                }
+                catch (InstantiationException e) {
+                    throw new CompileException("unable to isntantiate class", e);
+                }
+                catch (IllegalAccessException e) {
+                    throw new CompileException("unable to instantiate class", e);
+                }
+                catch (InvocationTargetException e) {
+                    throw new CompileException("unable to instantiate class", e);
+
+                }
+                catch (ClassNotFoundException e) {
+                    throw new CompileException("class not found: " + e.getMessage(), e);
+                }
+
+                return 1;
+        }
+        return 0;
+    }
+
+    /**
+     * This method is called when we reach the point where we must reduce a trinary operation in the expression.
+     * (ie. val1 op val2).  This is not the same as a binary operation, although binary operations would appear
+     * to have 3 structures as well.  A binary structure (or also a junction in the expression) compares the
+     * current state against 2 downrange structures (usually an op and a val).
+     */
+    private void reduceTrinary() {
+        Object v1 = null, v2;
+        Operator operator;
+        try {
+            while (stk.size() > 1) {
+                if ((v1 = stk.pop()) instanceof Boolean) {
+                    /**
+                     * There is a boolean value at the top of the stk, so we
+                     * are at a boolean junction.
+                     */
+                    operator = (Operator) stk.pop();
+                    v2 = processToken(stk.pop());
+                }
+                else if ((fields & Token.EVAL_RIGHT) != 0) {
+                    operator = (Operator) v1;
+                    v2 = processToken(stk.pop());
+                    v1 = processToken(stk.pop());
+                }
+                else {
+                    operator = (Operator) v1;
+                    v1 = processToken(stk.pop());
+                    v2 = processToken(stk.pop());
+                }
+
+                switch (operator) {
+                    case ADD:
+                        if (v1 instanceof BigDecimal && v2 instanceof BigDecimal) {
+                            stk.push(((BigDecimal) v1).add((BigDecimal) v2));
+                        }
+                        else {
+                            stk.push(valueOf(v2) + valueOf(v1));
+                        }
+                        break;
+
+                    case SUB:
+                        stk.push(((BigDecimal) v2).subtract(((BigDecimal) v1)));
+                        break;
+
+                    case DIV:
+                        stk.push(((BigDecimal) v2).divide(((BigDecimal) v1), 20, roundingMode));
+                        break;
+
+                    case MULT:
+                        stk.push(((BigDecimal) v2).multiply((BigDecimal) v1));
+                        break;
+
+                    case MOD:
+                        stk.push(((BigDecimal) v2).remainder((BigDecimal) v1));
+                        break;
+
+                    case EQUAL:
+                        if (v1 instanceof BigDecimal && v2 instanceof BigDecimal) {
+                            stk.push(((BigDecimal) v2).compareTo((BigDecimal) v1) == 0);
+                        }
+                        else if (v1 != null)
+                            stk.push(v1.equals(v2));
+                        else if (v2 != null)
+                            stk.push(v2.equals(v1));
+                        else
+                            stk.push(v1 == v2);
+                        break;
+
+                    case NEQUAL:
+                        if (v1 instanceof BigDecimal && v2 instanceof BigDecimal) {
+                            stk.push(((BigDecimal) v2).compareTo((BigDecimal) v1) != 0);
+                        }
+                        else if (v1 != null)
+                            stk.push(!v1.equals(v2));
+                        else if (v2 != null)
+                            stk.push(!v2.equals(v1));
+                        else
+                            stk.push(v1 != v2);
+                        break;
+                    case GTHAN:
+                        stk.push(((BigDecimal) v2).compareTo((BigDecimal) v1) == 1);
+                        break;
+                    case LTHAN:
+                        stk.push(((BigDecimal) v2).compareTo((BigDecimal) v1) == -1);
+                        break;
+                    case GETHAN:
+                        stk.push(((BigDecimal) v2).compareTo((BigDecimal) v1) >= 0);
+                        break;
+                    case LETHAN:
+                        stk.push(((BigDecimal) v2).compareTo((BigDecimal) v1) <= 0);
+                        break;
+
+                    case AND:
+                        if (v2 instanceof Boolean && v1 instanceof Boolean) {
+                            stk.push(((Boolean) v2) && ((Boolean) v1));
+                            break;
+                        }
+                        else if (((Boolean) v2)) {
+                            stk.push(v2, Operator.AND, v1);
+                        }
+                        return;
+
+                    case OR:
+                        if (v2 instanceof Boolean && v1 instanceof Boolean) {
+                            stk.push(((Boolean) v2) || ((Boolean) v1));
+                            break;
+                        }
+                        else {
+                            stk.push(v2, Operator.OR, v1);
+                            return;
+                        }
+
+                    case CHOR:
+                        if (!isEmpty(v2) || !isEmpty(v1)) {
+                            stk.clear();
+                            stk.push(!isEmpty(v2) ? v2 : v1);
+                            return;
+                        }
+                        else stk.push(null);
+                        break;
+
+                    case REGEX:
+                        stk.push(compile(valueOf(v1)).matcher(valueOf(v2)).matches());
+                        break;
+
+                    case INSTANCEOF:
+                        if (v1 instanceof Class)
+                            stk.push(((Class) v1).isInstance(v2));
+                        else
+                            stk.push(forName(valueOf(v1)).isInstance(v2));
+
+                        break;
+
+                    case CONVERTABLE_TO:
+                        if (v1 instanceof Class)
+                            stk.push(canConvert(v2.getClass(), (Class) v1));
+                        else
+                            stk.push(canConvert(v2.getClass(), forName(valueOf(v1))));
+                        break;
+
+                    case CONTAINS:
+                        stk.push(containsCheck(v2, v1));
+                        break;
+
+                    case BW_AND:
+                        stk.push(asInt(v2) & asInt(v1));
+                        break;
+
+                    case BW_OR:
+                        stk.push(asInt(v2) | asInt(v1));
+                        break;
+
+                    case BW_XOR:
+                        stk.push(asInt(v2) ^ asInt(v1));
+                        break;
+
+                    case BW_SHIFT_LEFT:
+                        stk.push(asInt(v2) << asInt(v1));
+                        break;
+
+                    case BW_USHIFT_LEFT:
+                        int iv2 = asInt(v2);
+                        if (iv2 < 0) iv2 *= -1;
+                        stk.push(iv2 << asInt(v1));
+                        break;
+
+                    case BW_SHIFT_RIGHT:
+                        stk.push(asInt(v2) >> asInt(v1));
+                        break;
+
+                    case BW_USHIFT_RIGHT:
+                        stk.push(asInt(v2) >>> asInt(v1));
+                        break;
+
+                    case STR_APPEND:
+                        stk.push(new StringBuilder(valueOf(v2)).append(valueOf(v1)).toString());
+                        break;
+
+                    case PROJECTION:
+                        try {
+                            List<Object> list = new ArrayList<Object>(((Collection) v1).size());
+                            for (Object o : (Collection) v1) {
+                                list.add(PropertyAccessor.get(valueOf(v2), o));
+                            }
+                            stk.push(list);
+                        }
+                        catch (ClassCastException e) {
+                            throw new ParseException("projections can only be peformed on collections");
+                        }
+                        break;
+
+                    case SOUNDEX:
+                        stk.push(Soundex.soundex(valueOf(v1)).equals(Soundex.soundex(valueOf(v2))));
+                        break;
+
+                    case SIMILARITY:
+                        stk.push(similarity(valueOf(v1), valueOf(v2)));
+                        break;
+
+                }
+            }
+        }
+        catch (ClassCastException e) {
+            if ((fields & Token.LOOKAHEAD) == 0) {
+                /**
+                 * This will allow for some developers who like messy expressions to compileGetChain
+                 * away with some messy constructs like: a + b < c && e + f > g + q instead
+                 * of using brackets like (a + b < c) && (e + f > g + q)
+                 */
+
+                fields |= Token.LOOKAHEAD;
+
+                Token tk = nextToken();
+                if (tk != null) {
+                    stk.push(v1, nextToken(), tk.getOperator());
+
+                    reduceTrinary();
+                    return;
+                }
+            }
+            throw new CompileException("syntax error or incomptable types", expr, cursor, e);
+
+        }
+        catch (Exception e) {
+            throw new CompileException("failed to reduce expression", e);
+        }
+
+    }
+
+    private static int asInt(final Object o) {
+        return ((BigDecimal) o).intValue();
+    }
+
+    private Object processToken(Object operand) {
+        setFieldFalse(Token.EVAL_RIGHT);
+
+        if (operand instanceof Token) {
+            if (((Token) operand).isNumeric()) {
+                return ((Token) operand).getNumericValue();
+            }
+            else if (!((Token) operand).isLiteral()) {
+                return ((Token) operand).getValue();
+            }
+            else {
+                if (((Token) operand).isEvalRight()) fields |= Token.EVAL_RIGHT;
+                return ((Token) operand).getValue();
+            }
+        }
+        else if (operand instanceof BigDecimal) {
+            return operand;
+        }
+        else if (isNumber(operand)) {
+            return new BigDecimal(valueOf(operand));
+        }
+        else {
+            return operand;
+        }
+    }
+
+
+    private void parseAndExecuteInterpreted() {
+        Token tk;
+        Operator operator;
+
+        while ((tk = nextToken()) != null) {
+
+            if (stk.size() == 0) {
+                if ((fields & Token.SUBEVAL) != 0) {
+                    stk.push(reduce(tk));
+                }
+                else {
+                    stk.push(tk);
+                }
+
+                if (!tk.isOperator() && (tk = nextToken()) == null) {
+                    return;
+                }
+            }
+
+            if (!tk.isOperator()) {
+                continue;
+            }
+
+            switch (reduceBinary(operator = tk.getOperator())) {
+                case-1:
+                    return;
+                case 0:
+                    break;
+                case 1:
+                    continue;
+            }
+
+            if ((tk = nextToken()) == null)
+                throw new CompileException("unexpected end of statament");
+
+            if ((fields & Token.SUBEVAL) != 0) {
+                stk.push(reduce(tk), operator);
+            }
+            else {
+                stk.push(tk, operator);
+            }
+
+            // stk.push(operator);
+
+            if (!compileMode) reduceTrinary();
+        }
+    }
+
+
+    private void parseAndExecuteAccelerated() {
+        Token tk;
+        Operator operator;
+
+        while ((tk = nextCompiledToken()) != null) {
+
+            if (stk.size() == 0) {
+                if ((fields & Token.SUBEVAL) != 0) {
+                    stk.push(reduce(tk));
+                }
+                else {
+                    stk.push(tk);
+                }
+
+                if (!tk.isOperator() && (tk = nextCompiledToken()) == null) {
+                    return;
+                }
+            }
+
+            if (!tk.isOperator()) {
+                continue;
+            }
+
+            switch (reduceBinary(operator = tk.getOperator())) {
+                case-1:
+                    return;
+                case 0:
+                    break;
+                case 1:
+                    continue;
+            }
+
+            tk = nextCompiledToken();
+
+            if ((fields & Token.SUBEVAL) != 0) {
+                stk.push(reduce(tk), operator);
+            }
+            else {
+                stk.push(tk, operator);
+            }
+
+            // stk.push(operator);
+
+            if (!compileMode) reduceTrinary();
+        }
+    }
+
+
+    private static Object valueOnly(Object o) {
+        return (o instanceof Token) ? ((Token) o).getValue() : o;
+    }
+
+    private Object reduceFast(Token tk) {
+        if ((tk.getFlags() & Token.SUBEVAL) != 0) {
+            setFieldFalse(Token.SUBEVAL);
+
+            if (compileMode) {
+                tk.setCompiledExpression((CompiledExpression) compileExpression(tk.getValueAsString()));
+            }
+            else if (fastExecuteMode) {
+                return tk.setFinalValue(executeExpression(tk.getCompiledExpression(), ctx, variableFactory)).getValue();
+            }
+        }
+        else if ((tk.getFlags() & Token.DO_NOT_REDUCE) == 0) {
+            return tk.setFinalValue(reduce(reduceToken(tk))).getValue();
+        }
+        return tk;
+    }
+
+    private static Object reduceParse(String ex, Object ctx, VariableResolverFactory variableFactory) {
+        return new ExpressionParser(ex, ctx, variableFactory).parse();
+    }
+
+
+    private Object reduce(Token tok) {
+        if ((tok.getFlags() & Token.NEGATION) != 0) {
+            return !((Boolean) reduceParse(tok.getValueAsString(), ctx, variableFactory));
+        }
+        else if ((tok.getFlags() & Token.INVERT) != 0) {
+            Object o = reduceParse(tok.getValueAsString(), ctx, variableFactory);
+
+            if (o instanceof Integer)
+                return ~((Integer) o);
+            else
+                return ~((BigDecimal) o).intValue();
+        }
+        else if (!compileMode && ((tok.getFlags() | fields) & Token.SUBEVAL) != 0) {
+            setFieldFalse(Token.SUBEVAL);
+            return reduceParse(tok.getValueAsString(), ctx, variableFactory);
+        }
+        else return tok.getValue();
+    }
+
+
+    /**
+     * Retrieve the next token in the expression.
+     *
+     * @return -
+     */
+    private Token nextToken() {
+        if (fastExecuteMode) return nextCompiledToken();
+
+        Token tk;
+
+        /**
+         * If the cursor is at the end of the expression, we have nothing more to do:
+         * return null.
+         */
+        if (cursor >= length) {
+            return null;
+        }
+
+        int brace, start = cursor;
+
+        /**
+         * Because of parser recursion for sub-expression parsing, we sometimes need to remain
+         * certain field states.  We do not reset for assignments, boolean mode, list creation or
+         * a capture only mode.
+         */
+        fields = ((fields & Token.ASSIGN) | (fields & Token.BOOLEAN_MODE) | (fields & Token.LISTCREATE)
+                | (fields & Token.CAPTURE_ONLY) | (fields & Token.NOCOMPILE) | (fields & Token.MAPCREATE)
+                | (fields & Token.ARRAYCREATE) | (fields & Token.PUSH) | (fields & Token.NEST) | (fields & Token.ENDNEST));
+
+
+        boolean capture = false;
+
+        /**
+         * Skip any whitespace currently under the starting point.
+         */
+        while (start < length && isWhitespace(expr[start])) start++;
+
+        for (cursor = start; cursor < length;) {
+            if (isIdentifierPart(expr[cursor])) {
+                /**
+                 * If the current character under the cursor is a valid
+                 * part of an identifier, we keep capturing.
+                 */
+
+                capture = true;
+                cursor++;
+                // continue;
+            }
+            else if (capture) {
+                /**
+                 * If we *were* capturing a token, and we just hit a non-identifier
+                 * character, we stop and figure out what to do.
+                 */
+
+                if (expr[cursor] == '(') {
+                    /**
+                     * If the current token is a method call or a constructor, we
+                     * simply capture the entire parenthesized range and allow
+                     * reduction to be dealt with through sub-parsing the property.
+                     */
+                    cursor++;
+                    for (brace = 1; cursor < length && brace > 0;) {
+                        switch (expr[cursor++]) {
+                            case'(':
+                                brace++;
+                                break;
+                            case')':
+                                brace--;
+                                break;
+                        }
+                    }
+
+                    /**
+                     * If the brace counter is greater than 0, we know we have
+                     * unbalanced braces in the expression.  So we throw a
+                     * compile error now.
+                     */
+                    if (brace > 0)
+                        throw new CompileException("unbalanced braces in expression: (" + brace + "):" + new String(expr));
+                }
+
+                /**
+                 * If we encounter any of the following cases, we are still dealing with
+                 * a contiguous token.
+                 */
+                if (cursor < length) {
+                    switch (expr[cursor]) {
+                        case']':
+                            if (((fields & Token.LISTCREATE) | (fields & Token.MAPCREATE)) != 0) break;
+                        case'[':
+                        case'\'':
+                        case'"':
+                        case'.':
+                            cursor++;
+                            continue;
+                    }
+
+                }
+
+                /**
+                 * Produce the token.
+                 */
+                return createToken(expr, start, cursor, fields);
+            }
+            else
+                switch (expr[cursor]) {
+                    case'=': {
+                        if (expr[++cursor] != '=') {
+                            return createToken(expr, start, cursor++, fields);
+                        }
+                        else {
+                            return createToken(expr, start, ++cursor, fields);
+                        }
+                    }
+
+                    case'-':
+                        if (!PropertyTools.isDigit(expr[cursor + 1])) {
+                            return createToken(expr, start, cursor++ + 1, fields);
+                        }
+                        else if ((cursor - 1) < 0 || (!isDigit(expr[cursor - 1])) && isDigit(expr[cursor + 1])) {
+                            cursor++;
+                            break;
+                        }
+
+                    case';':
+                    case'#':
+                    case'?':
+                    case':':
+                    case'^':
+                    case'/':
+                    case'+':
+                    case'*':
+                    case'%': {
+                        return createToken(expr, start, cursor++ + 1, fields);
+                    }
+
+                    case'(': {
+                        cursor++;
+
+                        for (brace = 1; cursor < length && brace > 0;) {
+                            switch (expr[cursor++]) {
+                                case'(':
+                                    brace++;
+                                    break;
+                                case')':
+                                    brace--;
+                                    break;
+                            }
+                        }
+                        if (brace > 0)
+                            throw new CompileException("unbalanced braces in expression: (" + brace + "):" + new String(expr));
+
+                        tk = createToken(expr, start + 1, cursor - 1, fields |= Token.SUBEVAL);
+
+                        if (cursor < length && (expr[cursor] == '.')) {
+                            stk.push(reduce(tk));
+                            continue;
+                        }
+
+                        return tk;
+                    }
+
+                    case'>': {
+                        if (expr[cursor + 1] == '>') {
+                            if (expr[cursor += 2] == '>') cursor++;
+                            return createToken(expr, start, cursor, fields);
+                        }
+                        else if (expr[cursor + 1] == '=') {
+                            return createToken(expr, start, cursor += 2, fields);
+                        }
+                        else {
+                            return createToken(expr, start, ++cursor, fields);
+                        }
+                    }
+
+
+                    case'<': {
+                        if (expr[++cursor] == '<') {
+                            if (expr[++cursor] == '<') cursor++;
+                            return createToken(expr, start, cursor, fields);
+                        }
+                        else if (expr[cursor] == '=') {
+                            return createToken(expr, start, ++cursor, fields);
+                        }
+                        else {
+                            return createToken(expr, start, cursor, fields);
+                        }
+                    }
+
+
+                    case'\'':
+                        while (++cursor < length && expr[cursor] != '\'') {
+                            if (expr[cursor] == '\\') ParseTools.handleEscapeSequence(expr[++cursor]);
+                        }
+
+                        if (cursor == length || expr[cursor] != '\'') {
+                            throw new CompileException("unterminated literal: " + new String(expr));
+                        }
+                        return createToken(expr, start + 1, cursor++, fields |= Token.STR_LITERAL | Token.LITERAL);
+
+
+                    case'"':
+                        while (++cursor < length && expr[cursor] != '"') {
+                            if (expr[cursor] == '\\') ParseTools.handleEscapeSequence(expr[++cursor]);
+                        }
+                        if (cursor == length || expr[cursor] != '"') {
+                            throw new CompileException("unterminated literal: " + new String(expr));
+                        }
+                        return createToken(expr, start + 1, cursor++, fields |= Token.STR_LITERAL | Token.LITERAL);
+
+
+                    case'&': {
+                        if (expr[cursor++ + 1] == '&') {
+                            return createToken(expr, start, ++cursor, fields);
+                        }
+                        else {
+                            return createToken(expr, start, cursor, fields);
+                        }
+                    }
+
+                    case'|': {
+                        if (expr[cursor++ + 1] == '|') {
+                            return createToken(expr, start, ++cursor, fields);
+                        }
+                        else {
+                            return createToken(expr, start, cursor, fields);
+                        }
+                    }
+
+                    case'~':
+                        if ((cursor - 1 < 0 || !isIdentifierPart(expr[cursor - 1]))
+                                && isDigit(expr[cursor + 1])) {
+
+                            fields |= Token.INVERT;
+                            start++;
+                            cursor++;
+                            break;
+                        }
+                        else if (expr[cursor + 1] == '(') {
+                            fields |= Token.INVERT;
+                            start = ++cursor;
+                            continue;
+                        }
+                        else {
+                            if (expr[cursor + 1] == '=') cursor++;
+                            return createToken(expr, start, ++cursor, fields);
+                        }
+
+                    case'!': {
+                        if (isIdentifierPart(expr[++cursor]) || expr[cursor] == '(') {
+                            start = cursor;
+                            fields |= Token.NEGATION;
+                            continue;
+                        }
+                        else if (expr[cursor] != '=')
+                            throw new CompileException("unexpected operator '!'", expr, cursor, null);
+                        else {
+                            return createToken(expr, start, ++cursor, fields);
+                        }
+                    }
+
+                    case'[':
+                        if (capture) {
+                            cursor++;
+                            continue;
+                        }
+
+                        cursor++;
+
+                        fields |= Token.LISTCREATE | Token.NOCOMPILE;
+
+                        Token tk1 = nextToken();
+
+                        fields |= Token.NOCOMPILE;
+                        Token tk2 = nextToken();
+
+                        if (tk2 != null && tk2.getName().equals(":")) {
+                            setFieldFalse(Token.LISTCREATE);
+
+                            if (compileMode) {
+                                setFieldFalse(Token.NOCOMPILE);
+                                tk1.setFlag(false, Token.LISTCREATE);
+                                tk1.setFlag(true, Token.MAPCREATE);
+
+                                tk2.setFlag(false, Token.LISTCREATE);
+                                tk2.setFlag(true, Token.MAPCREATE);
+
+                                ((TokenMap) tokenMap).addTokenNode(new Token('[', Token.MAPCREATE | Token.NEST));
+                                ((TokenMap) tokenMap).addTokenNode(tk1);
+                            }
+
+                            tk2 = nextToken();
+
+                            fields |= Token.MAPCREATE;
+
+                            Map<Object, Object> map = new HashMap<Object, Object>();
+                            map.put(reduce(tk1), reduce(tk2));
+                            skipWhitespace();
+
+                            try {
+                                while (expr[cursor++] != ']') {
+                                    tk1 = nextToken();
+                                    fields |= Token.NOCOMPILE;
+
+                                    if ((tk2 = nextToken()) == null
+                                            || (!tk2.isOperator() || (tk2.getOperator() != Operator.TERNARY_ELSE)))
+                                        throw new CompileException("unexpected token or end of expression, in map creation construct: " + tk2.getName());
+
+                                    map.put(reduce(tk1), reduce(nextToken()));
+
+                                    skipWhitespace();
+                                }
+                            }
+                            catch (ArrayIndexOutOfBoundsException e) {
+                                throw new CompileException("unterminated list projection");
+                            }
+
+                            if (compileMode) ((TokenMap) tokenMap).addTokenNode(new Token(']', Token.ENDNEST));
+
+                            setFieldFalse(Token.MAPCREATE);
+
+                            if (cursor < length && (expr[cursor] == '.')) {
+                                capture = false;
+
+                                fields |= Token.PUSH;
+
+                                stk.push(map);
+
+                                continue;
+                            }
+
+                            return (createToken(expr, start + 1, cursor - 1, fields |= Token.DO_NOT_REDUCE | Token.NOCOMPILE))
+                                    .setValue(map);
+
+                        }
+                        else {
+                            tk1.setFlag(false, Token.MAPCREATE);
+
+                            ArrayList<Object> projectionList = new ArrayList<Object>();
+                            projectionList.add(reduce(tk1));
+
+                            if (compileMode) {
+                                ((TokenMap) tokenMap).addTokenNode(new Token('[', Token.LISTCREATE | Token.NEST));
+                                ((TokenMap) tokenMap).addTokenNode(tk1);
+                            }
+
+                            try {
+                                while (expr[cursor++] != ']') {
+                                    projectionList.add(reduce(nextToken()));
+                                }
+
+                                if (compileMode) {
+                                    addTokenToMap(new Token(']', fields | Token.ENDNEST));
+                                }
+                            }
+                            catch (ArrayIndexOutOfBoundsException e) {
+                                throw new CompileException("unterminated list projection");
+                            }
+
+                            setFieldFalse(Token.LISTCREATE);
+
+                            if (cursor < length && (expr[cursor] == '.')) {
+                                capture = false;
+
+                                fields |= Token.PUSH;
+
+                                stk.push(projectionList);
+                                continue;
+                            }
+
+                            return (createToken(expr, start + 1, cursor - 1, fields |= Token.DO_NOT_REDUCE | Token.NOCOMPILE))
+                                    .setValue(projectionList);
+                        }
+
+
+                    case'{':
+                        fields |= Token.ARRAYCREATE;
+
+                        if (compileMode) {
+                            addTokenToMap(new Token('{', fields | Token.NEST));
+                        }
+
+                        ArrayList<Object> projectionList = new ArrayList<Object>();
+
+                        try {
+                            while (expr[cursor++] != '}') {
+                                projectionList.add(reduce(nextToken()));
+                            }
+
+                            if (compileMode) {
+                                addTokenToMap(new Token('}', fields | Token.ENDNEST));
+                            }
+
+                        }
+                        catch (ArrayIndexOutOfBoundsException e) {
+                            throw new CompileException("unterminated list projection");
+                        }
+
+                        setFieldFalse(Token.ARRAYCREATE);
+
+                        if (cursor < length && (expr[cursor] == '.')) {
+                            capture = false;
+
+                            fields |= Token.PUSH;
+
+                            stk.push(projectionList.toArray());
+                            continue;
+                        }
+
+
+                        return (createToken(expr, start + 1, cursor - 1, fields |= Token.DO_NOT_REDUCE | Token.NOCOMPILE))
+                                .setValue(projectionList.toArray());
+
+                    case']':
+                    case'}':
+                    case',':
+                        if (((fields & Token.LISTCREATE | fields & Token.ARRAYCREATE | fields & Token.MAPCREATE)) != 0) {
+                            return createToken(expr, start, cursor, fields |= Token.DO_NOT_REDUCE | Token.NOCOMPILE);
+                        }
+                        else if (!capture) {
+                            throw new CompileException("unexpected: " + expr[cursor]);
+
+                        }
+                        else {
+                            ++cursor;
+                            continue;
+                        }
+
+                    case'.':
+                        start++;
+                        if (!capture) {
+                            cursor++;
+                            fields |= Token.CAPTURE_ONLY | Token.PUSH;
+                            tk = nextToken();
+                            setFieldFalse(Token.CAPTURE_ONLY);
+                            setFieldFalse(Token.PUSH);
+
+                            if (!compileMode)
+                                return tk.setValue(PropertyAccessor.get((tk).getName(), stk.pop()));
+                            else
+                                return tk;
+                        }
+
+                    default:
+                        cursor++;
+
+                }
+
+        }
+
+
+        return createToken(expr, start, cursor, fields);
+    }
+
+    private Token createToken(char[] expr, int start, int end, int fields) {
+        Token tk = new Token(expr, start, end, fields);
+
+        if (compileMode) {
+            if ((tk.getFlags() & Token.NOCOMPILE) == 0) {
+                ((TokenMap) tokenMap).addTokenNode(tk);
+
+                if ((tk.getFlags() & Token.SUBEVAL) != 0) reduceFast(tk);
+            }
+            setFieldFalse(Token.NOCOMPILE);
+        }
+        else if ((tk.getFlags() & Token.IDENTIFIER) != 0 && (fields & Token.DO_NOT_REDUCE) == 0) {
+            return reduceToken(tk);
+        }
+
+        if ((tk.getFlags() & Token.THISREF) != 0) tk.setFinalValue(ctx);
+
+        return tk;
+    }
+
+    private Token reduceToken(Token token) {
+        String s;
+
+        int tkflags = token.getFlags();
+
+        if (((fields & Token.CAPTURE_ONLY) | (tkflags & Token.LITERAL)) != 0) {
+            return token;
+        }
+
+        if (fastExecuteMode) {
+            try {
+                if (token.isOptimized()) {
+                    return token.getOptimizedValue((((tkflags | fields) & Token.PUSH) != 0) ? valueOnly(stk.pop()) : ctx, ctx, variableFactory);
+                }
+                else {
+                    try {
+                        Object cCtx;
+                        token.optimizeAccessor(cCtx = (((tkflags | fields) & Token.PUSH) != 0) ? valueOnly(stk.pop()) : ctx, variableFactory);
+                        return token.getOptimizedValue(cCtx, ctx, variableFactory);
+                    }
+                    catch (Exception e) {
+                        if (!lookAhead()) throw e;
+                        else {
+                            token.createDeferralOptimization();
+                            return token;
+                        }
+                    }
+                }
+
+            }
+            catch (PropertyAccessException e) {
+                throw e;
+            }
+            catch (Exception e) {
+                try {
+                    synchronized (token) {
+                        token.deOptimize();
+                        return reduceToken(token);
+                    }
+                }
+                catch (Exception e2) {
+                    throw new CompileException("optimization failure for: " + new String(expr), e);
+                }
+            }
+        }
+
+
+        if (propertyAccessor == null) propertyAccessor = new PropertyAccessor(variableFactory, ctx);
+
+        if (((tkflags | fields) & Token.PUSH) != 0) {
+            return token.setValue(propertyAccessor.setParameters(expr, token.getStart(), token.getEnd(), valueOnly(stk.pop())).get());
+        }
+        else if ((tkflags & Token.DEEP_PROPERTY) != 0) {
+            if (Token.LITERALS.containsKey(s = token.getAbsoluteRootElement())) {
+                Object literal = Token.LITERALS.get(s);
+                if (literal == ThisLiteral.class) literal = ctx;
+
+                return token.setValue(propertyAccessor.setParameters(expr, token.getStart() + token.getFirstUnion(), token.getEnd(), literal).get());
+            }
+            else if (variableFactory != null && variableFactory.isResolveable(s)) {
+                return token.setValue(propertyAccessor.setParameters(expr, token.getStart() +
+                        token.getAbsoluteFirstPart(),
+                        token.getEnd(), variableFactory.getVariableResolver(s).getValue()).get());
+
+            }
+            else if (ctx != null) {
+                try {
+                    return token.setValue(propertyAccessor.setParameters(expr, token.getStart(), token.getEnd(), ctx).get());
+                }
+                catch (PropertyAccessException e) {
+
+                    /**
+                     * Make a last-ditch effort to resolve this as a static-class reference.
+                     */
+                    Token tk = tryStaticAccess(token);
+                    if (tk == null) throw e;
+                    return tk;
+                }
+            }
+            else {
+                Token tk = tryStaticAccess(token);
+                if (tk == null) throw new CompileException("unable to resolve token: " + s);
+                return tk;
+            }
+        }
+        else {
+            if (Token.LITERALS.containsKey(s = token.getAbsoluteName())) {
+                return token.setValue(Token.LITERALS.get(s));
+            }
+            else if (variableFactory != null && variableFactory.isResolveable(s)) {
+                if ((token.getFlags() & Token.COLLECTION) != 0) {
+                    return token.setValue(propertyAccessor.setParameters(expr, token.getStart()
+                            + token.getEndOfName(), token.getEnd(), variableFactory.getVariableResolver(s).getValue()).get());
+                }
+                return token.setValue(variableFactory.getVariableResolver(s).getValue());
+            }
+            else if (ctx != null) {
+                try {
+                    return token.setValue(propertyAccessor.setParameters(expr, token.getStart(),
+                            token.getEnd(), ctx).get());
+                }
+                catch (RuntimeException e) {
+                    if (!lookAhead()) throw e;
+                }
+            }
+            else {
+                if (!lookAhead())
+                    throw new CompileException("unable to resolve token: " + s);
+            }
+        }
+        return token;
+    }
+
+    private Token tryStaticAccess(Token token) {
+        try {
+            /**
+             * Try to resolve this *smartly* as a static class reference.
+             *
+             * This starts at the end of the token and starts to step backwards to figure out whether
+             * or not this may be a static class reference.  We search for method calls simply by
+             * inspecting for ()'s.  The first union area we come to where no brackets are present is our
+             * test-point for a class reference.  If we find a class, we pass the reference to the
+             * property accessor along  with trailing methods (if any).
+             *
+             */
+            boolean meth = false;
+            int depth = 0;
+            int last = token.getEnd();
+            for (int i = last - 1; i > token.getStart(); i--) {
+                switch (expr[i]) {
+                    case'.':
+                        if (!meth) {
+                            return token.setValue(
+                                    propertyAccessor.setParameters(
+                                            expr, last, token.getEnd(),
+                                            forName(new String(expr, token.getStart(), last - token.getStart()))
+                                    ).get());
+                        }
+                        meth = false;
+                        last = i;
+                        break;
+                    case')':
+                        if (depth++ == 0)
+                            meth = true;
+                        break;
+                    case'(':
+                        depth--;
+                        break;
+                }
+            }
+        }
+        catch (Exception cnfe) {
+            // do nothing.
+        }
+
+        return null;
+    }
+
+    private boolean lookAhead() {
+        Token tk;
+
+        int cursorCurrent = cursor;
+        if (!compileMode && (tk = nextToken()) != null) {
+            if (!tk.isOperator()) {
+                throw new CompileException("expected operator but encountered token: " + tk.getName());
+            }
+            else if (tk.getOperator() == Operator.ASSIGN || tk.getOperator() == Operator.PROJECTION) {
+                cursor = cursorCurrent;
+                if (fastExecuteMode) {
+                    tokenMap.back();
+                }
+            }
+            else
+                return false;
+        }
+        else {
+            return false;
+        }
+        return true;
+    }
+
+    public String getExpression() {
+        return new String(expr);
+    }
+
+    private void skipWhitespace() {
+        while (isWhitespace(expr[cursor])) cursor++;
+    }
+
+    public ExpressionParser setExpression(String expression) {
+        if (expression != null && !"".equals(expression)) {
+            if (!EX_PRECACHE.containsKey(expression)) {
+                length = (this.expr = expression.toCharArray()).length;
+
+                // trim any whitespace.
+                while (isWhitespace(this.expr[length - 1])) length--;
+
+                char[] e = new char[length];
+                System.arraycopy(this.expr, 0, e, 0, length);
+
+                EX_PRECACHE.put(expression, e);
+            }
+            else {
+                length = (expr = EX_PRECACHE.get(expression)).length;
+            }
+        }
+        return this;
+    }
+
+
+    public ExpressionParser setExpressionArray(char[] expressionArray) {
+        this.length = (this.expr = expressionArray).length;
+        return this;
+    }
+
+    public void setExpressionArray(char[] expressionArray, int start, int offset) {
+        arraycopy(expressionArray, start, this.expr = new char[this.length = offset - start], 0, offset);
+    }
+
+    public char[] getExpressionArray() {
+        return expr;
+    }
+
+    public RoundingMode getRoundingMode() {
+        return roundingMode;
+    }
+
+    public void setRoundingMode(RoundingMode roundingMode) {
+        this.roundingMode = roundingMode;
+    }
+
+    public boolean isReturnBigDecimal() {
+        return returnBigDecimal;
+    }
+
+    public void setReturnBigDecimal(boolean returnBigDecimal) {
+        this.returnBigDecimal = returnBigDecimal;
+    }
+
+    private void setFieldFalse(int flag) {
+        if (((fields & flag) != 0)) {
+            fields = fields ^ flag;
+        }
+    }
+
+    public boolean isBooleanModeOnly() {
+        return (fields & Token.BOOLEAN_MODE) != 0;
+    }
+
+    /**
+     * <p>Sets the compiler into boolean mode.  When operating in boolean-mode, the
+     * parser ALWAYS returns a Boolean value based on the Boolean-only rules.</p>
+     * <p/>
+     * The returned boolean value will be returned based on the following rules, in this order:
+     * <p/>
+     * 1. Is the terminal value on the stack a Boolean? If so, return it directly.<br/>
+     * 2. Is the value on the stack null? If so, return false.<br/>
+     * 3. Is the value on the stack empty (0, zero-length, or an empty collection? If so, return false.<br/>
+     * 4. Otherwise return true.<br/>
+     *
+     * @param booleanModeOnly - boolean denoting mode.
+     */
+    public void setBooleanModeOnly(boolean booleanModeOnly) {
+        if (booleanModeOnly)
+            fields |= Token.BOOLEAN_MODE;
+        else
+            setFieldFalse(Token.BOOLEAN_MODE);
+    }
+
+    private ExpressionParser setCompileMode(boolean compileMode) {
+        if (this.compileMode = compileMode) tokenMap = new TokenMap(null);
+        return this;
+    }
+
+    public ExpressionParser setPrecompiledExpression(Object expression) {
+        (this.tokenMap = ((CompiledExpression) expression).getTokenMap()).reset();
+
+        this.fastExecuteMode = true;
+        return this;
+    }
+
+    private void addTokenToMap(Token tk) {
+        ((TokenMap) tokenMap).addTokenNode(tk);
+    }
+
+    public Token nextCompiledToken() {
+        Token tk;
+        /**
+         * If we're running in fast-execute mode (aka. running a compiled expression)
+         * we retrieve the next token from the compiled stack
+         *
+         * TODO: Move this to another method ASAP.  This is ridiculous.  (Note from Mike to Mike)
+         */
+
+        if ((tk = tokenMap.nextToken()) != null) {
+            if (tk.isOperator() && tk.getOperator() == Operator.ASSIGN) {
+                return tk;
+            }
+            else if (tk.isCollectionCreation()) {
+                /**
+                 * We must handle collection creation differently for compiled
+                 * execution.  This is not code duplication.  Don't report this.
+                 */
+                switch (tk.getCollectionCreationType()) {
+                    case Token.LISTCREATE: {
+                        List<Object> newList = new ArrayList<Object>();
+
+                        newList.add(handleSubNesting(tk.isNestBegin() ? tokenMap.nextToken() : tk));
+
+                        while (tokenMap.hasMoreTokens() &&
+                                (tokenMap.peekToken().getFlags() & Token.ENDNEST) == 0) {
+
+                            newList.add(handleSubNesting(tokenMap.nextToken()));
+                        }
+
+                        tokenMap.nextToken();
+
+                        tk.setFlag(true, Token.DO_NOT_REDUCE);
+                        return tk.setFinalValue(newList);
+                    }
+
+                    case Token.MAPCREATE: {
+                        tk = tk.isNestBegin() ? tokenMap.nextToken() : tk;
+
+                        Map<Object, Object> newMap = new HashMap<Object, Object>();
+
+                        newMap.put(handleSubNesting(tk), handleSubNesting(tokenMap.nextToken()));
+
+                        while (tokenMap.hasMoreTokens() && (tokenMap.peekToken().getFlags() & Token.ENDNEST) == 0) {
+                            newMap.put(handleSubNesting(tokenMap.nextToken()), handleSubNesting(tokenMap.nextToken()));
+                        }
+
+                        tokenMap.nextToken();
+
+                        tk.setFlag(true, Token.DO_NOT_REDUCE);
+                        tk.setFinalValue(newMap);
+                    }
+                    break;
+
+                    case Token.ARRAYCREATE: {
+                        List<Object> newList = new ArrayList<Object>();
+
+                        newList.add(handleSubNesting(tk.isNestBegin() ? tokenMap.nextToken() : tk));
+
+                        while (tokenMap.hasMoreTokens() &&
+                                (tokenMap.peekToken().getFlags() & Token.ENDNEST) == 0) {
+                            newList.add(handleSubNesting(tokenMap.nextToken()));
+                        }
+
+                        tokenMap.nextToken();
+
+                        tk.setFlag(true, Token.DO_NOT_REDUCE);
+                        return tk.setFinalValue(newList.toArray());
+                    }
+                }
+
+                if (tokenMap.hasMoreTokens() && (tokenMap.peekToken().getFlags() & Token.PUSH) != 0) {
+                    stk.push(tk.getValue());
+                    return (tk = tokenMap.nextToken()).setFinalValue(PropertyAccessor.get(tk.getName(), stk.pop()));
+                }
+            }
+            else if ((tk.getFlags() & Token.IDENTIFIER) != 0) {
+                reduceToken(tk);
+            }
+            else if ((tk.getFlags() & Token.THISREF) != 0) {
+                tk.setFinalValue(ctx);
+            }
+
+            fields |= (tk.getFlags() & Token.SUBEVAL);
+
+            if ((tk.getFlags() & Token.PUSH) != 0) {
+                stk.push(tk.getValue());
+            }
+        }
+
+        return tk;
+    }
+
+    private Object handleSubNesting(Token token) {
+        if ((token.getFlags() & Token.NEST) != 0) {
+            return nextCompiledToken().getValue();
+        }
+        else {
+            return reduceToken(token).getValue();
+        }
+    }
+
+    private VariableResolverFactory finalLocalVariableFactory() {
+        VariableResolverFactory v = variableFactory;
+        while (v != null) {
+            if (v instanceof LocalVariableResolverFactory) return v;
+            v = v.getNextFactory();
+        }
+        if (variableFactory == null)
+            return variableFactory = new LocalVariableResolverFactory(new HashMap<String, Object>());
+        else
+            return new LocalVariableResolverFactory(new HashMap<String, Object>()).setNextFactory(variableFactory);
+    }
+
+
+    ExpressionParser(char[] expression, Object ctx, Map<String, Object> variables) {
+        this.expr = expression;
+        this.length = expr.length;
+        this.ctx = ctx;
+        //  this.tokens = tokens;
+        this.variableFactory = new MapVariableResolverFactory(variables);
+    }
+
+    ExpressionParser(String expression, Object ctx, Map<String, Object> variables) {
+        setExpression(expression);
+        this.ctx = ctx;
+        //   this.tokens = tokens;
+
+        this.variableFactory = new MapVariableResolverFactory(variables);
+
+    }
+
+    ExpressionParser(String expression) {
+        setExpression(expression);
+    }
+
+    ExpressionParser(char[] expression) {
+        this.expr = expression;
+    }
+
+
+    ExpressionParser() {
+    }
+
+    ExpressionParser(Object precompiedExpr) {
+        (this.tokenMap = (this.compiledExpression = (CompiledExpression) precompiedExpr).getTokenMap()).reset();
+        //      this.expr = compiledExpression.getExpression();
+        this.fastExecuteMode = true;
+    }
+
+    ExpressionParser(Object precompiedExpr, Object ctx) {
+        (this.tokenMap = (this.compiledExpression = (CompiledExpression) precompiedExpr).getTokenMap()).reset();
+        //      this.expr = compiledExpression.getExpression();
+        this.ctx = ctx;
+
+        this.fastExecuteMode = true;
+    }
+
+    ExpressionParser(Object precompiedExpr, VariableResolverFactory factory) {
+        (this.tokenMap = (this.compiledExpression = (CompiledExpression) precompiedExpr).getTokenMap()).reset();
+        //    this.expr = compiledExpression.getExpression();
+        this.variableFactory = factory;
+        this.fastExecuteMode = true;
+    }
+
+
+    ExpressionParser(Object precompiedExpr, Object ctx, Map<String, Object> variables) {
+        (this.tokenMap = (this.compiledExpression = (CompiledExpression) precompiedExpr).getTokenMap()).reset();
+        setExpressionArray(compiledExpression.getExpression());
+
+        this.ctx = ctx;
+
+        this.variableFactory = variables != null ? new MapVariableResolverFactory(variables) : null;
+        this.fastExecuteMode = true;
+    }
+
+    ExpressionParser(Object precompiedExpr, Object ctx, VariableResolverFactory resolverFactory) {
+        (this.tokenMap = (this.compiledExpression = (CompiledExpression) precompiedExpr).getTokenMap()).reset();
+        setExpressionArray(compiledExpression.getExpression());
+
+        //      this.expr = compiledExpression.getExpression();
+
+        this.ctx = ctx;
+
+        this.variableFactory = resolverFactory;
+        this.fastExecuteMode = true;
+    }
+
+    ExpressionParser(char[] expr, Object ctx, VariableResolverFactory resolverFactory) {
+        this.length = (this.expr = expr).length;
+        this.ctx = ctx;
+        this.variableFactory = resolverFactory;
+    }
+
+
+    ExpressionParser(String expression, Object ctx, Map<String, Object> variables, boolean booleanMode) {
+        setExpression(expression);
+        this.ctx = ctx;
+        this.variableFactory = new MapVariableResolverFactory(variables);
+        this.fields = booleanMode ? fields | Token.BOOLEAN_MODE : fields;
+    }
+
+    ExpressionParser(Object ctx, Map<String, Object> variables) {
+        this.ctx = ctx;
+        this.variableFactory = new MapVariableResolverFactory(variables);
+    }
+
+    ExpressionParser(String expression, Object ctx, VariableResolverFactory resolverFactory) {
+        setExpression(expression);
+        this.ctx = ctx;
+        this.variableFactory = resolverFactory;
+    }
+
+    ExpressionParser(String expression, VariableResolverFactory resolverFactory) {
+        setExpression(expression);
+        this.variableFactory = resolverFactory;
+    }
+
+    ExpressionParser(String expression, Object ctx) {
+        setExpression(expression);
+        this.ctx = ctx;
+    }
+
+
+}
+

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/FastTokenIterator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/FastTokenIterator.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/FastTokenIterator.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,95 @@
+package org.mvel;
+
+import java.util.ArrayList;
+
+public class FastTokenIterator implements TokenIterator, Cloneable {
+    private Token[] token;
+    private int length = 0;
+    private int cursor = 0;
+
+    public FastTokenIterator(TokenIterator map) {
+        ArrayList<Token> tokens = new ArrayList<Token>();
+        map.reset();
+        while (map.hasMoreTokens()) {
+            tokens.add(map.nextToken());
+        }
+
+        token = tokens.toArray(new Token[length = tokens.size()]);
+    }
+
+    public void reset() {
+        cursor = 0;
+        for (Token tk : token) {
+            tk.reset();
+        }
+    }
+
+    public Token nextToken() {
+        if (cursor < length)
+            return token[cursor++];
+        else
+            return null;
+    }
+
+    public Token peekToken() {
+        if (cursor < length)
+            return token[cursor];
+        else
+            return null;
+    }
+
+    public Token peekLast() {
+        if (cursor > 0) {
+            return token[cursor - 1];
+        }
+        else {
+            return null;
+        }
+    }
+
+
+    public Token tokensBack(int offset) {
+        if (cursor - offset >= 0) {
+            return token[cursor - offset];
+        }
+        else {
+            return null;
+        }
+    }
+
+    public void back() {
+        cursor--;
+    }
+
+    public boolean hasMoreTokens() {
+        return cursor < length;
+    }
+
+
+    public String showTokenChain() {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < length; i++) {
+            sb.append("(" + i + "): <<" + token[i].getName() + ">> = <<" + token[i].getValue() + ">> [" + (token[i].getValue() != null ? token[i].getValue().getClass() : "null") + "]").append("\n");
+        }
+
+        return sb.toString();
+    }
+
+
+    public TokenIterator clone() {
+        try {
+            FastTokenIterator ti = (FastTokenIterator) super.clone();
+            ti.token = new Token[token.length];
+
+            for (int i = 0; i < token.length; i++) {
+                ti.token[i] = token[i].clone();
+            }
+            return ti;
+        }
+        catch (CloneNotSupportedException e) {
+            // no handling needed.
+            return null;
+        }
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Interpreter.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Interpreter.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Interpreter.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,504 @@
+package org.mvel;
+
+import org.mvel.util.ExecutionStack;
+import static org.mvel.ExpressionParser.compileExpression;
+import static org.mvel.ExpressionParser.executeExpression;
+
+import java.io.*;
+import static java.lang.String.valueOf;
+import static java.lang.System.arraycopy;
+import java.nio.ByteBuffer;
+import static java.nio.ByteBuffer.allocateDirect;
+import java.nio.channels.ReadableByteChannel;
+import java.util.Collection;
+import static java.util.Collections.synchronizedMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+/**
+ * The MVEL Template Interpreter.  Naming this an "Interpreter" is not inaccurate.   All template expressions
+ * are pre-compiled by the the {@link TemplateCompiler} prior to being processed by this interpreter.<br/>
+ * <br/>
+ * Under normal circumstances, it is completely acceptable to execute the parser/interpreter from the static
+ * convenience methods in this class.
+ *
+ * @author Christopher Brock
+ */
+public class Interpreter {
+
+    public static boolean cacheAggressively = false;
+
+    /**
+     * Evaluates the template expression and returns a String value.  This is only a convenience method that
+     * has the same semantics as using <tt>String.valueOf(eval(expr, vars, ctx))</tt>.
+     *
+     * @param template - the template to be evaluated
+     * @param ctx      - the virtual root / context of the expression.
+     * @return the resultant value represented in it's equivelant string value.
+     */
+    public static String evalToString(String template, Object ctx) {
+        return valueOf(eval(template, ctx));
+    }
+
+
+    /**
+     * Evaluates the template expression and returns a String value.  This is only a convenience method that
+     * has the same semantics as using <tt>String.valueOf(eval(expr, vars, ctx))</tt>.
+     *
+     * @param template  - the template to be evaluated
+     * @param variables - a map of variables for use in the expression.
+     * @return the resultant value represented in it's equivelant string value.
+     */
+    public static String evalToString(String template, Map variables) {
+        return valueOf(eval(template, variables));
+    }
+
+    /**
+     * Evaluates the template expression and returns a String value.  This is only a convenience method that
+     * has the same semantics as using <tt>String.valueOf(eval(expr, vars, ctx))</tt>.
+     *
+     * @param template  - the template to be evaluated
+     * @param ctx       - the virtual root / context of the expression.
+     * @param variables - a map of variables for use in the expression.
+     * @return the resultant value represented in it's equivelant string value.
+     */
+    public static String evalToString(String template, Object ctx, Map variables) {
+        return valueOf(eval(template, ctx, variables));
+    }
+
+    /**
+     * @param template - the template to be evaluated
+     * @param ctx      - the virtual root / context of the expression.
+     * @return see description.
+     * @see #eval(String,Object,Map)
+     */
+    public static Object eval(String template, Object ctx) {
+        if (template == null) return null;
+        return new Interpreter(template).execute(ctx, null);
+    }
+
+    /**
+     * @param template  - the template to be evaluated
+     * @param variables - a map of variables for use in the expression.
+     * @return see description.
+     * @see #eval(String,Object,Map)
+     */
+    public static Object eval(String template, Map variables) {
+        return new Interpreter(template).execute(null, variables);
+    }
+
+    /**
+     * Compiles, interprets and returns the result from a template.  The value that this returns is dependant
+     * on whether or not the template actually contains any literal values.<br/>
+     * <br/>
+     * For example, an expression that is simply "<tt>@{foobar}</tt>" will return the value of <tt>foobar</tt>,
+     * not a string value.  An expression that only contains a single tag is a defacto expression and is not
+     * considered a template.<br/>
+     * <br/>
+     * An expression such as "<tt>Hello my name is: @{name}</tt>" will return the a String value as it clearly a
+     * template.<br/>
+     *
+     * @param template  - the template to be evaluated
+     * @param ctx       - the virtual root / context of the expression.
+     * @param variables - a map of variables for use in the expression.
+     * @return see description.
+     */
+    public static Object eval(String template, Object ctx, Map variables) {
+        if (template == null) return null;
+        //noinspection unchecked
+        return new Interpreter(template).execute(ctx, variables);
+    }
+
+    private char[] expression;
+    private boolean debug = false;
+    private Node[] nodes;
+    private int node = 0;
+
+    private static Map<CharSequence, char[]> EX_PRECACHE;
+    private static Map<Object, Node[]> EX_NODE_CACHE;
+    private static Map<Object, Object> EX_PRECOMP_CACHE;
+
+    static {
+         configureFactory();
+    }
+
+    static void configureFactory() {
+        if (MVEL.THREAD_SAFE) {
+            EX_PRECACHE = synchronizedMap(new WeakHashMap<CharSequence, char[]>());
+            EX_NODE_CACHE = synchronizedMap(EX_NODE_CACHE = new WeakHashMap<Object, Node[]>());
+            EX_PRECOMP_CACHE = synchronizedMap(EX_PRECOMP_CACHE = new WeakHashMap<Object, Object>());
+        }
+        else {
+            EX_PRECACHE = (new WeakHashMap<CharSequence, char[]>());
+            EX_NODE_CACHE = (EX_NODE_CACHE = new WeakHashMap<Object, Node[]>());
+            EX_PRECOMP_CACHE = (EX_PRECOMP_CACHE = new WeakHashMap<Object, Object>());
+        }
+    }
+
+    private ExecutionStack stack;
+
+    /**
+     * Creates a new intepreter
+     *
+     * @param template -
+     */
+    public Interpreter(CharSequence template) {
+        if (!EX_PRECACHE.containsKey(template)) {
+            EX_PRECACHE.put(template, this.expression = template.toString().toCharArray());
+            EX_NODE_CACHE.put(template, nodes = new TemplateCompiler(this).compileExpression());
+        }
+        else {
+            this.expression = EX_PRECACHE.get(template);
+            this.nodes = EX_NODE_CACHE.get(template);
+        }
+    }
+
+    public Interpreter(String expression) {
+        if (!EX_PRECACHE.containsKey(expression)) {
+            EX_PRECACHE.put(expression, this.expression = expression.toCharArray());
+            EX_NODE_CACHE.put(expression, nodes = new TemplateCompiler(this).compileExpression());
+        }
+        else {
+            this.expression = EX_PRECACHE.get(expression);
+            this.nodes = EX_NODE_CACHE.get(expression);
+        }
+    }
+
+    public Interpreter(char[] expression) {
+        this.expression = expression;
+    }
+
+    public boolean isDebug() {
+        return debug;
+    }
+
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    public static void parseToStream(File template, Object ctx, Map<String, Object> tokens, OutputStream out)
+            throws IOException {
+        Object result = parse(template, ctx, tokens);
+        CharSequence cs;
+
+        if (result == null) return;
+        else if (result instanceof CharSequence) {
+            cs = (CharSequence) result;
+        }
+        else {
+            cs = valueOf(result);
+        }
+
+        OutputStreamWriter writer = new OutputStreamWriter(out);
+
+        int len = cs.length();
+        for (int i = 0; i < len; i++) {
+            writer.write(cs.charAt(i));
+        }
+        writer.flush();
+        writer.close();
+    }
+
+    public static Object parse(File file, Object ctx, Map<String, Object> tokens) throws IOException {
+        if (!file.exists())
+            throw new CompileException("cannot find file: " + file.getName());
+
+        FileInputStream inStream = null;
+        ReadableByteChannel fc = null;
+        try {
+            inStream = new FileInputStream(file);
+            fc = inStream.getChannel();
+            ByteBuffer buf = allocateDirect(10);
+
+            StringBuilder sb = new StringBuilder((int) file.length());
+
+            int read = 0;
+            while (read >= 0) {
+                buf.rewind();
+                read = fc.read(buf);
+                buf.rewind();
+
+                for (; read > 0; read--) {
+                    sb.append((char) buf.get());
+                }
+            }
+
+            return parse(sb, ctx, tokens);
+
+        }
+        catch (FileNotFoundException e) {
+            // this can't be thrown, we check for this explicitly.
+        }
+        finally {
+            if (inStream != null) inStream.close();
+            if (fc != null) fc.close();
+        }
+
+        return null;
+    }
+
+
+    public static Object parse(CharSequence expression, Object ctx, Map<String, Object> vars) {
+        if (expression == null) return null;
+        return new Interpreter(expression).execute(ctx, vars);
+    }
+
+
+    public static Object parse(String expression, Object ctx, Map<String, Object> vars) {
+        if (expression == null) return null;
+
+        return new Interpreter(expression).execute(ctx, vars);
+    }
+
+
+    public Object execute(Object ctx, Map tokens) {
+        if (nodes == null) {
+            return new String(expression);
+        }
+        else if (nodes.length == 2) {
+            switch (nodes[0].getToken()) {
+                case PROPERTY_EX:
+                    //noinspection unchecked
+                    //  return ExpressionParser.eval(getInternalSegment(nodes[0]), ctx, tokens);
+
+                    if (!cacheAggressively) {
+                        char[] seg = new char[expression.length - 3];
+                        arraycopy(expression, 2, seg, 0, seg.length);
+
+                        return ExpressionParser.eval(seg, ctx, tokens);
+                    }
+                    else {
+                        String s = new String(expression, 2, expression.length - 3);
+                        if (!EX_PRECOMP_CACHE.containsKey(s)) {
+                            EX_PRECOMP_CACHE.put(s, compileExpression(s));
+                        }
+
+                        return executeExpression(EX_PRECOMP_CACHE.get(s), ctx, tokens);
+
+                    }
+                case LITERAL:
+                    return new String(expression);
+            }
+
+            return new String(expression);
+        }
+
+        Object register = null;
+
+        StringBuilder sbuf = new StringBuilder(10);
+        Node currNode = null;
+
+        try {
+            ExpressionParser oParser = new ExpressionParser(ctx, tokens);
+
+            initStack();
+            pushAndForward();
+
+            while ((currNode = pop()) != null) {
+                node = currNode.getNode();
+
+                switch (currNode.getToken()) {
+                    case LITERAL: {
+                        sbuf.append(register = new String(expression, currNode.getStartPos(),
+                                currNode.getEndPos() - currNode.getStartPos()));
+                        break;
+                    }
+                    case PROPERTY_EX: {
+                        sbuf.append(
+                                valueOf(register = oParser.setExpressionArray(getInternalSegment(currNode)).parse())
+                        );
+                        break;
+                    }
+                    case IF:
+                    case ELSEIF: {
+                        try {
+                            oParser.setBooleanModeOnly(true);
+                            if (!((Boolean) oParser.setExpressionArray(getInternalSegment(currNode)).parse())) {
+                                exitContext();
+                            }
+                            oParser.setBooleanModeOnly(false);
+                        }
+                        catch (ClassCastException e) {
+                            throw new CompileException("IF expression does not return a boolean: " + new String(getSegment(currNode)));
+                        }
+                        break;
+                    }
+
+                    case FOREACH: {
+                        if (currNode.getRegister() == null) {
+                            try {
+                                currNode.setRegister(
+                                        ((Collection) new ExpressionParser(getForEachSegment(currNode), ctx, tokens).parse()).iterator()
+                                );
+                            }
+                            catch (ClassCastException e) {
+                                throw new CompileException("expression for collection does not return a collection object: " + new String(getSegment(currNode)));
+                            }
+                            catch (NullPointerException e) {
+                                throw new CompileException("null returned for foreach in expression: " + (getForEachSegment(currNode)));
+                            }
+                        }
+
+                        Iterator iter = (Iterator) currNode.getRegister();
+                        if (iter.hasNext()) {
+                            push();
+                            //noinspection unchecked
+                            tokens.put(currNode.getAlias(), iter.next());
+                        }
+                        else {
+                            tokens.remove(currNode.getAlias());
+                            exitContext();
+                        }
+                        break;
+                    }
+                    case ELSE:
+                    case END:
+                        if (stack.isEmpty()) forwardAndPush();
+                        continue;
+                    case GOTO:
+                        pushNode(currNode.getEndNode());
+                        continue;
+                    case TERMINUS: {
+                        if (nodes.length == 2) {
+                            return register;
+                        }
+                        else {
+                            return sbuf.toString();
+                        }
+                    }
+                }
+
+                forwardAndPush();
+            }
+            throw new CompileException("expression did not end properly: expected TERMINUS node");
+        }
+        catch (CompileException e) {
+            throw e;
+        }
+        catch (Exception e) {
+            if (currNode != null) {
+                throw new CompileException("problem encountered at node [" + currNode.getNode() + "] "
+                        + currNode.getToken() + "{" + currNode.getStartPos() + "," + currNode.getEndPos() + "}", e);
+            }
+            throw new CompileException("unhandled fatal exception (node:" + node + ")", e);
+        }
+    }
+
+
+    private void initStack() {
+        stack = new ExecutionStack();
+    }
+
+    private void push() {
+        push(nodes[node]);
+    }
+
+    private void push(Node node) {
+        if (node == null) return;
+        stack.push(node);
+    }
+
+    private void pushNode(int i) {
+        stack.push(nodes[i]);
+    }
+
+    private void exitContext() {
+        node = nodes[node].getEndNode();
+    }
+
+
+    public void forwardAndPush() {
+        node++;
+        push();
+    }
+
+    private void pushAndForward() {
+        push();
+        node++;
+    }
+
+    private Node pop() {
+        return (Node) stack.pop();
+    }
+
+
+ 
+    /**
+     * @param expression -
+     * @param ctx -
+     * @param tokens -
+     * @return -
+     * 
+     * @deprecated
+     */
+    public static Object getValuePE(String expression, Object ctx, Map<String, Object> tokens) {
+        return new Interpreter(expression).execute(ctx, tokens);
+    }
+
+
+    /**
+     * @param expression -
+     * @param ctx -
+     * @param preParseCx -
+     * @param value -
+     * @deprecated
+     */
+    public static void setValuePE(String expression, Object ctx, Object preParseCx, Object value) {
+        PropertyAccessor.set(ctx, valueOf(eval(expression, preParseCx)), value);
+    }
+
+    public char[] getExpression() {
+        return expression;
+    }
+
+    public void setExpression(char[] expression) {
+        this.expression = expression;
+    }
+
+    private char[] getSegment(Node n) {
+        char[] ca = new char[n.getLength()];
+        arraycopy(expression, n.getStartPos(), ca, 0, ca.length);
+        return ca;
+    }
+
+    private char[] getInternalSegment(Node n) {
+        int start = n.getStartPos();
+        int depth = 1;
+
+        //noinspection StatementWithEmptyBody
+        while ((expression[start++] != '{')) ;
+
+        int end = start;
+        while (depth > 0) {
+            switch (expression[++end]) {
+                case'{':
+                    depth++;
+                    break;
+                case'}':
+                    depth--;
+                    break;
+            }
+        }
+
+        char[] ca = new char[end - start];
+        arraycopy(expression, start, ca, 0, ca.length);
+        return ca;
+    }
+
+    private String getForEachSegment(Node n) {
+        if (n.getAlias() == null) return new String(getInternalSegment(n));
+        else {
+            return n.getName();
+        }
+    }
+
+
+    public static boolean isCacheAggressively() {
+        return cacheAggressively;
+    }
+
+    public static void setCacheAggressively(boolean cacheAggressively) {
+        Interpreter.cacheAggressively = cacheAggressively;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/MVEL.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/MVEL.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/MVEL.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,23 @@
+package org.mvel;
+
+public class MVEL {
+    static boolean THREAD_SAFE = Boolean.getBoolean("mvflex.expression.threadsafety");
+
+    /**
+     * Force MVEL to use thread-safe caching.  This can also be specified enivromentally using the
+     * <tt>mvflex.expression.threadsafety</tt> system property.
+     *
+     * @param threadSafe - true enabled thread-safe caching - false disables thread-safety.
+     */
+    public static void setThreadSafe(boolean threadSafe) {
+        THREAD_SAFE = threadSafe;
+        PropertyAccessor.configureFactory();
+        Interpreter.configureFactory();
+        ExpressionParser.configureFactory();
+    }
+
+    public static boolean isThreadSafe() {
+        return THREAD_SAFE;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/MVELSH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/MVELSH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/MVELSH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,132 @@
+package org.mvel;
+
+import org.mvel.integration.impl.LocalVariableResolverFactory;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MVELSH {
+    public static void main(String[] args) {
+        System.out.println("MVEL (MVFLEX Expression Language) Command-line Interpreter Tool");
+        System.out.println("Copyright (C) 2006 The MVFLEX/Valhalla Project");
+        System.out.println("Version 1.1.008  -- Written by: Christopher Brock\n\n");
+
+        Map map = new HashMap();
+
+        boolean output = true;
+        boolean stacktrace = false;
+        boolean showExecTime = false;
+        boolean benchmarkMode = false;
+        boolean template = false;
+
+
+        String in;
+
+        LocalVariableResolverFactory lvrf = new LocalVariableResolverFactory(new HashMap<String, Object>());
+
+        //    ExpressionParser parser = new ExpressionParser();
+
+        Object out = null;
+
+        long time;
+
+        while (true) {
+            try {
+                System.out.print("mvel$ ");
+                in = new BufferedReader(new InputStreamReader(System.in)).readLine();
+
+                if (in.length() == 0) continue;
+
+                if ("quit;".equals(in) || "exit;".equals(in)) return;
+                if ("stacktrace;".equals(in)) {
+                    stacktrace = !stacktrace;
+                    System.out.println("STACKTRACES: " + (stacktrace ? "ON" : "OFF"));
+                    continue;
+                }
+
+                if ("echo;".equals(in)) {
+                    output = !output;
+
+                    System.out.println("OUTPUT ECHO: " + (output ? "ON" : "OFF"));
+
+                    continue;
+                }
+
+                if ("template;".equals(in)) {
+                    template = !template;
+                    System.out.println("TEMPLATE INTERPRETER: " + (template ? "ON" : "OFF"));
+                    continue;
+                }
+
+                if ("exectime;".equals(in)) {
+                    showExecTime = !showExecTime;
+                    System.out.println("SHOW EXEC TIME: " + (showExecTime ? "ON " : "OFF"));
+                    continue;
+                }
+                if ("benchmark;".equals(in)) {
+                    benchmarkMode = !benchmarkMode;
+                    showExecTime = true;
+                    System.out.println("MVELSH BENCHMARK MODE: " + (benchmarkMode ? "ON" : "OFF"));
+                    continue;
+                }
+                if ("clear;".equals(in)) {
+                    map.clear();
+                    System.out.println("CLEARED VARIABLES.");
+                    continue;
+                }
+                if ("help;".equals(in)) {
+                    showHelp();
+                    continue;
+                }
+
+                if (template) {
+                    time = System.currentTimeMillis();
+                    out = Interpreter.parse(in, null, map);
+                    time = System.currentTimeMillis() - time;
+                }
+                else if (benchmarkMode) {
+                    System.out.println("HOTSPOT WARMUP ...");
+                    for (int i = 10000; i != 0; i--) {
+                        ExpressionParser.eval(in, lvrf);
+                    }
+                    System.out.println("RUNNING BENCHMARK (10,000 times) ...");
+
+                    time = System.currentTimeMillis();
+                    for (int i = 10000; i != 0; i--) {
+                        out = ExpressionParser.eval(in, lvrf);
+
+                    }
+                    time = System.currentTimeMillis() - time;
+                }
+                else {
+                    time = System.currentTimeMillis();
+                    out = ExpressionParser.eval(in, lvrf);
+                    time = System.currentTimeMillis() - time;
+                }
+
+                if (showExecTime) System.out.println("DONE in : " + time + "ms.");
+                if (output) System.out.println((template ? "TOUT: " : "OUT: ") + out);
+            }
+            catch (Exception e) {
+                if (stacktrace) e.printStackTrace();
+                else
+                    System.out.println("ERROR: " + e.getMessage());
+            }
+        }
+    }
+
+    private static void showHelp() {
+        System.out.println("Commands");
+        System.out.println("--------");
+        System.out.println("echo            -   toggles output echo on/off");
+        System.out.println("template        -   use the template parser shell");
+        System.out.println("stacktrace      -   toggles stacktraces on/off");
+        System.out.println("benchmark       -   toggles benchmark mode on/off");
+        System.out.println("exectime        -   toggles execution time display on/off");
+        System.out.println("clear           -   clears all variables");
+        System.out.println("quit            -   exits the shell");
+        System.out.println("\n");
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Node.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Node.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Node.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,137 @@
+package org.mvel;
+
+
+public class Node {
+    private NodeType nodeType = NodeType.PROPERTY_EX;
+
+    private int startPos;
+    private int length;
+//    private char[] expression;
+
+    private int node;
+    private int endNode;
+
+    private String alias;
+
+    private Object register;
+
+    private String name;
+
+    Node() {
+    }
+
+
+    Node(int startPos) {
+        this.startPos = startPos;
+    }
+
+    Node(int node, NodeType nodeType) {
+        this.node = node;
+        this.nodeType = nodeType;
+    }
+
+    Node(int node, NodeType nodeType, int endNode) {
+        this.node = node;
+        this.nodeType = nodeType;
+        this.endNode = endNode;
+    }
+
+    Node(int startPos, int length) {
+        this.startPos = startPos;
+        this.length = length;
+    }
+
+    Node(int node, NodeType nodeType, int startPos, int length, int endNode) {
+        this.nodeType = nodeType;
+        this.startPos = startPos;
+        this.length = length;
+        this.node = node;
+        this.endNode = endNode;
+    }
+
+    public NodeType getToken() {
+        return nodeType;
+    }
+
+    public void setToken(NodeType nodeType) {
+        this.nodeType = nodeType;
+    }
+
+    public int getLength() {
+        return length;
+    }
+
+    public void setLength(int length) {
+        this.length = length;
+    }
+
+    public int getStartPos() {
+        return startPos;
+    }
+
+    public void setStartPos(int startPos) {
+        this.startPos = startPos;
+    }
+
+    public int getEndPos() {
+        return startPos + length;
+    }
+
+    public int getNode() {
+        return node;
+    }
+
+    public void setEndPos(int position) {
+        this.length = position - startPos;
+    }
+
+
+    public Node setNode(int node) {
+        this.node = node;
+        this.endNode = node + 1;
+
+        return this;
+    }
+
+    public int getEndNode() {
+        return endNode;
+    }
+
+    public void setEndNode(int endNode) {
+        this.endNode = endNode;
+    }
+
+    public Object getRegister() {
+        return register;
+    }
+
+    public void setRegister(Object register) {
+        this.register = register;
+    }
+
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public NodeType getNodeType() {
+        return nodeType;
+    }
+
+    public void setNodeType(NodeType nodeType) {
+        this.nodeType = nodeType;
+    }
+
+    public String getAlias() {
+        return alias;
+    }
+
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/NodeType.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/NodeType.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/NodeType.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,5 @@
+package org.mvel;
+
+public enum NodeType {
+    IF, FOREACH, ELSEIF, ELSE, END, PROPERTY_EX, LITERAL, TERMINUS, GOTO, OPERATOR
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Operator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Operator.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Operator.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,11 @@
+package org.mvel;
+
+public enum Operator {
+    ADD, SUB, MULT, DIV, MOD, EQUAL, NEQUAL, LTHAN, GTHAN, LETHAN, GETHAN,
+    AND, OR, CHOR, REGEX, INSTANCEOF, CONTAINS, STR_APPEND, SOUNDEX, SIMILARITY,
+    BW_AND, BW_OR, BW_XOR, BW_SHIFT_RIGHT, BW_SHIFT_LEFT, BW_USHIFT_RIGHT, BW_USHIFT_LEFT,
+    TERNARY, TERNARY_ELSE,
+    ASSIGN, INC_ASSIGN, DEC_ASSIGN,
+    NEW, PROJECTION, CONVERTABLE_TO,
+    END_OF_STMT
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ParseException.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ParseException.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ParseException.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,20 @@
+package org.mvel;
+
+public class ParseException extends RuntimeException {
+
+    public ParseException() {
+        super();
+    }
+
+    public ParseException(String message) {
+        super(message);
+    }
+
+    public ParseException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ParseException(Throwable cause) {
+        super(cause);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Projection.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Projection.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Projection.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,4 @@
+package org.mvel;
+
+public class Projection {
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/PropertyAccessException.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/PropertyAccessException.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/PropertyAccessException.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,20 @@
+package org.mvel;
+
+public class PropertyAccessException extends RuntimeException {
+
+    public PropertyAccessException() {
+        super();
+    }
+
+    public PropertyAccessException(String message) {
+        super(message);
+    }
+
+    public PropertyAccessException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public PropertyAccessException(Throwable cause) {
+        super(cause);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/PropertyAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/PropertyAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/PropertyAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,612 @@
+package org.mvel;
+
+import static org.mvel.DataConversion.canConvert;
+import static org.mvel.DataConversion.convert;
+import static org.mvel.ExpressionParser.executeExpression;
+import org.mvel.integration.VariableResolverFactory;
+import static org.mvel.util.ParseTools.getBestCanadidate;
+import static org.mvel.util.ParseTools.parseParameterList;
+import static org.mvel.util.PropertyTools.getFieldOrAccessor;
+import static org.mvel.util.PropertyTools.getFieldOrWriteAccessor;
+
+import java.io.Serializable;
+import static java.lang.Character.isJavaIdentifierPart;
+import static java.lang.Character.isWhitespace;
+import static java.lang.Integer.parseInt;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.*;
+import static java.util.Collections.synchronizedMap;
+
+public class PropertyAccessor {
+    private int start = 0;
+    private int cursor = 0;
+
+    private char[] property;
+    private int length;
+
+    private Object thisReference;
+    private Object ctx;
+    private Object curr;
+
+    private VariableResolverFactory resolver;
+
+    private static final int DONE = -1;
+    private static final int NORM = 0;
+    private static final int METH = 1;
+    private static final int COL = 2;
+
+    private static final Object[] EMPTYARG = new Object[0];
+
+    private static Map<Class, Map<Integer, Member>> READ_PROPERTY_RESOLVER_CACHE;
+    private static Map<Class, Map<Integer, Member>> WRITE_PROPERTY_RESOLVER_CACHE;
+    private static Map<Class, Map<Integer, Object[]>> METHOD_RESOLVER_CACHE;
+
+    static {
+        configureFactory();
+    }
+
+    static void configureFactory() {
+        if (MVEL.THREAD_SAFE) {
+            READ_PROPERTY_RESOLVER_CACHE = synchronizedMap(new WeakHashMap<Class, Map<Integer, Member>>(10));
+            WRITE_PROPERTY_RESOLVER_CACHE = synchronizedMap(new WeakHashMap<Class, Map<Integer, Member>>(10));
+            METHOD_RESOLVER_CACHE = synchronizedMap(new WeakHashMap<Class, Map<Integer, Object[]>>(10));
+        }
+        else {
+            READ_PROPERTY_RESOLVER_CACHE = (new WeakHashMap<Class, Map<Integer, Member>>(10));
+            WRITE_PROPERTY_RESOLVER_CACHE = (new WeakHashMap<Class, Map<Integer, Member>>(10));
+            METHOD_RESOLVER_CACHE = (new WeakHashMap<Class, Map<Integer, Object[]>>(10));
+        }
+    }
+
+    public PropertyAccessor(char[] property, Object ctx) {
+        this.property = property;
+        this.length = property.length;
+        this.ctx = ctx;
+    }
+
+    public PropertyAccessor(char[] property, Object ctx, VariableResolverFactory resolver, Object thisReference) {
+        this.property = property;
+        this.length = property.length;
+        this.ctx = ctx;
+        this.resolver = resolver;
+        this.thisReference = thisReference;
+    }
+
+    public PropertyAccessor(VariableResolverFactory resolver, Object thisReference) {
+        this.resolver = resolver;
+        this.thisReference = thisReference;
+    }
+
+
+    public PropertyAccessor(char[] property, int offset, int end, Object ctx, VariableResolverFactory resolver) {
+        this.property = property;
+        this.cursor = offset;
+        this.length = end;
+        this.ctx = ctx;
+        this.resolver = resolver;
+    }
+
+    public PropertyAccessor(String property, Object ctx) {
+        this.length = (this.property = property.toCharArray()).length;
+        this.ctx = ctx;
+    }
+
+    public static Object get(String property, Object ctx) {
+        return new PropertyAccessor(property, ctx).get();
+    }
+
+    public static Object get(char[] property, Object ctx, VariableResolverFactory resolver, Object thisReference) {
+        return new PropertyAccessor(property, ctx, resolver, thisReference).get();
+    }
+
+    public static Object get(char[] property, int offset, int end, Object ctx, VariableResolverFactory resolver) {
+        return new PropertyAccessor(property, offset, end, ctx, resolver).get();
+    }
+
+    public static Object get(String property, Object ctx, VariableResolverFactory resolver, Object thisReference) {
+        return new PropertyAccessor(property.toCharArray(), ctx, resolver, thisReference).get();
+    }
+
+    public static void set(Object ctx, String property, Object value) {
+        new PropertyAccessor(property, ctx).set(value);
+    }
+
+    public PropertyAccessor setParameters(char[] property, int offset, int end, Object ctx) {
+        this.property = property;
+        this.cursor = offset;
+        this.length = end;
+        this.ctx = ctx;
+        return this;
+    }
+
+
+    public Object get() {
+        curr = ctx;
+
+        try {
+            while (cursor < length) {
+                if (curr == null) {
+                    throw new PropertyAccessException("null pointer exception in property: " + new String(property) + " (" + capture() + " is null)");
+                }
+
+                switch (nextToken()) {
+                    case NORM:
+                        curr = getBeanProperty(curr, capture());
+                        break;
+                    case METH:
+                        curr = getMethod(curr, capture());
+                        break;
+                    case COL:
+                        curr = getCollectionProperty(curr, capture());
+                        break;
+                    case DONE:
+                        break;
+                }
+            }
+
+            return curr;
+        }
+        catch (InvocationTargetException e) {
+            throw new PropertyAccessException("could not access property", e);
+        }
+        catch (IllegalAccessException e) {
+            throw new PropertyAccessException("could not access property", e);
+        }
+        catch (IndexOutOfBoundsException e) {
+            throw new PropertyAccessException("array or collection index out of bounds (property: " + new String(property) + ")", e);
+        }
+        catch (PropertyAccessException e) {
+            throw new PropertyAccessException("failed to access property: <<" + new String(property) + ">> in: " + (ctx!=null?ctx.getClass():null), e);
+        }
+        catch (CompileException e) {
+            throw e;
+        }
+        catch (NullPointerException e) {
+            throw new PropertyAccessException("null pointer exception in property: " + new String(property), e);
+        }
+        catch (Exception e) {
+            throw new PropertyAccessException("unknown exception in expression: " + new String(property), e);
+        }
+    }
+
+    private void set(Object value) {
+        curr = ctx;
+
+        try {
+            String tk = null;
+            while (cursor < length) {
+                tk = captureNext();
+                if (!hasMore()) break;
+                curr = getBeanProperty(curr, tk);
+            }
+
+            Member member = checkWriteCache(curr.getClass(), tk == null ? 0 : tk.hashCode());
+            if (member == null) {
+                addWriteCache(curr.getClass(), tk == null ? 0 : tk.hashCode(), (member = getFieldOrWriteAccessor(curr.getClass(), tk)));
+            }
+
+            if (member instanceof Field) {
+                Field fld = (Field) member;
+
+                if (value != null && !fld.getType().isAssignableFrom(value.getClass())) {
+                    if (!canConvert(fld.getType(), value.getClass())) {
+                        throw new ConversionException("cannot convert type: "
+                                + value.getClass() + ": to " + fld.getType());
+                    }
+
+                    fld.set(curr, convert(value, fld.getType()));
+                }
+                else
+                    fld.set(curr, value);
+            }
+            else if (member != null) {
+                Method meth = (Method) member;
+
+                if (value != null && !meth.getParameterTypes()[0].isAssignableFrom(value.getClass())) {
+                    if (!canConvert(meth.getParameterTypes()[0], value.getClass())) {
+                        throw new ConversionException("cannot convert type: "
+                                + value.getClass() + ": to " + meth.getParameterTypes()[0]);
+                    }
+
+                    meth.invoke(curr, convert(value, meth.getParameterTypes()[0]));
+                }
+                else {
+                    meth.invoke(curr, value);
+                }
+            }
+            else {
+                throw new PropertyAccessException("could not access property (" + property + ") in: " + ctx.getClass().getName());
+            }
+        }
+        catch (InvocationTargetException e) {
+            throw new PropertyAccessException("could not access property", e);
+        }
+        catch (IllegalAccessException e) {
+            throw new PropertyAccessException("could not access property", e);
+        }
+
+    }
+
+
+    private boolean hasMore() {
+        return cursor < length;
+    }
+
+    private String captureNext() {
+        nextToken();
+        return capture();
+    }
+
+    private int nextToken() {
+        switch (property[start = cursor]) {
+            case'[':
+                return COL;
+            case'.':
+                cursor = ++start;
+        }
+
+        //noinspection StatementWithEmptyBody
+        while (++cursor < length && isJavaIdentifierPart(property[cursor])) ;
+
+
+        if (cursor < length) {
+            switch (property[cursor]) {
+                case'[':
+                    return COL;
+                case'(':
+                    return METH;
+                default:
+                    return 0;
+            }
+        }
+        return 0;
+    }
+
+    private String capture() {
+        return new String(property, start, cursor - start);
+    }
+
+
+    public static void clearPropertyResolverCache() {
+        READ_PROPERTY_RESOLVER_CACHE.clear();
+        WRITE_PROPERTY_RESOLVER_CACHE.clear();
+        METHOD_RESOLVER_CACHE.clear();
+    }
+
+    public static void reportCacheSizes() {
+        System.out.println("read property cache: " + READ_PROPERTY_RESOLVER_CACHE.size());
+        for (Class cls : READ_PROPERTY_RESOLVER_CACHE.keySet()) {
+            System.out.println(" [" + cls.getName() + "]: " + READ_PROPERTY_RESOLVER_CACHE.get(cls).size() + " entries.");
+        }
+        System.out.println("write property cache: " + WRITE_PROPERTY_RESOLVER_CACHE.size());
+        for (Class cls : WRITE_PROPERTY_RESOLVER_CACHE.keySet()) {
+            System.out.println(" [" + cls.getName() + "]: " + WRITE_PROPERTY_RESOLVER_CACHE.get(cls).size() + " entries.");
+        }
+        System.out.println("method cache: " + METHOD_RESOLVER_CACHE.size());
+        for (Class cls : METHOD_RESOLVER_CACHE.keySet()) {
+            System.out.println(" [" + cls.getName() + "]: " + METHOD_RESOLVER_CACHE.get(cls).size() + " entries.");
+        }
+    }
+
+    private static void addReadCache(Class cls, Integer property, Member member) {
+        if (!READ_PROPERTY_RESOLVER_CACHE.containsKey(cls)) {
+            READ_PROPERTY_RESOLVER_CACHE.put(cls, new WeakHashMap<Integer, Member>());
+        }
+        READ_PROPERTY_RESOLVER_CACHE.get(cls).put(property, member);
+    }
+
+    public static Member checkReadCache(Class cls, Integer property) {
+        if (READ_PROPERTY_RESOLVER_CACHE.containsKey(cls)) {
+            return READ_PROPERTY_RESOLVER_CACHE.get(cls).get(property);
+        }
+        return null;
+    }
+
+    private static void addWriteCache(Class cls, Integer property, Member member) {
+        if (!WRITE_PROPERTY_RESOLVER_CACHE.containsKey(cls)) {
+            WRITE_PROPERTY_RESOLVER_CACHE.put(cls, new WeakHashMap<Integer, Member>());
+        }
+        WRITE_PROPERTY_RESOLVER_CACHE.get(cls).put(property, member);
+    }
+
+    public static Member checkWriteCache(Class cls, Integer property) {
+        if (WRITE_PROPERTY_RESOLVER_CACHE.containsKey(cls)) {
+            return WRITE_PROPERTY_RESOLVER_CACHE.get(cls).get(property);
+        }
+        return null;
+    }
+
+
+    private static void addMethodCache(Class cls, Integer property, Method member) {
+        if (!METHOD_RESOLVER_CACHE.containsKey(cls)) {
+            METHOD_RESOLVER_CACHE.put(cls, new WeakHashMap<Integer, Object[]>());
+        }
+        METHOD_RESOLVER_CACHE.get(cls).put(property, new Object[]{member, member.getParameterTypes()});
+    }
+
+    public static Object[] checkMethodCache(Class cls, Integer property) {
+        if (METHOD_RESOLVER_CACHE.containsKey(cls)) {
+            return METHOD_RESOLVER_CACHE.get(cls).get(property);
+        }
+        return null;
+    }
+
+
+    private Object getBeanProperty(Object ctx, String property)
+            throws IllegalAccessException, InvocationTargetException {
+
+        Class cls;
+        Member member = checkReadCache(cls = (ctx instanceof Class ? ((Class) ctx) : ctx.getClass()), property.hashCode());
+
+        if (member == null) {
+            addReadCache(cls, property.hashCode(), member = getFieldOrAccessor(cls, property));
+        }
+
+        if (member instanceof Field) {
+            return ((Field) member).get(ctx);
+        }
+        else if (member != null) {
+            return ((Method) member).invoke(ctx, EMPTYARG);
+        }
+        else if (ctx instanceof Map && ((Map) ctx).containsKey(property)) {
+            return ((Map) ctx).get(property);
+        }
+        else if ("this".equals(property)) {
+            return this.thisReference;
+        }
+        else {
+            throw new PropertyAccessException("could not access property (" + property + ")");
+        }
+    }
+
+    private void whiteSpaceSkip() {
+        if (cursor < length)
+            //noinspection StatementWithEmptyBody
+            while (isWhitespace(property[cursor]) && ++cursor < length) ;
+    }
+
+    private boolean scanTo(char c) {
+        for (; cursor < length; cursor++) {
+            if (property[cursor] == c) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private int containsStringLiteralTermination() {
+        int pos = cursor;
+        for (pos--; pos > 0; pos--) {
+            if (property[pos] == '\'' || property[pos] == '"') return pos;
+            else if (!isWhitespace(property[pos])) return pos;
+        }
+        return -1;
+    }
+
+
+    /**
+     * Handle accessing a property embedded in a collection, map, or array
+     *
+     * @param ctx  -
+     * @param prop -
+     * @return -
+     * @throws Exception -
+     */
+    private Object getCollectionProperty(Object ctx, String prop) throws Exception {
+        if (prop.length() > 0) ctx = getBeanProperty(ctx, prop);
+
+        int start = ++cursor;
+
+        whiteSpaceSkip();
+
+        if (cursor == length)
+            throw new PropertyAccessException("unterminated '['");
+
+        String item;
+
+        if (property[cursor] == '\'' || property[cursor] == '"') {
+            start++;
+
+            int end;
+
+            if (!scanTo(']'))
+                throw new PropertyAccessException("unterminated '['");
+            if ((end = containsStringLiteralTermination()) == -1)
+                throw new PropertyAccessException("unterminated string literal in collection accessor");
+
+            item = new String(property, start, end - start);
+        }
+        else {
+            if (!scanTo(']'))
+                throw new PropertyAccessException("unterminated '['");
+
+            item = new String(property, start, cursor - start);
+        }
+
+        ++cursor;
+
+        if (ctx instanceof Map) {
+            return ((Map) ctx).get(item);
+        }
+        else if (ctx instanceof List) {
+            return ((List) ctx).get(parseInt(item));
+        }
+        else if (ctx instanceof Collection) {
+            int count = parseInt(item);
+            if (count > ((Collection) ctx).size())
+                throw new PropertyAccessException("index [" + count + "] out of bounds on collection");
+
+            Iterator iter = ((Collection) ctx).iterator();
+            for (int i = 0; i < count; i++) iter.next();
+            return iter.next();
+        }
+        else if (ctx instanceof Object[]) {
+            return ((Object[]) ctx)[parseInt(item)];
+        }
+        else if (ctx instanceof CharSequence) {
+            return ((CharSequence) ctx).charAt(parseInt(item));
+        }
+        else {
+            throw new PropertyAccessException("illegal use of []: unknown type: " + (ctx == null ? null : ctx.getClass().getName()));
+        }
+    }
+
+    private static final Map<String, Serializable[]> SUBEXPRESSION_CACHE = new WeakHashMap<String, Serializable[]>();
+
+    /**
+     * Find an appropriate method, execute it, and return it's response.
+     *
+     * @param ctx  -
+     * @param name -
+     * @return -
+     * @throws Exception -
+     */
+    @SuppressWarnings({"unchecked"})
+    private Object getMethod(Object ctx, String name) throws Exception {
+        int st = cursor;
+
+        int depth = 1;
+
+        while (cursor++ < length - 1 && depth != 0) {
+            switch (property[cursor]) {
+                case'(':
+                    depth++;
+                    continue;
+                case')':
+                    depth--;
+
+            }
+        }
+        cursor--;
+
+        String tk = (cursor - st) > 1 ? new String(property, st + 1, cursor - st - 1) : "";
+
+        cursor++;
+
+        Object[] args;
+        Serializable[] es;
+
+        if (tk.length() == 0) {
+            args = new Object[0];
+            es = null;
+        }
+        else {
+            if (SUBEXPRESSION_CACHE.containsKey(tk)) {
+                es = SUBEXPRESSION_CACHE.get(tk);
+                args = new Object[es.length];
+                for (int i = 0; i < es.length; i++) {
+                    args[i] = executeExpression(es[i], ctx, resolver);
+                }
+
+            }
+            else {
+                String[] subtokens = parseParameterList(tk.toCharArray(), 0, -1);
+
+                es = new Serializable[subtokens.length];
+                args = new Object[subtokens.length];
+                for (int i = 0; i < subtokens.length; i++) {
+                    es[i] = ExpressionParser.compileExpression(subtokens[i]);
+                    args[i] = executeExpression(es[i], thisReference, resolver);
+                    ((CompiledExpression) es[i]).setKnownEgressType(args[i] != null ? args[i].getClass() : null);
+                }
+
+                SUBEXPRESSION_CACHE.put(tk, es);
+            }
+
+        }
+
+        /**
+         * If the target object is an instance of java.lang.Class itself then do not
+         * adjust the Class scope target.
+         */
+        Class cls = ctx instanceof Class ? (Class) ctx : ctx.getClass();
+
+    //    Integer signature = ;
+
+        /**
+         * Check to see if we have already cached this method;
+         */
+        Object[] cache = checkMethodCache(cls, createSignature(name, tk));
+
+        Method m;
+        Class[] parameterTypes;
+
+        if (cache != null) {
+            m = (Method) cache[0];
+            parameterTypes = (Class[]) cache[1];
+        }
+        else {
+            m = null;
+            parameterTypes = null;
+        }
+
+        /**
+         * If we have not cached the method then we need to go ahead and try to resolve it.
+         */
+        if (m == null) {
+            /**
+             * Try to find an instance method from the class target.
+             */
+
+            if ((m = getBestCanadidate(args, name, cls.getMethods())) != null) {
+                addMethodCache(cls, createSignature(name, tk), m);
+                parameterTypes = m.getParameterTypes();
+            }
+
+            if (m == null) {
+                /**
+                 * If we didn't find anything, maybe we're looking for the actual java.lang.Class methods.
+                 */
+                if ((m = getBestCanadidate(args, name, cls.getClass().getDeclaredMethods())) != null) {
+                    addMethodCache(cls, createSignature(name, tk), m);
+                    parameterTypes = m.getParameterTypes();
+                }
+            }
+        }
+
+        if (m == null) {
+            StringBuilder errorBuild = new StringBuilder();
+            for (int i = 0; i < args.length; i++) {
+                errorBuild.append(args[i] != null ? args[i].getClass().getName() : null);
+                if (i < args.length - 1) errorBuild.append(", ");
+            }
+
+            throw new PropertyAccessException("unable to resolve method: " + cls.getName() + "." + name + "(" + errorBuild.toString() + ") [arglength=" + args.length + "]");
+        }
+        else {
+            if (es != null) {
+                CompiledExpression cExpr;
+                for (int i = 0; i < es.length; i++) {
+                    cExpr = ((CompiledExpression) es[i]);
+                    if (cExpr.getKnownIngressType() == null) {
+                        cExpr.setKnownIngressType(parameterTypes[i]);
+                        cExpr.pack();
+                    }
+                    if (!cExpr.isConvertableIngressEgress()) {
+                        args[i] = convert(args[i], parameterTypes[i]);
+                    }
+                }
+            }
+            else {
+                /**
+                 * Coerce any types if required.
+                 */
+                for (int i = 0; i < args.length; i++)
+                    args[i] = convert(args[i], parameterTypes[i]);
+            }
+            
+            /**
+             * Invoke the target method and return the response.
+             */
+            return m.invoke(ctx, args);
+        }
+    }
+
+    private static int createSignature(String name, String args) {
+        return name.hashCode() + args.hashCode();
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Soundex.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Soundex.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Soundex.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,145 @@
+package org.mvel;
+
+/*
+ * Copyright (c) Ian F. Darwin, http://www.darwinsys.com/, 1996-2002.
+ * All rights reserved. Software written by Ian F. Darwin and others.
+ * $Id: Soundex.java,v 1.2 2006/12/12 20:40:53 cbrock Exp $
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Java, the Duke mascot, and all variants of Sun's Java "steaming coffee
+ * cup" logo are trademarks of Sun Microsystems. Sun's, and James Gosling's,
+ * pioneering role in inventing and promulgating (and standardizing) the Java
+ * language and environment is gratefully acknowledged.
+ *
+ * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
+ * inventing predecessor languages C and C++ is also gratefully acknowledged.
+ *
+ * ---
+ *
+ * Soundex - the Soundex Algorithm, as described by Knuth
+ * <p>
+ * This class implements the soundex algorithm as described by Donald
+ * Knuth in Volume 3 of <I>The Art of Computer Programming</I>.  The
+ * algorithm is intended to hash words (in particular surnames) into
+ * a small space using a simple model which approximates the sound of
+ * the word when spoken by an English speaker.  Each word is reduced
+ * to a four character string, the first character being an upper case
+ * letter and the remaining three being digits. Double letters are
+ * collapsed to a single digit.
+ *
+ * <h2>EXAMPLES</h2>
+ * Knuth's examples of various names and the soundex codes they map
+ * to are:
+ * <b>Euler, Ellery -> E460
+ * <b>Gauss, Ghosh -> G200
+ * <b>Hilbert, Heilbronn -> H416
+ * <b>Knuth, Kant -> K530
+ * <b>Lloyd, Ladd -> L300
+ * <b>Lukasiewicz, Lissajous -> L222
+ *
+ * <h2>LIMITATIONS</h2>
+ * As the soundex algorithm was originally used a <B>long</B> time ago
+ * in the United States of America, it uses only the English alphabet
+ * and pronunciation.
+ * <p>
+ * As it is mapping a large space (arbitrary length strings) onto a
+ * small space (single letter plus 3 digits) no inference can be made
+ * about the similarity of two strings which end up with the same
+ * soundex code.  For example, both "Hilbert" and "Heilbronn" end up
+ * with a soundex code of "H416".
+ * <p>
+ * The soundex() method is static, as it maintains no per-instance
+ * state; this means you never need to instantiate this class.
+ *
+ * @author Perl implementation by Mike Stok (<stok at cybercom.net>) from
+ * the description given by Knuth.  Ian Phillips (<ian at pipex.net>) and
+ * Rich Pinder (<rpinder at hsc.usc.edu>) supplied ideas and spotted
+ * mistakes.
+ * @author Ian Darwin, http://www.darwinsys.com/ (Java Version)
+ * @author Christopher Brock (performance and code revisions)
+ * @version $Id: Soundex.java,v 1.2 2006/12/12 20:40:53 cbrock Exp $
+ */
+public class Soundex {
+
+    /* Implements the mapping
+    * from: AEHIOUWYBFPVCGJKQSXZDTLMNR
+    * to:   00000000111122222222334556
+    */
+    public static final char[] MAP = {
+            //A  B   C   D   E   F   G   H   I   J   K   L   M
+            '0', '1', '2', '3', '0', '1', '2', '0', '0', '2', '2', '4', '5',
+            //N  O   P   W   R   S   T   U   V   W   X   Y   Z
+            '5', '0', '1', '2', '6', '2', '3', '0', '1', '0', '2', '0', '2'
+    };
+
+    /**
+     * Convert the given String to its Soundex code.
+     *
+     * @param s input string
+     * @return null If the given string can't be mapped to Soundex.
+     */
+    public static String soundex(String s) {
+        char[] ca = s.toUpperCase().toCharArray();
+
+        StringBuilder res = new StringBuilder();
+        char c, prev = '?';
+
+        // Main loop: find up to 4 chars that map.
+        for (int i = 0; i < ca.length && res.length() < 4 &&
+                (c = ca[i]) != ','; i++) {
+
+            // Check to see if the given character is alphabetic.
+            // Text is already converted to uppercase. Algorithm
+            // only handles ASCII letters, do NOT use Character.isLetter()!
+            // Also, skip double letters.
+            if (c >= 'A' && c <= 'Z' && c != prev) {
+                prev = c;
+
+                // First char is installed unchanged, for sorting.
+                if (i == 0)
+                    res.append(c);
+                else {
+                    char m = MAP[c - 'A'];
+                    if (m != '0')
+                        res.append(m);
+                }
+            }
+        }
+        if (res.length() == 0)
+            return null;
+
+        for (int i = res.length(); i < 4; i++)
+            res.append('0');
+
+        return res.toString();
+    }
+
+    /**
+     * main
+     */
+    public static void main(String[] args) {
+
+
+        System.out.println(soundex("kirwin") + "=" + soundex("kurwyn"));
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TemplateCompiler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TemplateCompiler.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TemplateCompiler.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,317 @@
+
+package org.mvel;
+
+import static org.mvel.NodeType.*;
+
+import static java.lang.Boolean.getBoolean;
+import static java.lang.Character.isWhitespace;
+import static java.lang.String.copyValueOf;
+import static java.lang.System.arraycopy;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TemplateCompiler {
+    private static final boolean DEFAULT_DEBUG = getBoolean("mvflex.expression.debug");
+
+    private char[] expressionArray;
+    private int length = 0;
+    private int cursor = 0;
+    private boolean debug = DEFAULT_DEBUG;
+    private int maxDepth = 10;
+
+    public TemplateCompiler(Interpreter interpreter) {
+        this.expressionArray = interpreter.getExpression();
+        this.length = expressionArray.length;
+    }
+
+    public Node[] compileExpression() {
+        Node[] expressions;
+        List<Node> aList = new ArrayList<Node>(10);
+
+        int depth = 0, literalRange = 0, length = expressionArray.length;
+
+        char[] exStr;
+
+        String token;
+
+        Node ex;
+        int node = 0;
+        for (; cursor < length; cursor++) {
+            if (expressionArray[cursor] == '$' || expressionArray[cursor] == '@') {
+                if (literalRange != 0) {
+                    aList.add(new Node(node++, LITERAL, cursor - literalRange, literalRange, node));
+                    literalRange = 0;
+                }
+
+                ex = new Node(cursor);
+                token = captureTo('{');
+                exStr = structuredCaptureArray(1);
+
+                if (token.length() != 0) {
+                    if ("if".equals(token)) {
+                        depth++;
+                        ex.setToken(IF);
+                    }
+                    else if ("elseif".equals(token)) {
+                        aList.add(new Node(node++, GOTO, -1));
+                        ex.setToken(ELSEIF);
+                    }
+                    else if ("else".equals(token)) {
+                        aList.add(new Node(node++, GOTO, -1));
+                        ex.setToken(ELSE);
+                    }
+                    else if ("foreach".equals(token)) {
+                        depth++;
+                        ex.setToken(FOREACH);
+                    }
+                    else if ("end".equals(token)) {
+                        depth--;
+                        if (exStr.length > 0)
+                            throw new CompileException("$end token cannot contain an expression (use $end{}) near: " + showCodeNearError());
+
+                        ex.setToken(END);
+                    }
+                    else {
+                        throw new CompileException("unknown token: " + token);
+                    }
+                }
+
+                if (ex.getNodeType() == FOREACH) {
+                    ex.setAlias("item");
+                    ex.setName(new String(exStr));
+
+                    int capture = -1;
+                    for (int i = 0; i < exStr.length; i++) {
+                        switch (exStr[i]) {
+                            case' ':
+                                if (capture == -1 && exStr[i + 1] == 'a' && exStr[i + 2] == 's'
+                                        && exStr[i + 3] == ' ') {
+
+                                    ex.setName(new String(exStr, 0, i));
+
+                                    capture = i += 4;
+
+                                    /**
+                                     * Scan to skip any excess whitespace.
+                                     */
+                                    //noinspection StatementWithEmptyBody
+                                    while (i < exStr.length && !isWhitespace(exStr[i++])) ;
+
+                                    /**
+                                     * Scan a second time to capture the token.
+                                     */
+                                    //noinspection StatementWithEmptyBody
+                                    while (i < exStr.length && !isWhitespace(exStr[i++])) ;
+
+                                    ex.setAlias(copyValueOf(exStr, capture, i - capture));
+                                }
+                                break;
+                        }
+                    }
+                }
+                else
+                    ex.setEndPos(cursor);
+
+                ex.setLength((cursor + 1) - ex.getStartPos());
+
+                if (depth > maxDepth) maxDepth = depth;
+
+                aList.add(ex.setNode(node++));
+            }
+            else {
+                literalRange++;
+            }
+        }
+        if (literalRange != 0) {
+            aList.add(new Node(node++, LITERAL, cursor - literalRange, literalRange, node));
+        }
+
+        if (depth == 1 && aList.size() == 1
+                && aList.get(0).getStartPos() == 0
+                && aList.get(0).getEndPos() == length) {
+
+        }
+        else if (depth > 0) {
+            throw new CompileException("unbalanced operators: expected $end{}");
+        }
+        else if (depth < 0) {
+            throw new CompileException("unexpected $end{} encountered");
+        }
+
+        aList.add(new Node(node, TERMINUS));
+
+        arraycopy(aList.toArray(), 0, expressions = new Node[aList.size()], 0, expressions.length);
+        ArrayList<Node> stk = new ArrayList<Node>(10);
+        
+        for (int i = 0; i < expressions.length; i++) {
+            switch (expressions[i].getToken()) {
+                case GOTO:
+                case LITERAL:
+                case PROPERTY_EX:
+                case ELSE:
+                case ELSEIF:
+                    break;
+
+                case END:
+                    Node e = stk.remove(stk.size() - 1);
+                    e.setEndNode(i);
+
+                    int last = -1;
+                    if (e.getToken() == IF) {
+                        for (int x = i; x >= e.getNode(); x--) {
+                            switch (expressions[x].getToken()) {
+                                case GOTO:
+                                    expressions[x].setEndNode(i + 1);
+                                    break;
+
+                                case IF:
+                                case ELSEIF:
+                                case ELSE:
+                                    if (last == -1) {
+                                        expressions[x].setEndNode(i);
+                                    }
+                                    else {
+                                        expressions[x].setEndNode(last);
+                                    }
+                                    last = x;
+                                    break;
+                            }
+                        }
+                    }
+
+                    break;
+                default:
+                    stk.add(expressions[i]);
+            }
+        }
+
+
+        if (debug) {
+            System.out.println("Expression:\n");
+            System.out.println(copyValueOf(expressionArray));
+            System.out.println("\n------------------------------------------");
+
+            System.out.println("Outputting Expression Tree");
+            System.out.println("--------------------------------------------");
+
+            depth = 0;
+            for (Node e : expressions) {
+                switch (e.getToken()) {
+                    case END:
+                        depth--;
+                }
+
+                System.out.println(indent(depth) + " + Node [" + e.getNode() + "] " + e.getToken()
+                        + " {" + e.getStartPos() + "," + e.getEndPos() + "} --> " + e.getEndNode());
+
+                switch (e.getToken()) {
+                    case IF:
+                    case FOREACH:
+                        depth++;
+                        break;
+                }
+
+            }
+
+            System.out.println("--------------------------------------------");
+
+        }
+
+        return expressions;
+    }
+
+    private static String indent(final int depth) {
+        final StringBuilder sb = new StringBuilder();
+        for (int i = depth; i >= 0; i--) {
+            sb.append("    ");
+        }
+        return sb.toString();
+    }
+
+    private String captureTo(char c) {
+        int start = cursor + 1;
+        if (lookahead(c)) {
+            return new String(expressionArray, start, cursor - start);
+        }
+        else
+            return null;
+
+    }
+
+    private boolean lookahead(char c) {
+        int start = cursor;
+        for (; cursor < length; cursor++) {
+            if (expressionArray[cursor] == c) {
+                return true;
+            }
+        }
+        cursor = start;
+        return false;
+    }
+
+    /**
+     * @return array
+     */
+    private char[] structuredCaptureArray(int depth) {
+        int start = cursor++ + 1;
+       // int depth = 1;
+
+      //  cursor++;
+        while (cursor < (length) && depth != 0) {
+            switch (expressionArray[cursor++]) {
+                case'@':
+                case'$':
+                    if (expressionArray[cursor] == '{') {
+                        cursor++;
+                        depth++;   
+                    }
+                    break;
+                case'}':
+                    depth--;
+                    break;
+                case'{':
+                    depth++;
+                    break;
+            }
+        }
+
+        if (depth > 0) {
+            throw new CompileException("unbalanced braces near: " + showCodeNearError() + " (" + depth + ")");
+        }
+
+        char[] array = new char[--cursor - start];
+        arraycopy(expressionArray, start, array, 0, cursor - start);
+
+        return array;
+    }
+
+    private CharSequence showCodeNearError() {
+        int start = cursor - 10;
+        int end = (cursor + 20);
+
+        if (start < 0) {
+            start = 0;
+        }
+        if (end > length) {
+            end = length - 1;
+        }
+        return "'" + copyValueOf(expressionArray, start, end - start) + "'";
+    }
+
+    public boolean isDebug() {
+        return debug;
+    }
+
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    public int getMaxDepth() {
+        return maxDepth;
+    }
+
+    public void setMaxDepth(int maxDepth) {
+        this.maxDepth = maxDepth;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TemplateParser.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TemplateParser.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TemplateParser.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,312 @@
+package org.mvel;
+
+import static org.mvel.NodeType.*;
+
+import static java.lang.Boolean.getBoolean;
+import static java.lang.Character.isWhitespace;
+import static java.lang.String.copyValueOf;
+import static java.lang.System.arraycopy;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TemplateParser {
+    private static final boolean DEFAULT_DEBUG = getBoolean("mvflex.expression.debug");
+
+    private char[] expressionArray;
+    private int length = 0;
+    private int cursor = 0;
+    private boolean debug = DEFAULT_DEBUG;
+    private int maxDepth = 10;
+
+    public TemplateParser(Interpreter interpreter) {
+        this.expressionArray = interpreter.getExpression();
+        this.length = expressionArray.length;
+    }
+
+    public Node[] compileExpression() {
+        Node[] expressions;
+        List<Node> aList = new ArrayList<Node>(10);
+
+        int length = expressionArray.length;
+        int depth = 0, literalRange = 0;
+
+        char[] exStr;
+
+        Node ex;
+        int node = 0;
+        for (; cursor < length; cursor++) {
+            if (expressionArray[cursor] == '$' || expressionArray[cursor] == '@') {
+                if (literalRange > 0) {
+                    aList.add(new Node(node++, LITERAL, cursor - literalRange, literalRange, node));
+                    literalRange = 0;
+                }
+
+                ex = new Node(cursor);
+                String token = captureTo('{');
+
+                exStr = structuredCaptureArray();
+
+                if (token.length() > 0) {
+                    if ("if".equals(token)) {
+                        depth++;
+                        ex.setToken(IF);
+                    }
+                    else if ("elseif".equals(token)) {
+                        aList.add(new Node(node++, GOTO, -1));
+                        ex.setToken(ELSEIF);
+                    }
+                    else if ("else".equals(token)) {
+                        aList.add(new Node(node++, GOTO, -1));
+                        ex.setToken(ELSE);
+                    }
+                    else if ("foreach".equals(token)) {
+                        depth++;
+                        ex.setToken(FOREACH);
+                    }
+                    else if ("end".equals(token)) {
+                        depth--;
+                        if (exStr.length > 0)
+                            throw new CompileException("$end token cannot contain an expression (use $end{}) near: " + showCodeNearError());
+
+                        ex.setToken(END);
+                    }
+                    else {
+                        throw new CompileException("unknown token: " + token);
+                    }
+                }
+
+                if (ex.getNodeType() == FOREACH) {
+                    ex.setAlias("item");
+
+                    int capture = -1;
+                    for (int i = 0; i < exStr.length; i++) {
+                        switch (exStr[i]) {
+                            case' ':
+                                if (capture == -1 && exStr[i + 1] == 'a' && exStr[i + 2] == 's'
+                                        && exStr[i + 3] == ' ') {
+
+                                    ex.setName(copyValueOf(exStr, 0, i));
+
+                                    i += 4;
+                                    capture = i;
+
+                                    /**
+                                     * Scan to skip any excess whitespace.
+                                     */
+                                    //noinspection StatementWithEmptyBody
+                                    while (i < exStr.length && !isWhitespace(exStr[i++])) ;
+
+                                    /**
+                                     * Scan a second time to capture the token.
+                                     */
+                                    //noinspection StatementWithEmptyBody
+                                    while (i < exStr.length && !isWhitespace(exStr[i++])) ;
+
+                                    ex.setAlias(copyValueOf(exStr, capture, i - capture));
+                                }
+                                break;
+                        }
+                    }
+                }
+                else
+                    ex.setEndPos(cursor);
+
+                ex.setLength((cursor + 1) - ex.getStartPos());
+
+                if (depth > maxDepth) maxDepth = depth;
+
+                aList.add(ex.setNode(node++));
+
+           //     node++;
+            }
+            else {
+                literalRange++;
+            }
+        }
+        if (literalRange > 0) {
+            aList.add(new Node(node++, LITERAL, cursor - literalRange, literalRange, node));
+        }
+
+        if (depth == 1 && aList.size() == 1
+                && aList.get(0).getStartPos() == 0
+                && aList.get(0).getEndPos() == length) {
+
+        }
+        else if (depth > 0) {
+            throw new CompileException("unbalanced operators: expected $end{}");
+        }
+        else if (depth < 0) {
+            throw new CompileException("unexpected $end{} encountered");
+        }
+
+        aList.add(new Node(node, TERMINUS));
+
+        expressions = new Node[aList.size()];
+        arraycopy(aList.toArray(), 0, expressions, 0, expressions.length);
+
+        ArrayList<Node> stk = new ArrayList<Node>(10);
+        for (int i = 0; i < expressions.length; i++) {
+            switch (expressions[i].getToken()) {
+                case GOTO:
+                case LITERAL:
+                case PROPERTY_EX:
+                case ELSE:
+                case ELSEIF:
+                    break;
+
+                case END:
+                    Node e = stk.remove(stk.size() - 1);
+                    e.setEndNode(i);
+
+                    int last = -1;
+                    if (e.getToken() == IF) {
+                        for (int x = i; x >= e.getNode(); x--) {
+                            switch (expressions[x].getToken()) {
+                                case GOTO:
+                                    expressions[x].setEndNode(i + 1);
+                                    break;
+
+                                case IF:
+                                case ELSEIF:
+                                case ELSE:
+                                    if (last == -1) {
+                                        expressions[x].setEndNode(i);
+                                    }
+                                    else {
+                                        expressions[x].setEndNode(last);
+                                    }
+                                    last = x;
+                                    break;
+                            }
+                        }
+                    }
+
+                    break;
+                default:
+                    stk.add(expressions[i]);
+            }
+        }
+
+
+        if (debug) {
+            System.out.println("Expression:\n");
+            System.out.println(copyValueOf(expressionArray));
+            System.out.println("\n------------------------------------------");
+
+            System.out.println("Outputting Expression Tree");
+            System.out.println("--------------------------------------------");
+
+            depth = 0;
+            for (Node e : expressions) {
+                switch (e.getToken()) {
+                    case END:
+                        depth--;
+                }
+
+                System.out.println(indent(depth) + " + Node [" + e.getNode() + "] " + e.getToken()
+                        + " {" + e.getStartPos() + "," + e.getEndPos() + "} --> " + e.getEndNode());
+
+                switch (e.getToken()) {
+                    case IF:
+                    case FOREACH:
+                        depth++;
+                        break;
+                }
+
+            }
+
+            System.out.println("--------------------------------------------");
+
+        }
+
+        return expressions;
+    }
+
+    private static String indent(final int depth) {
+        final StringBuilder sb = new StringBuilder();
+        for (int i = depth; i >= 0; i--) {
+            sb.append("    ");
+        }
+        return sb.toString();
+    }
+
+    private String captureTo(char c) {
+        int start = cursor + 1;
+        if (lookahead(c)) {
+            return copyValueOf(expressionArray, start, cursor - start);
+        }
+        else
+            return null;
+
+    }
+
+    private boolean lookahead(char c) {
+        int start = cursor;
+        for (; cursor < length; cursor++) {
+            if (expressionArray[cursor] == c) {
+                return true;
+            }
+        }
+        cursor = start;
+        return false;
+    }
+
+    /**
+     * @return array
+     */
+    private char[] structuredCaptureArray() {
+        int start = cursor + 1;
+        int depth = 1;
+
+        while (cursor < (length) && depth > 0) {
+            switch (expressionArray[cursor++]) {
+                case'@':
+                case'$':
+                    if (expressionArray[cursor] == '{') depth++;
+                    break;
+                case'}':
+                    depth--;
+                    break;
+            }
+        }
+
+
+        if (depth > 0) {
+            throw new CompileException("unbalanced braces near: " + showCodeNearError());
+        }
+
+        char[] array = new char[--cursor - start];
+        arraycopy(expressionArray, start, array, 0, cursor - start);
+        return array;
+    }
+
+    private CharSequence showCodeNearError() {
+        int start = cursor - 10;
+        int end = (cursor + 20);
+
+        if (start < 0) {
+            start = 0;
+        }
+        if (end > length) {
+            end = length - 1;
+        }
+        return "'" + copyValueOf(expressionArray, start, end - start) + "'";
+    }
+
+    public boolean isDebug() {
+        return debug;
+    }
+
+    public void setDebug(boolean debug) {
+        this.debug = debug;
+    }
+
+    public int getMaxDepth() {
+        return maxDepth;
+    }
+
+    public void setMaxDepth(int maxDepth) {
+        this.maxDepth = maxDepth;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Tester.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Tester.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Tester.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,20 @@
+package org.mvel;
+
+import org.mvel.util.ParseTools;
+
+import java.util.Map;
+import java.util.HashMap;
+
+public class Tester {
+    public static void main(String[] args) {
+        Map<Integer, String> b = new HashMap<Integer, String>();
+
+        Class[] test = new Class[] { String.class, int.class };
+        b.put(ParseTools.createClassSignatureHash(test), "Hello");
+
+        System.out.println(ParseTools.createClassSignatureHash(test));
+
+        System.out.println(b.containsKey(ParseTools.createClassSignatureHash(new Class[] { String.class, int.class })));
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ThisLiteral.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ThisLiteral.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/ThisLiteral.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,4 @@
+package org.mvel;
+
+public class ThisLiteral {
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Token.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Token.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/Token.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,603 @@
+package org.mvel;
+
+import static org.mvel.DataConversion.convert;
+import static org.mvel.Operator.*;
+import org.mvel.compiled.CompiledAccessor;
+import org.mvel.compiled.Deferral;
+import org.mvel.integration.VariableResolverFactory;
+import static org.mvel.util.ArrayTools.findFirst;
+import static org.mvel.util.ParseTools.handleEscapeSequence;
+import static org.mvel.util.PropertyTools.isNumber;
+
+import java.io.Serializable;
+import static java.lang.Boolean.FALSE;
+import static java.lang.Boolean.TRUE;
+import static java.lang.Integer.parseInt;
+import static java.lang.String.valueOf;
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Token implements Cloneable, Serializable {
+    public static final int LITERAL = 1;
+    public static final int DEEP_PROPERTY = 1 << 1;
+    public static final int OPERATOR = 1 << 2;
+    public static final int IDENTIFIER = 1 << 3;
+    public static final int SUBEVAL = 1 << 4;
+    public static final int NUMERIC = 1 << 5;
+    public static final int NEGATION = 1 << 6;
+    public static final int EVAL_RIGHT = 1 << 7;
+    public static final int INVERT = 1 << 8;
+    public static final int REQUIRE_REDUCTION = 1 << 9;
+    public static final int BOOLEAN_MODE = 1 << 10;
+    public static final int TERNARY = 1 << 11;
+    public static final int ASSIGN = 1 << 12;
+    public static final int LOOKAHEAD = 1 << 13;
+    public static final int COLLECTION = 1 << 14;
+    public static final int LISTCREATE = 1 << 15;
+    public static final int DO_NOT_REDUCE = 1 << 16;
+    public static final int CAPTURE_ONLY = 1 << 17;
+    public static final int MAPCREATE = 1 << 18;
+    public static final int THISREF = 1 << 19;
+    public static final int ARRAYCREATE = 1 << 20;
+    public static final int NOCOMPILE = 1 << 21;
+    public static final int STR_LITERAL = 1 << 25;
+
+    public static final int PUSH = 1 << 22;
+
+    public static final int NEST = 1 << 23;   // token begins a nesting area
+    public static final int ENDNEST = 1 << 24; // token ends a nesting area
+
+    public static final int OPTIMIZED_REF = 1 << 31; // future use
+
+    private int start;
+    private int end;
+    private int firstUnion;
+    private int endOfName;
+
+    private char[] name;
+    private String nameCache;
+
+    private transient Object value;
+    private transient Object resetValue;
+
+    private BigDecimal numericValue;
+
+    private int fields = 0;
+
+    private CompiledExpression compiledExpression;
+    private CompiledAccessor compiledAccessor;
+//    private Class knownType;
+
+    public static final Map<String, Object> LITERALS =
+            new HashMap<String, Object>(35, 0.6f);
+
+    static {
+
+        /**
+         * Setup the basic literals
+         */
+        LITERALS.put("true", TRUE);
+        LITERALS.put("false", FALSE);
+
+        LITERALS.put("null", null);
+        LITERALS.put("nil", null);
+
+        LITERALS.put("empty", BlankLiteral.INSTANCE);
+
+        LITERALS.put("this", ThisLiteral.class);
+
+        /**
+         * Add System and all the class wrappers from the JCL.
+         */
+        LITERALS.put("System", System.class);
+
+        LITERALS.put("String", String.class);
+        LITERALS.put("Integer", Integer.class);
+        LITERALS.put("Long", Long.class);
+        LITERALS.put("Boolean", Boolean.class);
+        LITERALS.put("Short", Short.class);
+        LITERALS.put("Character", Character.class);
+        LITERALS.put("Double", Double.class);
+        LITERALS.put("Float", Float.class);
+        LITERALS.put("Math", Math.class);
+        LITERALS.put("Void", Void.class);
+        LITERALS.put("Object", Object.class);
+
+        LITERALS.put("Class", Class.class);
+        LITERALS.put("ClassLoader", ClassLoader.class);
+        LITERALS.put("Runtime", Runtime.class);
+        LITERALS.put("Thread", Thread.class);
+        LITERALS.put("Compiler", Compiler.class);
+        LITERALS.put("StringBuffer", StringBuffer.class);
+        LITERALS.put("StringBuilder", StringBuilder.class);
+        LITERALS.put("ThreadLocal", ThreadLocal.class);
+        LITERALS.put("SecurityManager", SecurityManager.class);
+        LITERALS.put("StrictMath", StrictMath.class);
+
+        LITERALS.put("Array", java.lang.reflect.Array.class);
+    }
+
+    private static final Map<String, Operator> OPERATORS =
+            new HashMap<String, Operator>(25 * 2, 0.6f);
+
+    static {
+        OPERATORS.put("+", ADD);
+        OPERATORS.put("-", SUB);
+        OPERATORS.put("*", MULT);
+        OPERATORS.put("/", DIV);
+        OPERATORS.put("%", MOD);
+        OPERATORS.put("==", EQUAL);
+        OPERATORS.put("!=", NEQUAL);
+        OPERATORS.put(">", GTHAN);
+        OPERATORS.put(">=", GETHAN);
+        OPERATORS.put("<", LTHAN);
+        OPERATORS.put("<=", LETHAN);
+        OPERATORS.put("&&", AND);
+        OPERATORS.put("and", AND);
+        OPERATORS.put("||", OR);
+        OPERATORS.put("or", CHOR);
+        OPERATORS.put("~=", REGEX);
+        OPERATORS.put("instanceof", INSTANCEOF);
+        OPERATORS.put("is", INSTANCEOF);
+        OPERATORS.put("contains", CONTAINS);
+        OPERATORS.put("soundslike", SOUNDEX);
+        OPERATORS.put("strsim", SIMILARITY);
+        OPERATORS.put("convertable_to", CONVERTABLE_TO);
+
+        OPERATORS.put("#", STR_APPEND);
+
+        OPERATORS.put("&", BW_AND);
+        OPERATORS.put("|", BW_OR);
+        OPERATORS.put("^", BW_XOR);
+        OPERATORS.put("<<", BW_SHIFT_LEFT);
+        OPERATORS.put("<<<", BW_USHIFT_LEFT);
+        OPERATORS.put(">>", BW_SHIFT_RIGHT);
+        OPERATORS.put(">>>", BW_USHIFT_RIGHT);
+
+        OPERATORS.put("?", Operator.TERNARY);
+        OPERATORS.put(":", TERNARY_ELSE);
+
+        OPERATORS.put("=", Operator.ASSIGN);
+
+        OPERATORS.put(";", END_OF_STMT);
+
+        OPERATORS.put("new", NEW);
+
+        OPERATORS.put("in", PROJECTION);
+    }
+
+
+    public Token(char[] expr, int start, int end, int fields) {
+        this.fields = fields;
+
+        char[] name = new char[end - start];
+        System.arraycopy(expr, this.start = start, name, 0, (this.end = end) - start);
+        setName(name);
+    }
+
+    public Token(char expr, int fields) {
+        this.fields = fields;
+        setName(new char[]{expr});
+    }
+
+    public Token(char[] expr, int fields) {
+        this.fields = fields;
+        setName(expr);
+    }
+
+    public int getStart() {
+        return start;
+    }
+
+    public void setStart(int start) {
+        this.start = start;
+    }
+
+    public int getEnd() {
+        return end;
+    }
+
+    public void setEnd(int end) {
+        this.end = end;
+    }
+
+    public boolean emptyRange() {
+        return this.start == this.end;
+    }
+
+    public boolean isLiteral() {
+        return (fields & LITERAL) != 0;
+    }
+
+    public void setLiteral(boolean literal) {
+        setFlag(literal, LITERAL);
+    }
+
+    public boolean isDeepProperty() {
+        return (fields & DEEP_PROPERTY) != 0;
+    }
+
+    public void setDeepProperty(boolean deepProperty) {
+        setFlag(deepProperty, DEEP_PROPERTY);
+    }
+
+    public boolean isOperator() {
+        return (fields & OPERATOR) != 0;
+    }
+
+    public Operator getOperator() {
+        return (Operator) value;
+    }
+
+    public void setOperator(boolean operator) {
+        setFlag(operator, OPERATOR);
+    }
+
+    public boolean isNegation() {
+        return getFlag(NEGATION);
+    }
+
+    public void setNegation(boolean negation) {
+        setFlag(negation, NEGATION);
+    }
+
+    public char[] createRootElementArray() {
+        if ((fields & DEEP_PROPERTY) != 0) {
+            char[] root = new char[(firstUnion)];
+            System.arraycopy(name, 0, root, 0, root.length);
+            return root;
+        }
+        return null;
+    }
+
+    public String getAbsoluteRootElement() {
+        if ((fields & DEEP_PROPERTY) != 0 || (fields & COLLECTION) != 0) {
+            return new String(name, 0, getAbsoluteFirstPart());
+        }
+        return null;
+    }
+
+    public String getRootElement() {
+        return (fields & DEEP_PROPERTY) != 0 ? new String(name, 0, firstUnion) : getName();
+        //   return new String(root);
+    }
+
+    public char[] createRemainderArray() {
+        if ((fields & DEEP_PROPERTY) != 0) {
+            char[] remainder = new char[(name.length - firstUnion - 1)];
+            System.arraycopy(name, firstUnion + 1, remainder, 0, remainder.length);
+            return remainder;
+        }
+        return null;
+    }
+
+
+    public String getRemainder() {
+        //   return new String(remainder);
+        return (fields & DEEP_PROPERTY) != 0 ? new String(name, firstUnion + 1, name.length - firstUnion - 1) : null;
+    }
+
+    public char[] getNameAsArray() {
+        return name;
+    }
+
+
+    public int getEndOfName() {
+        return endOfName;
+    }
+
+    public int getAbsoluteFirstPart() {
+        if ((fields & Token.COLLECTION) != 0) {
+            if (firstUnion < 0 || endOfName < firstUnion) return endOfName;
+            else return firstUnion;
+        }
+        else if ((fields & Token.DEEP_PROPERTY) != 0) {
+            return firstUnion;
+        }
+        else {
+            return -1;
+        }
+
+    }
+
+    public String getAbsoluteName() {
+        if ((fields & COLLECTION) != 0) {
+            return new String(name, 0, getAbsoluteFirstPart());
+        }
+        else {
+            return getName();
+
+        }
+    }
+
+    public String getName() {
+        if (nameCache != null) return nameCache;
+        else if (name != null) return nameCache = new String(name);
+        return "";
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public Token getOptimizedValue(Object ctx, Object elCtx, VariableResolverFactory variableFactory) throws Exception {
+        if ((fields & NUMERIC) != 0) {
+            value = numericValue = convert(compiledAccessor.getValue(ctx, elCtx, variableFactory), BigDecimal.class);
+        }
+        else
+            value = compiledAccessor.getValue(ctx, elCtx, variableFactory);
+
+        if ((fields & NEGATION) != 0) value = !((Boolean)value);
+
+        return this;
+    }
+
+
+    public void createDeferralOptimization() {
+        compiledAccessor = new CompiledAccessor(null, null, null);
+        compiledAccessor.addAccessorNode(new Deferral());
+    }
+
+
+    public void optimizeAccessor(Object ctx, VariableResolverFactory variableFactory) {
+        compiledAccessor = new CompiledAccessor(name, ctx, variableFactory);
+        setNumeric(false);
+
+        Object test = compiledAccessor.compileGetChain();
+
+      //  if (test != null) knownType = test.getClass();
+
+        setNumeric(isNumber(test));
+        setFlag(true, Token.OPTIMIZED_REF);
+    }
+
+    public void deOptimize()  {
+        compiledAccessor = null;
+    }
+
+    public boolean isOptimized() {
+        return compiledAccessor != null;
+    }
+
+    public BigDecimal getNumericValue() {
+        return numericValue;
+    }
+
+    public String getValueAsString() {
+        if (value instanceof String) return (String) value;
+        else if (value instanceof char[]) return new String((char[]) value);
+        else return valueOf(value);
+    }
+
+    public char[] getValueAsCharArray() {
+        if (value instanceof char[]) return ((char[]) value);
+        else if (value instanceof String) return ((String) value).toCharArray();
+        else return valueOf(value).toCharArray();
+    }
+
+    public Token setValue(Object value) {
+        String s;
+        try {
+            if ((fields & NEGATION) != 0 && (fields & BOOLEAN_MODE) != 0) {
+                this.value = BlankLiteral.INSTANCE.equals(value);
+            }
+            else if ((fields & NEGATION) != 0) {
+                if (value instanceof Boolean) {
+                    this.value = !((Boolean) value);
+                }
+                else {
+                    throw new CompileException("illegal negation - not a boolean expression");
+                }
+            }
+            else {
+                if (value instanceof BigDecimal) {
+                    fields |= NUMERIC;
+                    this.numericValue = (BigDecimal) value;
+                }
+                else if (isNumber(value)) {
+                    fields |= NUMERIC;
+                    // this.numericValue = new BigDecimal(valueOf(value));
+                    this.numericValue = convert(value, BigDecimal.class);
+                }
+                this.value = value;
+            }
+        }
+        catch (NumberFormatException e) {
+            throw new CompileException("unable to create numeric value from: '" + value + "'");
+        }
+
+        return this;
+    }
+
+    public Token setFinalValue(Object value) {
+        this.value = value;
+        return this;
+    }
+
+    public boolean isIdentifier() {
+        return (fields & IDENTIFIER) != 0;
+    }
+
+    public void setIdentifier(boolean identifier) {
+        setFlag(identifier, IDENTIFIER);
+    }
+
+    public boolean isExpand() {
+        return (fields & SUBEVAL) != 0;
+    }
+
+    public void setExpand(boolean unreduced) {
+        setFlag(unreduced, SUBEVAL);
+    }
+
+    public boolean isNumeric() {
+        return (fields & NUMERIC) != 0;
+    }
+
+    public void setNumeric(boolean numeric) {
+        setFlag(numeric, NUMERIC);
+    }
+
+    public boolean isEvalRight() {
+        return (fields & EVAL_RIGHT) != 0;
+    }
+
+    public void setEvalRight(boolean evalRight) {
+        setFlag(evalRight, EVAL_RIGHT);
+    }
+
+    public boolean isInvert() {
+        return (fields & INVERT) != 0;
+    }
+
+    public void setInvert(boolean invert) {
+        setFlag(invert, INVERT);
+    }
+
+
+    @SuppressWarnings({"SuspiciousMethodCalls"})
+    public void setName(char[] name) {
+
+        if ((fields & STR_LITERAL) != 0) {
+            fields |= LITERAL;
+            int escapes = 0;
+            for (int i = 0; i < name.length; i++) {
+                if (name[i] == '\\') {
+                    name[i++] = 0;
+                    name[i] = handleEscapeSequence(name[i]);
+                    escapes++;
+                }
+            }
+
+            char[] processedEscapeString = new char[name.length - escapes];
+            int cursor = 0;
+            for (char aName : name) {
+                if (aName == 0) {
+                    continue;
+                }
+                processedEscapeString[cursor++] = aName;
+            }
+
+            this.value = new String(this.name = processedEscapeString);
+
+        }
+        else {
+            this.value = new String(this.name = name);
+        }
+
+        if ((fields & (SUBEVAL | LITERAL)) != 0) {
+            //    return;
+        }
+        else if (LITERALS.containsKey(value)) {
+            fields |= EVAL_RIGHT | LITERAL;
+            if ((value = LITERALS.get(value)) == ThisLiteral.class) fields |= THISREF;
+        }
+        else if (OPERATORS.containsKey(value)) {
+            fields |= OPERATOR;
+            resetValue = value = OPERATORS.get(value);
+            return;
+        }
+        else if (((fields & NUMERIC) != 0) || isNumber(name)) {
+            if (((fields |= LITERAL | NUMERIC) & INVERT) != 0) {
+                value = this.numericValue = new BigDecimal(~parseInt((String) value));
+            }
+            else {
+                value = this.numericValue = new BigDecimal(valueOf(name));
+            }
+        }
+        else if ((firstUnion = findFirst('.', name)) > 0) {
+            fields |= DEEP_PROPERTY | IDENTIFIER;
+        }
+        else {
+            fields |= IDENTIFIER;
+        }
+
+        if ((endOfName = findFirst('[', name)) > 0) fields |= COLLECTION;
+
+        resetValue = value;
+    }
+
+    public int getFlags() {
+        return fields;
+    }
+
+    private boolean getFlag(int field) {
+        return (fields & field) != 0;
+    }
+
+    public void setFlag(boolean setting, int flag) {
+        if (getFlag(flag) ^ setting) {
+            fields = fields ^ flag;
+        }
+        else if (setting) {
+            fields = fields | flag;
+        }
+    }
+
+
+    public String toString() {
+        return valueOf(value);
+    }
+
+    public boolean equals(Object obj) {
+        if (obj instanceof Token)
+            return value == null ? ((Token) obj).value == null : value.equals(((Token) obj).value);
+        else
+            return value == null ? obj == value : value.equals(obj);
+    }
+
+    public int hashCode() {
+        return value == null ? super.hashCode() : value.hashCode();
+    }
+
+    public boolean isValidNameIdentifier() {
+        return !Character.isDigit(name[0]);
+    }
+
+
+    public int getFirstUnion() {
+        return firstUnion;
+    }
+
+    public CompiledExpression getCompiledExpression() {
+        return compiledExpression;
+    }
+
+    public void setCompiledExpression(CompiledExpression compiledExpression) {
+        this.compiledExpression = compiledExpression;
+    }
+
+    public boolean isCollectionCreation() {
+        return ((fields & MAPCREATE) | (fields & ARRAYCREATE) | (fields & LISTCREATE)) != 0;
+    }
+
+    public int getCollectionCreationType() {
+        return ((fields & MAPCREATE) | (fields & ARRAYCREATE) | (fields & LISTCREATE));
+    }
+
+    public boolean isNestBegin() {
+        return (fields & Token.NEST) != 0;
+    }
+
+
+    public Token clone() throws CloneNotSupportedException {
+        try {
+            return (Token) super.clone();
+        }
+        catch (CloneNotSupportedException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    public void reset() {
+        if (resetValue == null) {
+            setLiteral(false);
+            setName(name);
+        }
+        else {
+            value = resetValue;
+        }
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenIterator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenIterator.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenIterator.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,14 @@
+package org.mvel;
+
+public interface TokenIterator extends Cloneable {
+    public void reset();
+    public Token nextToken();
+    public Token peekToken();
+    public Token peekLast();
+    public void back();
+    public Token tokensBack(int offset);
+    public boolean hasMoreTokens();
+    public String showTokenChain();
+    @SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException"})
+    public TokenIterator clone();
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenMap.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenMap.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenMap.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,70 @@
+package org.mvel;
+
+public class TokenMap implements TokenIterator {
+    private TokenNode firstToken;
+    private TokenNode current;
+
+    public TokenMap(TokenNode firstToken) {
+        this.current = this.firstToken = firstToken;
+    }
+
+    public void addTokenNode(Token token) {
+        if (this.current == null) {
+            this.firstToken = this.current = new TokenNode(token);
+        }
+        else {
+           this.current = this.current.next = new TokenNode(token);
+        }
+    }
+
+    public void reset() {
+        this.current = firstToken;
+    }
+
+    public boolean hasMoreTokens() {
+        return this.current != null;
+    }
+
+    public Token nextToken() {
+        if (current == null) return null;
+
+        Token tk = current.token;
+        current = current.next;
+        return tk;
+    }
+
+
+    public Token peekToken() {
+        if (current == null) return null;
+        return current.token;
+    }
+
+    public void removeToken() {
+        if (current != null) {
+            current = current.next;
+        }
+    }
+
+    public Token peekLast() {
+        throw new RuntimeException("unimplemented");
+    }
+
+    public Token tokensBack(int offset) {
+        throw new RuntimeException("unimplemented");
+    }
+
+
+    public void back() {
+        throw new RuntimeException("unimplemented");
+    }
+
+    public String showTokenChain() {
+        throw new RuntimeException("unimplemented");        
+    }
+
+
+    @SuppressWarnings({"CloneDoesntDeclareCloneNotSupportedException"})
+    public TokenIterator clone() {
+        return null;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenNode.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/TokenNode.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,15 @@
+package org.mvel;
+
+public class TokenNode implements Cloneable {
+    public TokenNode(Token token) {
+        try {
+            this.token = token.clone();
+        }
+        catch (CloneNotSupportedException e) {
+            throw new RuntimeException("unable to clone node", e);
+        }
+    }
+
+    public Token token;
+    public TokenNode next;
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ArrayAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ArrayAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ArrayAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,43 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.util.Map;
+
+public class ArrayAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    private int index;
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vars) throws Exception {
+        if (nextNode != null) {
+            return nextNode.getValue(((Object[])ctx)[index], elCtx, vars);
+        }
+        else {
+            return ((Object[])ctx)[index];
+        }
+    }
+
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+
+
+    public String toString() {
+        return "Array Accessor -> [" + index + "]";
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/CompiledAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/CompiledAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/CompiledAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,512 @@
+package org.mvel.compiled;
+
+import org.mvel.*;
+import static org.mvel.ExpressionParser.compileExpression;
+import static org.mvel.ExpressionParser.executeExpression;
+import org.mvel.integration.VariableResolverFactory;
+import org.mvel.util.ParseTools;
+import static org.mvel.util.ParseTools.parseParameterList;
+import org.mvel.util.PropertyTools;
+
+import java.io.Serializable;
+import static java.lang.Class.forName;
+import static java.lang.Integer.parseInt;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.*;
+
+public class CompiledAccessor {
+    private int start = 0;
+    private int cursor = 0;
+
+    private char[] property;
+    private int length;
+
+    private AccessorNode rootNode;
+    private AccessorNode currNode;
+
+    private Object ctx;
+
+    private VariableResolverFactory variableFactory;
+
+    private static final int DONE = -1;
+    private static final int BEAN = 0;
+    private static final int METH = 1;
+    private static final int COL = 2;
+
+    private static final Object[] EMPTYARG = new Object[0];
+
+    public CompiledAccessor(char[] property, Object ctx) {
+        this.property = property;
+        this.length = property.length;
+        this.ctx = ctx;
+    }
+
+    public CompiledAccessor(char[] property, Object ctx, VariableResolverFactory variableFactory) {
+        this.property = property;
+        this.length = property != null ? property.length : 0;
+        this.ctx = ctx;
+        this.variableFactory = variableFactory;
+    }
+
+
+
+    public CompiledAccessor(String property, Object ctx) {
+        this.length = (this.property = property.toCharArray()).length;
+        this.ctx = ctx;
+    }
+
+
+    public Object compileGetChain() {
+        Object curr = ctx;
+
+        try {
+            while (cursor < length) {
+                switch (nextToken()) {
+                    case BEAN:
+                        curr = getBeanProperty(curr, capture());
+                        break;
+                    case METH:
+                        curr = getMethod(curr, capture());
+                        break;
+                    case COL:
+                        curr = getCollectionProperty(curr, capture());
+                        break;
+                    case DONE:
+                        break;
+                }
+            }
+
+            return curr;
+        }
+        catch (InvocationTargetException e) {
+            throw new PropertyAccessException("could not access property", e);
+        }
+        catch (IllegalAccessException e) {
+            throw new PropertyAccessException("could not access property", e);
+        }
+        catch (IndexOutOfBoundsException e) {
+            throw new PropertyAccessException("array or collection index out of bounds (property: " + new String(property) + ")", e);
+        }
+        catch (PropertyAccessException e) {
+            throw new PropertyAccessException("failed to access property: <<" + new String(property) + ">> in: " + (ctx != null ? ctx.getClass() : null), e);
+        }
+        catch (CompileException e) {
+            throw e;
+        }
+        catch (NullPointerException e) {
+            throw new PropertyAccessException("null pointer exception in property: " + new String(property), e);
+        }
+        catch (Exception e) {
+            throw new PropertyAccessException("unknown exception in expression: " + new String(property), e);
+        }
+    }
+
+
+    private int nextToken() {
+        switch (property[start = cursor]) {
+            case'[':
+                return COL;
+            case'.':
+                cursor = ++start;
+        }
+
+        //noinspection StatementWithEmptyBody
+        while (++cursor < length && Character.isJavaIdentifierPart(property[cursor])) ;
+
+
+        if (cursor < length) {
+            switch (property[cursor]) {
+                case'[':
+                    return COL;
+                case'(':
+                    return METH;
+                default:
+                    return 0;
+            }
+        }
+        return 0;
+    }
+
+    private String capture() {
+        return new String(property, start, cursor - start);
+    }
+
+    public void addAccessorNode(AccessorNode an) {
+        if (currNode == null)
+            rootNode = currNode = an;
+        else {
+            currNode = currNode.setNextNode(an);
+        }
+    }
+
+
+    private Object getBeanProperty(Object ctx, String property)
+            throws IllegalAccessException, InvocationTargetException {
+
+        Class cls = (ctx instanceof Class ? ((Class) ctx) : ctx != null ? ctx.getClass() : null);
+        Member member = cls != null ? PropertyTools.getFieldOrAccessor(cls, property) : null;
+
+        if (member instanceof Field) {
+            FieldAccessor accessor = new FieldAccessor();
+            accessor.setField((Field) member);
+
+            addAccessorNode(accessor);
+
+            return ((Field) member).get(ctx);
+        }
+        else if (member != null) {
+            GetterAccessor accessor = new GetterAccessor((Method) member);
+            addAccessorNode(accessor);
+
+            return ((Method) member).invoke(ctx, EMPTYARG);
+        }
+        else if (ctx instanceof Map && ((Map) ctx).containsKey(property)) {
+            MapAccessor accessor = new MapAccessor();
+            accessor.setProperty(property);
+
+            addAccessorNode(accessor);
+
+            return ((Map) ctx).get(property);
+        }
+        else if ("this".equals(property)) {
+            ThisValueAccessor accessor = new ThisValueAccessor();
+
+            addAccessorNode(accessor);
+
+            return this.ctx;
+        }
+        else if (variableFactory != null && variableFactory.isResolveable(property)) {
+            VariableAccessor accessor = new VariableAccessor(property, variableFactory);
+
+            addAccessorNode(accessor);
+
+            return variableFactory.getVariableResolver(property).getValue();
+        }
+        else if (Token.LITERALS.containsKey(property)) {
+            StaticReferenceAccessor accessor = new StaticReferenceAccessor();
+            accessor.setLiteral(Token.LITERALS.get(property));
+
+            addAccessorNode(accessor);
+
+            return accessor.getLiteral();
+        }
+        else {
+            Class tryStaticMethodRef = tryStaticAccess();
+
+            if (tryStaticMethodRef != null) {
+                StaticReferenceAccessor accessor = new StaticReferenceAccessor();
+                accessor.setLiteral(tryStaticMethodRef);
+
+                addAccessorNode(accessor);
+
+                return tryStaticMethodRef;
+            }
+            else
+                throw new PropertyAccessException("could not access property (" + property + ")");
+        }
+    }
+
+    private void whiteSpaceSkip() {
+        if (cursor < length)
+            //noinspection StatementWithEmptyBody
+            while (Character.isWhitespace(property[cursor]) && ++cursor < length) ;
+    }
+
+    private boolean scanTo(char c) {
+        for (; cursor < length; cursor++) {
+            if (property[cursor] == c) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private int containsStringLiteralTermination() {
+        int pos = cursor;
+        for (pos--; pos > 0; pos--) {
+            if (property[pos] == '\'' || property[pos] == '"') return pos;
+            else if (!Character.isWhitespace(property[pos])) return pos;
+        }
+        return -1;
+    }
+
+
+    /**
+     * Handle accessing a property embedded in a collection, map, or array
+     *
+     * @param ctx  -
+     * @param prop -
+     * @return -
+     * @throws Exception -
+     */
+    private Object getCollectionProperty(Object ctx, String prop) throws Exception {
+        if (prop.length() > 0) ctx = getBeanProperty(ctx, prop);
+
+        int start = ++cursor;
+
+        whiteSpaceSkip();
+
+        if (cursor == length)
+            throw new PropertyAccessException("unterminated '['");
+
+        String item;
+
+        if (property[cursor] == '\'' || property[cursor] == '"') {
+            start++;
+
+            int end;
+
+            if (!scanTo(']'))
+                throw new PropertyAccessException("unterminated '['");
+            if ((end = containsStringLiteralTermination()) == -1)
+                throw new PropertyAccessException("unterminated string literal in collection accessor");
+
+            item = new String(property, start, end - start);
+        }
+        else {
+            if (!scanTo(']'))
+                throw new PropertyAccessException("unterminated '['");
+
+            item = new String(property, start, cursor - start);
+        }
+
+        ++cursor;
+
+        if (ctx instanceof Map) {
+            MapAccessor accessor = new MapAccessor();
+            accessor.setProperty(item);
+
+            addAccessorNode(accessor);
+
+            return ((Map) ctx).get(item);
+        }
+        else if (ctx instanceof List) {
+            ListAccessor accessor = new ListAccessor();
+            accessor.setIndex(parseInt(item));
+
+            addAccessorNode(accessor);
+
+            return ((List) ctx).get(accessor.getIndex());
+        }
+        else if (ctx instanceof Collection) {
+            int count = parseInt(item);
+            if (count > ((Collection) ctx).size())
+                throw new PropertyAccessException("index [" + count + "] out of bounds on collection");
+
+            Iterator iter = ((Collection) ctx).iterator();
+            for (int i = 0; i < count; i++) iter.next();
+            return iter.next();
+        }
+        else if (ctx instanceof Object[]) {
+            ArrayAccessor accessor = new ArrayAccessor();
+            accessor.setIndex(parseInt(item));
+
+            addAccessorNode(accessor);
+
+            return ((Object[]) ctx)[accessor.getIndex()];
+        }
+        else if (ctx instanceof CharSequence) {
+            IndexedCharSeqAccessor accessor = new IndexedCharSeqAccessor();
+            accessor.setIndex(parseInt(item));
+
+            addAccessorNode(accessor);
+
+            return ((CharSequence) ctx).charAt(accessor.getIndex());
+        }
+        else {
+            throw new PropertyAccessException("illegal use of []: unknown type: " + (ctx == null ? null : ctx.getClass().getName()));
+        }
+    }
+
+    private static final Map<String, Serializable[]> SUBEXPRESSION_CACHE = new WeakHashMap<String, Serializable[]>();
+
+    /**
+     * Find an appropriate method, execute it, and return it's response.
+     *
+     * @param ctx  -
+     * @param name -
+     * @return -
+     * @throws Exception -
+     */
+    @SuppressWarnings({"unchecked"})
+    private Object getMethod(Object ctx, String name) throws Exception {
+        int st = cursor;
+
+        int depth = 1;
+
+        while (cursor++ < length - 1 && depth != 0) {
+            switch (property[cursor]) {
+                case'(':
+                    depth++;
+                    continue;
+                case')':
+                    depth--;
+
+            }
+        }
+        cursor--;
+
+        String tk = (cursor - st) > 1 ? new String(property, st + 1, cursor - st - 1) : "";
+
+        cursor++;
+
+        Object[] args;
+        Serializable[] es;
+
+        if (tk.length() == 0) {
+            args = new Object[0];
+            es = null;
+        }
+        else {
+            if (SUBEXPRESSION_CACHE.containsKey(tk)) {
+                es = SUBEXPRESSION_CACHE.get(tk);
+                args = new Object[es.length];
+                for (int i = 0; i < es.length; i++) {
+                    args[i] = executeExpression(es[i], ctx, variableFactory);
+                }
+
+            }
+            else {
+                String[] subtokens = parseParameterList(tk.toCharArray(), 0, -1);
+
+                es = new Serializable[subtokens.length];
+                args = new Object[subtokens.length];
+                for (int i = 0; i < subtokens.length; i++) {
+                    es[i] = compileExpression(subtokens[i]);
+                    args[i] = executeExpression(es[i], this.ctx, variableFactory);
+                    ((CompiledExpression) es[i]).setKnownEgressType(args[i] != null ? args[i].getClass() : null);
+                }
+
+                SUBEXPRESSION_CACHE.put(tk, es);
+            }
+
+        }
+
+        /**
+         * If the target object is an instance of java.lang.Class itself then do not
+         * adjust the Class scope target.
+         */
+        Class cls = ctx instanceof Class ? (Class) ctx : ctx.getClass();
+
+        //    Integer signature = ;
+
+        Method m;
+        Class[] parameterTypes = null;
+
+        /**
+         * If we have not cached the method then we need to go ahead and try to resolve it.
+         */
+        /**
+         * Try to find an instance method from the class target.
+         */
+
+        if ((m = ParseTools.getBestCanadidate(args, name, cls.getMethods())) != null) {
+            parameterTypes = m.getParameterTypes();
+        }
+
+        if (m == null) {
+            /**
+             * If we didn't find anything, maybe we're looking for the actual java.lang.Class methods.
+             */
+            if ((m = ParseTools.getBestCanadidate(args, name, cls.getClass().getDeclaredMethods())) != null) {
+                parameterTypes = m.getParameterTypes();
+            }
+        }
+
+
+        if (m == null) {
+            StringBuilder errorBuild = new StringBuilder();
+            for (int i = 0; i < args.length; i++) {
+                errorBuild.append(args[i] != null ? args[i].getClass().getName() : null);
+                if (i < args.length - 1) errorBuild.append(", ");
+            }
+
+            throw new PropertyAccessException("unable to resolve method: " + cls.getName() + "." + name + "(" + errorBuild.toString() + ") [arglength=" + args.length + "]");
+        }
+        else {
+            if (es != null) {
+                CompiledExpression cExpr;
+                for (int i = 0; i < es.length; i++) {
+                    cExpr = ((CompiledExpression) es[i]);
+                    if (cExpr.getKnownIngressType() == null) {
+                        cExpr.setKnownIngressType(parameterTypes[i]);
+                        cExpr.pack();
+                    }
+                    if (!cExpr.isConvertableIngressEgress()) {
+                        args[i] = DataConversion.convert(args[i], parameterTypes[i]);
+                    }
+                }
+            }
+            else {
+                /**
+                 * Coerce any types if required.
+                 */
+                for (int i = 0; i < args.length; i++)
+                    args[i] = DataConversion.convert(args[i], parameterTypes[i]);
+            }
+
+
+            MethodAccessor access = new MethodAccessor();
+            access.setMethod(m);
+            access.setCompiledParameters(es);
+
+            addAccessorNode(access);
+
+            /**
+             * Invoke the target method and return the response.
+             */
+            return m.invoke(ctx, args);
+        }
+    }
+
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory variableFactory) throws Exception {
+        return rootNode.getValue(ctx, elCtx, variableFactory);
+    }
+
+    private Class tryStaticAccess() {
+        try {
+            /**
+             * Try to resolve this *smartly* as a static class reference.
+             *
+             * This starts at the end of the token and starts to step backwards to figure out whether
+             * or not this may be a static class reference.  We search for method calls simply by
+             * inspecting for ()'s.  The first union area we come to where no brackets are present is our
+             * test-point for a class reference.  If we find a class, we pass the reference to the
+             * property accessor along  with trailing methods (if any).
+             *
+             */
+            boolean meth = false;
+            int depth = 0;
+            int last = property.length;
+            for (int i = property.length - 1; i > 0; i--) {
+                switch (property[i]) {
+                    case'.':
+                        if (!meth) {
+                            return forName(new String(property, 0, last));
+                        }
+
+                        meth = false;
+                        last = i;
+                        break;
+                    case')':
+                        if (depth++ == 0)
+                            meth = true;
+                        break;
+                    case'(':
+                        depth--;
+                        break;
+                }
+            }
+        }
+        catch (Exception cnfe) {
+            // do nothing.
+        }
+
+        return null;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/Deferral.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/Deferral.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/Deferral.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,20 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.util.Map;
+
+public class Deferral implements AccessorNode {
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vr) throws Exception {
+        return null;
+    }
+
+    public AccessorNode getNextNode() {
+        return null;
+    }
+
+    public AccessorNode setNextNode(AccessorNode accessorNode) {
+        return null;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/FieldAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/FieldAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/FieldAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,37 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.lang.reflect.Field;
+
+public class FieldAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    private Field field;
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vars) throws Exception {
+        if (nextNode != null) {
+            return nextNode.getValue(field.get(ctx), elCtx, vars);
+        }
+        else {
+            return field.get(ctx);
+        }
+    }
+
+    public Field getField() {
+        return field;
+    }
+
+    public void setField(Field field) {
+        this.field = field;
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/GetterAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/GetterAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/GetterAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,45 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+public class GetterAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    private final Method method;
+
+    public static final Object[] EMPTY = new Object[0];
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vars) throws Exception {
+        if (nextNode != null) {
+            return nextNode.getValue(method.invoke(ctx, EMPTY), elCtx, vars);
+        }
+        else {
+            return method.invoke(ctx, EMPTY);
+        }
+    }
+
+
+    public GetterAccessor(Method method) {
+        this.method = method;
+    }
+
+    public Method getMethod() {
+        return method;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public String toString() {
+        return method.getDeclaringClass().getName() + "." + method.getName();
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/IndexedCharSeqAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/IndexedCharSeqAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/IndexedCharSeqAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,44 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.util.Map;
+import java.util.List;
+
+public class IndexedCharSeqAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    private int index;
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vars) throws Exception {
+        if (nextNode != null) {
+            return nextNode.getValue(((String)ctx).charAt(index), elCtx, vars);
+        }
+        else {
+            return ((String)ctx).charAt(index);
+        }
+    }
+
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+
+
+    public String toString() {
+        return "Array Accessor -> [" + index + "]";
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ListAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ListAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ListAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,44 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.util.Map;
+import java.util.List;
+
+public class ListAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    private int index;
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vars) throws Exception {
+        if (nextNode != null) {
+            return nextNode.getValue(((List)ctx).get(index), elCtx, vars);
+        }
+        else {
+            return ((List)ctx).get(index);
+        }
+    }
+
+
+    public int getIndex() {
+        return index;
+    }
+
+    public void setIndex(int index) {
+        this.index = index;
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+
+
+    public String toString() {
+        return "Array Accessor -> [" + index + "]";
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/MapAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/MapAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/MapAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,42 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.util.Map;
+
+public class MapAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    private Object property;
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vrf) throws Exception {
+        if (nextNode != null) {
+            return nextNode.getValue(((Map)ctx).get(property), elCtx, vrf);
+        }
+        else {
+            return ((Map)ctx).get(property);
+        }
+    }
+
+    public Object getProperty() {
+        return property;
+    }
+
+    public void setProperty(Object property) {
+        this.property = property;
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+
+
+    public String toString() {
+        return "Map Accessor -> [" + property + "]";
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/MethodAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/MethodAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/MethodAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,88 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+import static org.mvel.DataConversion.convert;
+import static org.mvel.ExpressionParser.executeAllExpression;
+import static org.mvel.ExpressionParser.executeExpression;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+public class MethodAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    private Method method;
+    private Class[] parameterTypes;
+    private Serializable[] compiledParameters;
+    private boolean coercionNeeded = false;
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vars) throws Exception {
+        if (!coercionNeeded) {
+            try {
+                if (nextNode != null) {
+                    return nextNode.getValue(
+                            method.invoke(ctx, executeAllExpression(compiledParameters, elCtx, vars)), elCtx, vars);
+                }
+                else {
+                    return method.invoke(ctx, executeAllExpression(compiledParameters, elCtx, vars));
+                }
+            }
+            catch (IllegalArgumentException e) {
+                coercionNeeded = true;
+                return getValue(ctx, elCtx, vars);
+            }
+
+        }
+        else {
+            if (nextNode != null) {
+                return nextNode.getValue(
+                        method.invoke(ctx, executeAndCoerce(compiledParameters, parameterTypes, elCtx, vars)), elCtx, vars);
+            }
+            else {
+                return method.invoke(ctx, executeAndCoerce(compiledParameters, parameterTypes, elCtx, vars));
+            }
+        }
+    }
+
+    private static Object[] executeAndCoerce(Serializable[] compiled, Class[] target, Object elCtx, VariableResolverFactory vars) {
+        Object[] values = new Object[compiled.length];
+        for (int i = 0; i < compiled.length; i++) {
+            //noinspection unchecked
+            values[i] = convert(executeExpression(compiled[i], elCtx, vars), target[i]);
+        }
+        return values;
+    }
+
+    public Method getMethod() {
+        return method;
+    }
+
+    public void setMethod(Method method) {
+        this.method = method;
+        this.parameterTypes = this.method.getParameterTypes();
+    }
+
+
+    public Serializable[] getCompiledParameters() {
+        return compiledParameters;
+    }
+
+    public void setCompiledParameters(Serializable[] compiledParameters) {
+        this.compiledParameters = compiledParameters;
+    }
+
+    public MethodAccessor() {
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+}
+
+

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/StaticReferenceAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/StaticReferenceAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/StaticReferenceAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,42 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+
+public class StaticReferenceAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    Object literal;
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vars) throws Exception {
+        if (nextNode != null) {
+            return nextNode.getValue(literal, elCtx, vars);
+        }
+        else {
+            return literal;
+        }
+    }
+
+    public Object getLiteral() {
+        return literal;
+    }
+
+    public void setLiteral(Object literal) {
+        this.literal = literal;
+    }
+
+    public StaticReferenceAccessor() {
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ThisValueAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ThisValueAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/ThisValueAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,29 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.integration.VariableResolverFactory;
+
+public class ThisValueAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vars) throws Exception {
+        if (nextNode != null) {
+            return this.nextNode.getValue(
+                    elCtx, elCtx, vars);
+        }
+        else {
+            return elCtx;
+        }
+    }
+
+    public ThisValueAccessor() {
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/VariableAccessor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/VariableAccessor.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/compiled/VariableAccessor.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,58 @@
+package org.mvel.compiled;
+
+import org.mvel.AccessorNode;
+import org.mvel.PropertyAccessException;
+import org.mvel.integration.VariableResolverFactory;
+
+public class VariableAccessor implements AccessorNode {
+    private AccessorNode nextNode;
+
+    private String property;
+ //   private VariableResolverFactory resolverFactory;
+
+    public VariableAccessor(String property, VariableResolverFactory vrf) {
+        this.property = property;
+
+//        while (vrf != null) {
+//            if (vrf.isTarget(property)) {
+//                this.resolverFactory = vrf;
+//                break;
+//            }
+//            vrf = vrf.getNextFactory();
+//        }
+
+    }
+
+    public Object getValue(Object ctx, Object elCtx, VariableResolverFactory vrf) throws Exception {
+        if (vrf == null) 
+            throw new PropertyAccessException("cannot property in optimized accessor: " + property);
+        if (nextNode != null) {
+            return nextNode.getValue(vrf.getVariableResolver(property).getValue(), elCtx, vrf);
+        }
+        else {
+            return vrf.getVariableResolver(property).getValue();
+        }
+    }
+
+
+    public Object getProperty() {
+        return property;
+    }
+
+    public void setProperty(String property) {
+        this.property = property;
+    }
+
+    public AccessorNode getNextNode() {
+        return nextNode;
+    }
+
+    public AccessorNode setNextNode(AccessorNode nextNode) {
+        return this.nextNode = nextNode;
+    }
+
+
+    public String toString() {
+        return "Map Accessor -> [" + property + "]";
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ArrayCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ArrayCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ArrayCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,71 @@
+package org.mvel.conversion;
+
+import static java.lang.String.valueOf;
+import static java.lang.Integer.parseInt;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+
+public class ArrayCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Boolean.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String[].class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        Object[] old = (Object[]) o;
+                        String[] n = new String[old.length];
+                        for (int i = 0; i < old.length; i++) {
+                            n[i] = valueOf(old[i]);
+                        }
+
+                        return n;
+                    }
+                }
+        );
+
+        CNV.put(Integer[].class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        Object[] old = (Object[]) o;
+                        Integer[] n = new Integer[old.length];
+                        for (int i = 0; i < old.length; i++) {
+                            n[i] = parseInt(valueOf(old[i]));
+                        }
+
+                        return n;
+                    }
+
+                });
+
+        CNV.put(int[].class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        Object[] old = (Object[]) o;
+                        int[] n = new int[old.length];
+                        for (int i = 0; i < old.length; i++) {
+                            n[i] = parseInt(valueOf(old[i]));
+                        }
+
+                        return n;
+                    }
+
+                });
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/BigDecimalCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/BigDecimalCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/BigDecimalCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,119 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class BigDecimalCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Integer.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(Object.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal(String.valueOf(o));
+                    }
+                }
+        );
+
+        CNV.put(BigDecimal.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return (BigDecimal) o;
+                    }
+                }
+        );
+
+
+        CNV.put(BigInteger.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal((BigInteger) o);
+                    }
+                }
+        );
+
+        CNV.put(String.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal((String) o);
+                    }
+                }
+        );
+
+        CNV.put(Double.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal((Double) o);
+                    }
+                }
+        );
+
+        CNV.put(Float.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal((Float) o);
+                    }
+                }
+        );
+
+
+        CNV.put(Short.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal((Short) o);
+                    }
+                }
+        );
+
+        CNV.put(Long.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal((Long) o);
+                    }
+                }
+        );
+
+        CNV.put(Integer.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal((Integer) o);
+                    }
+                }
+        );
+
+        CNV.put(String.class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal((String) o);
+                    }
+                }
+        );
+
+        CNV.put(char[].class,
+                new Converter() {
+                    public BigDecimal convert(Object o) {
+                        return new BigDecimal((char[]) o);
+                    }
+                }
+
+        );
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/BooleanCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/BooleanCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/BooleanCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,96 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import static java.lang.Integer.parseInt;
+import static java.lang.String.valueOf;
+
+public class BooleanCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Boolean.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return !(((String) o).equalsIgnoreCase("false"))
+                                || (((String) o).equalsIgnoreCase("no"))
+                                || (((String) o).equalsIgnoreCase("off"))
+                                || (o.equals("0"));
+                    }
+                }
+        );
+
+        CNV.put(Object.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return CNV.get(String.class).convert(valueOf(o));
+                    }
+                }
+        );
+
+        CNV.put(Boolean.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return o;
+                    }
+                }
+        );
+
+        CNV.put(Integer.class,
+                new Converter() {
+                    public Boolean convert(Object o) {
+                        return (((Integer) o) > 0);
+                    }
+                }
+        );
+
+        CNV.put(Float.class,
+                new Converter() {
+                    public Boolean convert(Object o) {
+                        return (((Float) o) > 0);
+                    }
+                }
+        );
+
+        CNV.put(Double.class,
+                new Converter() {
+                    public Boolean convert(Object o) {
+                        return (((Double) o) > 0);
+                    }
+                }
+        );
+
+        CNV.put(Short.class,
+                new Converter() {
+                    public Boolean convert(Object o) {
+                        return (((Short) o) > 0);
+                    }
+                }
+        );
+
+        CNV.put(Long.class,
+                new Converter() {
+                    public Boolean convert(Object o) {
+                        return (((Long) o) > 0);
+                    }
+                }
+        );
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ByteCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ByteCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ByteCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,54 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import static java.lang.String.valueOf;
+
+public class ByteCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Integer.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return Byte.parseByte(((String) o));
+                    }
+                }
+        );
+
+        CNV.put(Object.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return CNV.get(String.class).convert(valueOf(o));
+                    }
+                }
+        );
+
+        CNV.put(Byte.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        return new Byte(((Byte) o));
+                    }
+                }
+        );
+
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/CharArrayCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/CharArrayCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/CharArrayCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,35 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+
+public class CharArrayCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Boolean.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return String.valueOf(o);
+                    }
+                }
+        );
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/CharCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/CharCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/CharCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,57 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import static java.lang.String.valueOf;
+
+public class CharCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Integer.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        if ((((String) o).length()) > 0)
+                            throw new ConversionException("cannot convert a string with a length greater than 1 to java.lang.Character");
+
+                        return (((String) o)).charAt(0);
+                    }
+                }
+        );
+
+        CNV.put(Object.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return CNV.get(String.class).convert(valueOf(o));
+                    }
+                }
+        );
+
+        CNV.put(Character.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        return new Character(((Character) o));
+                    }
+                }
+        );
+
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/Converter.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/Converter.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/Converter.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,5 @@
+package org.mvel.conversion;
+
+public interface Converter {
+    public Object convert(Object o);
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/DoubleCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/DoubleCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/DoubleCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,122 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import static java.lang.String.valueOf;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class DoubleCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Integer.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return Double.parseDouble(((String) o));
+                    }
+                }
+        );
+
+        CNV.put(Object.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return CNV.get(String.class).convert(valueOf(o));
+                    }
+                }
+        );
+
+        CNV.put(BigDecimal.class,
+                new Converter() {
+                    public Double convert(Object o) {
+                        return ((BigDecimal) o).doubleValue();
+                    }
+                }
+        );
+
+
+        CNV.put(BigInteger.class,
+                new Converter() {
+                    public Double convert(Object o) {
+                        return ((BigInteger) o).doubleValue();
+                    }
+                }
+        );
+
+
+        CNV.put(Double.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return o;
+                    }
+                }
+        );
+
+        CNV.put(Float.class,
+                new Converter() {
+                    public Double convert(Object o) {
+                        if (((Float) o) > Double.MAX_VALUE) {
+                            throw new ConversionException("cannot coerce Float to Double since the value ("
+                                    + valueOf(o) + ") exceeds that maximum precision of Double.");
+
+                        }
+
+                        return ((Float) o).doubleValue();
+                    }
+                });
+
+        CNV.put(Integer.class,
+                new Converter() {
+                    public Double convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        return ((Integer) o).doubleValue();
+                    }
+                }
+        );
+
+        CNV.put(Short.class,
+                new Converter() {
+                    public Double convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        return ((Short) o).doubleValue();
+                    }
+                }
+        );
+
+        CNV.put(Long.class,
+                new Converter() {
+                    public Double convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        return ((Long) o).doubleValue();
+                    }
+                }
+        );
+
+
+        CNV.put(Boolean.class,
+                new Converter() {
+                    public Double convert(Object o) {
+                        if ((Boolean) o) return 1d;
+                        else return 0d;
+                    }
+                }
+        );
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/FloatCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/FloatCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/FloatCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,116 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import static java.lang.String.valueOf;
+
+public class FloatCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Integer.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return Float.parseFloat(((String) o));
+                    }
+                }
+        );
+
+
+        CNV.put(Object.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return CNV.get(String.class).convert(valueOf(o));
+                    }
+                }
+        );
+
+        CNV.put(BigDecimal.class,
+                new Converter() {
+                    public Float convert(Object o) {
+                        return ((BigDecimal) o).floatValue();
+                    }
+                }
+        );
+
+
+        CNV.put(BigInteger.class,
+                new Converter() {
+                    public Float convert(Object o) {
+                        return ((BigInteger) o).floatValue();
+                    }
+                }
+        );
+
+
+        CNV.put(Float.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return o;
+                    }
+                }
+        );
+
+        CNV.put(Integer.class,
+                new Converter() {
+                    public Float convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        return ((Integer) o).floatValue();
+                    }
+                }
+        );
+
+
+        CNV.put(Double.class,
+                new Converter() {
+                    public Float convert(Object o) {
+                        return ((Double) o).floatValue();
+                    }
+                }
+        );
+
+        CNV.put(Long.class,
+                new Converter() {
+                    public Float convert(Object o) {
+                        return ((Long) o).floatValue();
+                    }
+                }
+        );
+
+        CNV.put(Short.class,
+                new Converter() {
+                    public Float convert(Object o) {
+                        return ((Short) o).floatValue();
+                    }
+                }
+        );
+
+        CNV.put(Boolean.class,
+                new Converter() {
+                    public Float convert(Object o) {
+                        if ((Boolean) o) return 1f;
+                        else return 0f;
+                    }
+                }
+        );
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/IntArrayCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/IntArrayCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/IntArrayCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,58 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+
+public class IntArrayCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+
+
+    public Object convertFrom(Object in) {
+
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Boolean.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String[].class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        String[] old = (String[]) o;
+                        Integer[] n = new Integer[old.length];
+                        for (int i = 0; i < old.length; i++) {
+                            n[i] = Integer.parseInt(old[i]);
+                        }
+
+                        return n;
+                    }
+                }
+        );
+
+        CNV.put(Object[].class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        Object[] old = (Object[]) o;
+                        Integer[] n = new Integer[old.length];
+                        for (int i = 0; i < old.length; i++) {
+                            n[i] = Integer.parseInt(String.valueOf(old[i]));
+                        }
+
+                        return n;
+                    }
+                }
+        );
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/IntegerCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/IntegerCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/IntegerCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,141 @@
+package org.mvel.conversion;
+
+import static java.lang.Integer.parseInt;
+import static java.lang.String.valueOf;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class IntegerCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>(10);
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Integer.class.getName());
+
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(Object.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return parseInt(valueOf(o));
+                    }
+                }
+        );
+
+        CNV.put(BigDecimal.class,
+                new Converter() {
+                    public Integer convert(Object o) {
+                        return ((BigDecimal) o).intValue();
+                    }
+                }
+        );
+
+
+        CNV.put(BigInteger.class,
+                new Converter() {
+                    public Integer convert(Object o) {
+                        return ((BigInteger) o).intValue();
+                    }
+                }
+        );
+
+        CNV.put(String.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return parseInt(((String) o));
+                    }
+                }
+        );
+
+        CNV.put(Short.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return ((Short) o).floatValue();
+                    }
+                }
+        );
+
+        CNV.put(Long.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        if (((Long) o) > Integer.MAX_VALUE) {
+                            throw new ConversionException("cannot coerce Long to Integer since the value ("
+                                    + valueOf(o) + ") exceeds that maximum precision of Integer.");
+                        }
+                        else {
+                            return ((Long) o).intValue();
+                        }
+                    }
+                }
+        );
+
+
+        CNV.put(Float.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        if (((Float) o) > Integer.MAX_VALUE) {
+                            throw new ConversionException("cannot coerce Float to Integer since the value ("
+                                    + valueOf(o) + ") exceeds that maximum precision of Integer.");
+                        }
+                        else {
+                            return ((Float) o).intValue();
+                        }
+                    }
+                }
+        );
+
+        CNV.put(Double.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        if (((Double) o) > Integer.MAX_VALUE) {
+                            throw new ConversionException("cannot coerce Long to Integer since the value ("
+                                    + valueOf(o) + ") exceeds that maximum precision of Integer.");
+                        }
+                        else {
+                            return ((Double) o).intValue();
+                        }
+                    }
+                }
+        );
+
+
+        CNV.put(Integer.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return o;
+                    }
+                }
+        );
+
+        CNV.put(Boolean.class,
+                new Converter() {
+                    public Integer convert(Object o) {
+                        if ((Boolean) o) return 1;
+                        else return 0;
+                    }
+                }
+        );
+
+
+    }
+
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/LongCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/LongCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/LongCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,99 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import static java.lang.String.valueOf;
+
+public class LongCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Long.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return Long.parseLong(((String) o));
+                    }
+                }
+        );
+
+        CNV.put(Object.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return CNV.get(String.class).convert(valueOf(o));
+                    }
+                }
+        );
+
+        CNV.put(BigDecimal.class,
+                new Converter() {
+                    public Long convert(Object o) {
+                        return ((BigDecimal) o).longValue();
+                    }
+                }
+        );
+
+
+        CNV.put(BigInteger.class,
+                new Converter() {
+                    public Long convert(Object o) {
+                        return ((BigInteger) o).longValue();
+                    }
+                }
+        );
+
+
+        CNV.put(Short.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        return ((Short) o).longValue();
+                    }
+                }
+        );
+
+        CNV.put(Long.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        return new Long(((Long) o));
+                    }
+                }
+        );
+
+        CNV.put(Integer.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        //noinspection UnnecessaryBoxing
+                        return ((Integer) o).longValue();
+                    }
+                }
+        );
+
+        CNV.put(Boolean.class,
+                new Converter() {
+                    public Long convert(Object o) {
+                        if ((Boolean) o) return 1l;
+                        else return 0l;
+                    }
+                }
+        );
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ObjectCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ObjectCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ObjectCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,14 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+
+public class ObjectCH implements ConversionHandler {
+    public Object convertFrom(Object in) {
+        return in;
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return true;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/PrimArrayHandler.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/PrimArrayHandler.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/PrimArrayHandler.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,74 @@
+package org.mvel.conversion;
+
+import static java.lang.reflect.Array.set;
+import static java.lang.reflect.Array.newInstance;
+
+import static org.mvel.DataConversion.convert;
+import static org.mvel.DataConversion.canConvert;
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+
+public class PrimArrayHandler implements ConversionHandler {
+    private final Map<Class, Converter> CNV = new HashMap<Class, Converter>();
+
+    private final Class primitiveType;
+
+    public PrimArrayHandler(Class type) {
+        this.primitiveType = type;
+
+        CNV.put(Object[].class, new Converter() {
+            public Object convert(Object o) {
+                return handleLooseTypeConversion(o.getClass(), (Object[]) o, primitiveType);
+            }
+        });
+
+        CNV.put(String[].class, new Converter() {
+            public Object convert(Object o) {
+                return handleLooseTypeConversion(o.getClass(), (String[]) o, primitiveType);
+            }
+        });
+    }
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + primitiveType.getName());
+
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+
+    /**
+     * Messy method to handle primitive boxing for conversion. If someone can re-write this more
+     * elegantly, be my guest.
+     *
+     * @param sourceType
+     * @param input
+     * @param targetType
+     * @return
+     */
+    private static Object handleLooseTypeConversion(Class sourceType, Object[] input, Class targetType) {
+        Class targType = targetType.getComponentType();
+
+        Object target = newInstance(targType, input.length);
+
+        if (input.length > 0
+                && canConvert(targetType.getComponentType(), sourceType.getComponentType())) {
+            for (int i = 0; i < input.length; i++) {
+                set(target, i, convert(input[i], targType));
+            }
+        }
+        else {
+            throw new ConversionException("cannot convert to type: "
+                    + targetType.getComponentType().getName() + "[] from " + sourceType.getComponentType().getName());
+        }
+
+        return target;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/PrimIntArrayCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/PrimIntArrayCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/PrimIntArrayCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,70 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+
+public class PrimIntArrayCH implements ConversionHandler {
+
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Boolean.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(String[].class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        String[] old = (String[]) o;
+                        int[] n = new int[old.length];
+                        for (int i = 0; i < old.length; i++) {
+                            n[i] = Integer.parseInt(old[i]);
+                        }
+
+                        return n;
+                    }
+                }
+        );
+
+        CNV.put(Object[].class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        Object[] old = (Object[]) o;
+                        int[] n = new int[old.length];
+                        for (int i = 0; i < old.length; i++) {
+                            n[i] = Integer.parseInt(String.valueOf(old[i]));
+                        }
+
+                        return n;
+                    }
+                }
+        );
+
+        CNV.put(Integer[].class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        Integer[] old = (Integer[]) o;
+                        int[] n = new int[old.length];
+                        for (int i = 0; i < old.length; i++) {
+                            n[i] = old[i];
+                        }
+
+                        return n;
+                    }
+                }
+        );
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ShortCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ShortCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/ShortCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,138 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionException;
+import org.mvel.ConversionHandler;
+
+import java.util.HashMap;
+import java.util.Map;
+import static java.lang.String.valueOf;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+public class ShortCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Short.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+
+    static {
+        CNV.put(String.class,
+                new Converter() {
+                    public Short convert(Object o) {
+                        return Short.parseShort(((String) o));
+                    }
+                }
+        );
+
+        CNV.put(Object.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return CNV.get(String.class).convert(valueOf(o));
+                    }
+                }
+        );
+
+        CNV.put(BigDecimal.class,
+                new Converter() {
+                    public Short convert(Object o) {
+                        return ((BigDecimal) o).shortValue();
+                    }
+                }
+        );
+
+
+        CNV.put(BigInteger.class,
+                new Converter() {
+                    public Short convert(Object o) {
+                        return ((BigInteger) o).shortValue();
+                    }
+                }
+        );
+
+
+        CNV.put(Short.class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        return o;
+                    }
+                }
+        );
+
+        CNV.put(Integer.class,
+                new Converter() {
+                    public Short convert(Object o) {
+                        if (((Integer) o) > Short.MAX_VALUE) {
+                            throw new ConversionException("cannot coerce Integer to Short since the value ("
+                                    + valueOf(o) + ") exceeds that maximum precision of Integer.");
+                        }
+                        else {
+                            return ((Integer) o).shortValue();
+                        }
+                    }
+                }
+        );
+
+        CNV.put(Float.class,
+                new Converter() {
+                    public Short convert(Object o) {
+                        if (((Float) o) > Short.MAX_VALUE) {
+                            throw new ConversionException("cannot coerce Float to Short since the value ("
+                                    + valueOf(o) + ") exceeds that maximum precision of Integer.");
+                        }
+                        else {
+                            return ((Float) o).shortValue();
+                        }
+                    }
+                }
+        );
+
+        CNV.put(Double.class,
+                new Converter() {
+                    public Short convert(Object o) {
+                        if (((Double) o) > Short.MAX_VALUE) {
+                            throw new ConversionException("cannot coerce Double to Short since the value ("
+                                    + valueOf(o) + ") exceeds that maximum precision of Integer.");
+                        }
+                        else {
+                            return ((Double) o).shortValue();
+                        }
+                    }
+                }
+        );
+
+        CNV.put(Long.class,
+                new Converter() {
+                    public Short convert(Object o) {
+                        if (((Long) o) > Short.MAX_VALUE) {
+                            throw new ConversionException("cannot coerce Integer to Short since the value ("
+                                    + valueOf(o) + ") exceeds that maximum precision of Integer.");
+                        }
+                        else {
+                            return ((Long) o).shortValue();
+                        }
+                    }
+                }
+        );
+
+        CNV.put(Boolean.class,
+                new Converter() {
+                    public Short convert(Object o) {
+                        if ((Boolean) o) return 1;
+                        else return 0;
+                    }
+                }
+        );
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/StringArrayCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/StringArrayCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/StringArrayCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,41 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+import org.mvel.ConversionException;
+
+import java.util.Map;
+import java.util.HashMap;
+
+public class StringArrayCH implements ConversionHandler {
+    private static final Map<Class, Converter> CNV =
+            new HashMap<Class, Converter>();
+
+
+    public Object convertFrom(Object in) {
+        if (!CNV.containsKey(in.getClass())) throw new ConversionException("cannot convert type: "
+                + in.getClass().getName() + " to: " + Boolean.class.getName());
+        return CNV.get(in.getClass()).convert(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return CNV.containsKey(cls);
+    }
+
+    static {
+        CNV.put(Object[].class,
+                new Converter() {
+                    public Object convert(Object o) {
+                        Object[] old = (Object[]) o;
+                        String[] n = new String[old.length];
+                        for (int i = 0; i < old.length; i++) {
+                            n[i] = String.valueOf(old[i]);
+                        }
+
+                        return n;
+                    }
+                }
+        );
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/StringCH.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/StringCH.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/conversion/StringCH.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,14 @@
+package org.mvel.conversion;
+
+import org.mvel.ConversionHandler;
+
+public class StringCH implements ConversionHandler {
+    public Object convertFrom(Object in) {
+        return String.valueOf(in);
+    }
+
+
+    public boolean canConvertFrom(Class cls) {
+        return true;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/IndexedProperty.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/IndexedProperty.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/IndexedProperty.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,6 @@
+package org.mvel.integration;
+
+public interface IndexedProperty {
+    public Object getProperty(Object property);
+    public void setProperty(Object property, Object value);
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/VariableResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/VariableResolver.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/VariableResolver.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,8 @@
+package org.mvel.integration;
+
+public interface VariableResolver {
+    public String getName();
+    public Class getKnownType();
+    public int getFlags();
+    public Object getValue();
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/VariableResolverFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/VariableResolverFactory.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/VariableResolverFactory.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,56 @@
+package org.mvel.integration;
+
+public interface VariableResolverFactory {
+    /**
+     * Creates a new variable.  This probably doesn't need to be implemented in most scenarios.  This is
+     * used for variable assignment.
+     * @param name - name of the variable being created
+     * @param value - value of the variable
+     * @return instance of the variable resolver associated with the variable
+     */
+    public VariableResolver createVariable(String name, Object value);
+
+    /**
+     * Returns the next factory in the factory chain.  MVEL uses a hierarchical variable resolution strategy,
+     * much in the same way as Classloaders in Java.   For performance reasons, it is the responsibility of
+     * the individual VariableResolverFactory to pass off to the next one.
+     * @return instance of the next factory - null if none.
+     */
+    public VariableResolverFactory getNextFactory();
+
+    /**
+     * Sets the next factory in the chain. Proper implementation:
+     * <code>
+     *
+     *      return this.nextFactory = resolverFactory;
+     * </code>
+     * @param resolverFactory - instance of next resolver factory
+     * @return - instance of next resolver factory
+     */
+    public VariableResolverFactory setNextFactory(VariableResolverFactory resolverFactory);
+
+    /**
+     * Return a variable resolver for the specified variable name.  This method is expected to traverse the
+     * heirarchy of ResolverFactories.
+     * @param name - variable name
+     * @return - instance of the VariableResolver for the specified variable
+     */
+    public VariableResolver getVariableResolver(String name);
+
+
+    /**
+     * Deterimines whether or not the current VariableResolverFactory is the physical target for the actual
+     * variable.
+     * @param name - variable name
+     * @return - boolean indicating whether or not factory is the physical target
+     */
+    public boolean isTarget(String name);
+
+
+    /**
+     * Determines whether or not the variable is resolver in the chain of factories.
+     * @param name - variable name
+     * @return - boolean
+     */
+    public boolean isResolveable(String name);
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/BaseVariableResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/BaseVariableResolver.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/BaseVariableResolver.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,28 @@
+package org.mvel.integration.impl;
+
+import org.mvel.integration.VariableResolver;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.util.Map;
+
+/**
+ * Use this class to extend you own VariableResolverFactories.
+ */
+public abstract class BaseVariableResolver implements VariableResolverFactory {
+    protected Map<String, VariableResolver> variableResolvers;
+    protected VariableResolverFactory nextFactory;
+
+    public VariableResolverFactory getNextFactory() {
+        return nextFactory;
+    }
+
+    public VariableResolverFactory setNextFactory(VariableResolverFactory resolverFactory) {
+        return nextFactory = resolverFactory;
+    }
+
+    public VariableResolver getVariableResolver(String name) {
+        return isResolveable(name) ? variableResolvers.get(name) :
+                nextFactory != null ? nextFactory.getVariableResolver(name) : null;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/ClassImportResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/ClassImportResolver.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/ClassImportResolver.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,46 @@
+package org.mvel.integration.impl;
+
+import org.mvel.CompileException;
+import org.mvel.integration.VariableResolver;
+
+public class ClassImportResolver implements VariableResolver {
+    private String name;
+    private Class knownType;
+
+    public ClassImportResolver(String fqcn, String name) {
+        this.name = name;
+        try {
+            this.knownType = Class.forName(fqcn);
+        }
+        catch (Exception e) {
+            throw new CompileException("failed import", e);
+        }
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setKnownType(Class knownType) {
+        this.knownType = knownType;
+    }
+
+
+    public String getName() {
+        return name;
+    }
+
+    public Class getKnownType() {
+        return Class.class;
+    }
+
+    public Object getValue() {
+        return knownType;
+    }
+
+    public int getFlags() {
+        return 0;
+    }
+
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/ClassImportResolverFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/ClassImportResolverFactory.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/ClassImportResolverFactory.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,25 @@
+package org.mvel.integration.impl;
+
+import org.mvel.integration.VariableResolver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ClassImportResolverFactory extends BaseVariableResolver {
+    private Map<String, VariableResolver> importsTable = new HashMap<String, VariableResolver>();
+
+    public VariableResolver createVariable(String name, Object value) {
+        VariableResolver vr = new ClassImportResolver(name.substring(name.lastIndexOf('.')), name);
+        importsTable.put(vr.getName(), vr);
+        return vr;
+    }
+
+
+    public boolean isTarget(String name) {
+        return importsTable.containsKey(name);
+    }
+
+    public boolean isResolveable(String name) {
+        return importsTable.containsKey(name) || nextFactory.isResolveable(name);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/LocalVariableResolverFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/LocalVariableResolverFactory.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/LocalVariableResolverFactory.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,9 @@
+package org.mvel.integration.impl;
+
+import java.util.Map;
+
+public class LocalVariableResolverFactory extends MapVariableResolverFactory {
+    public LocalVariableResolverFactory(Map<String, Object> variables) {
+        super(variables);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/MapVariableResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/MapVariableResolver.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/MapVariableResolver.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,52 @@
+package org.mvel.integration.impl;
+
+import org.mvel.integration.VariableResolver;
+
+import java.util.Map;
+
+public class MapVariableResolver implements VariableResolver {
+    private String name;
+    private Class knownType;
+
+    private Map variableMap;
+
+    public MapVariableResolver(Map variableMap, String name) {
+        this.variableMap = variableMap;
+        this.name = name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public void setKnownType(Class knownType) {
+        this.knownType = knownType;
+    }
+
+    public void setVariableMap(Map variableMap) {
+        this.variableMap = variableMap;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Class getKnownType() {
+        if (knownType == null && variableMap.containsKey(name)) {
+            knownType = variableMap.get(name) != null ? variableMap.get(name).getClass() : Object.class;
+        }
+        else {
+            knownType = Object.class;
+        }
+
+        return knownType;
+    }
+
+    public Object getValue() {
+        return variableMap.get(name);
+    }
+
+    public int getFlags() {
+        return 0;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/MapVariableResolverFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/MapVariableResolverFactory.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/integration/impl/MapVariableResolverFactory.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,70 @@
+package org.mvel.integration.impl;
+
+import org.mvel.integration.VariableResolver;
+import org.mvel.integration.VariableResolverFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MapVariableResolverFactory implements VariableResolverFactory {
+    /**
+     * Holds the instance of the variables.
+     */
+    private Map<String, Object> variables;
+
+    private Map<String, VariableResolver> variableResolvers;
+    private VariableResolverFactory nextFactory;
+
+
+    public MapVariableResolverFactory(Map<String, Object> variables) {
+        this.variables = variables;
+    }
+
+    public VariableResolver createVariable(String name, Object value) {
+        variables.put(name, value);
+        return new MapVariableResolver(variables, name);
+    }
+
+    public VariableResolverFactory getNextFactory() {
+        return nextFactory;
+    }
+
+    public VariableResolverFactory setNextFactory(VariableResolverFactory resolverFactory) {
+        return nextFactory = resolverFactory;
+    }
+
+    public VariableResolver getVariableResolver(String name) {
+        return isResolveable(name) ? variableResolvers.get(name) :
+                nextFactory != null ? nextFactory.getVariableResolver(name) : null;
+    }
+
+
+    public boolean isResolveable(String name) {
+        if (variableResolvers != null && variableResolvers.containsKey(name)) {
+            return true;
+        }
+        else if (variables != null && variables.containsKey(name)) {
+            if (variableResolvers == null) variableResolvers = new HashMap<String, VariableResolver>();
+            variableResolvers.put(name, new MapVariableResolver(variables, name));
+            return true;
+        }
+        else if (nextFactory != null) {
+            return nextFactory.isResolveable(name);
+        }
+        return false;
+    }
+
+    public void pack() {
+        if (variables != null) {
+            if (variableResolvers == null) variableResolvers = new HashMap<String,VariableResolver>();
+            for (String s : variables.keySet()) {
+                variableResolvers.put(s, new MapVariableResolver(variables, s));
+            }
+        }
+    }
+
+
+    public boolean isTarget(String name) {
+        return variableResolvers.containsKey(name);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ArrayTools.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ArrayTools.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ArrayTools.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,208 @@
+package org.mvel.util;
+
+
+import static java.lang.reflect.Array.newInstance;
+import java.util.*;
+
+public class ArrayTools {
+    public static int[] intTranspose(Object[] a) {
+        int[] b = new int[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = Integer.parseInt(String.valueOf(a[i]));
+        }
+        return b;
+    }
+
+    public static long[] longTranspose(Object[] a) {
+        long[] b = new long[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = Long.parseLong(String.valueOf(a[i]));
+        }
+        return b;
+    }
+
+    public static char[] charTranspose(Object[] a) {
+        char[] b = new char[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = String.valueOf(a[i]).charAt(0);
+        }
+        return b;
+    }
+
+    public static float[] floatTranspose(Object[] a) {
+        float[] b = new float[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = Float.parseFloat(String.valueOf(a[i]));
+        }
+        return b;
+    }
+
+    public static boolean[] booleanTranspose(Object[] a) {
+        boolean[] b = new boolean[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = PropertyTools.parseBoolean(String.valueOf(a[i]));
+        }
+        return b;
+    }
+
+    public static short[] shortTranspose(Object[] a) {
+        short[] b = new short[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = Short.parseShort(String.valueOf(a[i]));
+        }
+
+        return b;
+    }
+
+    public static String[] stringTranspose(Object[] a) {
+        String[] b = new String[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = String.valueOf(a[i]);
+        }
+        return b;
+    }
+
+    public static String[] stringTranspose(int[] a) {
+        String[] b = new String[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = String.valueOf(a[i]);
+        }
+        return b;
+    }
+
+    public static String[] stringTranspose(long[] a) {
+        String[] b = new String[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = String.valueOf(a[i]);
+        }
+        return b;
+    }
+
+    public static String[] stringTranspose(short[] a) {
+        String[] b = new String[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = String.valueOf(a[i]);
+        }
+        return b;
+    }
+
+    public static String[] stringTranspose(boolean[] a) {
+        String[] b = new String[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = String.valueOf(a[i]);
+        }
+        return b;
+    }
+
+    public static String[] stringTranspose(double[] a) {
+        String[] b = new String[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = String.valueOf(a[i]);
+        }
+        return b;
+    }
+
+    public static String[] stringTranspose(char[] a) {
+        String[] b = new String[a.length];
+        for (int i = a.length - 1; i >= 0; i--) {
+            b[i] = String.valueOf(a[i]);
+        }
+        return b;
+    }
+
+    public static String[] stringTranspose(Collection col) {
+        String[] b = new String[col.size()];
+        int i = 0;
+        for (Object o : col) {
+            b[i++] = String.valueOf(o);
+        }
+        return b;
+    }
+
+    public static List listTranspose(int[] a) {
+        List b = new ArrayList(a.length);
+        for (int i = a.length - 1; i >= 0; i--) {
+            b.add(i, a[i]);
+        }
+        return b;
+    }
+
+    public static List listTranspose(char[] a) {
+        List b = new ArrayList(a.length);
+        for (int i = a.length - 1; i >= 0; i--) {
+            b.add(i, a[i]);
+        }
+        return b;
+    }
+
+    public static List listTranspose(long[] a) {
+        List b = new ArrayList(a.length);
+        for (int i = a.length - 1; i >= 0; i--) {
+            b.add(i, a[i]);
+        }
+        return b;
+    }
+
+    public static List listTranspose(boolean[] a) {
+        List b = new ArrayList(a.length);
+        for (int i = a.length - 1; i >= 0; i--) {
+            b.add(i, a[i]);
+        }
+        return b;
+    }
+
+    public static List listTranspose(short[] a) {
+        List b = new ArrayList(a.length);
+        for (int i = a.length - 1; i >= 0; i--) {
+            b.add(i, a[i]);
+        }
+        return b;
+    }
+
+    public static List listTranspose(double[] a) {
+        List b = new ArrayList(a.length);
+        for (int i = a.length - 1; i >= 0; i--) {
+            b.add(i, a[i]);
+        }
+        return b;
+    }
+
+    public static List listTranspose(String[] a) {
+        if (a == null) return new ArrayList(0);
+
+        List b = new ArrayList(a.length);
+        for (int i = a.length - 1; i >= 0; i--) {
+            b.add(i, a[i]);
+        }
+        return b;
+    }
+
+    public static Set setTranspose(String[] a) {
+        if (a == null) return new HashSet(0);
+
+        Set b = new HashSet(a.length * 2);
+        for (String c : a) {
+            b.add(c);
+        }
+        return b;
+    }
+
+    public static <T> T[] collectionTranspose(Collection col, Class<T> type) {
+        //noinspection unchecked
+        T[] a = (T[]) newInstance(type, col.size());
+
+        int i = 0;
+        for (Object item : col) {
+            a[i++] = (T) item;
+        }
+
+        return a;
+    }
+
+    public static int findFirst(char c, char[] array) {
+        for (int i = 0; i < array.length; i++) {
+            if (array[i] == c) return i;
+        }
+        return -1;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ExecutionStack.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ExecutionStack.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ExecutionStack.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,69 @@
+package org.mvel.util;
+
+import static org.mvel.util.ParseTools.debug;
+
+public class ExecutionStack implements Stack {
+    private StackElement element;
+    private int size = 0;
+
+    public boolean isEmpty() {
+        return element == null;
+    }
+
+    public void push(Object o) {
+        size++;
+        element = new StackElement(element, o);
+    }
+
+    public Object pushAndPeek(Object o) {
+        size++;
+        element = new StackElement(element, o);
+        return o;
+    }
+
+
+    public void push(Object obj1, Object obj2) {
+        size += 2;
+        element = new StackElement(new StackElement(element, obj1), obj2);
+    }
+
+    public void push(Object obj1, Object obj2, Object obj3) {
+        size += 3;
+        element = new StackElement(new StackElement(new StackElement(element, obj1), obj2), obj3);
+    }
+
+    public Object peek() {
+        if (size == 0) return null;
+        else return element.value;
+    }
+
+    public Object pop() {
+        if (size-- == 0) return null;
+        Object el = element.value;
+        element = element.next;
+        return el;
+    }
+
+    public void discard() {
+        if (size-- != 0)
+            element = element.next;
+    }
+
+    public int size() {
+        return size;
+    }
+
+    public void clear() {
+        size = 0;
+        element = null;
+    }
+
+
+    public void showStack() {
+        StackElement el = element;
+        do {
+            System.out.println("->" + el.value);
+        }
+        while ((el = el.next) != null);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/FastExecutionStack.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/FastExecutionStack.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/FastExecutionStack.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,53 @@
+package org.mvel.util;
+
+public class FastExecutionStack implements Stack {
+    private Object[] stack = new Object[15];
+    private int size = 0;
+
+    public boolean isEmpty() {
+        return size == 0;
+    }
+
+    public Object peek() {
+        return stack[size];
+    }
+
+    public void push(Object obj) {
+        stack[++size] = obj;
+    }
+
+    public Object pushAndPeek(Object obj) {
+        return stack[++size] = obj;
+    }
+
+    public void push(Object obj1, Object obj2) {
+        stack[++size] = obj1;
+        stack[++size] = obj2;
+    }
+
+    public void push(Object obj1, Object obj2, Object obj3) {
+        stack[++size] = obj1;
+        stack[++size] = obj2;
+        stack[++size] = obj3;
+    }
+
+    public Object pop() {
+        return stack[size--];
+    }
+
+    public void discard() {
+        --size;
+    }
+
+    public void clear() {
+        size = 0;
+    }
+
+    public int size() {
+        return size;
+    }
+
+    public void showStack() {
+
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ParseTools.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ParseTools.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ParseTools.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,387 @@
+package org.mvel.util;
+
+import static org.mvel.DataConversion.canConvert;
+import static org.mvel.DataConversion.convert;
+import static org.mvel.ExpressionParser.eval;
+import org.mvel.Token;
+import org.mvel.CompileException;
+import org.mvel.ParseException;
+import org.mvel.integration.VariableResolverFactory;
+
+import static java.lang.Character.isWhitespace;
+import static java.lang.Class.forName;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+
+public class ParseTools {
+    public static String[] parseMethodOrConstructor(char[] parm) {
+        int start = -1;
+        for (int i = 0; i < parm.length; i++) {
+            if (parm[i] == '(') {
+                start = ++i;
+                break;
+            }
+        }
+        if (start != -1) {
+            for (int i = parm.length - 1; i > 0; i--) {
+                if (parm[i] == ')') {
+                    return parseParameterList(parm, start, i - start);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public static String[] parseParameterList(char[] parm, int offset, int length) {
+        List<String> list = new LinkedList<String>();
+
+        if (length == -1) length = parm.length;
+
+        int adepth = 0;
+        int start = offset;
+        int i = offset;
+        int end = i + length;
+
+        for (; i < end; i++) {
+            switch (parm[i]) {
+                case'[':
+                case'{':
+                    if (adepth++ == 0) start = i;
+                    continue;
+
+                case']':
+                case'}':
+                    if (--adepth == 0) {
+                        list.add(new String(parm, start, i - start + 1));
+
+                        while (isWhitespace(parm[i])) i++;
+
+                        start = i + 1;
+                    }
+                    continue;
+
+                case',':
+                    if (adepth != 0) continue;
+
+                    if (i > start) {
+                        while (isWhitespace(parm[start])) start++;
+
+                        list.add(new String(parm, start, i - start));
+                    }
+
+                    while (isWhitespace(parm[i])) i++;
+
+                    start = i + 1;
+            }
+        }
+
+        if (start < length && i > start) {
+            String s = new String(parm, start, i - start).trim();
+            if (s.length() > 0)
+                list.add(s);
+        }
+        else if (list.size() == 0) {
+            String s = new String(parm, start, length).trim();
+            if (s.length() > 0)
+                list.add(s);
+        }
+
+        return list.toArray(new String[list.size()]);
+    }
+
+    private static Map<String, Map<Integer, Method>> RESOLVED_METH_CACHE =
+            new WeakHashMap<String, Map<Integer, Method>>(10);
+
+    public static Method getBestCanadidate(Object[] arguments, String method, Method[] methods) {
+        Class[] parmTypes;
+        Method bestCandidate = null;
+        int bestScore = 0;
+        int score = 0;
+
+        Class[] targetParms = new Class[arguments.length];
+
+        for (int i = 0; i < arguments.length; i++)
+            targetParms[i] = arguments[i] != null ? arguments[i].getClass() :  Object.class;
+
+        Integer hash = createClassSignatureHash(targetParms);
+
+        if (RESOLVED_METH_CACHE.containsKey(method) && RESOLVED_METH_CACHE.get(method).containsKey(hash))
+            return RESOLVED_METH_CACHE.get(method).get(hash);
+
+        for (Method meth : methods) {
+            if (method.equals(meth.getName())) {
+                if ((parmTypes = meth.getParameterTypes()).length != arguments.length) continue;
+                else if (arguments.length == 0 && parmTypes.length == 0) return meth;
+
+                for (int i = 0; i < arguments.length; i++) {
+                    if (parmTypes[i].isPrimitive() && boxPrimitive(parmTypes[i]) == targetParms[i]) score += 3;
+                    else if (parmTypes[i] == targetParms[i]) score += 4;
+                    else if (parmTypes[i].isAssignableFrom(targetParms[i])) score += 2;
+                    else if (canConvert(parmTypes[i], targetParms[i])) score += 1;
+                    else {
+                        score = 0;
+                        break;
+                    }
+                }
+
+                if (score != 0 && score > bestScore) {
+                    bestCandidate = meth;
+                    bestScore = score;
+                }
+                score = 0;
+            }
+        }
+
+
+        if (bestCandidate != null) {
+            if (!RESOLVED_METH_CACHE.containsKey(method))
+                RESOLVED_METH_CACHE.put(method, new WeakHashMap<Integer, Method>());
+
+            RESOLVED_METH_CACHE.get(method).put(hash, bestCandidate);
+        }
+
+        return bestCandidate;
+    }
+
+    private static Map<Class, Map<Integer, Constructor>> RESOLVED_CONST_CACHE = new WeakHashMap<Class, Map<Integer, Constructor>>(10);
+    private static Map<Constructor, Class[]> CONSTRUCTOR_PARMS_CACHE = new WeakHashMap<Constructor, Class[]>(10);
+
+
+    private static Class[] getConstructors(Constructor cns) {
+        if (CONSTRUCTOR_PARMS_CACHE.containsKey(cns))
+            return CONSTRUCTOR_PARMS_CACHE.get(cns);
+        else {
+            Class[] c = cns.getParameterTypes();
+            CONSTRUCTOR_PARMS_CACHE.put(cns, c);
+            return c;
+        }
+    }
+
+    public static Constructor getBestConstructorCanadidate(Object[] arguments, Class cls) {
+        Class[] parmTypes;
+        Constructor bestCandidate = null;
+        int bestScore = 0;
+        int score = 0;
+
+        Class[] targetParms = new Class[arguments.length];
+
+        for (int i = 0; i < arguments.length; i++)
+            targetParms[i] = arguments[i] != null ? arguments[i].getClass() : Object.class;
+
+        Integer hash = createClassSignatureHash(targetParms);
+
+        if (RESOLVED_CONST_CACHE.containsKey(cls) && RESOLVED_CONST_CACHE.get(cls).containsKey(hash))
+            return RESOLVED_CONST_CACHE.get(cls).get(hash);
+
+        for (Constructor construct : getConstructors(cls)) {
+            if ((parmTypes = getConstructors(construct)).length != arguments.length) continue;
+            else if (arguments.length == 0 && parmTypes.length == 0) return construct;
+
+            for (int i = 0; i < arguments.length; i++) {
+                if (parmTypes[i].isPrimitive() && boxPrimitive(parmTypes[i]) == targetParms[i]) score += 3;
+                else if (parmTypes[i] == targetParms[i]) score += 4;
+                else if (parmTypes[i].isAssignableFrom(targetParms[i])) score += 2;
+                else if (canConvert(parmTypes[i], targetParms[i])) score += 1;
+                else {
+                    score = 0;
+                    break;
+                }
+            }
+
+            if (score != 0 && score > bestScore) {
+                bestCandidate = construct;
+                bestScore = score;
+            }
+            score = 0;
+
+        }
+
+
+        if (bestCandidate != null) {
+            if (!RESOLVED_CONST_CACHE.containsKey(cls))
+                RESOLVED_CONST_CACHE.put(cls, new WeakHashMap<Integer, Constructor>());
+
+            RESOLVED_CONST_CACHE.get(cls).put(hash, bestCandidate);
+        }
+
+        return bestCandidate;
+    }
+
+    private static Map<String, Class> CLASS_RESOLVER_CACHE = new WeakHashMap<String, Class>(10);
+    private static Map<Class, Constructor[]> CLASS_CONSTRUCTOR_CACHE = new WeakHashMap<Class, Constructor[]>(10);
+
+    private static Class createClass(String className) throws ClassNotFoundException {
+        if (CLASS_RESOLVER_CACHE.containsKey(className))
+            return CLASS_RESOLVER_CACHE.get(className);
+        else {
+            Class cls = Class.forName(className);
+            CLASS_RESOLVER_CACHE.put(className, cls);
+            return cls;
+        }
+    }
+
+    private static Constructor[] getConstructors(Class cls) {
+        if (CLASS_CONSTRUCTOR_CACHE.containsKey(cls))
+            return CLASS_CONSTRUCTOR_CACHE.get(cls);
+        else {
+            Constructor[] cns = cls.getConstructors();
+            CLASS_CONSTRUCTOR_CACHE.put(cls, cns);
+            return cns;
+        }
+    }
+
+    public static Object constructObject(String expression, Object ctx, VariableResolverFactory vrf)
+            throws InstantiationException, IllegalAccessException, InvocationTargetException,
+            ClassNotFoundException {
+
+        String[] constructorParms = parseMethodOrConstructor(expression.toCharArray());
+
+        if (constructorParms != null) {
+            Class cls = Token.LITERALS.containsKey(expression = expression.substring(0, expression.indexOf('('))) ?
+                    ((Class) Token.LITERALS.get(expression)) : createClass(expression);
+
+            Object[] parms = new Object[constructorParms.length];
+            for (int i = 0; i < constructorParms.length; i++) {
+                parms[i] = (eval(constructorParms[i], ctx, vrf));
+            }
+
+            Constructor cns = getBestConstructorCanadidate(parms, cls);
+
+            if (cns == null)
+                throw new CompileException("unable to find constructor for: " + cls.getName());
+
+            for (int i = 0; i < parms.length; i++) {
+                //noinspection unchecked
+                parms[i] = convert(parms[i], cns.getParameterTypes()[i]);
+            }
+
+            return cns.newInstance(parms);
+        }
+        else {
+            return forName(expression).newInstance();
+        }
+    }
+
+    public static String[] captureContructorAndResidual(String token) {
+        char[] cs = token.toCharArray();
+
+        int depth = 0;
+
+        for (int i = 0; i < cs.length; i++) {
+            switch (cs[i]) {
+                case'(':
+                    depth++;
+                    continue;
+                case')':
+                    if (1 == depth--) {
+                        return new String[]{new String(cs, 0, ++i), new String(cs, i, cs.length - i)};
+                    }
+            }
+        }
+        return new String[]{token};
+    }
+
+    public static Class boxPrimitive(Class cls) {
+        if (cls == int.class) {
+            return Integer.class;
+        }
+        else if (cls == int[].class) {
+            return Integer[].class;
+        }
+        else if (cls == long.class) {
+            return Long.class;
+        }
+        else if (cls == long[].class) {
+            return Long[].class;
+        }
+        else if (cls == short.class) {
+            return Short.class;
+        }
+        else if (cls == short[].class) {
+            return Short[].class;
+        }
+        else if (cls == double.class) {
+            return Double.class;
+        }
+        else if (cls == double[].class) {
+            return Double[].class;
+        }
+        else if (cls == float.class) {
+            return Float.class;
+        }
+        else if (cls == float[].class) {
+            return Float[].class;
+        }
+        else if (cls == boolean.class) {
+            return Boolean.class;
+        }
+        else if (cls == boolean[].class) {
+            return Boolean[].class;
+        }
+        else if (cls == byte.class) {
+            return Byte.class;
+        }
+        else if (cls == byte[].class) {
+            return Byte[].class;
+        }
+
+        return null;
+    }
+
+    public static boolean containsCheck(Object compareTo, Object compareTest) {
+        if (compareTo == null)
+            return false;
+        else if (compareTo instanceof String)
+            return ((String) compareTo).contains(String.valueOf(compareTest));
+        else if (compareTo instanceof Collection)
+            return ((Collection) compareTo).contains(compareTest);
+        else if (compareTo instanceof Map)
+            return ((Map) compareTo).containsKey(compareTest);
+        else if (compareTo.getClass().isArray()) {
+            for (Object o : ((Object[]) compareTo)) {
+                if (compareTest == null && o == null) return true;
+                else if (o != null && o.equals(compareTest)) return true;
+            }
+        }
+        return false;
+    }
+
+    public static int createClassSignatureHash(Class[] sig) {
+        int hash = 0;
+        for (Class cls : sig) {
+            if (cls != null) hash += cls.hashCode();
+        }
+        return hash + sig.length;
+    }
+
+    public static char handleEscapeSequence(char escapedChar) {
+        switch (escapedChar) {
+            case'\\':
+                return '\\';
+            case't':
+                return '\t';
+            case'r':
+                return '\r';
+            case'\'':
+                return '\'';
+            case'"':
+                return '"';
+            default:
+                throw new ParseException("illegal escape sequence: " + escapedChar);
+        }
+    }
+
+    public static void main(String[] args) {
+        for (Package p : Package.getPackages()) {
+            System.out.println(p);
+        }
+    }
+
+    public static boolean debug(String str) {
+        System.out.println(str);
+        return true;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/PropertyTools.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/PropertyTools.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/PropertyTools.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,367 @@
+package org.mvel.util;
+
+
+import static java.lang.String.valueOf;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import static java.lang.reflect.Modifier.PUBLIC;
+import static java.lang.reflect.Modifier.isPublic;
+import java.math.BigDecimal;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+import static java.util.regex.Pattern.compile;
+
+public class PropertyTools {
+    private static final Pattern truePattern = compile("(on|yes|true|1|hi|high|y)");
+    public static final Pattern ognlStatement = compile("[{}\\[\\]'\"]");
+
+    public static Object[] arrayWrap(Object o) {
+        if (o == null) return null;
+        if (o.getClass().isArray()) return (Object[]) o;
+        return new Object[]{o};
+    }
+
+    public static Object arrayUnwrap(Object o) {
+        if (o == null) return null;
+        if (o.getClass().isArray()) {
+            return ((Object[]) o)[0];
+        }
+        return o;
+    }
+
+    /**
+     * Converts a standard wildcard string to a compiled regular expression.
+     *
+     * @param wildcard - a wildcard expression.
+     * @return compiled expr.
+     */
+    public static Pattern wildcardToRegex(String wildcard) {
+        return compile(wildcard
+                .replaceAll("(\\*|%)", ".+")
+                .replaceAll("\\.", "\\.")
+                .replaceAll("\\?", "."));
+    }
+
+    /**
+     * Queries a map based on the specified wildcard and returns a Map containing
+     * only matching elements.
+     *
+     * @param wildcard a wildcard expression
+     * @param map      a map
+     * @return Map
+     */
+    public static <K, V> Map<K, V> mapQuery(String wildcard, Map<K, V> map) {
+        Pattern qPattern = wildcardToRegex(wildcard);
+
+        if (map == null) return null;
+        Map<K, V> newMap = new HashMap<K, V>(map.size() * 2);
+
+        for (K name : map.keySet()) {
+            if (qPattern.matcher(valueOf(name)).find())
+                newMap.put(name, map.get(name));
+        }
+
+        return newMap;
+    }
+
+    public static boolean isEmptyOrWhitespace(Object o) {
+        return (o == null || isEmpty(String.valueOf(o).trim()));
+    }
+
+    public static boolean isEmpty(Object o) {
+        if (o != null) {
+            if (o instanceof Object[]) {
+                return ((Object[]) o).length == 0 ||
+                        (((Object[]) o).length == 1 && isEmpty(((Object[]) o)[0]));
+            }
+            else {
+                return ("".equals(valueOf(o)))
+                        || "null".equals(valueOf(o))
+                        || (o instanceof Collection && ((Collection) o).size() == 0)
+                        || (o instanceof Map && ((Map) o).size() == 0);
+            }
+        }
+        return true;
+    }
+
+    public static boolean valueInArray(Object[] array, Object value) {
+        if (array.length == 0) return false;
+        for (Object aArray : array) {
+            if (aArray.equals(value)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean safeEquals(Object one, Object two) {
+        return !((one == null) ^ (two == null)) && (one == null || one.equals(two));
+    }
+
+    public static boolean parseBoolean(Object value) {
+        return truePattern.matcher(valueOf(value).toLowerCase()).matches();
+    }
+
+    public static Method getSetter(Class clazz, String property) {
+        String setter = ReflectionUtil.getSetter(property);
+
+        for (Method meth : clazz.getDeclaredMethods()) {
+            if ((meth.getModifiers() & PUBLIC) == 0
+                    && meth.getParameterTypes().length != 0) continue;
+
+            if (setter.equals(meth.getName())) {
+                return meth;
+            }
+        }
+
+        return null;
+
+    }
+
+    public static boolean hasGetter(Field field) {
+        Method meth = getGetter(field.getDeclaringClass(), field.getName());
+        return meth != null && field.getType().isAssignableFrom(meth.getReturnType());
+    }
+
+    public static boolean hasSetter(Field field) {
+        Method meth = getSetter(field.getDeclaringClass(), field.getName());
+        return meth != null && meth.getParameterTypes().length == 1 &&
+                field.getType().isAssignableFrom(meth.getParameterTypes()[0]);
+    }
+
+    public static Method getGetter(Class clazz, String property) {
+        String get = ReflectionUtil.getGetter(property);
+        String isGet = ReflectionUtil.getIsGetter(property);
+
+        for (Method meth : clazz.getDeclaredMethods()) {
+            if ((meth.getModifiers() & PUBLIC) == 0
+                    || meth.getParameterTypes().length != 0
+                    ) {
+            }
+            else if (get.equals(meth.getName()) ||
+                    isGet.equals(meth.getName())) {
+                return meth;
+            }
+        }
+
+        return null;
+    }
+
+    public static boolean isPropertyReadAndWrite(Field field) {
+        return isPublic(field.getModifiers()) || hasGetter(field) && hasSetter(field);
+    }
+
+    public static boolean isPropertyReadAndWrite(Class clazz, String property) {
+        return getWritableFieldOrAccessor(clazz, property) != null &&
+                getFieldOrAccessor(clazz, property) != null;
+    }
+
+    public static Member getWritableFieldOrAccessor(Class clazz, String property) {
+        Field field;
+        try {
+            if ((field = clazz.getField(property)) != null &&
+                    isPublic(field.getModifiers())) return field;
+        }
+        catch (NullPointerException e) {
+            return null;
+        }
+        catch (NoSuchFieldException e) {
+            // do nothing.
+        }
+
+        return getSetter(clazz, property);
+    }
+
+    public static Member getFieldOrAccessor(Class clazz, String property) {
+        if (property.charAt(property.length() - 1) == ')') return getGetter(clazz, property);
+
+        try {
+            Field fld = clazz.getField(property);
+
+            if ((fld.getModifiers() & PUBLIC) != 0) return fld;
+        }
+        catch (Exception e) {
+            // do nothing.
+        }
+        return getGetter(clazz, property);
+    }
+
+    public static Member getFieldOrWriteAccessor(Class clazz, String property) {
+        Field field;
+        try {
+            if ((field = clazz.getField(property)) != null &&
+                    isPublic(field.getModifiers())) {
+                return field;
+            }
+        }
+        catch (NullPointerException e) {
+            return null;
+        }
+        catch (NoSuchFieldException e) {
+            // do nothing.
+        }
+
+        return getSetter(clazz, property);
+    }
+
+  
+    public static boolean isNumeric(Object val) {
+        if (val == null) return false;
+
+        Class clz;
+        if (val instanceof Class) {
+            clz = (Class) val;
+        }
+        else {
+            clz = val.getClass();
+        }
+
+        return clz == int.class || clz == long.class || clz == short.class || clz == double.class ||
+                clz == float.class || Number.class.isAssignableFrom(clz);
+
+    }
+
+    public static boolean isNumber(char[] val) {
+        int len = val.length;
+        char c;
+        int i = 0;
+        if (len > 1) {
+            if (val[0] == '-') i++;
+            else if (val[0] == '~') {
+                i++;
+                if (val[1] == '-') i++;
+            }
+        }
+        for (; i < len; i++) {
+            if (!isDigit(c = val[i]) && c != '.') return false;
+        }
+
+        return len > 0;      
+    }
+
+
+    public static boolean isNumber(Object val) {
+        if (val == null) return false;
+        if (val instanceof String) return isNumber((String) val);
+        if (val instanceof char[]) return isNumber((char[]) val);
+        return val instanceof Integer || val instanceof BigDecimal
+                || val instanceof Float || val instanceof Double || val instanceof Long
+                || val instanceof Short;
+    }
+   
+    public static boolean isNumber(final String val) {
+        int len = val.length();
+        char[] a = val.toCharArray();
+        char c;
+        int i = 0;
+        if (len > 1) {
+            if (a[0] == '-') i++;
+            else if (a[0] == '~') {
+                i++;
+                if (a[1] == '-') i++;
+            }
+        }
+        for (; i < len; i++) {
+            if (!isDigit(c = a[i]) && c != '.') return false;
+        }
+
+        return len > 0;
+    }
+
+    public static boolean contains(Object toCompare, Object testValue) {
+        if (toCompare == null)
+            return false;
+        else if (toCompare instanceof String)
+            return ((String) toCompare).contains(valueOf(testValue));
+        else if (toCompare instanceof Collection)
+            return ((Collection) toCompare).contains(testValue);
+        else if (toCompare instanceof Map)
+            return ((Map) toCompare).containsKey(testValue);
+        else if (toCompare.getClass().isArray()) {
+            for (Object o : ((Object[]) toCompare)) {
+                if (testValue == null && o == null) return true;
+                else if (o != null && o.equals(testValue)) return true;
+            }
+        }
+        return false;
+    }
+
+    public static int find(char[] c, char find) {
+        for (int i = 0; i < c.length; i++) if (c[i] == find) return i;
+        return -1;
+    }
+
+    public static boolean equals(char[] obj1, String obj2) {
+        for (int i = 0; i < obj1.length && i < obj2.length(); i++) {
+            if (obj1[i] == obj2.charAt(i)) return false;
+        }
+        return true;
+    }
+
+
+    public static boolean isIdentifierPart(final int c) {
+        return ((c >= 97 && c <= 122)
+                || (c >= 65 && c <= 90) || (c >= 48 && c <= 57) || (c == '_') || (c == '$'));
+    }
+
+    public static boolean isDigit(final int c) {
+        return c >= '0' && c <= '9';
+    }
+
+
+    public static float similarity(String s1, String s2) {
+        if (s1 == null || s2 == null)
+            return s1 == null && s2 == null ? 1f : 0f;
+
+        char[] c1 = s1.toCharArray();
+        char[] c2 = s2.toCharArray();
+        
+        char[] comp;
+        char[] against;
+
+        float same = 0;
+        float baselength;
+
+        int cur1 = 0;
+        //      int cur2 = 0;
+
+        if (c1.length > c2.length) {
+            baselength = c1.length;
+            comp = c1;
+            against = c2;
+        }
+        else {
+            baselength = c2.length;
+            comp = c2;
+            against = c1;
+        }
+
+
+        while (cur1 < comp.length && cur1 < against.length) {
+            if (comp[cur1] == against[cur1]) {
+                same++;
+            }
+
+            cur1++;
+        }
+
+        if (c1.length != c2.length) {
+            cur1--;
+            int offset = c2.length - c1.length;
+
+            while (cur1 > 0) {
+                if (comp[cur1] == against[cur1 - offset]) {
+                    same++;
+                }
+
+                cur1--;
+            }
+        }
+
+        return same / baselength;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ReflectionUtil.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ReflectionUtil.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ReflectionUtil.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,144 @@
+package org.mvel.util;
+
+import static java.util.regex.Pattern.compile;
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+import java.util.regex.Pattern;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * Utilities for working with reflection.
+ */
+public class ReflectionUtil {
+
+    /**
+     * This new method 'slightly' outperforms the old method, it was
+     * essentially a perfect example of me wasting my time and a
+     * premature optimization.  But what the hell...
+     *
+     * @param s
+     * @return String
+     */
+    public static String getSetter(String s) {
+        char[] chars = new char[s.length() + 3];
+
+        chars[0] = 's';
+        chars[1] = 'e';
+        chars[2] = 't';
+
+        if (s.charAt(0) > 'Z')
+            chars[3] = (char) (s.charAt(0) - ('z' - 'Z'));
+
+        for (int i = s.length() - 1; i != 0; i--) {
+            chars[i + 3] = s.charAt(i);
+        }
+
+        return new String(chars);
+    }
+
+
+
+    public static String getGetter(String s) {
+        char[] c = s.toCharArray();
+        char[] chars = new char[c.length + 3];
+
+        chars[0] = 'g';
+        chars[1] = 'e';
+        chars[2] = 't';
+
+        if (s.charAt(0) > 'Z')
+            chars[3] = (char) (c[0] - ('z' - 'Z'));
+
+        System.arraycopy(c, 1, chars, 4, c.length - 1);
+
+        return new String(chars);
+    }
+
+
+    public static String getIsGetter(String s) {
+        char[] c = s.toCharArray();
+        char[] chars = new char[c.length + 2];
+
+        chars[0] = 'i';
+        chars[1] = 's';
+
+        if (s.charAt(0) > 'Z')
+            chars[2] = (char) (s.charAt(0) - ('z' - 'Z'));
+
+        System.arraycopy(c, 1, chars, 3, c.length - 1);        
+
+        return new String(chars);
+    }
+
+    public static String parameterizeClassName(String s) {
+        char[] chars = s.toCharArray();
+        if (s.charAt(0) < 'a') {
+            chars[0] = (char) (s.charAt(0) + ('z' - 'Z'));
+        }
+
+        return new String(chars);
+    }
+
+    public static String parameterizeClassName(Class c) {
+        return parameterizeClassName(c.getName().substring(c.getName().lastIndexOf('.')+1));
+    }
+
+
+    public static String getParameterFromAccessor(String s) {
+        if (s.charAt(0) == 'i') {
+            char[] chars = new char[s.length() - 2];
+
+            for (int i = chars.length; i > 0; i--) {
+                chars[i - 1] = s.charAt(i + 1);
+            }
+
+            if (s.charAt(2) < 'a') {
+                chars[0] = (char) (s.charAt(2) + ('z' - 'Z'));
+            }
+
+            return new String(chars);
+        }
+        else {
+            char[] chars = new char[s.length() - 3];
+
+            for (int i = chars.length; i > 0; i--) {
+                chars[i - 1] = s.charAt(i + 2);
+            }
+
+            if (s.charAt(3) < 'a') {
+                chars[0] = (char) (s.charAt(3) + ('z' - 'Z'));
+            }
+
+            return new String(chars);
+        }
+    }
+
+    static final Pattern GETTER_PATTERN = compile("^compileGetChain.+");
+    public static boolean isAccessor(Method method) {
+        if (method == null) return false;
+        return GETTER_PATTERN.matcher(method.getName()).matches()
+                && method.getReturnType() != null;
+    }
+
+    public static boolean isAssignable(Object instance, Class interfaceClass) {
+        if (instance == null) return false;
+        Class ref = instance.getClass();
+
+        while (ref != Object.class) {
+            if (interfaceClass.isAssignableFrom(ref)) return true;
+            ref = ref.getSuperclass();
+        }
+
+        return false;
+    }
+
+    public static Set<Field> getAllFields(Class cls) {
+        Set<Field> allFields = new HashSet<Field>(cls.getFields().length + cls.getDeclaredFields().length, 1.0f);
+
+        for (Field fld : cls.getFields()) allFields.add(fld);
+        for (Field fld : cls.getDeclaredFields()) allFields.add(fld);
+
+        return allFields;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/Sandbox.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/Sandbox.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/Sandbox.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,27 @@
+package org.mvel.util;
+
+public class Sandbox {
+    public static final int TEST = 1 << 1;
+
+    public static void main(String[] args) {
+        boolean bool;
+        boolean second = true;
+
+        int field = 10;
+
+        long tm = System.currentTimeMillis();
+        for (int i = 0; i < 1000000000; i++) {
+            bool = (field & TEST) != 0;
+        }
+        System.out.println(System.currentTimeMillis() - tm);
+
+        tm = System.currentTimeMillis();
+        for (int i = 0; i < 1000000000; i++) {
+            bool = second ? false : true;
+        }
+        System.out.println(System.currentTimeMillis() - tm);
+
+
+    }
+
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ShadowingExecutionStack.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ShadowingExecutionStack.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/ShadowingExecutionStack.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,73 @@
+package org.mvel.util;
+
+public final class ShadowingExecutionStack implements Stack {
+    private StackElement element;
+    private StackElement shadowElement;
+
+    public ShadowingExecutionStack() {
+    }
+
+
+    private int size = 0;
+
+    public boolean isEmpty() {
+        return element == null;
+    }
+
+    public void push(Object o) {
+        size++;
+        element = new StackElement(element, o);
+        shadowElement = new StackElement(shadowElement, o);
+    }
+
+
+    public Object pushAndPeek(Object o) {
+        size++;
+        element = new StackElement(element, o);
+        shadowElement = new StackElement(shadowElement, o);
+        return o;
+    }
+
+
+    public void discard() {
+
+    }
+
+    public void push(Object obj1, Object obj2) {
+
+    }
+
+    public void push(Object obj1, Object obj2, Object obj3) {
+
+    }
+
+    public Object peek() {
+        if (size == 0) return null;
+        else return element.value;
+    }
+
+    public Object pop() {
+        if (size == 0) return null;
+        size--;
+        Object el = element.value;
+        element = element.next;
+        return el;
+    }
+
+    public int size() {
+        return size;
+    }
+
+    public void clear() {
+        size = 0;
+        element = null;
+    }
+
+    public void showStack() {
+        Object el = element;
+        do {
+            System.out.println("->" + ((StackElement) el).value);
+        }
+        while ((el = element.next) != null);
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/Stack.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/Stack.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/Stack.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,18 @@
+package org.mvel.util;
+
+public interface Stack {
+    public boolean isEmpty();
+    public Object peek();
+
+    public void push(Object obj);
+    public Object pushAndPeek(Object obj);
+    public void push(Object obj1, Object obj2);
+    public void push(Object obj1, Object obj2, Object obj3);
+
+    public Object pop();
+    public void discard();
+    public void clear();
+    public int size();
+
+    public void showStack();
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/StackElement.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/StackElement.java	2007-01-07 20:00:51 UTC (rev 8754)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/mvel/util/StackElement.java	2007-01-07 20:50:16 UTC (rev 8755)
@@ -0,0 +1,11 @@
+package org.mvel.util;
+
+public class StackElement {
+    public StackElement(StackElement next, Object value) {
+        this.next = next;
+        this.value = value;
+    }
+
+    public StackElement next;
+    public Object value;
+}




More information about the jboss-svn-commits mailing list