Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/tripi/asp/VBScriptGlobals.java


1   /**
2    * ArrowHead ASP Server 
3    * This is a source file for the ArrowHead ASP Server - an 100% Java
4    * VBScript interpreter and ASP server.
5    *
6    * For more information, see http://www.tripi.com/arrowhead
7    *
8    * Copyright (C) 2002  Terence Haddock
9    *
10   * This program is free software; you can redistribute it and/or modify
11   * it under the terms of the GNU General Public License as published by
12   * the Free Software Foundation; either version 2 of the License, or
13   * (at your option) any later version.
14   *
15   * This program is distributed in the hope that it will be useful,
16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   * GNU General Public License for more details.
19   *
20   * You should have received a copy of the GNU General Public License
21   * along with this program; if not, write to the Free Software
22   * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23   *
24   */
25  package com.tripi.asp;
26  
27  import org.apache.log4j.Category;
28  import java.text.DateFormatSymbols;
29  import java.text.DecimalFormat;
30  import java.text.NumberFormat;
31  import java.util.Date;
32  import java.util.Random;
33  import java.util.Vector;
34  import java.util.Calendar;
35  import java.util.GregorianCalendar;
36  import java.util.Hashtable;
37  
38  /**
39   * The VBScriptGlobals class handles variables global to every VBScript
40   * expression, such as global functions and variables.
41   * <p>State of variable implementation:
42   * <ul>
43   * <li>Color Constants
44   *  <ul>
45   *  <li><i>vbBlack</i> - <b>TODO</b> Not implemented.
46   *  <li><i>vbBlue</i> - <b>TODO</b> Not implemented.
47   *  <li><i>vbRed</i> - <b>TODO</b> Not implemented.
48   *  <li><i>vbMagenta</i> - <b>TODO</b> Not implemented.
49   *  <li><i>vbGreen</i> - <b>TODO</b> Not implemented.
50   *  <li><i>vbCyan</i> - <b>TODO</b> Not implemented.
51   *  <li><i>vbYellow</i> - <b>TODO</b> Not implemented.
52   *  <li><i>vbWhite</i> - <b>TODO</b> Not implemented.
53   *  </ul>
54   * <li>Comparison Constants
55   *  <ul>
56   *  <li><i>vbBinaryCompare</i> - Fully implemented.
57   *  <li><i>vbTextCompare</i> - Fully implemented.
58   *  </ul>
59   * <li>Date and Time Constants
60   *  <ul>
61   *  <li><i>vbSunday</i> - Fully implemented.
62   *  <li><i>vbMonday</i> - Fully implemented.
63   *  <li><i>vbTuesday</i> - Fully implemented.
64   *  <li><i>vbWednesday</i> - Fully implemented.
65   *  <li><i>vbThursday</i> - Fully implemented.
66   *  <li><i>vbFriday</i> - Fully implemented.
67   *  <li><i>vbSaturday</i> - Fully implemented.
68   *  <li><i>vbUseSystem</i> - Fully implemented.
69   *  <li><i>vbUseSystemDayOfWeek</i> - <b>TODO</b> Not implemented.
70   *  <li><i>vbFirstJan1</i> - <b>TODO</b> Not implemented.
71   *  <li><i>vbFirstFourDays</i> - <b>TODO</b> Not implemented.
72   *  <li><i>vbFirstFullWeek</i> - <b>TODO</b> Not implemented.
73   *  </ul>
74   * <li>Date Format Constants
75   *  <ul>
76   *  <li><i>vbGeneralDate</i> - Implemented.
77   *  <li><i>vbLongDate</i> - Implemented.
78   *  <li><i>vbLongTime</i> - Implemented.
79   *  <li><i>vbShortDate</i> - Implemented.
80   *  <li><i>vbShortTime</i> - Implemented.
81   *  </ul>
82   * <li>Error Constants
83   *  <ul>
84   *  <li><i>vbObjectError</i> - <b>TODO</b> Not implemented.
85   *  </ul>
86   * <li>Logical and Tri-State Constants
87   *  <ul>
88   *  <li><i>NULL</i> - Fully implemented
89   *  <li><i>FALSE</i> - Fully implemented
90   *  <li><i>TRUE</i> - Fully implemented
91   *  <li><i>vbTrue</i> - <b>TODO</b> Not implemented.
92   *  <li><i>vbFalse</i> - <b>TODO</b> Not implemented.
93   *  <li><i>vbUseDefault</i> - <b>TODO</b> Not implemented.
94   *  </ul>
95   * <li>Special Character Constants
96   *  <ul>
97   *  <li><i>vbCr</i> - <b>TODO</b> Not implemented.
98   *  <li><i>vbNullChar</i> - <b>TODO</b> Not implemented.
99   *  <li><i>vbCrLf</i> - Fully implemented.
100  *  <li><i>vbNullString</i> - <b>TODO</b> Not implemented.
101  *  <li><i>vbFormFeed</i> - <b>TODO</b> Not implemented.
102  *  <li><i>vbTab</i> - <b>TODO</b> Not implemented.
103  *  <li><i>vbLf</i> - <b>TODO</b> Not implemented.
104  *  <li><i>vbVericalTab</i> - <b>TODO</b> Not implemented.
105  *  <li><i>vbNewline</i> - Fully Implemented
106  *  </ul>
107  * <li>Variable Sub-Type Constants
108  *  <ul>
109  *  <li><i>vbArray</i> - <b>TODO</b> Not implemented.
110  *  <li><i>vbError</i> - <b>TODO</b> Not implemented.
111  *  <li><i>vbBoolean</i> - <b>TODO</b> Not implemented.
112  *  <li><i>vbInteger</i> - <b>TODO</b> Not implemented.
113  *  <li><i>vbByte</i> - <b>TODO</b> Not implemented.
114  *  <li><i>vbLong</i> - <b>TODO</b> Not implemented.
115  *  <li><i>vbCurrency</i> - <b>TODO</b> Not implemented.
116  *  <li><i>vbNull</i> - <b>TODO</b> Not implemented.
117  *  <li><i>vbDataObject</i> - <b>TODO</b> Not implemented.
118  *  <li><i>vbObject</i> - <b>TODO</b> Not implemented.
119  *  <li><i>vbDate</i> - <b>TODO</b> Not implemented.
120  *  <li><i>vbSingle</i> - <b>TODO</b> Not implemented.
121  *  <li><i>vbDecimal</i> - <b>TODO</b> Not implemented.
122  *  <li><i>vbString</i> - <b>TODO</b> Not implemented.
123  *  <li><i>vbDouble</i> - <b>TODO</b> Not implemented.
124  *  <li><i>vbVariant</i> - <b>TODO</b> Not implemented.
125  *  <li><i>vbEmpty</i> - <b>TODO</b> Not implemented.
126  *  </ul>
127  * </ul>
128  * <p>State of function implementation:
129  * <ul>
130  * <li><i>abs</i> - Implemented for double and int. <b>TODO</b> Not implemented
131  * for NULL value, nor undefined.
132  * <li><i>array</i> - Fully implemented.
133  * <li><i>asc</i> - Fully implemented (as Unicode).
134  * <li><i>ascb</i> - Fully implemented
135  * <li><i>ascw</i> - Fully implemented.
136  * <li><i>atn</i> - Fully implemented.
137  * <li><i>cbool</i> - Fully implemented.
138  * <li><i>cbyte</i> - Fully implemented.
139  * <li><i>ccur</i> - <b>TODO</b> Not implemented.
140  * <li><i>cdate</i> - Works for string expression. <B>TODO</b> works for
141  * numeric values?
142  * <li><i>cdbl</i> - Fully implemented.
143  * <li><i>chr</i> - Fully implemented.
144  * <li><i>chrb</i> - <b>TODO</b> Not implemented.
145  * <li><i>chrw</i> - Fully implemented.
146  * <li><i>cint</i> - Implemented. <b>TODO</b> Does not handle out-of-range.
147  * <li><i>clng</i> - <b>TODO</b> converts to a long, 32-bit integer.
148  * <li><i>cos</i> - Fully implemented.
149  * <li><i>createobject</i> - Implemented, <b>TODO</b> does not handle the
150  * location variable. Also, there is no way to define custom names.
151  * <li><i>csng</i> - Implemented, <b>TODO</b> does not handle out-of-range.
152  * <li><i>cstr</i> - Implemented, <b>TODO</b> does not throw error
153  *                   on NULL values.
154  * <li><i>date</i> - Fully implemented.
155  * <li><i>dateadd</i> - Fully implemented.
156  * <li><i>datediff</i> - Implemented, <b>TODO</b> not for 'w', nor
157  * 'ww' field, nor handles fourth and fifth fields.
158  * <li><i>datepart</i> - Implemented, <b>TODO</b> weekday constants may not
159  * be correct.
160  * <li><i>dateserial</i> - Fully implemented.
161  * <li><i>datevalue</i> - Fully implemented.
162  * <li><i>day</i> - <b>TODO</b> Not implemented.
163  * <li><i>erase</i> - Fully implemented.
164  * <li><i>exp</i> - Fully implemented.
165  * <li><i>filter</i> - <b>TODO</b> Not implemented.
166  * <li><i>fix</i> - Fully implemented.
167  * <li><i>formatcurrency</i> - <b>TODO</b> Not implemented.
168  * <li><i>formatdatetime</i> - Implemented, <b>TODO</b> does not handle
169  * vbGeneralDate properly because there is no distinction between date
170  * and time in java.util.Date.
171  * <li><i>formatnumber</i> - Implemented, <b>TODO</b> does not handle all
172  * parameters
173  * <li><i>formatpercent</i> - <b>TODO</b> Not implemented.
174  * <li><i>getlocale</i> - <b>TODO</b> Not implemented.
175  * <li><i>getobject</i> - <b>TODO</b> Not implemented.
176  * <li><i>getref</i> - <b>TODO</b> Not implemented.
177  * <li><i>hex</i> - Fully implemented.
178  * <li><i>hour</i> - Fully implemented.
179  * <li><i>instr</i> - Fully implemented.
180  * <li><i>instrb</i> - <b>TODO</b> Not implemented.
181  * <li><i>instrrev</i> - Fully implemented.
182  * <li><i>int</i> - Fully implemented.
183  * <li><i>isarray</i> - Fully implemented.
184  * <li><i>isdate</i> - Fully implemented
185  * <li><i>isempty</i> - Fully implemented
186  * <li><i>isnull</i> - Fully implemented
187  * <li><i>isnumeric</i> - Fully implemented
188  * <li><i>isobject</i> - Fully implemented
189  * <li><i>join</i> - Fully implemented.
190  * <li><i>lbound</i> - Fully implemented.
191  * <li><i>lcase</i> - Fully implemented.
192  * <li><i>left</i> - Fully implemented.
193  * <li><i>leftb</i> - <b>TODO</b> Not implemented.
194  * <li><i>len</i> - Implemented <b>TODO</b> "number of bytes to store a 
195  * varaible" not implemented.
196  * <li><i>lenb</i> - <b>TODO</b> Not implemented.
197  * <li><i>log</i> - Fully implemented.
198  * <li><i>ltrim</i> - Fully implemented.
199  * <li><i>mid</i> - Fully implemented.
200  * <li><i>midb</i> - <b>TODO</b> Not implemented.
201  * <li><i>minute</i> - Fully implemented.
202  * <li><i>month</i> - Fully implemented.
203  * <li><i>monthname</i> - Fully implemented.
204  * <li><i>now</i> - Fully implemented.
205  * <li><i>replace</i> - Fully implemented.
206  * <li><i>rgb</i> - Fully implemented.
207  * <li><i>randomize</i> - Fully implemented.
208  * <li><i>right</i> - Fully implemented.
209  * <li><i>rightb</i> - <b>TODO</b> Not implemented.
210  * <li><i>rnd</i> - Fully implemented.
211  * <li><i>round</i> - Fully implemented.
212  * <li><i>rtrim</i> - Fully implemented.
213  * <li><i>scriptengine</i> - Fully implemented.
214  * <li><i>scriptenginebuildengine</i> - Fully implemented.
215  * <li><i>scriptenginemajorversion</i> - Fully implemented.
216  * <li><i>scriptengineminorversion</i> - Fully implemented.
217  * <li><i>second</i> - Fully implemented.
218  * <li><i>setlocale</i> - <b>TODO</b> Not implemented.
219  * <li><i>sgn</i> - Fully implemented.
220  * <li><i>sin</i> - Fully implemented.
221  * <li><i>space</i> - Fully implemented.
222  * <li><i>split</i> - Fully implemented.
223  * <li><i>sqr</i> - Fully implemented.
224  * <li><i>strcomp</i> - Fully implemented.
225  * <li><i>string</i> - Fully implemented.
226  * <li><i>strreverse</i> - Fully implemented.
227  * <li><i>tan</i> - Fully implemented.
228  * <li><i>time</i> - Fully implemented.
229  * <li><i>timer</i> - <b>TODO</b> Not implemented.
230  * <li><i>timeserial</i> - Fully implemented.
231  * <li><i>timevalue</i> - <b>TODO</b> Not implemented.
232  * <li><i>trim</i> - Fully implemented.
233  * <li><i>typename</i> - <b>TODO</b> Not implemented.
234  * <li><i>ucase</i> - Fully implemented.
235  * <li><i>vartype</i> - <b>TODO</b> Not implemented.
236  * <li><i>weekday</i> - Fully implemented.
237  * <li><i>weekdayname</i> - Implemented, <b>TODO</b> but not for first day
238  * of week parameter.
239  * <li><i>year</i> - Fully implemented.
240  * </ul>
241  *
242  * @author Terence Haddock
243  * @version 0.9
244  */
245 public class VBScriptGlobals
246 {
247     /** Debugging category */
248     static final private Category DBG =
249         Category.getInstance(VBScriptGlobals.class);
250 
251     /* Constants */
252     /** "General" date */
253     public final static int vbGeneralDate = 0;
254     /** "Long" date format */
255     public final static int vbLongDate = 1;
256     /** "Short" date format */
257     public final static int vbShortDate = 2;
258     /** "Long" time format */
259     public final static int vbLongTime = 3;
260     /** "Short" time format */
261     public final static int vbShortTime = 4;
262 
263     /* Comparison constants */
264     /** Binary compare */
265     public final static int vbBinaryCompare = 0;
266     /** Text compare */
267     public final static int vbTextCompare = 1;
268 
269     /** Private constructor, so class cannot be initialized */
270     private VBScriptGlobals() {};
271 
272     /** Constructor, takes no arguments */
273     static protected void initScope(Hashtable context) throws AspException
274     {
275         /* Global variables */
276         /* Constants */
277         context.put(new IdentNode("false"), new Boolean(false));
278         context.put(new IdentNode("true"), new Boolean(true));
279         context.put(new IdentNode("null"), Constants.nullNode);
280         context.put(new IdentNode("nothing"), Constants.nothingNode);
281         context.put(new IdentNode("empty"), Constants.undefinedValueNode);
282         context.put(new IdentNode("vbcrlf"), "\r\n");
283         context.put(new IdentNode("vbnewline"), "\n");
284         context.put(new IdentNode("vbcr"), "\r");
285         context.put(new IdentNode("vblf"), "\n");
286         context.put(new IdentNode("vbgeneraldate"), new Integer(vbGeneralDate));
287         context.put(new IdentNode("vblongdate"), new Integer(vbLongDate));
288         context.put(new IdentNode("vbshortdate"), new Integer(vbShortDate));
289         context.put(new IdentNode("vblongtime"), new Integer(vbLongTime));
290         context.put(new IdentNode("vbshorttime"), new Integer(vbShortTime));
291         context.put(new IdentNode("vbbinarycompare"), new Integer(vbBinaryCompare));
292         context.put(new IdentNode("vbtextcompare"), new Integer(vbTextCompare));
293         context.put(new IdentNode("vbusesystem"), new Integer(0));
294         context.put(new IdentNode("vbsunday"), new Integer(1));
295         context.put(new IdentNode("vbmonday"), new Integer(2));
296         context.put(new IdentNode("vbtuesday"), new Integer(3));
297         context.put(new IdentNode("vbwednesday"), new Integer(4));
298         context.put(new IdentNode("vbthursday"), new Integer(5));
299         context.put(new IdentNode("vbfriday"), new Integer(6));
300         context.put(new IdentNode("vbsaturday"), new Integer(7));
301         /* Functions */
302         context.put(new IdentNode("abs"), new AbsFunction());
303         context.put(new IdentNode("array"), new ArrayFunction());
304         context.put(new IdentNode("asc"), new AscFunction());
305         context.put(new IdentNode("ascb"), new AscBFunction());
306         context.put(new IdentNode("ascw"), new AscFunction());
307         context.put(new IdentNode("atn"), new AtnFunction());
308         context.put(new IdentNode("cbool"), new CBoolFunction());
309         context.put(new IdentNode("cbyte"), new CByteFunction());
310         context.put(new IdentNode("ccur"), new CDblFunction());
311         context.put(new IdentNode("cdate"), new CDateFunction());
312         context.put(new IdentNode("cdbl"), new CDblFunction());
313         context.put(new IdentNode("chr"), new ChrFunction());
314         context.put(new IdentNode("chrw"), new ChrFunction());
315         context.put(new IdentNode("cint"), new CIntFunction());
316         context.put(new IdentNode("clng"), new CLngFunction());
317         context.put(new IdentNode("cos"), new CosFunction());
318         context.put(new IdentNode("createobject"), new CreateObjectFunction());
319         context.put(new IdentNode("csng"), new CDblFunction());
320         context.put(new IdentNode("cstr"), new CStrFunction());
321         context.put(new IdentNode("date"), new DateFunction());
322         context.put(new IdentNode("dateadd"), new DateAddFunction());
323         context.put(new IdentNode("datediff"), new DateDiffFunction());
324         context.put(new IdentNode("datepart"), new DatePartFunction());
325         context.put(new IdentNode("dateserial"), new DateSerialFunction());
326         context.put(new IdentNode("datevalue"), new DateValueFunction());
327         context.put(new IdentNode("day"), new DayFunction());
328         context.put(new IdentNode("erase"), new EraseFunction());
329         context.put(new IdentNode("exp"), new ExpFunction());
330         context.put(new IdentNode("fix"), new FixFunction());
331         context.put(new IdentNode("formatdatetime"), new FormatDateFunction());
332         context.put(new IdentNode("formatnumber"), new FormatNumberFunction());
333         context.put(new IdentNode("hex"), new HexFunction());
334         context.put(new IdentNode("hour"), new HourFunction());
335         context.put(new IdentNode("instr"), new InStrFunction());
336         context.put(new IdentNode("instrrev"), new InStrRevFunction());
337         context.put(new IdentNode("int"), new IntFunction());
338         context.put(new IdentNode("isarray"), new IsArrayFunction());
339         context.put(new IdentNode("isdate"), new IsDateFunction());
340         context.put(new IdentNode("isempty"), new IsEmptyFunction());
341         context.put(new IdentNode("isnull"), new IsNullFunction());
342         context.put(new IdentNode("isnumeric"), new IsNumericFunction());
343         context.put(new IdentNode("isobject"), new IsObjectFunction());
344         context.put(new IdentNode("join"), new JoinFunction());
345         context.put(new IdentNode("lbound"), new LBoundFunction());
346         context.put(new IdentNode("lcase"), new LCaseFunction());
347         context.put(new IdentNode("left"), new LeftFunction());
348         context.put(new IdentNode("len"), new LenFunction());
349         context.put(new IdentNode("log"), new LogFunction());
350         context.put(new IdentNode("ltrim"), new LTrimFunction());
351         context.put(new IdentNode("mid"), new MidFunction());
352         context.put(new IdentNode("minute"), new MinuteFunction());
353         context.put(new IdentNode("month"), new MonthFunction());
354         context.put(new IdentNode("monthname"), new MonthNameFunction());
355         context.put(new IdentNode("now"), new NowFunction());
356         context.put(new IdentNode("oct"), new OctFunction());
357         context.put(new IdentNode("randomize"), new RandomizeFunction());
358         context.put(new IdentNode("replace"), new ReplaceFunction());
359         context.put(new IdentNode("rgb"), new RGBFunction());
360         context.put(new IdentNode("right"), new RightFunction());
361         context.put(new IdentNode("rnd"), new RndFunction());
362         context.put(new IdentNode("round"), new RoundFunction());
363         context.put(new IdentNode("rtrim"), new RTrimFunction());
364         context.put(new IdentNode("scriptengine"), new ScriptEngineFunction());
365         context.put(new IdentNode("scriptenginebuildversion"),
366             new ScriptEngineBuildVersionFunction());
367         context.put(new IdentNode("scriptenginemajorversion"),
368             new ScriptEngineMajorVersionFunction());
369         context.put(new IdentNode("scriptengineminorversion"),
370             new ScriptEngineMinorVersionFunction());
371         context.put(new IdentNode("second"), new SecondFunction());
372         context.put(new IdentNode("sgn"), new SgnFunction());
373         context.put(new IdentNode("sin"), new SinFunction());
374         context.put(new IdentNode("space"), new SpaceFunction());
375         context.put(new IdentNode("split"), new SplitFunction());
376         context.put(new IdentNode("sqr"), new SqrFunction());
377         context.put(new IdentNode("strcomp"), new StrCompFunction());
378         context.put(new IdentNode("string"), new StringFunction());
379         context.put(new IdentNode("strreverse"), new StrReverseFunction());
380         context.put(new IdentNode("tan"), new TanFunction());
381         context.put(new IdentNode("time"), new TimeFunction());
382         context.put(new IdentNode("timeserial"), new TimeSerialFunction());
383         context.put(new IdentNode("trim"), new TrimFunction());
384         context.put(new IdentNode("ubound"), new UBoundFunction());
385         context.put(new IdentNode("ucase"), new UCaseFunction());
386         context.put(new IdentNode("weekday"), new WeekdayFunction());
387         context.put(new IdentNode("weekdayname"), new WeekdayNameFunction());
388         context.put(new IdentNode("year"), new YearFunction());
389         
390         /* Error code */
391         context.put(new IdentNode("err"),
392             new JavaObjectNode(new AspNestedException()));
393     }
394 
395     /** Absolute function */
396     static class AbsFunction extends AbstractFunctionNode
397     {
398         /**
399          * Executes this function.
400          * @param values Parameters for this expression.
401          * @param context Context under which to evaluate this expression.
402          * @return Return value of this expression.
403          * @throws AspException if an error occurs.
404          * @see AbstractFunction#execute(Vector,AspContext)
405          */
406         public Object execute(Vector values, AspContext context)
407             throws AspException
408         {
409             if (values.size()!=1) {
410                 throw new AspException("Invalid number of arguments: " +
411                     values.size());
412             }
413             Object value = values.get(0);
414             if (Constants.nullNode.equals(value)) {
415                 return value;
416             } else if (value instanceof Integer) {
417                 Integer iVal = Types.coerceToInteger(value);
418                 return new Integer(Math.abs(iVal.intValue()));
419             } else {
420                 Double dVal = Types.coerceToDouble(value);
421                 return new Double(Math.abs(dVal.doubleValue()));
422             }
423         }
424     }
425 
426     /** Array creation function */
427     static class ArrayFunction extends AbstractFunctionNode
428     {
429         /**
430          * Executes this function.
431          * @param values Parameters for this expression.
432          * @param context AspContext under which to evaluate this expression.
433          * @return Return value of this expression.
434          * @throws AspException if an error occurs.
435          * @see AbstractFunction#execute(Vector,AspContext)
436          */
437         public Object execute(Vector values, AspContext context)
438             throws AspException
439         {
440             ArrayNode array = new ArrayNode(values.size());
441             for (int i = 0; i < values.size(); i++) {
442                 array._setValue(i, values.get(i));
443             }
444             return array;
445         }
446     }
447 
448     /** Ascii function */
449     static class AscFunction extends AbstractFunctionNode
450     {
451         /**
452          * Executes this function.
453          * @param values Parameters for this expression.
454          * @param context AspContext under which to evaluate this expression.
455          * @return Return value of this expression.
456          * @throws AspException if an error occurs.
457          * @see AbstractFunction#execute(Vector,AspContext)
458          */
459         public Object execute(Vector values, AspContext context)
460             throws AspException
461         {
462             if (values.size()!=1) {
463                 throw new AspException("Invalid number of arguments: " +
464                     values.size());
465             }
466             String value = Types.coerceToString(values.get(0));
467             return new Integer((int)value.charAt(0));
468         }
469     }
470 
471     /** Ascii Byte function */
472     static class AscBFunction extends AbstractFunctionNode
473     {
474         /**
475          * Executes this function.
476          * @param values Parameters for this expression.
477          * @param context AspContext under which to evaluate this expression.
478          * @return Return value of this expression.
479          * @throws AspException if an error occurs.
480          * @see AbstractFunction#execute(Vector,AspContext)
481          */
482         public Object execute(Vector values, AspContext context)
483             throws AspException
484         {
485             if (values.size()!=1) {
486                 throw new AspException("Invalid number of arguments: " +
487                     values.size());
488             }
489             String value = Types.coerceToString(values.get(0));
490             byte b = (byte)value.charAt(0);
491             return new Integer(b);
492         }
493     }
494 
495     /** Arc-Tangent function */
496     static class AtnFunction extends AbstractFunctionNode
497     {
498         /**
499          * Executes this function.
500          * @param values Parameters for this expression.
501          * @param context AspContext under which to evaluate this expression.
502          * @return Return value of this expression.
503          * @throws AspException if an error occurs.
504          * @see AbstractFunction#execute(Vector,AspContext)
505          */
506         public Object execute(Vector values, AspContext context)
507             throws AspException
508         {
509             if (values.size()!=1) {
510                 throw new AspException("Invalid number of arguments: " +
511                     values.size());
512             }
513             Object value = values.get(0);
514             Double dVal = Types.coerceToDouble(value);
515             return new Double(Math.atan(dVal.doubleValue()));
516         }
517     }
518 
519     /** Boolean conversion function */
520     static class CBoolFunction extends AbstractFunctionNode
521     {
522         /**
523          * Executes this function.
524          * @param values Parameters for this expression.
525          * @param context AspContext under which to evaluate this expression.
526          * @return Return value of this expression.
527          * @throws AspException if an error occurs.
528          * @see AbstractFunction#execute(Vector,AspContext)
529          */
530         public Object execute(Vector values, AspContext context)
531             throws AspException
532         {
533             if (values.size()!=1) {
534                 throw new AspException("Invalid number of arguments: " +
535                     values.size());
536             }
537             Object value = values.get(0);
538             return Types.coerceToBoolean(value);
539         }
540     }
541 
542     /** Byte (range 0-255) conversion function */
543     static class CByteFunction extends AbstractFunctionNode
544     {
545         /**
546          * Executes this function.
547          * @param values Parameters for this expression.
548          * @param context AspContext under which to evaluate this expression.
549          * @return Return value of this expression.
550          * @throws AspException if an error occurs.
551          * @see AbstractFunction#execute(Vector,AspContext)
552          */
553         public Object execute(Vector values, AspContext context)
554             throws AspException
555         {
556             if (values.size()!=1) {
557                 throw new AspException("Invalid number of arguments: " +
558                     values.size());
559             }
560             Integer iVal = Types.coerceToInteger(values.get(0));
561             if (iVal.intValue() < 0 || iVal.intValue() > 255)
562                 throw new AspOverflowException(iVal.toString());
563             return iVal;
564         }
565     }
566 
567     /** Date conversion function */
568     static class CDateFunction extends AbstractFunctionNode
569     {
570         /**
571          * Executes this function.
572          * @param values Parameters for this expression.
573          * @param context AspContext under which to evaluate this expression.
574          * @return Return value of this expression.
575          * @throws AspException if an error occurs.
576          * @see AbstractFunction#execute(Vector,AspContext)
577          */
578         public Object execute(Vector values, AspContext context)
579             throws AspException
580         {
581             if (values.size()!=1) {
582                 throw new AspException("Invalid number of arguments: " +
583                     values.size());
584             }
585             return Types.coerceToDate(values.get(0));
586         }
587     }
588 
589     /** Double conversion function */
590     static class CDblFunction extends AbstractFunctionNode
591     {
592         /**
593          * Executes this function.
594          * @param values Parameters for this expression.
595          * @param context AspContext under which to evaluate this expression.
596          * @return Return value of this expression.
597          * @throws AspException if an error occurs.
598          * @see AbstractFunction#execute(Vector,AspContext)
599          */
600         public Object execute(Vector values, AspContext context)
601             throws AspException
602         {
603             if (values.size()!=1) {
604                 throw new AspException("Invalid number of arguments: " +
605                     values.size());
606             }
607             Object value = values.get(0);
608             return Types.coerceToDouble(value);
609         }
610     }
611 
612     /** Character conversion function */
613     static class ChrFunction extends AbstractFunctionNode
614     {
615         /**
616          * Executes this function.
617          * @param values Parameters for this expression.
618          * @param context AspContext under which to evaluate this expression.
619          * @return Return value of this expression.
620          * @throws AspException if an error occurs.
621          * @see AbstractFunction#execute(Vector,AspContext)
622          */
623         public Object execute(Vector values, AspContext context)
624             throws AspException
625         {
626             if (values.size()!=1) {
627                 throw new AspException("Invalid number of arguments: " +
628                     values.size());
629             }
630             Integer intVal = Types.coerceToInteger(values.get(0));
631             return new String(""+((char)intVal.intValue()));
632         }
633     }
634 
635     /** 16-bit integer conversion function */
636     static class CIntFunction extends AbstractFunctionNode
637     {
638         /**
639          * Executes this function.
640          * @param values Parameters for this expression.
641          * @param context AspContext under which to evaluate this expression.
642          * @return Return value of this expression.
643          * @throws AspException if an error occurs.
644          * @see AbstractFunction#execute(Vector,AspContext)
645          */
646         public Object execute(Vector values, AspContext context)
647             throws AspException
648         {
649             if (values.size()!=1) {
650                 throw new AspException("Invalid number of arguments: " +
651                     values.size());
652             }
653             double dVal = Types.coerceToDouble(values.get(0)).doubleValue();
654             double fPart = dVal - Math.floor(dVal);
655             dVal = Math.round(dVal);
656             if ((fPart == 0.5) && ((dVal % 2) != 0)) dVal--;
657             return new Integer((int)dVal);
658         }
659     }
660 
661     /** 32-bit integer conversion function */
662     static class CLngFunction extends AbstractFunctionNode
663     {
664         /**
665          * Executes this function.
666          * @param values Parameters for this expression.
667          * @param context AspContext under which to evaluate this expression.
668          * @return Return value of this expression.
669          * @throws AspException if an error occurs.
670          * @see AbstractFunction#execute(Vector,AspContext)
671          */
672         public Object execute(Vector values, AspContext context)
673             throws AspException
674         {
675             if (values.size()!=1) {
676                 throw new AspException("Invalid number of arguments: " +
677                     values.size());
678             }
679             double dVal = Types.coerceToDouble(values.get(0)).doubleValue();
680             double fPart = dVal - Math.floor(dVal);
681             dVal = Math.round(dVal);
682             if ((fPart == 0.5) && ((dVal % 2) != 0)) dVal--;
683             return new Integer((int)dVal);
684         }
685     }
686 
687     /** Trigometric cosine function */
688     static class CosFunction extends AbstractFunctionNode
689     {
690         /**
691          * Executes this function.
692          * @param values Parameters for this expression.
693          * @param context AspContext under which to evaluate this expression.
694          * @return Return value of this expression.
695          * @throws AspException if an error occurs.
696          * @see AbstractFunction#execute(Vector,AspContext)
697          */
698         public Object execute(Vector values, AspContext context)
699             throws AspException
700         {
701             if (values.size()!=1) {
702                 throw new AspException("Invalid number of arguments: " +
703                     values.size());
704             }
705             double dVal = Types.coerceToDouble(values.get(0)).doubleValue();
706             return new Double(Math.cos(dVal));
707         }
708     }
709 
710     /** Object creation function */
711     static class CreateObjectFunction extends AbstractFunctionNode
712     {
713         /**
714          * Executes this function.
715          * @param values Parameters for this expression.
716          * @param context AspContext under which to evaluate this expression.
717          * @return Return value of this expression.
718          * @throws AspException if an error occurs.
719          * @see AbstractFunction#execute(Vector,AspContext)
720          */
721         public Object execute(Vector values, AspContext context)
722             throws AspException
723         {
724             if (values.size()!=1) {
725                 throw new AspException("Invalid number of arguments: " +
726                     values.size());
727             }
728 
729             final IdentNode serverIdent = new IdentNode("server");
730             JavaObjectNode serverObj =
731                 (JavaObjectNode)context.getValue(serverIdent);
732             Server server = (Server)serverObj.getSubObject();
733             String objectName = Types.coerceToString(values.get(0));
734             try {
735                 return Types.coerceToNode(    
736                     server.CreateObject(objectName));
737             } catch (Exception ex) {
738                 throw new AspNestedException(ex);
739             }
740         }
741     }
742 
743     /** String conversion function */
744     static class CStrFunction extends AbstractFunctionNode
745     {
746         /**
747          * Executes this function.
748          * @param values Parameters for this expression.
749          * @param context AspContext under which to evaluate this expression.
750          * @return Return value of this expression.
751          * @throws AspException if an error occurs.
752          * @see AbstractFunction#execute(Vector,AspContext)
753          */
754         public Object execute(Vector values, AspContext context)
755             throws AspException
756         {
757             if (values.size()!=1) {
758                 throw new AspException("Invalid number of arguments: " +
759                     values.size());
760             }
761             Object value = values.get(0);
762             /* XXX This should really be something like Null Pointer Exception */
763             if (value == null || value instanceof NullNode)
764                 throw new AspCastException("NULL");
765             return Types.coerceToString(values.get(0));
766         }
767     }
768 
769     /** Date current time function */
770     static class DateFunction extends AbstractFunctionNode
771     {
772         /**
773          * Executes this function.
774          * @param values Parameters for this expression.
775          * @param context AspContext under which to evaluate this expression.
776          * @return Return value of this expression.
777          * @throws AspException if an error occurs.
778          * @see AbstractFunction#execute(Vector,AspContext)
779          */
780         public Object execute(Vector values, AspContext context)
781             throws AspException
782         {
783             if (values.size()!=0) {
784                 throw new AspException("Invalid number of arguments: " +
785                     values.size());
786             }
787             Date date = new java.util.Date(System.currentTimeMillis());
788             return new AspDate(date, false, true);
789         }
790     }
791 
792     /** Date addition function */
793     static class DateAddFunction extends AbstractFunctionNode
794     {
795         /**
796          * Executes this function.
797          * @param values Parameters for this expression.
798          * @param context AspContext under which to evaluate this expression.
799          * @return Return value of this expression.
800          * @throws AspException if an error occurs.
801          * @see AbstractFunction#execute(Vector,AspContext)
802          */
803         public Object execute(Vector values, AspContext context)
804             throws AspException
805         {
806             if (values.size()!=3) {
807                 throw new AspException("Invalid number of " +
808                     "arguments: " + values.size());
809             }
810             String field = Types.coerceToString(values.get(0));
811             Object obj = values.get(1);
812             int offset;
813             if (obj == null || obj instanceof NullNode)
814                 offset = 0;
815             else
816                 offset = (int)Math.round(Types.coerceToDouble(values.get(1)).
817                     doubleValue());
818             AspDate date = Types.coerceToDate(values.get(2));
819     
820             Calendar cal = date.toCalendar();
821             int fieldID;
822             if (field.equalsIgnoreCase("yyyy")) {
823                 fieldID = cal.YEAR;
824             } else if (field.equalsIgnoreCase("q")) {
825                 offset *= 3;
826                 fieldID = cal.MONTH;
827             } else if (field.equalsIgnoreCase("m")) {
828                 fieldID = cal.MONTH;
829             } else if (field.equalsIgnoreCase("y")) {
830                 fieldID = cal.DAY_OF_YEAR;
831             } else if (field.equalsIgnoreCase("d")) {
832                 fieldID = cal.DAY_OF_MONTH;
833             } else if (field.equalsIgnoreCase("w")) {
834                 fieldID = cal.DAY_OF_MONTH;
835             } else if (field.equalsIgnoreCase("ww")) {
836                 fieldID = cal.WEEK_OF_YEAR;
837             } else if (field.equalsIgnoreCase("h")) {
838                 fieldID = cal.HOUR_OF_DAY;
839             } else if (field.equalsIgnoreCase("n")) {
840                 fieldID = cal.MINUTE;
841             } else if (field.equalsIgnoreCase("s")) {
842                 fieldID = cal.SECOND;
843             } else {
844                 throw new AspException("Unknown date field identifier: " + field);
845             }
846             cal.add(fieldID, offset);
847             return new AspDate(cal, date.hasTime(), true);
848         }
849     }
850 
851     /** Date difference function */
852     static class DateDiffFunction extends AbstractFunctionNode
853     {
854         /**
855          * Executes this function.
856          * @param values Parameters for this expression.
857          * @param context AspContext under which to evaluate this expression.
858          * @return Return value of this expression.
859          * @throws AspException if an error occurs.
860          * @see AbstractFunction#execute(Vector,AspContext)
861          */
862         public Object execute(Vector values, AspContext context)
863             throws AspException
864         {
865             if (values.size()!=3) {
866                 throw new AspException("Invalid number of " +
867                     "arguments: " + values.size());
868             }
869             String field = Types.coerceToString(values.get(0));
870             AspDate aDate = Types.coerceToDate(values.get(1));
871             Calendar aCal = aDate.toCalendar();
872 
873             AspDate bDate = Types.coerceToDate(values.get(2));
874             Calendar bCal = bDate.toCalendar();
875 
876             int diff;
877     
878             if (field.equalsIgnoreCase("yyyy")) {
879                 int aYear = aCal.get(aCal.YEAR);
880                 int bYear = bCal.get(bCal.YEAR);
881                 diff = bYear - aYear;
882             } else if (field.equalsIgnoreCase("q")) {
883                 int aYear = aCal.get(aCal.YEAR);
884                 int aMonth = aCal.get(aCal.MONTH);
885                 int bYear = bCal.get(bCal.YEAR);
886                 int bMonth = bCal.get(bCal.MONTH);
887                 diff = (bMonth - aMonth) + ((bYear - aYear)*12);
888                 diff /= 3;
889             } else if (field.equalsIgnoreCase("m")) {
890                 int aYear = aCal.get(aCal.YEAR);
891                 int aMonth = aCal.get(aCal.MONTH);
892                 int bYear = bCal.get(bCal.YEAR);
893                 int bMonth = bCal.get(bCal.MONTH);
894                 diff = (bMonth - aMonth) + ((bYear - aYear)*12);
895             } else if (field.equalsIgnoreCase("y") ||
896                     field.equalsIgnoreCase("d")) {
897                 long aTime = aDate.toDate().getTime()/1000;
898                 long bTime = bDate.toDate().getTime()/1000;
899                 int aDays = (int)(aTime / 86400);
900                 int bDays = (int)(bTime / 86400);
901 
902                 if (DBG.isDebugEnabled())
903                 {
904                     DBG.debug("aTime: " + aTime);
905                     DBG.debug("aDays: " + aDays);
906                     DBG.debug("bTime: " + bTime);
907                     DBG.debug("bDays: " + bDays);
908                 }
909     
910                 return new Integer((int)(bDays - aDays));
911             } else if (field.equalsIgnoreCase("w")) {
912                 throw new AspNotImplementedException("'w' field in datediff");
913             } else if (field.equalsIgnoreCase("ww")) {
914                 throw new AspNotImplementedException("'ww' field in datediff");
915             } else if (field.equalsIgnoreCase("h")) {
916                 long aTime = aDate.toDate().getTime() / 1000;
917                 long bTime = bDate.toDate().getTime() / 1000;
918 
919                 return new Integer((int)(bTime - aTime)/3600);
920             } else if (field.equalsIgnoreCase("n")) {
921                 long aTime = aDate.toDate().getTime() / 1000;
922                 long bTime = bDate.toDate().getTime() / 1000;
923     
924                 return new Integer((int)(bTime - aTime)/60);
925             } else if (field.equalsIgnoreCase("s")) {
926                 long aTime = aDate.toDate().getTime() / 1000;
927                 long bTime = bDate.toDate().getTime() / 1000;
928     
929                 return new Integer((int)(bTime - aTime));
930             } else {
931                 throw new AspException("Unknown date field identifier: " + field);
932             }
933             return new Integer(diff);
934         }
935     }
936 
937     /** Date part function */
938     static class DatePartFunction extends AbstractFunctionNode
939     {
940         /**
941          * Executes this function.
942          * @param values Parameters for this expression.
943          * @param context AspContext under which to evaluate this expression.
944          * @return Return value of this expression.
945          * @throws AspException if an error occurs.
946          * @see AbstractFunction#execute(Vector,AspContext)
947          */
948         public Object execute(Vector values, AspContext context)
949             throws AspException
950         {
951             if (values.size()!=2) {
952                 throw new AspException("Invalid number of " +
953                     "arguments: " + values.size());
954             }
955             String field = Types.coerceToString(values.get(0));
956             AspDate aDate = Types.coerceToDate(values.get(1));
957             Calendar aCal = aDate.toCalendar();
958 
959             int val;
960 
961             if (field.equalsIgnoreCase("yyyy")) {
962                 val = aCal.get(aCal.YEAR);
963             } else if (field.equalsIgnoreCase("q")) {
964                 val = (aCal.get(aCal.MONTH) / 4)+1;
965             } else if (field.equalsIgnoreCase("m")) {
966                 val = (aCal.get(aCal.MONTH))+1;
967             } else if (field.equalsIgnoreCase("y")) {
968                 val = aCal.get(aCal.DAY_OF_YEAR);
969             } else if (field.equalsIgnoreCase("d")) {
970                 val = aCal.get(aCal.DAY_OF_MONTH);
971             } else if (field.equalsIgnoreCase("w")) {
972                 val = aCal.get(aCal.DAY_OF_WEEK);
973             } else if (field.equalsIgnoreCase("ww")) {
974                 val = aCal.get(aCal.WEEK_OF_YEAR);
975             } else if (field.equalsIgnoreCase("h")) {
976                 val = aCal.get(aCal.HOUR_OF_DAY);
977             } else if (field.equalsIgnoreCase("n")) {
978                 val = aCal.get(aCal.MINUTE);
979             } else if (field.equalsIgnoreCase("s")) {
980                 val = aCal.get(aCal.SECOND);
981             } else {
982                 throw new AspException("Unknown date field identifier: " + field);
983             }
984             return new Integer(val);
985         }
986     }
987 
988     /** Date serial function */
989     static class DateSerialFunction extends AbstractFunctionNode
990     {
991         /**
992          * Executes this function.
993          * @param values Parameters for this expression.
994          * @param context AspContext under which to evaluate this expression.
995          * @return Return value of this expression.
996          * @throws AspException if an error occurs.
997          * @see AbstractFunction#execute(Vector,AspContext)
998          */
999         public Object execute(Vector values, AspContext context)
1000            throws AspException
1001        {
1002            if (values.size()!=3) {
1003                throw new AspException("Invalid number of " +
1004                    "arguments: " + values.size());
1005            }
1006            int year = Types.coerceToInteger(values.get(0)).intValue();
1007            if (year < 100) year += 1900;
1008            int month = Types.coerceToInteger(values.get(1)).intValue()-1;
1009            int day = Types.coerceToInteger(values.get(2)).intValue();
1010            return new AspDate(month,day,year);
1011        }
1012    }
1013
1014    /** Date value function */
1015    static class