[stringtemplate-interest] Managing template parameters
Terence Parr
parrt at cs.usfca.edu
Fri Nov 21 10:52:44 PST 2008
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
>
>
More information about the stringtemplate-interest
mailing list