tags:

views:

1184

answers:

3

I'm not sure if there is a way to do this in Velocity or not:

I have a User POJO which a property named Status, which looks like an enum (but it is not, since I am stuck on Java 1.4), the definition looks something like this:

public class User  {

    // default status to User
    private Status status = Status.USER;

    public void setStatus(Status status) {
        this.status = status;
    }

    public Status getStatus() {
        return status;
    }

And Status is a static inner class:

public static final class Status {

    private String statusString;

    private Status(String statusString) {
        this.statusString = statusString;
    }

    public final static Status USER = new Status("user");
    public final static Status ADMIN = new Status("admin");
    public final static Status STATUS_X = new Status("blah");

    //.equals() and .hashCode() implemented as well
}

With this pattern, a user status can easily be tested in a conditional such as

if(User.Status.ADMIN.equals(user.getStatus())) ...

... without having to reference any constants for the status ID, any magic numbers, etc.

However, I can't figure out how to test these conditionals in my Velocity template with VTL. I'd like to just print a simple string based upon the user's status, such as:

Welcome <b>${user.name}</b>!
<br/>
<br/>

#if($user.status == com.company.blah.User.Status.USER)
    You are a regular user
#elseif($user.status == com.company.blah.User.Status.ADMIN)
    You are an administrator
#etc...

#end

But this throws an Exception that looks like org.apache.velocity.exception.ParseErrorException: Encountered "User" at webpages/include/dashboard.inc[line 10, column 21] Was expecting one of: "[" ...

From the VTL User Guide, there is no mention of accessing a Java class/static member directly in VTL, it appears that the right hand side (RHS) of a conditional can only be a number literal, string literal, property reference, or method reference.

So is there any way that I can access static Java properties/references in a Velocity template? I'm aware that as a workaround, I could embed the status ID or some other identifier as a reference in my controller (this is a web MVC application using Velocity as the View technology), but I strongly do not want to embed any magic numbers or constants in the view layer.

+2  A: 

I figured out a workaround that allows me to add each User.Status object to the Velocity context, which avoids any sort of references to constants or magic numbers in the template.

On the controller/Java side:

// put the statuses directly into the model
Map statusMap = new HashMap();
statusMap.put("user", User.Status.USER);
statusMap.put("groupOperator", User.Status.ADMIN);
...
modelAndView.addObject("statusmap", statusMap);

And then in the template these values can be referenced like so:

#if($user.status == $statusmap.user)
   You are a regular user
#elseif($user.status == $statusmap.admin)
    You are an administrator
##etc...
#end
matt b
+2  A: 

Yeah, Velocity doesn't natively grok classes and packages. You could do what you did, or use the FieldMethodizer class to automate that. Another option would be the FieldTool in VelocityTools 2.0.

Nathan Bubna
A: 

Try to use FieldMethodizer of Velocity, it's not the best solution but you can do something.

With this class you can call to static public constants, please see the link:

FieldMethodizer API

Vudko