问题
Is it possible to embed executable java code inside a ST4 template? eg if I want to pass a string to my template, which sometimes prints the string as-is, and sometimes prints it in caps, so I want a java code to do the necessary conversion. Without this feature, I see 3 ways to achieve the same functionality:
(1) pre-compute the alternative values in java, and pass them all to the template at one shot (but this may result in too many arguments):
// in the below code, if the template can compute DESCRIPTION_CAPS from DESCRIPTION, using embedded java code, that reduces one argument
test(DESCRIPTION, DESCRIPTION_CAPS) ::= <<
this is original <DESCRIPTION>
this is caps <DESCRIPTION_CAPS>
>>
(2) If there become too many such arguments, the other option is to break up the temlpate into smaller parts, but that makes the code ugly and unreadable:
test1(DESCRIPTION) ::= <<
this is original <DESCRIPTION>
>>
test2(DESCRIPTION_CAPS) ::= <<
this is caps <DESCRIPTION_CAPS>
>>
(3) Pre-compute all relevant values inside a class, and let the template call the getter functions (without arguments) to simply get the relevant values from the class.
test() ::= <<
this is original <values.description>
this is caps <values.description_caps>
>>
As of now (if the embedding java class is not available) the 3rd option looks like the best solution. Please advise if a better solution exists.
Note: in the above example, I have used CAPS as only as an example, there could be more complex java functions also needed.
回答1:
No, java code embedding into a Template is not intended / not provided. That makes it easier to prevent a mess / mixture of view and model/logic.
In Your case, You can easily put the calculated things into java property getter function, which can be referenced and evaluated by StringTemplate as a kind of bean property.
e.g.
Put in Your template group file MyTemplate.stg
:
myTemplate(f) ::= <<
...
Blabla <f.message> blabla
...
>>
Put in Your Java source code:
class MyClass() {
...
private String internal_message;
public getMessage() {
return internal_message;
}
...
}
Invoke the template:
STGroupFile stg = new STGroupFile("MyTemplate.stg");
ST templ = stg.getInstanceOf("myTemplate");
templ.add("f", new MyClass());
With this, the template logic <f.message>
invokes getMessage()
of Your java object instance f
.
回答2:
As @Hartmut said, no you can't embed java code inside a template, but you can create a custom StringRenderer that you could use to format the strings in the way you want.
You could then pass your custom format string to the renderer like this:
test(description) ::= <<
this is original <description>
this is caps <description; format="upper">
this is custom format <description; format="my-format-string">
>>
P.S if you're just interested in changing the text case you might not need to roll your own, just add a reference to the StringRenderer that comes bundled with StringTemplate using:
templateGroup.registerRenderer(String.class, new StringRenderer());
and pass "upper", "lower", or "cap" as the format string
See my answer here for more info
来源:https://stackoverflow.com/questions/25864154/embed-java-code-inside-a-template