You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ar...@apache.org on 2007/08/06 15:56:49 UTC

svn commit: r563138 - in /incubator/qpid/trunk/qpid/java/common: ./ src/main/grammar/ src/main/java/org/apache/qpidity/filter/

Author: arnaudsimon
Date: Mon Aug  6 06:56:47 2007
New Revision: 563138

URL: http://svn.apache.org/viewvc?view=rev&rev=563138
Log:
moved from client

Added:
    incubator/qpid/trunk/qpid/java/common/src/main/grammar/
    incubator/qpid/trunk/qpid/java/common/src/main/grammar/SelectorParser.jj
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ArithmeticExpression.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BinaryExpression.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BooleanExpression.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ComparisonExpression.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ConstantExpression.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/Expression.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/JMSSelectorFilter.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/LogicExpression.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/MessageFilter.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/PropertyExpression.java   (with props)
    incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/UnaryExpression.java   (with props)
Modified:
    incubator/qpid/trunk/qpid/java/common/pom.xml

Modified: incubator/qpid/trunk/qpid/java/common/pom.xml
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/pom.xml?view=diff&rev=563138&r1=563137&r2=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/pom.xml (original)
+++ incubator/qpid/trunk/qpid/java/common/pom.xml Mon Aug  6 06:56:47 2007
@@ -97,6 +97,26 @@
                     </execution>
                 </executions>
             </plugin>
+            
+            <!-- Generates message selector grammar --> 
+              <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>javacc-maven-plugin</artifactId>
+                <version>2.0</version>
+                <executions>
+                    <execution>
+                        <phase>generate-sources</phase>
+                        <configuration>
+                            <sourceDirectory>${basedir}/src/main/grammar</sourceDirectory>
+                            <outputDirectory>${project.build.directory}/generated-sources/selector</outputDirectory>
+                            <packageName>org.apache.qpidity.filter.selector</packageName>
+                        </configuration>
+                        <goals>
+                            <goal>javacc</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
 
             <!-- Backports the module to Java 1.4. This is done during the packaging phase as a transformation of the Jar. -->
             <plugin>
@@ -171,6 +191,10 @@
             <artifactId>retrotranslator-runtime</artifactId>
             <scope>provided</scope>
         </dependency>
-
+			<!--- This is used by filter -->
+ 			<dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-jms_1.1_spec</artifactId>
+        </dependency>
     </dependencies>
 </project>

