[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