1 28 29 package com.caucho.xpath.expr; 30 31 import com.caucho.xml.XmlUtil; 32 import com.caucho.xpath.Env; 33 import com.caucho.xpath.Expr; 34 import com.caucho.xpath.ExprEnvironment; 35 import com.caucho.xpath.XPathException; 36 import com.caucho.xpath.pattern.AbstractPattern; 37 38 import org.w3c.dom.Node ; 39 40 import java.util.ArrayList ; 41 import java.util.Iterator ; 42 43 public class NumericExpr extends Expr { 44 private int _code; 45 private Expr _left; 46 private Expr _right; 47 private double _value; 48 private ArrayList <Expr> _args; 49 private AbstractPattern _axis; 50 private AbstractPattern _pattern; 51 52 public NumericExpr(int code, Expr left, Expr right) 53 { 54 _code = code; 55 _left = left; 56 _right = right; 57 } 58 59 public NumericExpr(int code, Expr expr) 60 { 61 _code = code; 62 _left = expr; 63 } 64 65 public NumericExpr(double value) 66 { 67 _code = CONST; 68 _value = value; 69 } 70 71 public NumericExpr(int code, ArrayList <Expr> args) 72 { 73 _code = code; 74 _args = args; 75 76 if (args.size() > 0) 77 _left = args.get(0); 78 if (args.size() > 1) 79 _right = args.get(1); 80 } 81 82 public NumericExpr(int code, AbstractPattern axis, AbstractPattern pattern) 83 { 84 _code = code; 85 _axis = axis; 86 _pattern = pattern; 87 } 88 89 public NumericExpr(int code, AbstractPattern listPattern) 90 { 91 _code = code; 92 93 if ((code == POSITION || code == LAST) && listPattern != null) { 94 _axis = listPattern.copyAxis(); 95 _pattern = listPattern.copyPosition(); 96 } 97 else 98 _pattern = listPattern; 99 } 100 101 public AbstractPattern getListContext() 102 { 103 switch (_code) { 104 case POSITION: 105 case LAST: 106 return _pattern; 107 108 default: 109 return null; 110 } 111 } 112 113 public boolean isNumber() 114 { 115 return true; 116 } 117 118 121 public boolean isConstant() 122 { 123 return _code == CONST; 124 } 125 126 129 public double getValue() 130 { 131 return _value; 132 } 133 134 142 public Var evalVar(Node node, ExprEnvironment env) 143 throws XPathException 144 { 145 double value = evalNumber(node, env); 146 147 return NumberVar.create(value); 148 } 149 150 158 public double evalNumber(Node node, ExprEnvironment env) 159 throws XPathException 160 { 161 switch (_code) { 162 case CONST: 163 return _value; 164 165 case NEG: 166 return - _left.evalNumber(node, env); 167 168 case ADD: 169 return (_left.evalNumber(node, env) + _right.evalNumber(node, env)); 170 171 case SUB: 172 return (_left.evalNumber(node, env) - _right.evalNumber(node, env)); 173 174 case MUL: 175 return (_left.evalNumber(node, env) * _right.evalNumber(node, env)); 176 177 case DIV: 178 return (_left.evalNumber(node, env) / _right.evalNumber(node, env)); 179 180 case QUO: 181 return (int) (_left.evalNumber(node, env) / 182 _right.evalNumber(node, env)); 183 184 case MOD: 185 return (_left.evalNumber(node, env) % _right.evalNumber(node, env)); 186 187 case NUMBER: 188 if (_left != null) 189 return _left.evalNumber(node, env); 190 else 191 return toDouble(node); 192 193 case FLOOR: 194 return Math.floor(_left.evalNumber(node, env)); 195 196 case CEILING: 197 return Math.ceil(_left.evalNumber(node, env)); 198 199 case ROUND: 200 return Math.rint(_left.evalNumber(node, env)); 201 202 case SUM: 203 return sum(node, env); 204 205 case POSITION: 206 return position(node, env); 207 208 case LAST: 209 return last(node, env); 210 211 case COUNT: 212 return count(node, env); 213 214 case STRING_LENGTH: 215 String str = _left.evalString(node, env); 216 if (str == null) 217 return 0; 218 else 219 return str.length(); 220 221 default: 222 throw new RuntimeException ("unknown code: " + (char) _code); 223 } 224 } 225 226 230 private int position(Node node, ExprEnvironment env) 231 throws XPathException 232 { 233 int position = env.getContextPosition(); 234 235 if (position > 0) 236 return position; 237 238 if (_axis == null || ! (env instanceof Env)) 239 throw new RuntimeException ("position called with no context"); 240 else if (_pattern == null) 241 return _axis.position(node, (Env) env, null); 242 else 243 return _axis.position(node, (Env) env, _pattern.copyPosition()); 244 } 245 246 private int last(Node node, ExprEnvironment env) 247 throws XPathException 248 { 249 int size = env.getContextSize(); 250 251 if (size > 0) 252 return size; 253 254 if (_axis == null || ! (env instanceof Env)) { 255 throw new RuntimeException ("last called with no context"); 256 } 257 else if (_pattern == null) 258 return _axis.position(node, (Env) env, null); 259 else 260 return _axis.count(node, (Env) env, _pattern.copyPosition()); 261 } 262 263 266 private int count(Node node, ExprEnvironment env) 267 throws XPathException 268 { 269 int count = 0; 270 271 Iterator iter = _pattern.selectUnique(node, env); 272 while (iter.hasNext()) { 273 iter.next(); 274 count++; 275 } 276 277 return count; 278 } 279 280 286 private double sum(Node node, ExprEnvironment env) 287 throws XPathException 288 { 289 double sum = 0; 290 291 Iterator iter = _pattern.selectUnique(node, env); 292 while (iter.hasNext()) { 293 Node subnode = (Node ) iter.next(); 294 String textValue = XmlUtil.textValue(subnode); 295 296 sum += stringToNumber(textValue); 297 } 298 299 return sum; 300 } 301 302 310 public boolean evalBoolean(Node node, ExprEnvironment env) 311 throws XPathException 312 { 313 double value = evalNumber(node, env); 314 315 return value != 0.0 && ! Double.isNaN(value); 316 } 317 318 326 public String evalString(Node node, ExprEnvironment env) 327 throws XPathException 328 { 329 double value = evalNumber(node, env); 330 331 if ((int) value == value) 332 return String.valueOf((int) value); 333 else 334 return String.valueOf(value); 335 } 336 337 345 public Object evalObject(Node node, ExprEnvironment env) 346 throws XPathException 347 { 348 return new Double (evalNumber(node, env)); 349 } 350 351 public String toString() 352 { 353 switch (_code) { 354 case CONST: return String.valueOf(_value); 355 case NEG: return "-" + _left; 356 case ADD: return "(" + _left + " + " + _right + ")"; 357 case SUB: return "(" + _left + " - " + _right + ")"; 358 case MUL: return "(" + _left + " * " + _right + ")"; 359 case DIV: return "(" + _left + " div " + _right + ")"; 360 case QUO: return "(" + _left + " quo " + _right + ")"; 361 case MOD: return "(" + _left + " mod " + _right + ")"; 362 363 case NUMBER: return "number(" + _left + ")"; 364 case SUM: return "sum(" + _pattern + ")"; 365 case FLOOR: return "floor(" + _left + ")"; 366 case CEILING: return "ceiling(" + _left + ")"; 367 case ROUND: return "round(" + _left + ")"; 368 369 case POSITION: return "position()"; 370 case COUNT: return "count(" + _pattern + ")"; 371 case LAST: return "last()"; 372 373 case STRING_LENGTH: 374 return "string-length(" + _left + ")"; 375 376 default: return super.toString(); 377 } 378 } 379 } 380 | Popular Tags |