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