Hi all!

I've gone and made a couple of changes to Velocity to help support my
project, and I thought I'd share them with the masses.

Earlier, I made a change to let the comparison routines support
"Compareable" objects. After playing with that, it wasn't what I needed.

So, now I've added support for a new class
org.apache.velocity.util.VelocityValue.

VelocityValue is a "multi-typed" value.

All of these "work"

new VelocityValue(1.0); // These are doubles
new VelocityValue(new Integer(1)); // It's still a double internally
new VelocityValue("Neato"); // Strings
new VelocityValue(new java.util.Date); // Dates
new VelocityValue(true); //Booleans
new VelocityValue(new Boolean(true)); // Same thing

Once things are placed into VelocityValues, you can do pretty normal things
with them.

Math and comparions, specifically.

For Math, I've changed the internals of the interpreter.

The interpreter now knows how to perform Math on Integers, Strings, and
VelocityValues.

// Assume:
// context.put("vInt", new VelocityValue(1));
// context.put("vStr", new VelocityValue("Bob"));
// context.put("vStrN, new VelocityValue("123"));
// context.put("vDate", new VelocityValue(new java.util.Date()));  // Dec
11, 2001

#set ($foo = 1 + 1)  // result is an Integer, 2
#set ($foo = 1 + $vInt) // result is an Integer, 2
#set ($foo = $vInt + 1) // result is a VelocityValue, 2
#set ($foo = "This" + "That") // result is a String, "ThisThat"
#set ($foo = "This" + $vStr) // result is a String, "ThisBob"
#set ($foo = $vStr + "That") // result is a VelocityValue, "BobThat"
#set ($foo = $vStrN + "4") // result is a VelocityValue, "1234"
#set ($foo = 1 + $vStrN) // result is an Integer, 124
#set ($foo = 1 + "234") // result is an Integer, 235
#set ($foo = "1" + 1) // result is a String, "11"
#set ($foo = $vDate + 1) // result is a VelocityValue, "tomorrow" (Dec 12,
2001).
#set ($foo = 1 + $vDate) // result is a Integer, 1 (objects used is where
they "don't belong" are "nothing", the result is the left hand side of the
expression.)

Note that the left hand side of the equation determines the result type.

You can compare object of like type, and as in normal expressions, the left
hand side will coerce the right hand side for comparisons.

#if (1 < 2) true #end
#if ("1" < "2") true #end
#if(1 < "2") true #end
#if("10000" < 1234) true #end  // This is non-obvious, but "10000" is less
than "1234"
#if(1234 < "10000") true #end  // Don't try this stuff at home, kids.

This works as well:
$if($vInt) // or any VelocityValue

VelocityValues support asString, asNumber, asBoolean, and asDate, that you
can then apply other methods to (like substring, for example). They will
automatically convert for you. So, #set($foo = $vInt.asString() + 1) = "11"
(Integer value converted to String coerces + to string expression,
converting 1 to "1").

One last thing, for you SQL folks out there. VelocityValues support NULLS.
Any math with NULLS results in a NULL value, however any comparision with
NULL results in FALSE. Note that SQL NULLs are different from Java Null.
They're there if you want them. There is an isNull() method.

For conversions:
To Number:
    Strings convert to the base 10 numbers, otherwise 0.
    Dates convert to their number of seconds since epoch.
    Booleans are 0 or 1

To String:
    Pretty standard. There isn't any way to control the Date format at the
moment.

To Date:
    Convert to a number, and use that number as the number of seconds since
epoch.

To Boolean:
    0 = false, "" = false, NULL is false, everything else is true.

A couple of key things to note.

I strived to maintain backward compatability, even within the implemenation.
For example, for the Math and Comparisons, it still uses the same code if
you pass in Integers instead of VelocityValues or Strings. Before, it would
check for Integers and Do The Right Thing, or raise an error. Now, rather
than raising an error, it does Other Things. This specifically means that
there shouldn't be any extra cost if you use Velocity without
VelocityValues.

The exceptions here are that where in the past things like #if(1 < "2")
would raise an error, now they Do Something. This means that they don't
necessarily return false (like they do now). (so, for example, the logical
test in the test suite currently fails).

The other issue is that, of course, I haven't changed how things are parsed.
So, for example, you can't put floats into your scripts yet. You also cannot
create VelocityValues within scripts. You can do sick things like
#($vInt.setValue("1.2")) which will set the internal value to a String of
1.2, and will then convert it to a double. So, $vInt * 10 would equal 12.

I don't really plan on doing that, personally. Do your logic in Java, I say.
:-)

It hasn't been really beat on yet, I'll be doing that tomorrow. Also, the
patch has a couple of System.out.println debug things left in there, but
they can be easily removed.

Anyway, the patch is attached. I'd appreciate any comments. I'm particularly
interested in weird exceptions, etc. One thing it doesn't do right now is
Date subtraction. (Date1 - Date2 = # of days)

The patch is applied at the src/java/org/apache level.

$ cd $velhome/src/java/org/apache
$ patch -d . -p0 < /tmp/patch.out

Regards,

Will Hartung
([EMAIL PROTECTED])

Attachment: patch.out
Description: Binary data

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to