[stringtemplate-interest] Maps with object keys

Caleb Lyness caleb.lyness at ezswitch.net
Fri Nov 30 05:06:33 PST 2007


John Snyders wrote:
> I wrote down my thoughts on what the data model for string template 
> should be here:
>
> http://hardlikesoftware.com/weblog/2007/06/01/thoughts-on-stringtemplate-part-1/
>
> I wrote "The keys of a map must be scalar strings.".  I was not 
> writing about the current implementation
> but about some idealized StringTemplate language. So why did I write 
> this? I'm sure I'm giving it more
> thought now than when I originally wrote it.
>
> The StringTemplate data model consists of scalars, lists and maps (yes 
> it also has objects but I think these
> should be treated like maps from the template point of view). The only 
> scalar type it has a literal syntax for
> is a string. The only other scalar type it knows anything about is 
> boolean which it only uses in if expressions.
> Basically StringTemplate has a very limited set of data types that it 
> knows about. I think this is a good thing.
>
> StringTemplate's job is to turn what you give it into strings - 
> nothing more. 
Hmmm, I fell into the trap of working with objects because it seemed a 
natural key, given that I was iterating
over a list of objects as compared to a list of strings.

"$hammers:{hammer|$stock.(hammer);null=\"0\"$}$"

I can see your point, but you must admit that it does not make it a particularly natural 
way to work:


            Map<String,Integer> hammersInStock = new HashMap<String,Integer>();
            hammersInStock.put(Hammer.MALLET.toString(), 5);
            hammersInStock.put(Hammer.CLUB.toString(), 2);
            st.setAttribute("stock", hammersInStock);		// map with key as object.toString
            st.setAttribute("hammers", hammers);		// list of objects
            String result = st.toString(); 

One has to know in detail what string template will do with the object to know if one must
insert a string or an object. If maps are only allowed to be indexed on a string then
a specialised map should be used and not a generic one accepting objects as the key. Restrictions
should be reflected clearly by the interface (usability-101). But I am getting side tracked.

>
> However it does have an important characteristic. It  lets scalars 
> pass through without type conversion
> from the program that created them to the renderer. This allows the 
> renderer to do type specific formatting.
> The default is a call to toString on the object. The renderer may know 
> about the objects type but the template
> should not know or care what type an attribute is other than is it a 
> scalar, list or map.
One does not add any additional type information here:

m.(x) gives

value = m.get(x)
if (value == null) value = m.get(x.toString())

x is still a "scalar" we know that m is a map. For maps we check for the 
scalar x before stringifying it and checking again.
>
> So although the scalar arguments that StringTemplate processes are 
> arbitrary types the only thing that
> it knows to do with them is turn them into strings. 
It knows how iterate over a collection of objects. That's a bit more 
than turning objects directly to strings. It also know about
null objects.
> Giving StringTemplate the ability to do any more than
> this (even in limited contexts) moves it closer to a general data 
> processing engine.
>
> We all know about how maps can be used to get around the view 
> separation (at the programmers
> discretion not the template writers). Allowing arbitrary types to be 
> passed to the "map" would make
> this easier to abuse. Currently if you wanted to pass complex data to 
> the map you need to serialize it as a string.
Can you explain more or give an example of how using an object as a map 
key would make it easier to abuse than it currently is?
>
> It makes sense to me that enums (hammer in the example) would be 
> converted to strings when used
> like this $stock.(hammer);null="0"$
Yes, it makes sense. But "stock" should only be allowed to be string 
based map... their would be no chance for confusion.
>
> The underlying question that this issue brings up is: should 
> StringTemplate be able to deal with any and all
> data structures the host language (e.g. Java) can implement or should 
> the program and it's data meet
> StringTemplate half way?
No. No additional type support required.
>
> StringTemplate does a lot already to make existing data structures 
> consumable to templates. But I don't think
> it should be expected to handle everything. Maps with non String keys 
> are an example.
>
> There are already any cases where ST requires the data model to 
> change. For example if you had a
> property for accountBalance you may need to add a property called 
> overdrawn because StringTemplate
> doesn't do math or comparisons.
>
> All this being said I wonder if an exception should be made for enums.
>
> Caleb, in your original example was Product an enum or are you looking 
> for maps with other key types?
It is an enum in the non java 5.0 sense

