KickJava   Java API By Example, From Geeks To Geeks.

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


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.util.CharBuffer;
32 import com.caucho.xml.XmlChar;
33 import com.caucho.xpath.Expr;
34 import com.caucho.xpath.ExprEnvironment;
35 import com.caucho.xpath.XPathException;
36
37 import org.w3c.dom.Node JavaDoc;
38
39 import java.util.ArrayList JavaDoc;
40 import java.util.Iterator JavaDoc;
41
42 /**
43  * Implements the builtin XPath string expressions.
44  */

45 public class StringExpr extends Expr {
46   // Code of the expression defined in Expr
47
private int _code;
48   // First argument
49
private Expr _left;
50   // Second argument
51
private Expr _right;
52   // Third
53
private Expr _third;
54   private String JavaDoc _value;
55   // Arguments for more than 3.
56
private ArrayList JavaDoc _args;
57
58   /**
59    * Create a StringExpression with three arguments.
60    *
61    * @param code the Expr code of the expression.
62    * @param left the first argument.
63    * @param right the second argument.
64    * @param third the third argument.
65    */

66   public StringExpr(int code, Expr left, Expr right, Expr third)
67   {
68     _code = code;
69     _left = left;
70     _right = right;
71     _third = third;
72   }
73
74   public StringExpr(int code, Expr left, Expr right)
75   {
76     _code = code;
77     _left = left;
78     _right = right;
79   }
80
81   public StringExpr(int code, Expr expr)
82   {
83     _code = code;
84     _left = expr;
85   }
86
87   public StringExpr(String JavaDoc value)
88   {
89     _code = CONST;
90     _value = value;
91   }
92
93   /**
94    * Creates a string expression from a list of arguments.
95    *
96    * @param code Expr code for the function.
97    * @param args array list of the arguments.
98    */

99   public StringExpr(int code, ArrayList JavaDoc args)
100   {
101     _code = code;
102     _args = args;
103
104     if (args.size() > 0)
105       _left = (Expr) args.get(0);
106     if (args.size() > 1)
107       _right = (Expr) args.get(1);
108     if (args.size() > 2)
109       _third = (Expr) args.get(2);
110   }
111
112   /**
113    * The StringExpr returns a string value.
114    */

115   public boolean isString()
116   {
117     return true;
118   }
119
120   public String JavaDoc getValue()
121   {
122     return _value;
123   }
124
125
126   /**
127    * Evaluates the expression as an string.
128    *
129    * @param node the current node
130    * @param env the variable environment.
131    *
132    * @return the string representation of the expression.
133    */

134   public String JavaDoc evalString(Node JavaDoc node, ExprEnvironment env)
135     throws XPathException
136   {
137     switch (_code) {
138     case CONST:
139       return _value;
140
141     case STRING:
142       return _left.evalString(node, env);
143
144     case CONCAT:
145       CharBuffer cb = CharBuffer.allocate();
146       for (int i = 0; i < _args.size(); i++)
147     ((Expr) _args.get(i)).evalString(cb, node, env);
148       return cb.close();
149
150     case SUBSTRING_BEFORE:
151       String JavaDoc lstr = _left.evalString(node, env);
152       String JavaDoc rstr = _right.evalString(node, env);
153       int index = lstr.indexOf(rstr);
154       return index > 0 ? lstr.substring(0, index) : "";
155
156     case SUBSTRING_AFTER:
157       lstr = _left.evalString(node, env);
158       rstr = _right.evalString(node, env);
159       index = lstr.indexOf(rstr);
160       return index >= 0 ? lstr.substring(index + rstr.length()) : "";
161
162     case NORMALIZE:
163       lstr = _left.evalString(node, env);
164       return normalize(lstr);
165
166     case TRANSLATE:
167       lstr = _left.evalString(node, env);
168       rstr = _right.evalString(node, env);
169       String JavaDoc tstr = _third.evalString(node, env);
170       return translate(lstr, rstr, tstr);
171
172     case FORMAT_NUMBER:
173       return _left.evalString(node, env);
174
175     case LOCAL_PART:
176       Object JavaDoc lobj = _left.evalObject(node, env);
177       Node JavaDoc nodeValue = toNode(lobj);
178       if (nodeValue != null)
179     return nodeValue.getLocalName();
180       else
181     return "";
182
183     case NAMESPACE:
184       lobj = _left.evalObject(node, env);
185       nodeValue = toNode(lobj);
186       if (nodeValue != null) {
187     String JavaDoc uri = nodeValue.getNamespaceURI();
188     return uri != null ? uri : "";
189       }
190       else
191     return "";
192
193     case QNAME:
194       lobj = _left.evalObject(node, env);
195       nodeValue = toNode(lobj);
196       if (nodeValue != null)
197     return nodeValue.getNodeName();
198       else
199     return "";
200
201     case GENERATE_ID:
202       Iterator JavaDoc iter = _left.evalNodeSet(node, env);
203       return "G" + String.valueOf(System.identityHashCode(iter.next()));
204
205     case SYSTEM_PROPERTY:
206       lstr = _left.evalString(node, env);
207       if (lstr == null)
208     return "";
209       else if (lstr.equals("xsl:version"))
210     return "1.0";
211       else
212     return "";
213
214     case SUBSTRING:
215       lstr = _left.evalString(node, env);
216       if (lstr == null)
217     lstr = "";
218       double start = _right.evalNumber(node, env) - 1;
219       
220       double end = lstr.length();
221       if (_third != null)
222     end = Math.round(start) + _third.evalNumber(node, env);
223
224       if (Double.isNaN(end) || Double.isNaN(start)) {
225         start = 0;
226         end = 0;
227       }
228
229       if (start < 0)
230         start = 0;
231       else if (lstr.length() < start)
232         start = lstr.length();
233       
234       if (end < 0)
235         end = 0;
236       else if (end < start)
237         end = start;
238       else if (lstr.length() < end)
239         end = lstr.length();
240
241       return lstr.substring((int) (start + 0.5), (int) (end + 0.5));
242
243     default:
244       throw new RuntimeException JavaDoc("unknown code: " + _code);
245     }
246   }
247
248   /**
249    * Evaluate the expression as a boolean, i.e. evaluate it as a string
250    * and then convert it to a boolean.
251    *
252    * @param node the current node
253    * @param env the variable environment.
254    *
255    * @return the boolean representation of the expression.
256    */

257   public boolean evalBoolean(Node JavaDoc node, ExprEnvironment env)
258     throws XPathException
259   {
260     String JavaDoc string = evalString(node, env);
261
262     return string != null && string.length() > 0;
263   }
264
265   /**
266    * Evaluate the expression as a double, i.e. evaluate it as a string
267    * and then convert it to a double.
268    *
269    * @param node the current node
270    * @param env the variable environment.
271    *
272    * @return the numeric representation of the expression.
273    */

274   public double evalNumber(Node JavaDoc node, ExprEnvironment env)
275     throws XPathException
276   {
277     return stringToNumber(evalString(node, env));
278   }
279
280   /**
281    * Evaluate the expression as an object, i.e. return the string value.
282    *
283    * @param node the current node
284    * @param env the variable environment.
285    *
286    * @return the boolean representation of the expression.
287    */

288   public Object JavaDoc evalObject(Node JavaDoc node, ExprEnvironment env)
289     throws XPathException
290   {
291     return evalString(node, env);
292   }
293
294   /**
295    * Normalize the string, converting all whitespace to a space and
296    * eliminating consecutive spaces.
297    */

298   private String JavaDoc normalize(String JavaDoc string)
299   {
300     CharBuffer result = new CharBuffer();
301
302     int i = 0;
303     int len = string.length();
304     for (; i < len && XmlChar.isWhitespace(string.charAt(i)); i++) {
305     }
306
307     boolean lastIsWhitespace = false;
308     for (; i < len; i++) {
309       if (XmlChar.isWhitespace(string.charAt(i))) {
310     lastIsWhitespace = true;
311       }
312       else if (lastIsWhitespace) {
313     result.append(' ');
314     result.append(string.charAt(i));
315     lastIsWhitespace = false;
316       }
317       else
318     result.append(string.charAt(i));
319     }
320
321     return result.toString();
322   }
323
324   /**
325    * Translate the string, converting characters. translate("foo", "f", "b")
326    * returns "boo".
327    *
328    * @param string the string to translate.
329    * @param from characters to convert from.
330    * @param to the replacement characters.
331    */

332   private String JavaDoc translate(String JavaDoc string, String JavaDoc from, String JavaDoc to)
333   {
334     CharBuffer result = new CharBuffer();
335
336   loop:
337     for (int i = 0; i < string.length(); i++) {
338       char ch = string.charAt(i);
339
340       for (int j = 0; j < from.length(); j++) {
341     if (ch == from.charAt(j)) {
342       if (to.length() > j)
343         result.append(to.charAt(j));
344       continue loop;
345     }
346       }
347
348       result.append(ch);
349     }
350
351     return result.toString();
352   }
353
354   /**
355    * Return the expression as a string. toString() returns a valid
356    * XPath expression. This lets applications like XSLT use toString()
357    * to print the string in the generated Java.
358    */

359   public String JavaDoc toString()
360   {
361     switch (_code) {
362     case CONST:
363       CharBuffer cb = CharBuffer.allocate();
364       cb.append("'");
365       for (int i = 0; i < _value.length(); i++) {
366         char ch = _value.charAt(i);
367         switch (ch) {
368         case '\n':
369           cb.append("\\n");
370           break;
371         case '\r':
372           cb.append("\\r");
373           break;
374         case '\\':
375           cb.append("\\\\");
376           break;
377         case '\'':
378           cb.append("\\'\\'");
379           break;
380         case '"':
381           cb.append("\\\"");
382           break;
383         default:
384           cb.append(ch);
385         }
386       }
387       cb.append("'");
388       return cb.toString();
389       
390     case STRING: return "string(" + _left + ")";
391
392     case CONCAT:
393       String JavaDoc result = "concat(";
394       for (int i = 0; i < _args.size(); i++) {
395     if (i > 0)
396       result = result + ", ";
397     result = result + _args.get(i);
398       }
399       return result + ")";
400
401     case SUBSTRING_BEFORE:
402       return "substring-before(" + _left + ", " + _right + ")";
403
404     case SUBSTRING_AFTER:
405       return "substring-after(" + _left + ", " + _right + ")";
406
407     case NORMALIZE:
408       return "normalize-space(" + _left + ")";
409
410     case TRANSLATE:
411       return "translate(" + _left + ", " + _right + ", " + _third + ")";
412
413     case FORMAT_NUMBER:
414       return "format-number(" + _left + ")";
415
416     case LOCAL_PART:
417       return "local-part(" + _left + ")";
418
419     case NAMESPACE:
420       return "namespace-uri(" + _left + ")";
421
422     case QNAME:
423       return "name(" + _left + ")";
424
425     case GENERATE_ID:
426       return "generate-id(" + _left + ")";
427
428     case SYSTEM_PROPERTY:
429       return "system-property(" + _left + ")";
430
431     case SUBSTRING:
432       return "substring(" + _left + "," + _right +
433     (_third == null ? "" : ("," + _third)) + ")";
434
435     case BASE_URI:
436       return "fn:base-uri(" + _left + ")";
437
438     default:
439       return super.toString();
440     }
441   }
442 }
443
Popular Tags