[stringtemplate-interest] Grid Problems

Bob citibob at comcast.net
Sat May 3 12:04:11 PDT 2008


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>




More information about the stringtemplate-interest mailing list