public class Product {

     public static X = Product("PX",10);
     public static Y = Product("PY",20);

     private Product(String name, long code) {
       ....
     }
    ....
}
>
> One problem I can see with a special case for enums is that ST doesn't 
> require Java 5.
Java 5 just adds a nice syntax for the enum concept. Still a very real 
pattern pre Java 5.
>
> -John
>
> Caleb Lyness wrote:
>> Terence Parr wrote:
>>> Hi Caleb! :)
>>>
>>> Heh, yeah, you're right...this is weird, though consistent with what  
>>> (x) means..(x) means "take the value of" or "immediately eval" rather  
>>> than lazy eval.  Sometimes you need to render an expression such as  
>>> for keys with maps.  It's an indirection and immediate eval.
>>>
>>> m.x gives m.get("x")
>>> m.(x) gives m.get(x.toString())
>>> m.(x+"foo") gives m.get(x + "foo")
>>>
>>> hmm...we do need a map look up with an object...i wonder what to do...
>>>   
>> Well as a step toward resolving the problem have a look at the 
>> attached test case.
>> Perhaps you would like to add it to TestStringTemplate and create an 
>> issue report
>> for the problem?
>>
>> Cheers
>>      Caleb
>>> Ter
>>>
>>> On Nov 23, 2007, at 3:34 AM, Caleb Lyness wrote:
>>>
>>>   
>>>> Hi all,
>>>>
>>>> I have not been keeping up to date with my string template mails...  
>>>> perhaps this has been covered before, just point me at the thread  
>>>> if already covered...
>>>> This is also being tested against ST-3.0.
>>>>
>>>> Here is a segment of a test template:
>>>>
>>>>   $products: {product |
>>>>   <tr>
>>>>      <td>$product$</td>
>>>>      <td>$report.productReadStats.(product);null="0"$</td>
>>>>      <td>$report.productActivationsStats.(product);null="0"$</td>
>>>>      <td>$report.productIssuedStats.(product);null="0"$</td>
>>>>   </tr>}$
>>>>
>>>> On the model side I had:
>>>>
>>>> public HashMap<Product, Integer> productReadStats = new  
>>>> HashMap<Product, Integer>();
>>>> public HashMap<Product, Integer> productIssuedStats = new  
>>>> HashMap<Product, Integer>();
>>>> public HashMap<Product, Integer> productActivationsStats = new  
>>>> HashMap<Product, Integer>();
>>>>
>>>> String template would always report the stats as 0 (via the null  
>>>> setting). My guess from what I am seeing
>>>> is that ST-3.0 is dereferencing (product) to a string and not an  
>>>> object. When looking up the value in the
>>>> map the string does not result in the correct map reference.
>>>>
>>>> Changing my map to a string based key:
>>>>
>>>> public HashMap<String, Integer> productReadStats = new  
>>>> HashMap<String, Integer>();
>>>> ... etc ...
>>>>
>>>> resulted in the correct values.
>>>>
>>>> Is this a known problem/limitation? Or is this considered the  
>>>> correct behaviour. Surely an attempt should be
>>>> made to lookup the object directly and then use the object.toString 
>>>> () as the key as a 2nd attempt?
>>>>
>>>> Cheers
>>>>       Caleb.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org:8080/pipermail/stringtemplate-interest/attachments/20071130/d69d11fb/attachment-0001.html 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 3269 bytes
Desc: S/MIME Cryptographic Signature
Url : http://www.antlr.org:8080/pipermail/stringtemplate-interest/attachments/20071130/d69d11fb/attachment-0001.bin 


More information about the stringtemplate-interest mailing list