[antlr-interest] StringTemplate enhancement question

Terence Parr parrt at cs.usfca.edu
Tue Jun 22 10:48:29 PDT 2004


To anyone playing with StringTemplate...

First, good news.  The use of StringTemplate 2.0b1 in my ANTLR 3.0 code 
generator is a truly a joy.

Next, I have a problem.  Recall that the distinguishing characteristic 
of ST is that it strictly enforces separation of model and view; that 
is, your view literally cannot become part of the program.  This 
manifests itself in, for example, the ANTLR code generator as a 
guarantee that the CodeGenerator object is truly language-independent 
and consequently ANTLR should be easily retargetable.  Literally every 
character that goes out to the generated Java file comes from a 
template; no literals in the CodeGenerator. :)

Ok, on to my desired enhancement...

I often have lists of things that need to be formatted, but the list 
items are actually pieces of data that are not already in an object.  I 
need ST to do something like:

Ter=3432
Tom=32234
....

using template:

$items:{$attr.name$=$attr.type$}$

This example will call getName() on the objects in items attribute, but 
what if they aren't objects?  I have perhaps two parallel arrays 
instead of a single array of objects containing two fields.  One 
solution is allow Maps to be handled like properties so that attr.name 
would fail getName() but then see that it's a Map and do 
attr.get("name") instead.

This very clean approach is espoused by some, but the problem is that 
it's a hole in my separation rules.  People can put the logic in the 
view because you could say: "go get bob's data" in the view:

Bob's Phone: $db.bob.phone$

A view should not be part of the program and hence should never be able 
to go ask for a specific person's data.  Humor me that it's good to be 
ruthless (or read my paper <snicker>).  Is there another way to fake 
aggregates by given separate pieces of data to ST and have it 
aggregate?

Well, first I tried passing in

new Object() {
   public String getName() {return "Ter";}
   public String getType() {return "234";}
}

But it complains that the damn anonymous class is not public :(  
Bastards!  Those things suck.

So, what about something like:

     st.setAttribute("items.name", "Ter");
     st.setAttribute("items.type", "342");

But that isn't quite it.  How does ST know when to make a new items 
object in the list versus setting a prop within the last item added or 
whatever.  Or, what about a new method:

     st.setupAttribute("items.name", "Ter");
     st.setupAttribute("items.type", "342");
     st.nextAttribute();

er something?

Seems like the various pieces could go in together like this:

     st.setAttribute("tokens.name,type", new Object[] {"Ter","342"});

which is weird, but would work.  I'd have to parse the attribute name a 
bit and pull apart stuff to make a little hashtable out of name/type.  
I suppose I could pass two arrays: one for the names and one for the 
values.  Ick.  Could do this I suppose:

     st.setAttribute("tokens", new Object[] {"name","Ter","type","342"});

Just intersperse the keys with the values.  gross ;)

A final option.  Believe it or not, due to the wacky init {...} syntax 
for anon inner classes, this would work too:

     st.setAttribute("tokens", new HashMap() {{put("name","Ter"); 
put("type","342");}});

The double {{ }} would be required.  That is, the following code

HashMap m = new HashMap() {{put("name","Ter"); put("type","342");}};
System.out.println(m);

prints

{type=342, name=Ter}

Again, though, how do I prevent people from passing in a regular 
HashMap that is actually just a proxy for their DB?  Then the view 
could do DB accesses!  Oh, I could make a special object that worked 
like a HashMap, but which wouldn't allow subclasses so people couldn't 
sneak in a modified version that was actually a database.

Which would you choose?  Anybody have some insight?

Ter
--
CS Professor & Grad Director, University of San Francisco
Creator, ANTLR Parser Generator, http://www.antlr.org
Cofounder, http://www.jguru.com
Cofounder, http://www.knowspam.net enjoy email again!
Cofounder, http://www.peerscope.com pure link sharing





 
Yahoo! Groups Links

<*> To visit your group on the web, go to:
     http://groups.yahoo.com/group/antlr-interest/

<*> To unsubscribe from this group, send an email to:
     antlr-interest-unsubscribe at yahoogroups.com

<*> Your use of Yahoo! Groups is subject to:
     http://docs.yahoo.com/info/terms/
 



More information about the antlr-interest mailing list