[antlr-interest] StringTemplate conditional

Kay Roepke kroepke at classdump.org
Fri Aug 3 06:42:17 PDT 2007


Hi Jeff!

On Aug 3, 2007, at 2:54 PM, Barnes, Jeff wrote:

> The StringTemplate declaration is not valid. Does this break model/ 
> view
> separation?

Sort of, yes.

> Why doesn't StringTemplate support this? Is there another
> way to conceptualize this problem?

StringTemplate doesn't support arbitrary comparisons. (The  
user=form.selectedUser is throwing it off.)

You will have to pass in the information whether a user is selected  
or not, doing the actual comparison
in code. This ensures that no (business) logic is in the view.  
StringTemplate is very rigorous with this,
providing (almost) no means to cirumvent this. But you wouldn't wanna  
do that anyway.

So, what are your options?
You could add a controller layer to shield your User object from  
needing to know whether it is selected or not.
That would add a lot of overhead, though.

Disclaimer: Written in mail, might not compile or might bring the  
world to an end.

It'd look like this (adding to your example):

	static class FormController {
		Form form;
		public FormController(Form form) { this.form = form; }
		public UserController[] getUsers() {
			int numUsers = form.getUsers().length;
			UserController[] users = new UserController[numUsers];
			for (int i=0; i<numUsers; i++) {
				User user = form.getUsers()[i];
				users[i] = new UserController(user, form.getSelectedUser() == user);
			}
			return users;
		}
	}
	
	static class UserController {
		User user;
		boolean selected;
		public UserController(User user, boolean selected) { this.user =  
user; this.selected = selected;}
		public String getName() { return user.getName(); }
		public boolean getSelected() { return selected; }
	}

     public static void main(String[] args)
     {
         User[] users = new User[2];
         users[0] = new User();
         users[0].name = "Terence";
         users[1] = new User();
         users[1].name = "Parr";

         Form f = new Form();
         f.users = users;
         f.selectedUser = users[1];

         StringTemplate st = new StringTemplate("$form.users:{user |  
<option"+
                "$if(user.selected)$ selected$endif$>" +
                "$user.name$</option>};separator=\"\n\"$");
         st.setAttribute("form", new FormController(f));
         System.out.println(st.toString());
     }

That prints the correct string, but is adding a lot of overhead.
Alternatively, if you are comfortable with adding presentation code  
to Form, you can do this:

import org.antlr.stringtemplate.StringTemplateGroup;
import org.antlr.stringtemplate.StringTemplate;

public class Test
{
     static class User {
         String name;
         public String getName() {
             return name;
         }
     }

     static class Form {
         User[] users;
         User selectedUser;
         public User[] getUsers() { return users; }
         public User getSelectedUser() { return selectedUser; }

		public StringTemplate[] getUserTemplates() {
			StringTemplate[] ts = new StringTemplate[users.length];
			for (int i = 0; i < users.length; i++) {
				ts[i] = new StringTemplate("<option$if(selected)$ selected$endif$> 
$name$</option>");
				ts[i].setAttribute("selected", users[i] == selectedUser);
				ts[i].setAttribute("name", users[i].getName());
			}
			return ts;
		}
     }

     public static void main(String[] args)
     {
         User[] users = new User[2];
         users[0] = new User();
         users[0].name = "Terence";
         users[1] = new User();
         users[1].name = "Parr";

         Form f = new Form();
         f.users = users;
         f.selectedUser = users[1];

         StringTemplate st = new StringTemplate 
("$form.userTemplates;separator=\"\n\"$");
         st.setAttribute("form", f);
         System.out.println(st.toString());
     }
}


Or naturally any abstraction you'd like to see.

OTOH if you do not depend on the order of the options (though most  
probably you do), you could
iterate over two different lists (one for the unselected users and on  
for the selected ones).
But I think iterating over one "annotated list" is better. It just  
depends on how you structure your
code, so that you have a clean separation of model and view in your  
Java code. But then again, this
is just another example of MVC at work :)

HTH,
-k

P.S.: This mail probably belongs on stringtemplate-interest but I  
didn't bother to crosspost or
set the reply-to. It's a bit off-topic for antlr-interest.
-- 
Kay Röpke
http://classdump.org/






More information about the antlr-interest mailing list