Replacing embedded model variables

6 messages Options
Embed this post
Permalink
Garth Dahlstrom

Replacing embedded model variables

Reply Threaded More More options
Print post
Permalink

Hi
I'm wondering if there is a recommended approach to replacing variables that occur within other variables.

I have text which I add to the model that comes from a properties file that looks like:
Intro=Hello ${Name}, welcome to the application
Name=John

I could break up intro into chunks in my template, but that will make things slightly more difficult to maintain, particularily when I send it for translation.

So, is there a way to get model-variable subsitution to run a second time or a way for me to change the to-be-rendered output to acomplish something like this?

Thanks,
-G

WarnerJan Veldhuis

Re: Replacing embedded model variables

Reply Threaded More More options
Print post
Permalink
Some javascript/style in this post has been disabled (why?)

I don't know about a recommended way, but couldn't you add the lines of your properties file to the Velocity model, using  Page#getModel().putAll( yourPropertiesObject )?

It might be a memory issue for huge properties files, so you could (should ?) add a caching mechanism.

HTH,

WarnerJan



On Mon, 2009-07-20 at 10:05 -0400, Garth Dahlstrom wrote:
Hi
I'm wondering if there is a recommended approach to replacing variables that occur within other variables.

I have text which I add to the model that comes from a properties file that looks like:
Intro=Hello ${Name}, welcome to the application
Name=John

I could break up intro into chunks in my template, but that will make things slightly more difficult to maintain, particularily when I send it for translation.

So, is there a way to get model-variable subsitution to run a second time or a way for me to change the to-be-rendered output to acomplish something like this?

Thanks,
-G

Bob Schellink-2

Re: Replacing embedded model variables

Reply Threaded More More options
Print post
Permalink
In reply to this post by Garth Dahlstrom
Hi Garth,

I've been wondering about this today. The most obvious solution is probably to
use Java's MessageFormat and replace the property variables before adding them
to the model. Off course MessageFormat doesn't support named parameters, only
numeric ones. So you have to use:

   Intro=Hello {0}, welcome to the app

Alternatively you might want to look at Velocity Renderable[1] interface. Its
new in 1.6.

Normally Velocity will invoke the toString() method of the variable it finds in
the template. However if the variable implements Renderable, Velocity will
invoke a callback method which allows you to manipulate the output as needed.

I haven't used this Velocity feature yet but it seems quite powerful.

Let us know what solution you end up using.

kind regards

bob

[1]:http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/Renderable.html

Garth Dahlstrom wrote:

> Hi
> I'm wondering if there is a recommended approach to replacing variables
> that occur within other variables.
>
> I have text which I add to the model that comes from a properties file
> that looks like:
> Intro=Hello ${Name}, welcome to the application
> Name=John
>
> I could break up intro into chunks in my template, but that will make
> things slightly more difficult to maintain, particularily when I send it
> for translation.
>
> So, is there a way to get model-variable subsitution to run a second
> time or a way for me to change the to-be-rendered output to acomplish
> something like this?
>
> Thanks,
> -G
>

Garth Dahlstrom

Re: Replacing embedded model variables

Reply Threaded More More options
Print post
Permalink
Hi Bob,

In the end, I ended up with a much more brutal low-tech approach that involves updating the velocity model directly, it does one extra pass to try to resolve embedded symbols.   Here is the code...

...
    protected String applyMapValuesToTemplate(String template, Map<String,Object> mapValues) {
        final String DELIMITER_PREFIX = "${";
        final String DELIMITER_SUFFIX = "}";
        for (String key : mapValues.keySet()) {
            String matchKey = DELIMITER_PREFIX + key + DELIMITER_SUFFIX;
            if (template.contains(matchKey)) {
                template = template.replace(matchKey, (String) mapValues.get(key));
            }
        }
        return template;
    }

....
// various calls to addModel including my Strings with embedded variable
....

        for (String key : ((Map<String,Object>) getModel()).keySet()) {
            String value = getModel().get(key).toString();
            if (value.contains("${") &&
                    value.contains("}") &&
                    value.indexOf("${") <
                    value.indexOf("}")) {
                value = applyMapValuesToTemplate(value, getModel());
                getModel().put(key, value);
            }
        }

Cheers,
-G
              __
--- == __/ t.O ==--
http://stacktrace.org/


On Tue, Jul 21, 2009 at 6:12 PM, Bob Schellink <[hidden email]> wrote:
Hi Garth,

I've been wondering about this today. The most obvious solution is probably to use Java's MessageFormat and replace the property variables before adding them to the model. Off course MessageFormat doesn't support named parameters, only numeric ones. So you have to use:

 Intro=Hello {0}, welcome to the app

Alternatively you might want to look at Velocity Renderable[1] interface. Its new in 1.6.

Normally Velocity will invoke the toString() method of the variable it finds in the template. However if the variable implements Renderable, Velocity will invoke a callback method which allows you to manipulate the output as needed.

I haven't used this Velocity feature yet but it seems quite powerful.

Let us know what solution you end up using.

kind regards

bob

[1]:http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/Renderable.html


Garth Dahlstrom wrote:
Hi
I'm wondering if there is a recommended approach to replacing variables that occur within other variables.

I have text which I add to the model that comes from a properties file that looks like:
Intro=Hello ${Name}, welcome to the application
Name=John

I could break up intro into chunks in my template, but that will make things slightly more difficult to maintain, particularily when I send it for translation.

