[stringtemplate-interest] Grid Problems

Terence Parr parrt at cs.usfca.edu
Fri Feb 19 14:12:50 PST 2010


Oh!  Well, any multi-valued attr should iterate. Can you make your own Aggregate?
Ter
On Feb 19, 2010, at 2:01 PM, James Briant wrote:

> Its Java 1.6 on OSX, using st 3.2. The problem is that a HashMap is treated as iterable. So when you do
> 
> <something.property:template()>
> 
> where .property evaluates to a HashMap, the HashMap is converted to a list of its values and then each entry is passed to template. Instead, it should pass the HashMap itself to the template, as happens with an Aggregate. Now since I imagine a lot of people use HashMap and expect to get a list of its values in this case, I suggest making Aggregate public, so that it can be used in place of a real class.
> 
> 	protected static Object convertAnythingIteratableToIterator(Object o) {
> 		Iterator iter = null;
> 		if ( o instanceof Collection ) {
> 			iter = ((Collection)o).iterator();
> 		}
> 		else if ( o instanceof Map ) {
> 			iter = ((Map)o).values().iterator();
> 		}
> 		else if ( o instanceof Iterator ) {
> 			iter = (Iterator)o;
> 		}
> 		if ( iter==null ) {
> 			return o;
> 		}
> 		return iter;
> 	}
> 
> Jamie
> 
> On Fri, Feb 19, 2010 at 1:00 PM, Terence Parr <parrt at cs.usfca.edu> wrote:
> Hi James, I'm very surprised that the map example doesn't work for you. I use it all the time and specifically designed ST to do that. what doesn't work? Oh, is this C# with an anonymous class?
> 
> > class  {
> >   public String name;
> >   public List<Number> phones;
> > }
> 
> perhaps make that class public
> T
> On Feb 19, 2010, at 11:41 AM, James Briant wrote:
> 
> > I have this same problem. Specifically,
> >
> > class  {
> >   public String name;
> >   public List<Number> phones;
> > }
> > class Number {
> >   public String number;
> > }
> >
> > Person person = new ....
> >
> > Will work with <person.phones:writephone()>
> >
> > Using a HashMap will not:
> >
> > HashMap person = new HashMap()
> > HashMap phone1 = new HashMap()
> > person.put("phones",phone1);
> >
> > But if you hack StringTemplate.Aggregate to make it public,
> >
> > Aggregate person = new Aggregate()
> > Aggregate phone1 = new Aggregate()
> > person.put("phones",phone1)
> >
> > This works.
> >
> >
> > This is because (in 3.2) in ASTExpr.java convertAnythingIteratableToIterator and convertAnythingToIterator will BOTH convert a HashMap to a list, but not a class, and not StringTemplate.Aggregate.
> >
> > I request that Aggregate, or an object like Aggregate is implemented so that during rapid prototyping I can create aggregate objects without having to create specific classes.
> >
> > Thanks!
> >
> >
> >
> > On Tue, May 6, 2008 at 9:27 AM, Terence Parr <parrt at cs.usfca.edu> wrote:
> > Hi Bob, i'm racing to get ANTLR v3.1 out the door...I'll get to this
> > as soon as i can.
> > T
> > On May 3, 2008, at 12:04 PM, Bob wrote:
> >
> > > I have a system that produces data in 2-D grids (rows-and-columns).
> > > Each column has a name.  This seemed like a perfect match for
> > > StringTemplate.
> > >
> > > I've included at the end of this email a template that I wish to use
> > > to
> > > generate a report from my 2-D grids.  In particular, I wish to:
> > >
> > > 1. Create a 1-row grid (person) containing one person record.
> > > 2. Create a multi-row grid (phones) containing phone numbers for the
> > > person.
> > > 3. Format it all together as shown in the template at the end of this
> > > message.
> > >
> > > The basic operation here is to set a StringTemplate attribute to one
> > > of
> > > my grids (StringTableModel).  I want to make a function like:
> > >
> > > public static void setAttribute(StringTemplate st, String var,
> > > StringTableModel val)
> > >       { ... }
> > >
> > > Then I use code as follows to generate my report:
> > >
> > >       StringTemplate st = ....;
> > >
> > >       StringTableModel sperson = new StringTableModel(dmod.getPersonSb(),
> > > sfmap);
> > >       setAttribute(st, "person", sperson);
> > >
> > >       StringTableModel sphones = new StringTableModel(dmod.getPhonesSb(),
> > > sfmap);
> > >       setAttribute(st, "phones", sphones);
> > >
> > >       return st.toString();
> > >
> > > Unfortunately, I came up against several difficulties in figuring out
> > > what to place in the body of the setAttribute(StringTemplate, String,
> > > StringTableModel) function:
> > >
> > > 1. I first tried setting multi-valued attributes as follows.  The
> > > parser
> > > complained that I couldn't have "." in an attribute name:
> > >       for (int col=0; col<val.getColumnCount(); ++col) {
> > >               String colName = var + "." + val.getColumnName(col) + "";
> > >               for (int row=0; row<val.getRowCount(); ++row) {
> > >                       st.setAttribute(colName, val.getValueAt(row, col));
> > >               }
> > >       }
> > >
> > > 2. Then I tried the syntax shown in the docs for 2-5 column multi-
> > > valued
> > > attributes, as follows.  The parser also did not understand this,
> > > since
> > > I'm only setting one column at a time:
> > >       for (int col=0; col<val.getColumnCount(); ++col) {
> > >               String colName = var + ".{" + val.getColumnName(col) + "}";
> > >               for (int row=0; row<val.getRowCount(); ++row) {
> > >                       st.setAttribute(colName, val.getValueAt(row, col));
> > >               }
> > >       }
> > >
> > >
> > > 3. Then I tried creating a HashMap for each row, and setting the value
> > > once per row.  This ALMOST worked.  It worked as long as you have 2 or
> > > more phone numbers.  But if you had just one phone number (and in my
> > > case 2 columns), the system interpreted the data as two single-valued
> > > attributes, as opposed to one aggregate attribute.  Thus, it worked
> > > if I
> > > had 2 phone numbers, but threw an exception if I had just one.  Is
> > > this
> > > a bug, or is that the intended behavior?
> > >       for (int row=0; row<val.getRowCount(); ++row) {
> > >               HashMap map = new HashMap();
> > >               for (int col=0; col<val.getColumnCount(); ++col) {
> > >                       map.put(val.getColumnName(col), val.getValueAt(row, col));
> > >               }
> > >               st.setAttribute(var, map);
> > >       }
> > >
> > > 4. I figured maybe if I make each column as a list of attributes, this
> > > would work.  No such luck...
> > >       HashMap map = new HashMap();
> > >       for (int col=0; col<val.getColumnCount(); ++col) {
> > >               List list = new ArrayList(val.getRowCount());
> > >               for (int row=0; row<val.getRowCount(); ++row) {
> > >                       list.add(val.getValueAt(row, col));
> > >               }
> > >               map.put(val.getColumnName(col), list);
> > >       }
> > >       st.setAttribute(var, map);
> > >
> > > 5. Finally, I hacked the source code, making StringTemplate.Aggregate
> > > public, to allow the following.  Since StringTemplate.Aggregate is
> > > basically a wrapper around HashMap, I'm surprised that behaved
> > > differently from the HashMap example above.  But it did: this worked,
> > > whereas the example above did not:
> > >
> > >
> > >       for (int row=0; row<val.getRowCount(); ++row) {
> > >               StringTemplate.Aggregate map = new StringTemplate.Aggregate();
> > >               for (int col=0; col<val.getColumnCount(); ++col) {
> > >                       map.put(val.getColumnName(col), val.getValueAt(row, col));
> > >               }
> > >               st.setAttribute(var, map);
> > >       }
> > >
> > > ---------------------
> > > Current status: at this point, I know of no way to do what I want
> > > without hacking the source code.  Any suggestions on a solution to
> > > this
> > > problem?
> > >
> > > Thanks,
> > > -- Bob
> > >
> > >
> > > // ===================================================
> > > // summary.st
> > >
> > > <ul>
> > > <li>Name: $person.firstname$ $person.lastname$</li>
> > > <li>Email: $person.email$</li>
> > > </ul>
> > >
> > >
> > > <h3>Phones</h3>
> > > <table border=1>
> > > $phones:{it |
> > >  <tr>
> > >    <td>$it.groupid$</td><td>$it.phone$</td>
> > >  </tr>
> > > }$
> > > </table>
> > >
> > >
> > > _______________________________________________
> > > stringtemplate-interest mailing list
> > > stringtemplate-interest at antlr.org
> > > http://www.antlr.org:8080/mailman/listinfo/stringtemplate-interest
> >
> > _______________________________________________
> > stringtemplate-interest mailing list
> > stringtemplate-interest at antlr.org
> > http://www.antlr.org:8080/mailman/listinfo/stringtemplate-interest
> >
> 
> _______________________________________________
> stringtemplate-interest mailing list
> stringtemplate-interest at antlr.org
> http://www.antlr.org/mailman/listinfo/stringtemplate-interest
> 



More information about the stringtemplate-interest mailing list