[stringtemplate-interest] Managing template parameters

Terence Parr parrt at cs.usfca.edu
Mon Dec 8 10:54:37 PST 2008


On Nov 23, 2008, at 4:38 PM, Nathan Ward wrote:

> That's more than I was suggesting.

Added feature request anyway. Sounds like a good idea:

http://www.antlr.org:8888/browse/ST-46

> I just wanted to be able do something like:
>
>     myTemplateGroup.setAttribute("project", myProject);
>
> Many of my templates don't need this object, but some low-level  
> templates,
> such as the msgKeyTag template shown below do need the project  
> object. In

Interesting...sort of a global attribute?

> order to test msgKeyTag template with a JUnit based test, I had to  
> make a
> base template group and a temporary template that takes the project  
> object
> as a formal parameter so that the object would be available when the
> msgKeyTag template was invoked.

Can't you use setUp or whatever with junit to set default parameters?  
Why not just have a method/factory create templates and set the  
default parameters?

Ter
>
>
> I would think that this situation is not uncommon. So, either other  
> people
> don't test small templates like this or other people also have to  
> come up
> with similar solutions to unit test these kinds of templates. So, I  
> thought
> this concept and API might make sense.
>
> // Implicit variable references: project
> // Calls different template based on project.properties.msgFormatName
> property,
> // e.g. jstlMsgFormat() template if msgFormatName is "jstl"
> msgKeyTag(msgKey) ::= <<
> $(msgFormatTemplateNameMap.(project.projectOptions.msgTagType))(...)$
>>>
>
> jstlMsgFormat(msgKey) ::= <<
> <fmt:message key="$msgKey$">
>>>
>
> strutsMsgFormat(msgKey) ::= <<
> <bean:message key="$msgKey$">
>>>
>
> springMsgFormat(msgKey) ::= <<
> <spring:message code="$msgKey$">
>>>
>
> // Maps msg format name to msg format template
> // e.g. "jstl" maps to jstlMsgFormat template to produce  
> <fmt:message ...
> tag
> // Used by msgKeyTag template
> msgFormatTemplateNameMap ::= [
>        "jstl":"jstlMsgFormat",
>        "struts":"strutsMsgFormat",
>        "spring":"springMsgFormat"
> ]
>
>
> -----Original Message-----
> From: Terence Parr [mailto:parrt at cs.usfca.edu]
> Sent: Friday, November 21, 2008 1:53 PM
> To: Nathan Ward
> Cc: stringtemplate-interest at antlr.org
> Subject: Re: [stringtemplate-interest] Managing template parameters
>
> Hi  Nathan,
>
> Yes, in general I am very much opposed to dynamic scoping. In the
> template world, it makes a huge amount of sense. Templates are very  
> dynamic
> creatures and our combined willy-nilly into large, nested trees of sub
> templates. I agree, however, that like we do with parameters, it  
> could be
> useful to say "heh,I'm going to reference this dynamically scoped
> variable... if it does not exist when I'm evaluated, throw an  
> exception".
> sort of like
>
> foo(a,b) uses title ::= "<a> <b> are parameters, <title> is from  
> above"
>
> Is that what you're talking about?
>
> Ter
>
> On Nov 14, 2008, at 10:10 AM, Nathan Ward wrote:
>
>> Terence,
>>
>> I got this working. My code is included below in case it would be of
>> use to someone else. I would think this would be a common problem
>> because I would think it is pretty common for template parameters to
>> become "tramp data" as Meiler Page-Jones defined in the book
>> Structured Systems Design many years ago (i.e. passing parameters
>> around for use in code that is called later down the line.
>>
>> I also think there is an interesting StringTemplate design issue
>> here... The solution described in the Meiler Page-Jones book was to
>> use "Information Hiding" is similar to using object-oriented design
>> but was before OOD. I had done this kind of thing when programming in
>> C where I would group data and processing (i.e. C functions) in the
>> same file. The variables defined at the top of the file where like
>> object attributes. Not exactly OO, but not bad when programming in C.
>>
>> Given that StringTemplate is designed with a syntax that encourages
>> good template design, I would think that implicit access to variables
>> like I am now doing should not be allowed, but an alternative should
>> be provided by allowing template groups to accept parameters. This
>> would be similar to an object having instance member variables. This
>> makes the intension to share data across templates more explicit and
>> help the template designer think about if the data really should be
>> shared this way or should be treated as formal parameters. This would
>> also eliminate the need for me to create this temporary template and
>> template group for testing purposes.
>>
>> Shared.stg:
>>
>> // Implicit variable references: screen
>> screenElementResourceBundleKey(screenElement, screenElementType) ::=
>> <<
>> <formClassName(screen)>.<screenElementType>.<screenElement.text>.Text
>>>>
>>
>>
>> SharedTemplateTestCase.java:
>>
>>   public void testScreenElementResourceBundleKey() {
>>
>>       Screen screen = new Screen();
>>       screen.setName("MY_SCREEN");
>>
>>       Button button = new Button();
>>       button.setText("MyButtonText");
>>
>>       super.setTemplateAttribute("screen", screen);
>>       super.setTemplateAttribute("screenElement", button);
>>       super.setTemplateAttribute("screenElementType", "Button");
>>       String templateString =
>> super.executeTemplateWithImplicitVariables(
>>               templateGroup, templateGroup,
>> "screenElementResourceBundleKey");
>>       super.logTemplateOutput(templateString);
>>       TestCase.assertEquals("MyScreenForm.Button.MyButtonText.Text",
>> templateString);
>>
>>   }
>>
>> BaseTemplateTestCase.java:
>>
>>   /**
>>    * Use this method to test templates that use one or more
>> <i>implicit variables</i>
>>    * rather than using only formal parameters. Implicit variables
>> should be used only
>>    * in cases where the immediate template doesn't need the parameter
>> other than to
>>    * pass it to other templates d several levels down in the template
>> calling chain.
>>    *
>>    * This method execute the template given by the templateName
>> parameter from a temporary
>>    * template that this method creates in the template group so that
>> the parameters
>>    * previously added by calling setTemplateAttribute() method will
>> be accessible to
>>    * the template under test.
>>    *
>>    * If the template under test does not use implicit variables,
>>    * (i.e. only uses formal parameters), then the StringTemplate API
>> can be used directly
>>    * rather than using this method.
>>    *
>>    * @param rootTemplateGroup The rootTemplateGroup in the template
>> group inheritance hierarchy
>>    * for the template group that the template under test is in. If
>> the target template group
>>    * does not inherit from another template group, then just pass the
>> target template group
>>    * as this parameter and also pass the same template group as the
>> targetTemplateGroup parameter.
>>    * @param targetTemplateGroup The template group in which the
>> template under test is defined.
>>    * @param templateName The name of the template under test.
>>    * @return
>>    */
>>   public String
>> executeTemplateWithImplicitVariables(StringTemplateGroup
>> rootTemplateGroup,
>>           StringTemplateGroup targetTemplateGroup, String
>> templateName) {
>>
>>       StringBuilder temporaryTemplateGroup = new StringBuilder();
>>       temporaryTemplateGroup.append("group temp;");
>>       temporaryTemplateGroup.append(newline);
>>       temporaryTemplateGroup.append("aTemplate(");
>>       boolean notFirst = false;
>>       for (final String parmName : parms.keySet()) {
>>           if (notFirst) {
>>               temporaryTemplateGroup.append(", ");
>>           }
>>           else {
>>               notFirst = true;
>>           }
>>           temporaryTemplateGroup.append(parmName);
>>       }
>>       temporaryTemplateGroup.append(") ::= <<");
>>       temporaryTemplateGroup.append(newline);
>>       temporaryTemplateGroup.append("<");
>>       temporaryTemplateGroup.append(templateName);
>>       temporaryTemplateGroup.append("(...) >");
>>       temporaryTemplateGroup.append(newline);
>>       temporaryTemplateGroup.append(">>");
>>
>>       String temporaryTemplateGroupString =
>> temporaryTemplateGroup.toString();
>>
>>       StringTemplateGroup newParentGroup = new
>> StringTemplateGroup(new StringReader(
>>               temporaryTemplateGroupString));
>>
>>       // Make the rootTemplateGroup inherit from the newParentGroup
>> that we created
>>       // from temporaryTemplateGroupString
>>       rootTemplateGroup.setSuperGroup(newParentGroup);
>>
>>       // Get an instance of the temporary template that we have
>> created named aTemplate
>>       // from the targetTemplateGroup. Important that we get the
>> instance from the targetTemplateGroup
>>       // rather than directly from the newParentGroup template so
>> that the template has access to
>>       // all other templates in the template group inheritance
>> hierarchy.
>>       StringTemplate template =
>> targetTemplateGroup.getInstanceOf("aTemplate");
>>
>>       for (final Map.Entry<String, Object> entry :
>> parms.entrySet()) {
>>           template.setAttribute(entry.getKey(), entry.getValue());
>>       }
>>       String templateString = template.toString();
>>       return templateString;
>>   }
>>
>>   public void setTemplateAttribute(String parmName, Object value) {
>>
>>       this.parms.put(parmName, value);
>>   }
>>
>> -----Original Message-----
>> From: Terence Parr [mailto:parrt at cs.usfca.edu]
>> Sent: Thursday, November 13, 2008 5:58 PM
>> To: Nathan Ward
>> Cc: stringtemplate-interest at antlr.org
>> Subject: Re: [stringtemplate-interest] Managing template parameters
>>
>>
>> On Nov 13, 2008, at 11:50 AM, Nathan Ward wrote:
>>
>>> I'm aware of that, but how can I make a JUnit test for the
>>> subtemplate if it uses an attribute that is not passed as a formal
>>> parameter?
>>> Hmmm, I guess I can create a template inline in my test code that
>>> uses the template that I'm testing, which is a string group template
>>> file.
>>> I'll try that. Thanks!
>>
>> That'll work. :)
>> Ter
>>
>>
>
>
>
> _______________________________________________
> stringtemplate-interest mailing list
> stringtemplate-interest at antlr.org
> http://www.antlr.org:8080/mailman/listinfo/stringtemplate-interest



More information about the stringtemplate-interest mailing list