Template output for array variables

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Template output for array variables

Jason Pettiss
Maybe I'm crazy, but here is an idea.  When using a template variable
which happens to be an array or list as a scalar, instead of using
toString() as the value, use the first item's toString().  If I have a
string array of size one under key 'name', ${name} will be replaced
with, say, "[Ljava.lang.String;@4dd1b".  Which is useful only insofar as
it tells me, the template author, that I need to use #foreach.

I suggest this because it would be useful to create a per-request
VelocityContext object that takes as its first constructor argument the
result of 'new HashMap(request.getParameterMap())'.  This effectively
allows me to treat request parameters the same as request scoped
objects, which greatly reduces the mundaneity of writing a typical
webapp.  The most annoying common thing I find myself doing is
ctx.put(paramName, request.getParameter(paramName)), just so the values
that are posted are available not only to my request handler, but also
to the resulting template page.  This is incredibly useful for
maintaining relatively stateless pages.

Anyway, the javadoc for ServletRequest.getParameterMap() says this:*
*
--
Returns an immutable java.util.Map containing parameter names as keys
and parameter values as map values. The keys in the parameter map are of
type String. The values in the parameter map are of type String array.
--

Thus back to my original suggestion.  Right now of course, I get
[Ljava.lang.String;@xxxxxx for all my request parameters that I try to
access on my template, unless I wrap them with an impotent foreach:
#foreach($myvar)$myvar#end.

Am I goofy?  Would it break anything to treat lists as scalars when they
are in scalar context in a template?  I can't imagine anyone uses the
current output of such a variable, other than for debugging purposes.

Jason Pettiss
[hidden email]



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Template output for array variables

Shinobu Kawai
Hi Jason,

> Maybe I'm crazy, but here is an idea.  When using a template variable
> which happens to be an array or list as a scalar, instead of using
> toString() as the value, use the first item's toString().  If I have a
> string array of size one under key 'name', ${name} will be replaced
> with, say, "[Ljava.lang.String;@4dd1b".  Which is useful only insofar as
> it tells me, the template author, that I need to use #foreach.

When there's a will, there's a way.  You can create a custom
ReferenceInsertionEventHandler to get the desired behaviour.
  http://jakarta.apache.org/velocity/developer-guide.html#EventCartridge%20and%20Event%20Handlers

Best regards,
-- Shinobu

--
Shinobu Kawai <[hidden email]>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Template output for array variables

Jason Pettiss
Amazing.  Awesome.  Exactly what I need.

class ReferenceInserter
    implements ReferenceInsertionEventHandler
{
    public Object referenceInsert(
        String reference,
        Object value)
    {
        if (value instanceof Object[])
        {
            Object[] a = (Object[])value;
            if (a.length>0) value = a[0];
        }
        return value;
    }  
}

I love velocity.  :-)

Thanks,

Jason Pettiss
[hidden email]



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Template output for array variables

Jason Pettiss
Update... I am constructing my VelocityContext by handing it new
HashMap(request.getParameterMap()) so as to allow request parameters to
be treated like request scoped variables and allow them to seamlessly
'flow through' a request.  I was having a problem as $paramName was
outputting an array toString rather than the actual parameter.  So I
constructed a ReferenceInsertionEventHandler, which fixed that problem.

Turns out this is just a bit daft, because now a simple #if against a
literal parameter will fail.  If I hit "?apples=yummy" and on my
template I have:

#if( $apples == 'yummy' )
Apples are yummy.
#else
I am daft.
#end

I will always be reminded that sometimes poking at a hornets' nest
stings you.  In this case I assume that since $apples is a String[]
instead of a String, that the #if is failing because it doesn't use
ReferenceInsertionEventHandler to obtain the value of a variable in
order to test against-- only to output.

Back to the drawing board.  Was hoping to make this 'efficient' by
simply wrapping the raw parameter map, but it's looking like it'll be
safer just to give up this angle of attack.  :-)

Jason Pettiss
[hidden email]


Jason Pettiss wrote:

> Amazing.  Awesome.  Exactly what I need.
>
> class ReferenceInserter
>    implements ReferenceInsertionEventHandler
> {
>    public Object referenceInsert(
>        String reference,
>        Object value)
>    {
>        if (value instanceof Object[])
>        {
>            Object[] a = (Object[])value;
>            if (a.length>0) value = a[0];
>        }
>        return value;
>    }   }
>
> I love velocity.  :-)
>
> Thanks,
>
> Jason Pettiss
> [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]