001 /** 002 * 003 * Copyright 2004 Hiram Chirino 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 **/ 018 package org.activemq.filter; 019 020 import java.math.BigDecimal; 021 import java.util.Collection; 022 import java.util.HashSet; 023 import java.util.Iterator; 024 import java.util.List; 025 026 import javax.jms.JMSException; 027 import javax.jms.Message; 028 029 /** 030 * An expression which performs an operation on two expression values 031 * 032 * @version $Revision: 1.1.1.1 $ 033 */ 034 public abstract class UnaryExpression implements Expression { 035 036 private static final BigDecimal BD_LONG_MIN_VALUE = BigDecimal.valueOf(Long.MIN_VALUE); 037 protected Expression right; 038 039 public static Expression createNegate(Expression left) { 040 return new UnaryExpression(left) { 041 public Object evaluate(Message message) throws JMSException { 042 Object rvalue = right.evaluate(message); 043 if (rvalue == null) { 044 return null; 045 } 046 if (rvalue instanceof Number) { 047 return negate((Number) rvalue); 048 } 049 return null; 050 } 051 052 public String getExpressionSymbol() { 053 return "-"; 054 } 055 }; 056 } 057 058 public static BooleanExpression createInExpression(PropertyExpression right, List elements, final boolean not) { 059 060 // Use a HashSet if there are many elements. 061 Collection t; 062 if( elements.size()==0 ) 063 t=null; 064 else if( elements.size() < 5 ) 065 t = elements; 066 else { 067 t = new HashSet(elements); 068 } 069 final Collection inList = t; 070 071 return new BooleanUnaryExpression(right) { 072 public Object evaluate(Message message) throws JMSException { 073 074 Object rvalue = right.evaluate(message); 075 if (rvalue == null) { 076 return null; 077 } 078 if( rvalue.getClass()!=String.class ) 079 return null; 080 081 if( (inList!=null && inList.contains(rvalue)) ^ not ) { 082 return Boolean.TRUE; 083 } else { 084 return Boolean.FALSE; 085 } 086 087 } 088 089 public String toString() { 090 StringBuffer answer = new StringBuffer(); 091 answer.append(right); 092 answer.append(" "); 093 answer.append(getExpressionSymbol()); 094 answer.append(" ( "); 095 096 int count=0; 097 for (Iterator i = inList.iterator(); i.hasNext();) { 098 Object o = (Object) i.next(); 099 if( count!=0 ) { 100 answer.append(", "); 101 } 102 answer.append(o); 103 count++; 104 } 105 106 answer.append(" )"); 107 return answer.toString(); 108 } 109 110 public String getExpressionSymbol() { 111 if( not ) 112 return "NOT IN"; 113 else 114 return "IN"; 115 } 116 }; 117 } 118 119 abstract static class BooleanUnaryExpression extends UnaryExpression implements BooleanExpression { 120 public BooleanUnaryExpression(Expression left) { 121 super(left); 122 } 123 }; 124 125 126 public static BooleanExpression createNOT(BooleanExpression left) { 127 return new BooleanUnaryExpression(left) { 128 public Object evaluate(Message message) throws JMSException { 129 Boolean lvalue = (Boolean) right.evaluate(message); 130 if (lvalue == null) { 131 return null; 132 } 133 return lvalue.booleanValue() ? Boolean.FALSE : Boolean.TRUE; 134 } 135 136 public String getExpressionSymbol() { 137 return "NOT"; 138 } 139 }; 140 } 141 142 public static BooleanExpression createXPath(final String xpath) { 143 return new XPathExpression(xpath); 144 } 145 146 public static BooleanExpression createXQuery(final String xpath) { 147 return new XQueryExpression(xpath); 148 } 149 150 public static BooleanExpression createBooleanCast(Expression left) { 151 return new BooleanUnaryExpression(left) { 152 public Object evaluate(Message message) throws JMSException { 153 Object lvalue = right.evaluate(message); 154 if (lvalue == null) 155 return null; 156 if (!lvalue.getClass().equals(Boolean.class)) 157 return Boolean.FALSE; 158 159 return lvalue; 160 } 161 162 public String getExpressionSymbol() { 163 return "NOT"; 164 } 165 }; 166 } 167 168 private static Number negate(Number left) { 169 Class clazz = left.getClass(); 170 if (clazz == Integer.class) { 171 return new Integer(-left.intValue()); 172 } 173 else if (clazz == Long.class) { 174 return new Long(-left.longValue()); 175 } 176 else if (clazz == Float.class) { 177 return new Float(-left.floatValue()); 178 } 179 else if (clazz == Double.class) { 180 return new Double(-left.doubleValue()); 181 } 182 else if (clazz == BigDecimal.class) { 183 // We ussually get a big deciamal when we have Long.MIN_VALUE constant in the 184 // Selector. Long.MIN_VALUE is too big to store in a Long as a positive so we store it 185 // as a Big decimal. But it gets Negated right away.. to here we try to covert it back 186 // to a Long. 187 BigDecimal bd = (BigDecimal)left; 188 bd = bd.negate(); 189 190 if( BD_LONG_MIN_VALUE.compareTo(bd)==0 ) { 191 return new Long(Long.MIN_VALUE); 192 } 193 return bd; 194 } 195 else { 196 throw new RuntimeException("Don't know how to negate: "+left); 197 } 198 } 199 200 public UnaryExpression(Expression left) { 201 this.right = left; 202 } 203 204 public Expression getRight() { 205 return right; 206 } 207 208 public void setRight(Expression expression) { 209 right = expression; 210 } 211 212 /** 213 * @see java.lang.Object#toString() 214 */ 215 public String toString() { 216 return "(" + getExpressionSymbol() + " " + right.toString() + ")"; 217 } 218 219 /** 220 * TODO: more efficient hashCode() 221 * 222 * @see java.lang.Object#hashCode() 223 */ 224 public int hashCode() { 225 return toString().hashCode(); 226 } 227 228 /** 229 * TODO: more efficient hashCode() 230 * 231 * @see java.lang.Object#equals(java.lang.Object) 232 */ 233 public boolean equals(Object o) { 234 235 if (o == null || !this.getClass().equals(o.getClass())) { 236 return false; 237 } 238 return toString().equals(o.toString()); 239 240 } 241 242 /** 243 * Returns the symbol that represents this binary expression. For example, addition is 244 * represented by "+" 245 * 246 * @return 247 */ 248 abstract public String getExpressionSymbol(); 249 250 }