Added: incubator/qpid/trunk/qpid/java/common/src/main/grammar/SelectorParser.jj
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/grammar/SelectorParser.jj?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/grammar/SelectorParser.jj (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/grammar/SelectorParser.jj Mon Aug  6 06:56:47 2007
@@ -0,0 +1,592 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+ //
+ // Original File from r450141 of the Apache ActiveMQ project <http://www.activemq.org/site/home.html>
+ //
+
+// ----------------------------------------------------------------------------
+// OPTIONS
+// ----------------------------------------------------------------------------
+options {
+  STATIC = false;
+  UNICODE_INPUT = true;
+
+  // some performance optimizations
+  OPTIMIZE_TOKEN_MANAGER = true;
+  ERROR_REPORTING = false;
+}
+
+// ----------------------------------------------------------------------------
+// PARSER
+// ----------------------------------------------------------------------------
+
+PARSER_BEGIN(SelectorParser)
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpidity.filter.selector;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+
+import org.apache.qpidity.QpidException;
+import org.apache.qpidity.filter.ArithmeticExpression;
+import org.apache.qpidity.filter.BooleanExpression;
+import org.apache.qpidity.filter.ComparisonExpression;
+import org.apache.qpidity.filter.ConstantExpression;
+import org.apache.qpidity.filter.Expression;
+import org.apache.qpidity.filter.LogicExpression;
+import org.apache.qpidity.filter.PropertyExpression;
+import org.apache.qpidity.filter.UnaryExpression;
+
+/**
+ * JMS Selector Parser generated by JavaCC
+ *
+ * Do not edit this .java file directly - it is autogenerated from SelectorParser.jj
+ */
+public class SelectorParser {
+
+    public SelectorParser() {
+        this(new StringReader(""));
+    }
+
+    public BooleanExpression parse(String sql) throws QpidException {
+        this.ReInit(new StringReader(sql));
+
+        try {
+            return this.JmsSelector();
+        }
+        catch (Throwable e) {
+	        throw new QpidException(sql,"filter error",e);
+        }
+
+    }
+
+    private BooleanExpression asBooleanExpression(Expression value) throws ParseException  {
+        if (value instanceof BooleanExpression) {
+            return (BooleanExpression) value;
+        }
+        if (value instanceof PropertyExpression) {
+            return UnaryExpression.createBooleanCast( value );
+        }
+        throw new ParseException("Expression will not result in a boolean value: " + value);
+    }
+
+
+}
+
+PARSER_END(SelectorParser)
+
+// ----------------------------------------------------------------------------
+// Tokens
+// ----------------------------------------------------------------------------
+
+/* White Space */
+SPECIAL_TOKEN :
+{
+  " " | "\t" | "\n" | "\r" | "\f"
+}
+
+/* Comments */
+SKIP:
+{
+  <LINE_COMMENT: "--" (~["\n","\r"])* ("\n"|"\r"|"\r\n") >
+}
+
+SKIP:
+{
+  <BLOCK_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
+}
+
+/* Reserved Words */
+TOKEN [IGNORE_CASE] :
+{
+    <  NOT     : "NOT">
+  | <  AND     : "AND">
+  | <  OR      : "OR">
+  | <  BETWEEN : "BETWEEN">
+  | <  LIKE    : "LIKE">
+  | <  ESCAPE  : "ESCAPE">
+  | <  IN      : "IN">
+  | <  IS      : "IS">
+  | <  TRUE    : "TRUE" >
+  | <  FALSE   : "FALSE" >
+  | <  NULL    : "NULL" >  
+}
+
+/* Literals */
+TOKEN [IGNORE_CASE] :
+{
+
+    < DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* (["l","L"])? >
+  | < HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
+  | < OCTAL_LITERAL: "0" (["0"-"7"])* >
+  | < FLOATING_POINT_LITERAL:
+          (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? // matches: 5.5 or 5. or 5.5E10 or 5.E10
+        | "." (["0"-"9"])+ (<EXPONENT>)?              // matches: .5 or .5E10
+        | (["0"-"9"])+ <EXPONENT>                     // matches: 5E10
+    >
+  | < #EXPONENT: "E" (["+","-"])? (["0"-"9"])+ >
+  | < STRING_LITERAL: "'" ( ("''") | ~["'"] )*  "'" >
+}
+
+TOKEN [IGNORE_CASE] :
+{
+    < ID : ["a"-"z", "_", "$"] (["a"-"z","0"-"9","_", "$"])* >
+}
+
+// ----------------------------------------------------------------------------
+// Grammer
+// ----------------------------------------------------------------------------
+BooleanExpression JmsSelector() :
+{
+    Expression left=null;
+}
+{
+    (
+        left = orExpression()
+    )
+    {
+        return asBooleanExpression(left);
+    }
+
+}
+
+Expression orExpression() :
+{
+    Expression left;
+    Expression right;
+}
+{
+    (
+        left = andExpression()
+        (
+            <OR> right = andExpression()
+            {
+                left = LogicExpression.createOR(asBooleanExpression(left), asBooleanExpression(right));
+            }
+        )*
+    )
+    {
+        return left;
+    }
+
+}
+
+
+Expression andExpression() :
+{
+    Expression left;
+    Expression right;
+}
+{
+    (
+        left = equalityExpression()
+        (
+            <AND> right = equalityExpression()
+            {
+                left = LogicExpression.createAND(asBooleanExpression(left), asBooleanExpression(right));
+            }
+        )*
+    )
+    {
+        return left;
+    }
+}
+
+Expression equalityExpression() :
+{
+    Expression left;
+    Expression right;
+}
+{
+    (
+        left = comparisonExpression()
+        (
+
+            "=" right = comparisonExpression()
+            {
+                left = ComparisonExpression.createEqual(left, right);
+            }
+            |
+            "<>" right = comparisonExpression()
+            {
+                left = ComparisonExpression.createNotEqual(left, right);
+            }
+            |
+            LOOKAHEAD(2)
+            <IS> <NULL>
+            {
+                left = ComparisonExpression.createIsNull(left);
+            }
+            |
+            <IS> <NOT> <NULL>
+            {
+                left = ComparisonExpression.createIsNotNull(left);
+            }
+        )*
+    )
+    {
+        return left;
+    }
+}
+
+Expression comparisonExpression() :
+{
+    Expression left;
+    Expression right;
+    Expression low;
+    Expression high;
+    String t, u;
+	boolean not;
+	ArrayList list;
+}
+{
+    (
+        left = addExpression()
+        (
+
+                ">" right = addExpression()
+                {
+                    left = ComparisonExpression.createGreaterThan(left, right);
+                }
+            |
+                ">=" right = addExpression()
+                {
+                    left = ComparisonExpression.createGreaterThanEqual(left, right);
+                }
+            |
+                "<" right = addExpression()
+                {
+                    left = ComparisonExpression.createLessThan(left, right);
+                }
+            |
+                "<=" right = addExpression()
+                {
+                    left = ComparisonExpression.createLessThanEqual(left, right);
+                }
+           |
+				{
+					u=null;
+				}
+		        <LIKE> t = stringLitteral()
+		        	[ <ESCAPE> u = stringLitteral() ]
+		        {
+                    left = ComparisonExpression.createLike(left, t, u);
+		        }
+           |
+	        	LOOKAHEAD(2)
+				{
+					u=null;
+				}
+		        <NOT> <LIKE> t = stringLitteral() [ <ESCAPE> u = stringLitteral() ]
+		        {
+                    left = ComparisonExpression.createNotLike(left, t, u);
+		        }
+            |
+		        <BETWEEN> low = addExpression() <AND> high = addExpression()
+		        {
+					left = ComparisonExpression.createBetween(left, low, high);
+		        }
+	        |
+	        	LOOKAHEAD(2)
+		        <NOT> <BETWEEN> low = addExpression() <AND> high = addExpression()
+		        {
+					left = ComparisonExpression.createNotBetween(left, low, high);
+		        }
+            |
+				<IN>
+		        "("
+		            t = stringLitteral()
+		            {
+			            list = new ArrayList();
+			            list.add( t );
+		            }
+			        (
+			        	","
+			            t = stringLitteral()
+			            {
+				            list.add( t );
+			            }
+
+			        )*
+		        ")"
+		        {
+		           left = ComparisonExpression.createInFilter(left, list);
+		        }
+            |
+	        	LOOKAHEAD(2)
+	            <NOT> <IN>
+		        "("
+		            t = stringLitteral()
+		            {
+			            list = new ArrayList();
+			            list.add( t );
+		            }
+			        (
+			        	","
+			            t = stringLitteral()
+			            {
+				            list.add( t );
+			            }
+
+			        )*
+		        ")"
+		        {
+		           left = ComparisonExpression.createNotInFilter(left, list);
+		        }
+
+        )*
+    )
+    {
+        return left;
+    }
+}
+
+Expression addExpression() :
+{
+    Expression left;
+    Expression right;
+}
+{
+    left = multExpr()
+    (
+	    LOOKAHEAD( ("+"|"-") multExpr())
+	    (
+	        "+" right = multExpr()
+	        {
+	            left = ArithmeticExpression.createPlus(left, right);
+	        }
+	        |
+	        "-" right = multExpr()
+	        {
+	            left = ArithmeticExpression.createMinus(left, right);
+	        }
+        )
+
+    )*
+    {
+        return left;
+    }
+}
+
+Expression multExpr() :
+{
+    Expression left;
+    Expression right;
+}
+{
+    left = unaryExpr()
+    (
+        "*" right = unaryExpr()
+        {
+	        left = ArithmeticExpression.createMultiply(left, right);
+        }
+        |
+        "/" right = unaryExpr()
+        {
+	        left = ArithmeticExpression.createDivide(left, right);
+        }
+        |
+        "%" right = unaryExpr()
+        {
+	        left = ArithmeticExpression.createMod(left, right);
+        }
+
+    )*
+    {
+        return left;
+    }
+}
+
+
+Expression unaryExpr() :
+{
+    String s=null;
+    Expression left=null;
+}
+{
+	(
+		LOOKAHEAD( "+" unaryExpr() )
+	    "+" left=unaryExpr()
+	    |
+	    "-" left=unaryExpr()
+	    {
+	        left = UnaryExpression.createNegate(left);
+	    }
+	    |
+	    <NOT> left=unaryExpr()
+	    {
+		    left = UnaryExpression.createNOT( asBooleanExpression(left) );
+	    }
+	    |	   
+	    left = primaryExpr()
+    )
+    {
+        return left;
+    }
+
+}
+
+Expression primaryExpr() :
+{
+    Expression left=null;
+}
+{
+    (
+        left = literal()
+        |
+        left = variable()
+        |
+        "(" left = orExpression() ")"
+    )
+    {
+        return left;
+    }
+}
+
+
+
+ConstantExpression literal() :
+{
+    Token t;
+    String s;
+    ConstantExpression left=null;
+}
+{
+    (
+        (
+            s = stringLitteral()
+            {
+                left = new ConstantExpression(s);
+            }
+        )
+        |
+        (
+            t = <DECIMAL_LITERAL>
+            {
+            	left = ConstantExpression.createFromDecimal(t.image);
+            }
+        )
+        |
+        (
+            t = <HEX_LITERAL>
+            {
+            	left = ConstantExpression.createFromHex(t.image);
+            }
+        )
+        |
+        (
+            t = <OCTAL_LITERAL>
+            {
+            	left = ConstantExpression.createFromOctal(t.image);
+            }
+        )
+        |
+        (
+            t = <FLOATING_POINT_LITERAL>
+            {
+            	left = ConstantExpression.createFloat(t.image);
+            }
+        )
+        |
+        (
+            <TRUE>
+            {
+                left = ConstantExpression.TRUE;
+            }
+        )
+        |
+        (
+            <FALSE>
+            {
+                left = ConstantExpression.FALSE;
+            }
+        )
+        |
+        (
+            <NULL>
+            {
+                left = ConstantExpression.NULL;
+            }
+        )
+    )
+    {
+        return left;
+    }
+}
+
+String stringLitteral() :
+{
+    Token t;
+    StringBuffer rc = new StringBuffer();
+    boolean first=true;
+}
+{
+    t = <STRING_LITERAL>
+    {
+    	// Decode the sting value.
+    	String image = t.image;
+    	for( int i=1; i < image.length()-1; i++ ) {
+    		char c = image.charAt(i);
+    		if( c == '\'' )
+    			i++;
+   			rc.append(c);
+    	}
+	    return rc.toString();
+    }
+}
+
+PropertyExpression variable() :
+{
+    Token t;
+    PropertyExpression left=null;
+}
+{
+    (
+        t = <ID>
+        {
+            left = new PropertyExpression(t.image);
+        }
+    )
+    {
+        return left;
+    }
+}

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ArithmeticExpression.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ArithmeticExpression.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ArithmeticExpression.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ArithmeticExpression.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,268 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.apache.qpidity.QpidException;
+
+import javax.jms.Message;
+
+/**
+ * An expression which performs an operation on two expression values
+ */
+public abstract class ArithmeticExpression extends BinaryExpression
+{
+
+    protected static final int INTEGER = 1;
+    protected static final int LONG = 2;
+    protected static final int DOUBLE = 3;
+
+
+    public ArithmeticExpression(Expression left, Expression right)
+    {
+        super(left, right);
+    }
+
+    public static Expression createPlus(Expression left, Expression right)
+    {
+        return new ArithmeticExpression(left, right)
+            {
+                protected Object evaluate(Object lvalue, Object rvalue)
+                {
+                    if (lvalue instanceof String)
+                    {
+                        String text = (String) lvalue;
+                        return text + rvalue;
+                    }
+                    else if (lvalue instanceof Number)
+                    {
+                        return plus((Number) lvalue, asNumber(rvalue));
+                    }
+
+                    throw new RuntimeException("Cannot call plus operation on: " + lvalue + " and: " + rvalue);
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "+";
+                }
+            };
+    }
+
+    public static Expression createMinus(Expression left, Expression right)
+    {
+        return new ArithmeticExpression(left, right)
+            {
+                protected Object evaluate(Object lvalue, Object rvalue)
+                {
+                    if (lvalue instanceof Number)
+                    {
+                        return minus((Number) lvalue, asNumber(rvalue));
+                    }
+
+                    throw new RuntimeException("Cannot call minus operation on: " + lvalue + " and: " + rvalue);
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "-";
+                }
+            };
+    }
+
+    public static Expression createMultiply(Expression left, Expression right)
+    {
+        return new ArithmeticExpression(left, right)
+            {
+
+                protected Object evaluate(Object lvalue, Object rvalue)
+                {
+                    if (lvalue instanceof Number)
+                    {
+                        return multiply((Number) lvalue, asNumber(rvalue));
+                    }
+
+                    throw new RuntimeException("Cannot call multiply operation on: " + lvalue + " and: " + rvalue);
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "*";
+                }
+            };
+    }
+
+    public static Expression createDivide(Expression left, Expression right)
+    {
+        return new ArithmeticExpression(left, right)
+            {
+
+                protected Object evaluate(Object lvalue, Object rvalue)
+                {
+                    if (lvalue instanceof Number)
+                    {
+                        return divide((Number) lvalue, asNumber(rvalue));
+                    }
+
+                    throw new RuntimeException("Cannot call divide operation on: " + lvalue + " and: " + rvalue);
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "/";
+                }
+            };
+    }
+
+    public static Expression createMod(Expression left, Expression right)
+    {
+        return new ArithmeticExpression(left, right)
+            {
+
+                protected Object evaluate(Object lvalue, Object rvalue)
+                {
+                    if (lvalue instanceof Number)
+                    {
+                        return mod((Number) lvalue, asNumber(rvalue));
+                    }
+
+                    throw new RuntimeException("Cannot call mod operation on: " + lvalue + " and: " + rvalue);
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "%";
+                }
+            };
+    }
+
+    protected Number plus(Number left, Number right)
+    {
+        switch (numberType(left, right))
+        {
+
+        case ArithmeticExpression.INTEGER:
+            return new Integer(left.intValue() + right.intValue());
+
+        case ArithmeticExpression.LONG:
+            return new Long(left.longValue() + right.longValue());
+
+        default:
+            return new Double(left.doubleValue() + right.doubleValue());
+        }
+    }
+
+    protected Number minus(Number left, Number right)
+    {
+        switch (numberType(left, right))
+        {
+
+        case ArithmeticExpression.INTEGER:
+            return new Integer(left.intValue() - right.intValue());
+
+        case ArithmeticExpression.LONG:
+            return new Long(left.longValue() - right.longValue());
+
+        default:
+            return new Double(left.doubleValue() - right.doubleValue());
+        }
+    }
+
+    protected Number multiply(Number left, Number right)
+    {
+        switch (numberType(left, right))
+        {
+
+        case ArithmeticExpression.INTEGER:
+            return new Integer(left.intValue() * right.intValue());
+
+        case ArithmeticExpression.LONG:
+            return new Long(left.longValue() * right.longValue());
+
+        default:
+            return new Double(left.doubleValue() * right.doubleValue());
+        }
+    }
+
+    protected Number divide(Number left, Number right)
+    {
+        return new Double(left.doubleValue() / right.doubleValue());
+    }
+
+    protected Number mod(Number left, Number right)
+    {
+        return new Double(left.doubleValue() % right.doubleValue());
+    }
+
+    private int numberType(Number left, Number right)
+    {
+        if (isDouble(left) || isDouble(right))
+        {
+            return ArithmeticExpression.DOUBLE;
+        }
+        else if ((left instanceof Long) || (right instanceof Long))
+        {
+            return ArithmeticExpression.LONG;
+        }
+        else
+        {
+            return ArithmeticExpression.INTEGER;
+        }
+    }
+
+    private boolean isDouble(Number n)
+    {
+        return (n instanceof Float) || (n instanceof Double);
+    }
+
+    protected Number asNumber(Object value)
+    {
+        if (value instanceof Number)
+        {
+            return (Number) value;
+        }
+        else
+        {
+            throw new RuntimeException("Cannot convert value: " + value + " into a number");
+        }
+    }
+
+    public Object evaluate(Message message) throws QpidException
+    {
+        Object lvalue = left.evaluate(message);
+        if (lvalue == null)
+        {
+            return null;
+        }
+
+        Object rvalue = right.evaluate(message);
+        if (rvalue == null)
+        {
+            return null;
+        }
+
+        return evaluate(lvalue, rvalue);
+    }
+
+    /**
+     * @param lvalue
+     * @param rvalue
+     * @return
+     */
+    protected abstract Object evaluate(Object lvalue, Object rvalue);
+
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ArithmeticExpression.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BinaryExpression.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BinaryExpression.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BinaryExpression.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BinaryExpression.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,103 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+/**
+ * An expression which performs an operation on two expression values.
+ */
+public abstract class BinaryExpression implements Expression
+{
+    protected Expression left;
+    protected Expression right;
+
+    public BinaryExpression(Expression left, Expression right)
+    {
+        this.left = left;
+        this.right = right;
+    }
+
+    public Expression getLeft()
+    {
+        return left;
+    }
+
+    public Expression getRight()
+    {
+        return right;
+    }
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        return "(" + left.toString() + " " + getExpressionSymbol() + " " + right.toString() + ")";
+    }
+
+    /**
+     * TODO: more efficient hashCode()
+     *
+     * @see Object#hashCode()
+     */
+    public int hashCode()
+    {
+        return toString().hashCode();
+    }
+
+    /**
+     * TODO: more efficient hashCode()
+     *
+     * @see Object#equals(Object)
+     */
+    public boolean equals(Object o)
+    {
+
+        if ((o == null) || !this.getClass().equals(o.getClass()))
+        {
+            return false;
+        }
+
+        return toString().equals(o.toString());
+
+    }
+
+    /**
+     * Returns the symbol that represents this binary expression.  For example, addition is
+     * represented by "+"
+     *
+     * @return
+     */
+    public abstract String getExpressionSymbol();
+
+    /**
+     * @param expression
+     */
+    public void setRight(Expression expression)
+    {
+        right = expression;
+    }
+
+    /**
+     * @param expression
+     */
+    public void setLeft(Expression expression)
+    {
+        left = expression;
+    }
+
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BinaryExpression.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BooleanExpression.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BooleanExpression.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BooleanExpression.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BooleanExpression.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,33 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.apache.qpidity.QpidException;
+
+import javax.jms.Message;
+
+/**
+ * A BooleanExpression is an expression that always
+ * produces a Boolean result.
+ */
+public interface BooleanExpression extends Expression
+{
+
+    public boolean matches(Message message) throws QpidException;
+
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/BooleanExpression.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ComparisonExpression.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ComparisonExpression.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ComparisonExpression.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ComparisonExpression.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,589 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.apache.qpidity.QpidException;
+
+import javax.jms.Message;
+import java.util.HashSet;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * A filter performing a comparison of two objects
+ */
+public abstract class ComparisonExpression extends BinaryExpression implements BooleanExpression
+{
+
+    public static BooleanExpression createBetween(Expression value, Expression left, Expression right)
+    {
+        return LogicExpression.createAND(ComparisonExpression.createGreaterThanEqual(value, left), ComparisonExpression.createLessThanEqual(value, right));
+    }
+
+    public static BooleanExpression createNotBetween(Expression value, Expression left, Expression right)
+    {
+        return LogicExpression.createOR(ComparisonExpression.createLessThan(value, left), ComparisonExpression.createGreaterThan(value, right));
+    }
+
+    private static final HashSet REGEXP_CONTROL_CHARS = new HashSet();
+
+    static
+    {
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('.'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('\\'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('['));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character(']'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('^'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('$'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('?'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('*'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('+'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('{'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('}'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('|'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('('));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character(')'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character(':'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('&'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('<'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('>'));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('='));
+        ComparisonExpression.REGEXP_CONTROL_CHARS.add(new Character('!'));
+    }
+
+    static class LikeExpression extends UnaryExpression implements BooleanExpression
+    {
+
+        Pattern likePattern;
+
+        /**
+         * @param right
+         */
+        public LikeExpression(Expression right, String like, int escape)
+        {
+            super(right);
+
+            StringBuffer regexp = new StringBuffer(like.length() * 2);
+            regexp.append("\\A"); // The beginning of the input
+            for (int i = 0; i < like.length(); i++)
+            {
+                char c = like.charAt(i);
+                if (escape == (0xFFFF & c))
+                {
+                    i++;
+                    if (i >= like.length())
+                    {
+                        // nothing left to escape...
+                        break;
+                    }
+
+                    char t = like.charAt(i);
+                    regexp.append("\\x");
+                    regexp.append(Integer.toHexString(0xFFFF & t));
+                }
+                else if (c == '%')
+                {
+                    regexp.append(".*?"); // Do a non-greedy match
+                }
+                else if (c == '_')
+                {
+                    regexp.append("."); // match one
+                }
+                else if (ComparisonExpression.REGEXP_CONTROL_CHARS.contains(new Character(c)))
+                {
+                    regexp.append("\\x");
+                    regexp.append(Integer.toHexString(0xFFFF & c));
+                }
+                else
+                {
+                    regexp.append(c);
+                }
+            }
+
+            regexp.append("\\z"); // The end of the input
+
+            likePattern = Pattern.compile(regexp.toString(), Pattern.DOTALL);
+        }
+
+        /**
+         *  org.apache.activemq.filter.UnaryExpression#getExpressionSymbol()
+         */
+        public String getExpressionSymbol()
+        {
+            return "LIKE";
+        }
+
+        /**
+         *  org.apache.activemq.filter.Expression#evaluate(MessageEvaluationContext)
+         */
+        public Object evaluate(Message message) throws QpidException
+        {
+
+            Object rv = this.getRight().evaluate(message);
+
+            if (rv == null)
+            {
+                return null;
+            }
+
+            if (!(rv instanceof String))
+            {
+                return
+                    Boolean.FALSE;
+                    // throw new RuntimeException("LIKE can only operate on String identifiers.  LIKE attemped on: '" + rv.getClass());
+            }
+
+            return likePattern.matcher((String) rv).matches() ? Boolean.TRUE : Boolean.FALSE;
+        }
+
+        public boolean matches(Message message) throws QpidException
+        {
+            Object object = evaluate(message);
+
+            return (object != null) && (object == Boolean.TRUE);
+        }
+    }
+
+    public static BooleanExpression createLike(Expression left, String right, String escape)
+    {
+        if ((escape != null) && (escape.length() != 1))
+        {
+            throw new RuntimeException(
+                "The ESCAPE string litteral is invalid.  It can only be one character.  Litteral used: " + escape);
+        }
+
+        int c = -1;
+        if (escape != null)
+        {
+            c = 0xFFFF & escape.charAt(0);
+        }
+
+        return new LikeExpression(left, right, c);
+    }
+
+    public static BooleanExpression createNotLike(Expression left, String right, String escape)
+    {
+        return UnaryExpression.createNOT(ComparisonExpression.createLike(left, right, escape));
+    }
+
+    public static BooleanExpression createInFilter(Expression left, List elements)
+    {
+
+        if (!(left instanceof PropertyExpression))
+        {
+            throw new RuntimeException("Expected a property for In expression, got: " + left);
+        }
+
+        return UnaryExpression.createInExpression((PropertyExpression) left, elements, false);
+
+    }
+
+    public static BooleanExpression createNotInFilter(Expression left, List elements)
+    {
+
+        if (!(left instanceof PropertyExpression))
+        {
+            throw new RuntimeException("Expected a property for In expression, got: " + left);
+        }
+
+        return UnaryExpression.createInExpression((PropertyExpression) left, elements, true);
+
+    }
+
+    public static BooleanExpression createIsNull(Expression left)
+    {
+        return ComparisonExpression.doCreateEqual(left, ConstantExpression.NULL);
+    }
+
+    public static BooleanExpression createIsNotNull(Expression left)
+    {
+        return UnaryExpression.createNOT(ComparisonExpression.doCreateEqual(left, ConstantExpression.NULL));
+    }
+
+    public static BooleanExpression createNotEqual(Expression left, Expression right)
+    {
+        return UnaryExpression.createNOT(ComparisonExpression.createEqual(left, right));
+    }
+
+    public static BooleanExpression createEqual(Expression left, Expression right)
+    {
+        ComparisonExpression.checkEqualOperand(left);
+        ComparisonExpression.checkEqualOperand(right);
+        ComparisonExpression.checkEqualOperandCompatability(left, right);
+
+        return ComparisonExpression.doCreateEqual(left, right);
+    }
+
+    private static BooleanExpression doCreateEqual(Expression left, Expression right)
+    {
+        return new ComparisonExpression(left, right)
+            {
+
+                public Object evaluate(Message message) throws QpidException
+                {
+                    Object lv = left.evaluate(message);
+                    Object rv = right.evaluate(message);
+
+                    // Iff one of the values is null
+                    if ((lv == null) ^ (rv == null))
+                    {
+                        return Boolean.FALSE;
+                    }
+
+                    if ((lv == rv) || lv.equals(rv))
+                    {
+                        return Boolean.TRUE;
+                    }
+
+                    if ((lv instanceof Comparable) && (rv instanceof Comparable))
+                    {
+                        return compare((Comparable) lv, (Comparable) rv);
+                    }
+
+                    return Boolean.FALSE;
+                }
+
+                protected boolean asBoolean(int answer)
+                {
+                    return answer == 0;
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "=";
+                }
+            };
+    }
+
+    public static BooleanExpression createGreaterThan(final Expression left, final Expression right)
+    {
+        ComparisonExpression.checkLessThanOperand(left);
+        ComparisonExpression.checkLessThanOperand(right);
+
+        return new ComparisonExpression(left, right)
+            {
+                protected boolean asBoolean(int answer)
+                {
+                    return answer > 0;
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return ">";
+                }
+            };
+    }
+
+    public static BooleanExpression createGreaterThanEqual(final Expression left, final Expression right)
+    {
+        ComparisonExpression.checkLessThanOperand(left);
+        ComparisonExpression.checkLessThanOperand(right);
+
+        return new ComparisonExpression(left, right)
+            {
+                protected boolean asBoolean(int answer)
+                {
+                    return answer >= 0;
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return ">=";
+                }
+            };
+    }
+
+    public static BooleanExpression createLessThan(final Expression left, final Expression right)
+    {
+        ComparisonExpression.checkLessThanOperand(left);
+        ComparisonExpression.checkLessThanOperand(right);
+
+        return new ComparisonExpression(left, right)
+            {
+
+                protected boolean asBoolean(int answer)
+                {
+                    return answer < 0;
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "<";
+                }
+
+            };
+    }
+
+    public static BooleanExpression createLessThanEqual(final Expression left, final Expression right)
+    {
+        ComparisonExpression.checkLessThanOperand(left);
+        ComparisonExpression.checkLessThanOperand(right);
+
+        return new ComparisonExpression(left, right)
+            {
+
+                protected boolean asBoolean(int answer)
+                {
+                    return answer <= 0;
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "<=";
+                }
+            };
+    }
+
+    /**
+     * Only Numeric expressions can be used in >, >=, < or <= expressions.s
+     *
+     * @param expr
+     */
+    public static void checkLessThanOperand(Expression expr)
+    {
+        if (expr instanceof ConstantExpression)
+        {
+            Object value = ((ConstantExpression) expr).getValue();
+            if (value instanceof Number)
+            {
+                return;
+            }
+
+            // Else it's boolean or a String..
+            throw new RuntimeException("Value '" + expr + "' cannot be compared.");
+        }
+
+        if (expr instanceof BooleanExpression)
+        {
+            throw new RuntimeException("Value '" + expr + "' cannot be compared.");
+        }
+    }
+
+    /**
+     * Validates that the expression can be used in == or <> expression.
+     * Cannot not be NULL TRUE or FALSE litterals.
+     *
+     * @param expr
+     */
+    public static void checkEqualOperand(Expression expr)
+    {
+        if (expr instanceof ConstantExpression)
+        {
+            Object value = ((ConstantExpression) expr).getValue();
+            if (value == null)
+            {
+                throw new RuntimeException("'" + expr + "' cannot be compared.");
+            }
+        }
+    }
+
+    /**
+     *
+     * @param left
+     * @param right
+     */
+    private static void checkEqualOperandCompatability(Expression left, Expression right)
+    {
+        if ((left instanceof ConstantExpression) && (right instanceof ConstantExpression))
+        {
+            if ((left instanceof BooleanExpression) && !(right instanceof BooleanExpression))
+            {
+                throw new RuntimeException("'" + left + "' cannot be compared with '" + right + "'");
+            }
+        }
+    }
+
+    /**
+     * @param left
+     * @param right
+     */
+    public ComparisonExpression(Expression left, Expression right)
+    {
+        super(left, right);
+    }
+
+    public Object evaluate(Message message) throws QpidException
+    {
+        Comparable lv = (Comparable) left.evaluate(message);
+        if (lv == null)
+        {
+            return null;
+        }
+
+        Comparable rv = (Comparable) right.evaluate(message);
+        if (rv == null)
+        {
+            return null;
+        }
+
+        return compare(lv, rv);
+    }
+
+    protected Boolean compare(Comparable lv, Comparable rv)
+    {
+        Class lc = lv.getClass();
+        Class rc = rv.getClass();
+        // If the the objects are not of the same type,
+        // try to convert up to allow the comparison.
+        if (lc != rc)
+        {
+            if (lc == Byte.class)
+            {
+                if (rc == Short.class)
+                {
+                    lv = new Short(((Number) lv).shortValue());
+                }
+                else if (rc == Integer.class)
+                {
+                    lv = new Integer(((Number) lv).intValue());
+                }
+                else if (rc == Long.class)
+                {
+                    lv = new Long(((Number) lv).longValue());
+                }
+                else if (rc == Float.class)
+                {
+                    lv = new Float(((Number) lv).floatValue());
+                }
+                else if (rc == Double.class)
+                {
+                    lv = new Double(((Number) lv).doubleValue());
+                }
+                else
+                {
+                    return Boolean.FALSE;
+                }
+            }
+            else if (lc == Short.class)
+            {
+                if (rc == Integer.class)
+                {
+                    lv = new Integer(((Number) lv).intValue());
+                }
+                else if (rc == Long.class)
+                {
+                    lv = new Long(((Number) lv).longValue());
+                }
+                else if (rc == Float.class)
+                {
+                    lv = new Float(((Number) lv).floatValue());
+                }
+                else if (rc == Double.class)
+                {
+                    lv = new Double(((Number) lv).doubleValue());
+                }
+                else
+                {
+                    return Boolean.FALSE;
+                }
+            }
+            else if (lc == Integer.class)
+            {
+                if (rc == Long.class)
+                {
+                    lv = new Long(((Number) lv).longValue());
+                }
+                else if (rc == Float.class)
+                {
+                    lv = new Float(((Number) lv).floatValue());
+                }
+                else if (rc == Double.class)
+                {
+                    lv = new Double(((Number) lv).doubleValue());
+                }
+                else
+                {
+                    return Boolean.FALSE;
+                }
+            }
+            else if (lc == Long.class)
+            {
+                if (rc == Integer.class)
+                {
+                    rv = new Long(((Number) rv).longValue());
+                }
+                else if (rc == Float.class)
+                {
+                    lv = new Float(((Number) lv).floatValue());
+                }
+                else if (rc == Double.class)
+                {
+                    lv = new Double(((Number) lv).doubleValue());
+                }
+                else
+                {
+                    return Boolean.FALSE;
+                }
+            }
+            else if (lc == Float.class)
+            {
+                if (rc == Integer.class)
+                {
+                    rv = new Float(((Number) rv).floatValue());
+                }
+                else if (rc == Long.class)
+                {
+                    rv = new Float(((Number) rv).floatValue());
+                }
+                else if (rc == Double.class)
+                {
+                    lv = new Double(((Number) lv).doubleValue());
+                }
+                else
+                {
+                    return Boolean.FALSE;
+                }
+            }
+            else if (lc == Double.class)
+            {
+                if (rc == Integer.class)
+                {
+                    rv = new Double(((Number) rv).doubleValue());
+                }
+                else if (rc == Long.class)
+                {
+                    rv = new Double(((Number) rv).doubleValue());
+                }
+                else if (rc == Float.class)
+                {
+                    rv = new Float(((Number) rv).doubleValue());
+                }
+                else
+                {
+                    return Boolean.FALSE;
+                }
+            }
+            else
+            {
+                return Boolean.FALSE;
+            }
+        }
+
+        return asBoolean(lv.compareTo(rv)) ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    protected abstract boolean asBoolean(int answer);
+
+    public boolean matches(Message message) throws QpidException
+    {
+        Object object = evaluate(message);
+
+        return (object != null) && (object == Boolean.TRUE);
+    }
+
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ComparisonExpression.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ConstantExpression.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ConstantExpression.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ConstantExpression.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ConstantExpression.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,204 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.apache.qpidity.QpidException;
+
+import javax.jms.Message;
+import java.math.BigDecimal;
+
+/**
+ * Represents a constant expression
+ */
+public class ConstantExpression implements Expression
+{
+
+    static class BooleanConstantExpression extends ConstantExpression implements BooleanExpression
+    {
+        public BooleanConstantExpression(Object value)
+        {
+            super(value);
+        }
+
+        public boolean matches(Message message) throws QpidException
+        {
+            Object object = evaluate(message);
+
+            return (object != null) && (object == Boolean.TRUE);
+        }
+    }
+
+    public static final BooleanConstantExpression NULL = new BooleanConstantExpression(null);
+    public static final BooleanConstantExpression TRUE = new BooleanConstantExpression(Boolean.TRUE);
+    public static final BooleanConstantExpression FALSE = new BooleanConstantExpression(Boolean.FALSE);
+
+    private Object value;
+
+    public static ConstantExpression createFromDecimal(String text)
+    {
+
+        // Strip off the 'l' or 'L' if needed.
+        if (text.endsWith("l") || text.endsWith("L"))
+        {
+            text = text.substring(0, text.length() - 1);
+        }
+
+        Number value;
+        try
+        {
+            value = new Long(text);
+        }
+        catch (NumberFormatException e)
+        {
+            // The number may be too big to fit in a long.
+            value = new BigDecimal(text);
+        }
+
+        long l = value.longValue();
+        if ((Integer.MIN_VALUE <= l) && (l <= Integer.MAX_VALUE))
+        {
+            value = new Integer(value.intValue());
+        }
+
+        return new ConstantExpression(value);
+    }
+
+    public static ConstantExpression createFromHex(String text)
+    {
+        Number value = new Long(Long.parseLong(text.substring(2), 16));
+        long l = value.longValue();
+        if ((Integer.MIN_VALUE <= l) && (l <= Integer.MAX_VALUE))
+        {
+            value = new Integer(value.intValue());
+        }
+
+        return new ConstantExpression(value);
+    }
+
+    public static ConstantExpression createFromOctal(String text)
+    {
+        Number value = new Long(Long.parseLong(text, 8));
+        long l = value.longValue();
+        if ((Integer.MIN_VALUE <= l) && (l <= Integer.MAX_VALUE))
+        {
+            value = new Integer(value.intValue());
+        }
+
+        return new ConstantExpression(value);
+    }
+
+    public static ConstantExpression createFloat(String text)
+    {
+        Number value = new Double(text);
+
+        return new ConstantExpression(value);
+    }
+
+    public ConstantExpression(Object value)
+    {
+        this.value = value;
+    }
+
+    public Object evaluate(Message message) throws QpidException
+    {
+        return value;
+    }
+
+    public Object getValue()
+    {
+        return value;
+    }
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        if (value == null)
+        {
+            return "NULL";
+        }
+
+        if (value instanceof Boolean)
+        {
+            return ((Boolean) value).booleanValue() ? "TRUE" : "FALSE";
+        }
+
+        if (value instanceof String)
+        {
+            return ConstantExpression.encodeString((String) value);
+        }
+
+        return value.toString();
+    }
+
+    /**
+     * TODO: more efficient hashCode()
+     *
+     * @see Object#hashCode()
+     */
+    public int hashCode()
+    {
+        return toString().hashCode();
+    }
+
+    /**
+     * TODO: more efficient hashCode()
+     *
+     * @see Object#equals(Object)
+     */
+    public boolean equals(Object o)
+    {
+
+        if ((o == null) || !this.getClass().equals(o.getClass()))
+        {
+            return false;
+        }
+
+        return toString().equals(o.toString());
+
+    }
+
+    /**
+     * Encodes the value of string so that it looks like it would look like
+     * when it was provided in a selector.
+     *
+     * @param s
+     * @return
+     */
+    public static String encodeString(String s)
+    {
+        StringBuffer b = new StringBuffer();
+        b.append('\'');
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+            if (c == '\'')
+            {
+                b.append(c);
+            }
+
+            b.append(c);
+        }
+
+        b.append('\'');
+
+        return b.toString();
+    }
+
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/ConstantExpression.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/Expression.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/Expression.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/Expression.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/Expression.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,34 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.apache.qpidity.QpidException;
+
+import javax.jms.Message;
+
+/**
+ * Represents an expression
+ */
+public interface Expression
+{
+    /**
+     * @param message The message to evaluate
+     * @return the value of this expression
+     */
+    public Object evaluate(Message message) throws QpidException;
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/Expression.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/JMSSelectorFilter.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/JMSSelectorFilter.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/JMSSelectorFilter.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/JMSSelectorFilter.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,70 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.qpidity.QpidException;
+import org.apache.qpidity.filter.selector.SelectorParser;
+
+import javax.jms.Message;
+
+public class JMSSelectorFilter implements MessageFilter
+{
+    /**
+     * this JMSSelectorFilter's logger
+     */
+    private static final Logger _logger = LoggerFactory.getLogger(JMSSelectorFilter.class);
+
+    private String _selector;
+    private BooleanExpression _matcher;
+
+    public JMSSelectorFilter(String selector) throws QpidException
+    {
+        _selector = selector;
+        if (JMSSelectorFilter._logger.isDebugEnabled())
+        {
+            JMSSelectorFilter._logger.debug("Created JMSSelectorFilter with selector:" + _selector);
+        }
+        _matcher = new SelectorParser().parse(selector);
+    }
+
+    public boolean matches(Message message)
+    {
+        try
+        {
+            boolean match = _matcher.matches(message);
+            if (JMSSelectorFilter._logger.isDebugEnabled())
+            {
+                JMSSelectorFilter._logger.debug(message + " match(" + match + ") selector(" + System
+                        .identityHashCode(_selector) + "):" + _selector);
+            }
+            return match;
+        }
+        catch (QpidException e)
+        {
+            JMSSelectorFilter._logger.warn("Caght exception when evaluating message selector for message  " + message, e);
+        }
+        return false;
+    }
+
+    public String getSelector()
+    {
+        return _selector;
+    }
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/JMSSelectorFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/LogicExpression.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/LogicExpression.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/LogicExpression.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/LogicExpression.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,108 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.apache.qpidity.QpidException;
+
+import javax.jms.Message;
+
+/**
+ * A filter performing a comparison of two objects
+ */
+public abstract class LogicExpression extends BinaryExpression implements BooleanExpression
+{
+
+    public static BooleanExpression createOR(BooleanExpression lvalue, BooleanExpression rvalue)
+    {
+        return new LogicExpression(lvalue, rvalue)
+            {
+
+                public Object evaluate(Message message) throws QpidException
+                {
+
+                    Boolean lv = (Boolean) left.evaluate(message);
+                    // Can we do an OR shortcut??
+                    if ((lv != null) && lv.booleanValue())
+                    {
+                        return Boolean.TRUE;
+                    }
+
+                    Boolean rv = (Boolean) right.evaluate(message);
+
+                    return (rv == null) ? null : rv;
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "OR";
+                }
+            };
+    }
+
+    public static BooleanExpression createAND(BooleanExpression lvalue, BooleanExpression rvalue)
+    {
+        return new LogicExpression(lvalue, rvalue)
+            {
+
+                public Object evaluate(Message message) throws QpidException
+                {
+
+                    Boolean lv = (Boolean) left.evaluate(message);
+
+                    // Can we do an AND shortcut??
+                    if (lv == null)
+                    {
+                        return null;
+                    }
+
+                    if (!lv.booleanValue())
+                    {
+                        return Boolean.FALSE;
+                    }
+
+                    Boolean rv = (Boolean) right.evaluate(message);
+
+                    return (rv == null) ? null : rv;
+                }
+
+                public String getExpressionSymbol()
+                {
+                    return "AND";
+                }
+            };
+    }
+
+    /**
+     * @param left
+     * @param right
+     */
+    public LogicExpression(BooleanExpression left, BooleanExpression right)
+    {
+        super(left, right);
+    }
+
+    public abstract Object evaluate(Message message) throws QpidException;
+
+    public boolean matches(Message message) throws QpidException
+    {
+        Object object = evaluate(message);
+
+        return (object != null) && (object == Boolean.TRUE);
+    }
+
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/LogicExpression.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/MessageFilter.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/MessageFilter.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/MessageFilter.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/MessageFilter.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,27 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.apache.qpidity.QpidException;
+
+import javax.jms.Message;
+
+public interface MessageFilter
+{
+    boolean matches(Message message) throws QpidException;
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/MessageFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/PropertyExpression.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/PropertyExpression.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/PropertyExpression.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/PropertyExpression.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,93 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.slf4j.LoggerFactory;
+import org.apache.qpidity.QpidException;
+
+import javax.jms.Message;
+import java.lang.reflect.Method;
+
+/**
+ * Represents a property  expression
+ */
+public class PropertyExpression implements Expression
+{
+    private static final org.slf4j.Logger _logger = LoggerFactory.getLogger(PropertyExpression.class);
+
+    private Method _getter;
+
+    public PropertyExpression(String name)
+    {
+        Class clazz = Message.class;
+        try
+        {
+            _getter = clazz.getMethod("get" + name, null);
+        }
+        catch (NoSuchMethodException e)
+        {
+            PropertyExpression._logger.warn("Cannot compare property: " + name, e);
+        }
+    }
+
+    public Object evaluate(Message message) throws QpidException
+    {
+        Object result = null;
+        if( _getter != null )
+        {
+            try
+            {
+                result = _getter.invoke(message, null);
+            }
+            catch (Exception e)
+            {
+                throw new QpidException("cannot evaluate property ", "message selector", e);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        return _getter.toString();
+    }
+
+    /**
+     * @see Object#hashCode()
+     */
+    public int hashCode()
+    {
+        return _getter.hashCode();
+    }
+
+    /**
+     * @see Object#equals(Object)
+     */
+    public boolean equals(Object o)
+    {
+        if ((o == null) || !this.getClass().equals(o.getClass()))
+        {
+            return false;
+        }
+        return _getter.equals(((PropertyExpression) o)._getter);
+    }
+
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/PropertyExpression.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/UnaryExpression.java
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/UnaryExpression.java?view=auto&rev=563138
==============================================================================
--- incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/UnaryExpression.java (added)
+++ incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/UnaryExpression.java Mon Aug  6 06:56:47 2007
@@ -0,0 +1,321 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.qpidity.filter;
+
+import org.apache.qpidity.QpidException;
+
+import javax.jms.Message;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * An expression which performs an operation on two expression values
+ */
+public abstract class UnaryExpression implements Expression
+{
+
+    private static final BigDecimal BD_LONG_MIN_VALUE = BigDecimal.valueOf(Long.MIN_VALUE);
+    protected Expression right;
+
+    public static Expression createNegate(Expression left)
+    {
+        return new UnaryExpression(left)
+        {
+            public Object evaluate(Message message) throws QpidException
+            {
+                Object rvalue = right.evaluate(message);
+                if (rvalue == null)
+                {
+                    return null;
+                }
+
+                if (rvalue instanceof Number)
+                {
+                    return UnaryExpression.negate((Number) rvalue);
+                }
+
+                return null;
+            }
+
+            public String getExpressionSymbol()
+            {
+                return "-";
+            }
+        };
+    }
+
+    public static BooleanExpression createInExpression(PropertyExpression right, List elements, final boolean not)
+    {
+
+        // Use a HashSet if there are many elements.
+        Collection t;
+        if (elements.size() == 0)
+        {
+            t = null;
+        }
+        else if (elements.size() < 5)
+        {
+            t = elements;
+        }
+        else
+        {
+            t = new HashSet(elements);
+        }
+
+        final Collection inList = t;
+
+        return new BooleanUnaryExpression(right)
+        {
+            public Object evaluate(Message message) throws QpidException
+            {
+
+                Object rvalue = right.evaluate(message);
+                if (rvalue == null)
+                {
+                    return null;
+                }
+
+                if (rvalue.getClass() != String.class)
+                {
+                    return null;
+                }
+
+                if (((inList != null) && inList.contains(rvalue)) ^ not)
+                {
+                    return Boolean.TRUE;
+                }
+                else
+                {
+                    return Boolean.FALSE;
+                }
+
+            }
+
+            public String toString()
+            {
+                StringBuffer answer = new StringBuffer();
+                answer.append(right);
+                answer.append(" ");
+                answer.append(getExpressionSymbol());
+                answer.append(" ( ");
+
+                int count = 0;
+                for (Iterator i = inList.iterator(); i.hasNext();)
+                {
+                    Object o = (Object) i.next();
+                    if (count != 0)
+                    {
+                        answer.append(", ");
+                    }
+
+                    answer.append(o);
+                    count++;
+                }
+
+                answer.append(" )");
+
+                return answer.toString();
+            }
+
+            public String getExpressionSymbol()
+            {
+                if (not)
+                {
+                    return "NOT IN";
+                }
+                else
+                {
+                    return "IN";
+                }
+            }
+        };
+    }
+
+    abstract static class BooleanUnaryExpression extends UnaryExpression implements BooleanExpression
+    {
+        public BooleanUnaryExpression(Expression left)
+        {
+            super(left);
+        }
+
+        public boolean matches(Message message) throws QpidException
+        {
+            Object object = evaluate(message);
+
+            return (object != null) && (object == Boolean.TRUE);
+        }
+    }
+
+    ;
+
+    public static BooleanExpression createNOT(BooleanExpression left)
+    {
+        return new BooleanUnaryExpression(left)
+        {
+            public Object evaluate(Message message) throws QpidException
+            {
+                Boolean lvalue = (Boolean) right.evaluate(message);
+                if (lvalue == null)
+                {
+                    return null;
+                }
+
+                return lvalue.booleanValue() ? Boolean.FALSE : Boolean.TRUE;
+            }
+
+            public String getExpressionSymbol()
+            {
+                return "NOT";
+            }
+        };
+    }
+    public static BooleanExpression createBooleanCast(Expression left)
+    {
+        return new BooleanUnaryExpression(left)
+        {
+            public Object evaluate(Message message) throws QpidException
+            {
+                Object rvalue = right.evaluate(message);
+                if (rvalue == null)
+                {
+                    return null;
+                }
+
+                if (!rvalue.getClass().equals(Boolean.class))
+                {
+                    return Boolean.FALSE;
+                }
+
+                return ((Boolean) rvalue).booleanValue() ? Boolean.TRUE : Boolean.FALSE;
+            }
+
+            public String toString()
+            {
+                return right.toString();
+            }
+
+            public String getExpressionSymbol()
+            {
+                return "";
+            }
+        };
+    }
+
+    private static Number negate(Number left)
+    {
+        Class clazz = left.getClass();
+        if (clazz == Integer.class)
+        {
+            return new Integer(-left.intValue());
+        }
+        else if (clazz == Long.class)
+        {
+            return new Long(-left.longValue());
+        }
+        else if (clazz == Float.class)
+        {
+            return new Float(-left.floatValue());
+        }
+        else if (clazz == Double.class)
+        {
+            return new Double(-left.doubleValue());
+        }
+        else if (clazz == BigDecimal.class)
+        {
+            // We ussually get a big deciamal when we have Long.MIN_VALUE constant in the
+            // Selector.  Long.MIN_VALUE is too big to store in a Long as a positive so we store it
+            // as a Big decimal.  But it gets Negated right away.. to here we try to covert it back
+            // to a Long.
+            BigDecimal bd = (BigDecimal) left;
+            bd = bd.negate();
+
+            if (UnaryExpression.BD_LONG_MIN_VALUE.compareTo(bd) == 0)
+            {
+                return new Long(Long.MIN_VALUE);
+            }
+
+            return bd;
+        }
+        else
+        {
+            throw new RuntimeException("Don't know how to negate: " + left);
+        }
+    }
+
+    public UnaryExpression(Expression left)
+    {
+        this.right = left;
+    }
+
+    public Expression getRight()
+    {
+        return right;
+    }
+
+    public void setRight(Expression expression)
+    {
+        right = expression;
+    }
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        return "(" + getExpressionSymbol() + " " + right.toString() + ")";
+    }
+
+    /**
+     * TODO: more efficient hashCode()
+     *
+     * @see Object#hashCode()
+     */
+    public int hashCode()
+    {
+        return toString().hashCode();
+    }
+
+    /**
+     * TODO: more efficient hashCode()
+     *
+     * @see Object#equals(Object)
+     */
+    public boolean equals(Object o)
+    {
+
+        if ((o == null) || !this.getClass().equals(o.getClass()))
+        {
+            return false;
+        }
+
+        return toString().equals(o.toString());
+
+    }
+
+    /**
+     * Returns the symbol that represents this binary expression.  For example, addition is
+     * represented by "+"
+     *
+     * @return
+     */
+    public abstract String getExpressionSymbol();
+
+}

Propchange: incubator/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpidity/filter/UnaryExpression.java
------------------------------------------------------------------------------
    svn:eol-style = native