KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > xpath > expr > NumericExpr


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

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 JavaDoc;
39
40 import java.util.ArrayList JavaDoc;
41 import java.util.Iterator JavaDoc;
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 JavaDoc<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 JavaDoc<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   /**
119    * Returns true of the expression is constant.
120    */

121   public boolean isConstant()
122   {
123     return _code == CONST;
124   }
125
126   /**
127    * Returns the expression's value.
128    */

129   public double getValue()
130   {
131     return _value;
132   }
133
134   /**
135    * Evaluates to a variable.
136    *
137    * @param node the node to evaluate and use as a context.
138    * @param env the variable environment.
139    *
140    * @return a variable containing the value.
141    */

142   public Var evalVar(Node JavaDoc node, ExprEnvironment env)
143     throws XPathException
144   {
145     double value = evalNumber(node, env);
146
147     return NumberVar.create(value);
148   }
149
150   /**
151    * Evaluates the expression as a number.
152    *
153    * @param node the node to evaluate and use as a context.
154    * @param env the variable environment.
155    *
156    * @return the numeric value
157    */

158   public double evalNumber(Node JavaDoc 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 JavaDoc 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 JavaDoc("unknown code: " + (char) _code);
223     }
224   }
225
226   /**
227    * Calculates the position of the node. For select patterns, the
228    * position will be given in the env variable.
229    */

230   private int position(Node JavaDoc 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 JavaDoc("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 JavaDoc 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 JavaDoc("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   /**
264    * Counts the nodes in a subpattern.
265    */

266   private int count(Node JavaDoc node, ExprEnvironment env)
267     throws XPathException
268   {
269     int count = 0;
270
271     Iterator JavaDoc iter = _pattern.selectUnique(node, env);
272     while (iter.hasNext()) {
273       iter.next();
274       count++;
275     }
276
277     return count;
278   }
279
280   /**
281    * Returns the sum of all the node values.
282    *
283    * @param node the current node
284    * @param env the variable environment
285    */

286   private double sum(Node JavaDoc node, ExprEnvironment env)
287     throws XPathException
288   {
289     double sum = 0;
290
291     Iterator JavaDoc iter = _pattern.selectUnique(node, env);
292     while (iter.hasNext()) {
293       Node JavaDoc subnode = (Node JavaDoc) iter.next();
294       String JavaDoc textValue = XmlUtil.textValue(subnode);
295
296       sum += stringToNumber(textValue);
297     }
298
299     return sum;
300   }
301
302   /**
303    * Evaluates the expression as a boolean.
304    *
305    * @param node the current node
306    * @param env the variable environment.
307    *
308    * @return the boolean representation of the number.
309    */

310   public boolean evalBoolean(Node JavaDoc 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   /**
319    * Evaluates the expression as a string.
320    *
321    * @param node the current node
322    * @param env the variable environment.
323    *
324    * @return the string representation of the number.
325    */

326   public String JavaDoc evalString(Node JavaDoc 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   /**
338    * Evaluates the expression as an object.
339    *
340    * @param node the current node
341    * @param env the variable environment.
342    *
343    * @return the Double representation of the number.
344    */

345   public Object JavaDoc evalObject(Node JavaDoc node, ExprEnvironment env)
346     throws XPathException
347   {
348     return new Double JavaDoc(evalNumber(node, env));
349   }
350   
351   public String JavaDoc 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