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