So, is there a way to get model-variable subsitution to run a second time or a way for me to change the to-be-rendered output to acomplish something like this?

Thanks,
-G



Bob Schellink-2

Re: Replacing embedded model variables

Reply Threaded More More options
Print post
Permalink
Looks good, thanks for sharing.

bob


Garth Dahlstrom wrote:

> Hi Bob,
>
> In the end, I ended up with a much more brutal low-tech approach that
> involves updating the velocity model directly, it does one extra pass to
> try to resolve embedded symbols.   Here is the code...
>
> ...
>     protected String applyMapValuesToTemplate(String template,
> Map<String,Object> mapValues) {
>         final String DELIMITER_PREFIX = "${";
>         final String DELIMITER_SUFFIX = "}";
>         for (String key : mapValues.keySet()) {
>             String matchKey = DELIMITER_PREFIX + key + DELIMITER_SUFFIX;
>             if (template.contains(matchKey)) {
>                 template = template.replace(matchKey, (String)
> mapValues.get(key));
>             }
>         }
>         return template;
>     }
>
> ....
> // various calls to addModel including my Strings with embedded variable
> ....
>
>         for (String key : ((Map<String,Object>) getModel()).keySet()) {
>             String value = getModel().get(key).toString();
>             if (value.contains("${") &&
>                     value.contains("}") &&
>                     value.indexOf("${") <
>                     value.indexOf("}")) {
>                 value = applyMapValuesToTemplate(value, getModel());
>                 getModel().put(key, value);
>             }
>         }
>
> Cheers,
> -G
>               __
> --- == __/ t.O ==--
> http://stacktrace.org/
>
>
> On Tue, Jul 21, 2009 at 6:12 PM, Bob Schellink <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Hi Garth,
>
>     I've been wondering about this today. The most obvious solution is
>     probably to use Java's MessageFormat and replace the property
>     variables before adding them to the model. Off course MessageFormat
>     doesn't support named parameters, only numeric ones. So you have to use:
>
>      Intro=Hello {0}, welcome to the app
>
>     Alternatively you might want to look at Velocity Renderable[1]
>     interface. Its new in 1.6.
>
>     Normally Velocity will invoke the toString() method of the variable
>     it finds in the template. However if the variable implements
>     Renderable, Velocity will invoke a callback method which allows you
>     to manipulate the output as needed.
>
>     I haven't used this Velocity feature yet but it seems quite powerful.
>
>     Let us know what solution you end up using.
>
>     kind regards
>
>     bob
>
>     [1]:http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/Renderable.html
>
>
>     Garth Dahlstrom wrote:
>
>         Hi
>         I'm wondering if there is a recommended approach to replacing
>         variables that occur within other variables.
>
>         I have text which I add to the model that comes from a
>         properties file that looks like:
>         Intro=Hello ${Name}, welcome to the application
>         Name=John
>
>         I could break up intro into chunks in my template, but that will
>         make things slightly more difficult to maintain, particularily
>         when I send it for translation.
>
>         So, is there a way to get model-variable subsitution to run a
>         second time or a way for me to change the to-be-rendered output
>         to acomplish something like this?
>
>         Thanks,
>         -G
>
>
>

Bob Schellink-2

Re: Replacing embedded model variables

Reply Threaded More More options
Print post
Permalink
In reply to this post by Bob Schellink-2
Another approach is to use Velocity #evaluate directive[1].

properties:
  Intro=Hello ${Name}, welcome to the application

Page.java:

  addModel("intro", getMessage("Intro"));
  addModel("Name", "John");


template.htm:

  #evaluate($intro)

bob

[1]:http://velocity.apache.org/engine/releases/velocity-1.6.2/user-guide.html#Evaluate


On 7/22/09, Bob Schellink <[hidden email]> wrote:

> Hi Garth,
>
> I've been wondering about this today. The most obvious solution is probably
> to
> use Java's MessageFormat and replace the property variables before adding
> them
> to the model. Off course MessageFormat doesn't support named parameters,
> only
> numeric ones. So you have to use:
>
>    Intro=Hello {0}, welcome to the app
>
> Alternatively you might want to look at Velocity Renderable[1] interface.
> Its
> new in 1.6.
>
> Normally Velocity will invoke the toString() method of the variable it finds
> in
> the template. However if the variable implements Renderable, Velocity will
> invoke a callback method which allows you to manipulate the output as
> needed.
>
> I haven't used this Velocity feature yet but it seems quite powerful.
>
> Let us know what solution you end up using.
>
> kind regards
>
> bob
>
> [1]:http://velocity.apache.org/engine/devel/apidocs/org/apache/velocity/runtime/Renderable.html
>
> Garth Dahlstrom wrote:
>> Hi
>> I'm wondering if there is a recommended approach to replacing variables
>> that occur within other variables.
>>
>> I have text which I add to the model that comes from a properties file
>> that looks like:
>> Intro=Hello ${Name}, welcome to the application
>> Name=John
>>
>> I could break up intro into chunks in my template, but that will make
>> things slightly more difficult to maintain, particularily when I send it
>> for translation.
>>
>> So, is there a way to get model-variable subsitution to run a second
>> time or a way for me to change the to-be-rendered output to acomplish
>> something like this?
>>
>> Thanks,
>> -G
>>
>
>


--
http://incubator.apache.org/click/