Deprecation in data model

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Deprecation in data model

Ista Pouss
Hey,

I have a term in the data model, for instance "term", and I use in
model ${term}, all is good.

But now I should want use "word" because I don't like "term" anymore.
And when I use term in a model, I should want freemarker say to me, in
a log, "Hey you don't like 'term', it's deprecated, use 'word' at line
xyz of template foo.ftl". And, of course, freemarker use "term" as
usual.

Is it possible to do that, and how ?

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
FreeMarker-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-user
Reply | Threaded
Open this post in threaded view
|

Re: Deprecation in data model

Daniel Dekany
Wednesday, December 30, 2009, 3:57:36 PM, Ista Pouss wrote:

> Hey,
>
> I have a term in the data model, for instance "term", and I use in
> model ${term}, all is good.
>
> But now I should want use "word" because I don't like "term" anymore.
> And when I use term in a model, I should want freemarker say to me, in
> a log, "Hey you don't like 'term', it's deprecated, use 'word' at line
> xyz of template foo.ftl". And, of course, freemarker use "term" as
> usual.
>
> Is it possible to do that, and how ?

As far as FreeMarker is concerned, yes, but it's always a question if
the framework your are using gives sufficiently low-level access to
FreeMarker... Anyway, if it does, since "term" is a top-level data,
you could use a custom TemplateHashModel implementation that does
this. (If are using a java.util.Map as the data-model root, you could
wrap it into your TemplateHashModel implementation just before passing
to the template.process call)

--
Best regards,
 Daniel Dekany


------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
FreeMarker-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-user
Reply | Threaded
Open this post in threaded view
|

Re: Deprecation in data model

Ista Pouss
2009/12/31 Daniel Dekany <[hidden email]>:

> Wednesday, December 30, 2009, 3:57:36 PM, Ista Pouss wrote:
>
> As far as FreeMarker is concerned, yes, but it's always a question if
> the framework your are using gives sufficiently low-level access to
> FreeMarker... Anyway, if it does, since "term" is a top-level data,
> you could use a custom TemplateHashModel implementation that does
> this. (If are using a java.util.Map as the data-model root, you could
> wrap it into your TemplateHashModel implementation just before passing
> to the template.process call)
>

Yes my root data model is a Map, so You say I do something like

template.process(new CustomTemplateHashModel(map), output);

and, in my Custom...

TemplateModel get(String key)
{
 if (deprecated(key))
   System.out.println("Damned! Deprecated!");
 return super.get(key);
}

Is it OK ?

But what's append if the deprecated term is, from root, thing in
"foo.bar.thing" ?

Thanks.

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
FreeMarker-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-user
Reply | Threaded
Open this post in threaded view
|

Re: Deprecation in data model

Daniel Dekany
Thursday, December 31, 2009, 1:49:53 PM, Ista Pouss wrote:

> 2009/12/31 Daniel Dekany <[hidden email]>:
>> Wednesday, December 30, 2009, 3:57:36 PM, Ista Pouss wrote:
>>
>> As far as FreeMarker is concerned, yes, but it's always a question if
>> the framework your are using gives sufficiently low-level access to
>> FreeMarker... Anyway, if it does, since "term" is a top-level data,
>> you could use a custom TemplateHashModel implementation that does
>> this. (If are using a java.util.Map as the data-model root, you could
>> wrap it into your TemplateHashModel implementation just before passing
>> to the template.process call)
>>
>
> Yes my root data model is a Map, so You say I do something like
>
> template.process(new CustomTemplateHashModel(map), output);
>
> and, in my Custom...
>
> TemplateModel get(String key)
> {
>  if (deprecated(key))
>    System.out.println("Damned! Deprecated!");
>  return super.get(key);
> }
>
> Is it OK ?

Yes, something like that.

> But what's append if the deprecated term is, from root, thing in
> "foo.bar.thing" ?

The basic idea is that the TemplateModel that you return with
get(String) must also be of a custom class so that it will be aware of
the name (path) of its parent and also of the whole deprecation
checking thing. More precisely, using a custom class for the return
value is only required if (a) the returned value itself is a hash (so
it can create further TemplateModel-s; you want to monitor that) (b)
you are still on a path that can lead to a deprecated object.

As of the implementation... I would write a custom ObjectWrapper by
extending BeansWrapper or DefaultObjectWrapper (whichever you plan to
use). Then I would configure FreeMarker to use that wrapper
(Configuration.setObjectWrapper or the "object_wrapper" property).

What should the custom implementation do? I would override the
wrap(Object) method, which would just call super.wrap, except if the
object to wrap is an instance of com.yourcompany.MapWithDeprecations,
in which case it would wrap it with
com.yourcompany.DeprecationAwareTemplateHashModel.
DeprecationAwareTemplateHashModel would be the extension of the class
that the ObjectWrapper you extended normally uses for maps (so if
those have any fancy extra features, yours will have them too).

MapWithDeprecations would be something that extends HashMap class. You
would instantiate it somehow like "new MapWithDeprecations(dataModel,
deprecations)", and that's what you pass to Template.process. So I
simply made the deprecations the part of the data-model, and made the
ObjectWrapper be aware of that information. If somewhere you just pass
in a plain HashMap as the data-model, it will still work, only without
the deprecation warnings. (Or if you pass in a MapWithDeprecations,
but you are using a standard ObjectWrapper, it will still work, just
again without deprecation warnings. Robust...)

> Thanks.

--
Best regards,
 Daniel Dekany


------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
FreeMarker-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-user
Reply | Threaded
Open this post in threaded view
|

Re: Deprecation in data model

Ista Pouss
Very intersting, thanks.

I'm trying my own root data model with an extends
freemarker.template.SimpleHash, and with a redefinition of get(String
key) method, With that I can see the calls to the terms in root model,
youpiii! It's a great new year!

Two questions :

- you say a custom class is required only if return value is a hash,
for the redefined get method in TemplateModel. But how I know if it's
a hash ? Il see than TemplatehashModel don't inherit from
java.util.Map.

- in a custom ObjectWrapper.wrap, how I know the template name of this object ?


Great year.



2009/12/31 Daniel Dekany <[hidden email]>:

> Thursday, December 31, 2009, 1:49:53 PM, Ista Pouss wrote:
>
>> 2009/12/31 Daniel Dekany <[hidden email]>:
>>> Wednesday, December 30, 2009, 3:57:36 PM, Ista Pouss wrote:
>>>
>>> As far as FreeMarker is concerned, yes, but it's always a question if
>>> the framework your are using gives sufficiently low-level access to
>>> FreeMarker... Anyway, if it does, since "term" is a top-level data,
>>> you could use a custom TemplateHashModel implementation that does
>>> this. (If are using a java.util.Map as the data-model root, you could
>>> wrap it into your TemplateHashModel implementation just before passing
>>> to the template.process call)
>>>
>>
>> Yes my root data model is a Map, so You say I do something like
>>
>> template.process(new CustomTemplateHashModel(map), output);
>>
>> and, in my Custom...
>>
>> TemplateModel get(String key)
>> {
>>  if (deprecated(key))
>>    System.out.println("Damned! Deprecated!");
>>  return super.get(key);
>> }
>>
>> Is it OK ?
>
> Yes, something like that.
>
>> But what's append if the deprecated term is, from root, thing in
>> "foo.bar.thing" ?
>
> The basic idea is that the TemplateModel that you return with
> get(String) must also be of a custom class so that it will be aware of
> the name (path) of its parent and also of the whole deprecation
> checking thing. More precisely, using a custom class for the return
> value is only required if (a) the returned value itself is a hash (so
> it can create further TemplateModel-s; you want to monitor that) (b)
> you are still on a path that can lead to a deprecated object.
>
> As of the implementation... I would write a custom ObjectWrapper by
> extending BeansWrapper or DefaultObjectWrapper (whichever you plan to
> use). Then I would configure FreeMarker to use that wrapper
> (Configuration.setObjectWrapper or the "object_wrapper" property).
>
> What should the custom implementation do? I would override the
> wrap(Object) method, which would just call super.wrap, except if the
> object to wrap is an instance of com.yourcompany.MapWithDeprecations,
> in which case it would wrap it with
> com.yourcompany.DeprecationAwareTemplateHashModel.
> DeprecationAwareTemplateHashModel would be the extension of the class
> that the ObjectWrapper you extended normally uses for maps (so if
> those have any fancy extra features, yours will have them too).
>
> MapWithDeprecations would be something that extends HashMap class. You
> would instantiate it somehow like "new MapWithDeprecations(dataModel,
> deprecations)", and that's what you pass to Template.process. So I
> simply made the deprecations the part of the data-model, and made the
> ObjectWrapper be aware of that information. If somewhere you just pass
> in a plain HashMap as the data-model, it will still work, only without
> the deprecation warnings. (Or if you pass in a MapWithDeprecations,
> but you are using a standard ObjectWrapper, it will still work, just
> again without deprecation warnings. Robust...)
>
>> Thanks.
>
> --
> Best regards,
>  Daniel Dekany
>
>
> ------------------------------------------------------------------------------
> This SF.Net email is sponsored by the Verizon Developer Community
> Take advantage of Verizon's best-in-class app development support
> A streamlined, 14 day to market process makes app distribution fast and easy
> Join now and get one step closer to millions of Verizon customers
> http://p.sf.net/sfu/verizon-dev2dev
> _______________________________________________
> FreeMarker-user mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/freemarker-user
>

------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
FreeMarker-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-user
Reply | Threaded
Open this post in threaded view
|

Re: Deprecation in data model

Daniel Dekany
Friday, January 1, 2010, 5:23:14 PM, Ista Pouss wrote:

> Very intersting, thanks.
>
> I'm trying my own root data model with an extends
> freemarker.template.SimpleHash, and with a redefinition of get(String
> key) method, With that I can see the calls to the terms in root model,
> youpiii! It's a great new year!
>
> Two questions :
>
> - you say a custom class is required only if return value is a hash,
> for the redefined get method in TemplateModel. But how I know if it's
> a hash ? Il see than TemplatehashModel don't inherit from
> java.util.Map.

It doesn't, as a hash is not necessarily a Map (and a Map is not
necessarily a hash). Like, a plain JavaBean is hash as far as the
template is concerned (you can write myBean.myProperty,
myBean["myProperty"], etc.), yet there is no Map behind.

How do you know if the return value is a hash... The thing is,
technically it's you, the implementator of the get(String) method who
decides the type of the return value. So if anyone then you are
supposed to know, as you decide it, you have the full control. But in
this case you want to left that decision to the ObjectWrapper that you
extend, so the question boils down to if customization techniques like
class extending will give you the proper "hooks" that you need here...
I'm afraid you will find that DefaultObjectWrapper/BeansWrapper
doesn't really provide the "hooks" necessary for a nice and clean
solution. Because, depending on what Java object is exposed as a hash
to the template, different TemplateHashModel classes are used, which
means that you certainly will have to extend all of them (by adding
some extra code that checks the deprecations and tracks the "path",
and then just call super.get), and then ensure that your
implementation is used instead of them (by overloading
ObjectWrapper.wrap, certainly). But maybe there happens to be a better
way... look into the source code and API docs, especially of
BeansWrapper. It has some extra "hooks" AFAIR. (What I don't like in
the way I described above is that your extension depends too much on
the details of how the extended ObjectWrapper works... dirty, and more
fragile then necessary. I wonder if some AOP could help here... like
advising TemplateHashModel.get-s, also adding a field for tracking the
names... Anyway, in many projects that would be too heavy-weight.)

> - in a custom ObjectWrapper.wrap, how I know the template name of this object ?

You don't (think about things returned by method calls or like...
values in general don't have an associated name), that's why you need
the a special root hash class and the special TemplateHashModel. Those
will keep the record of how you get to the value.

>
> Great year.
>
>
>
> 2009/12/31 Daniel Dekany <[hidden email]>:
>> Thursday, December 31, 2009, 1:49:53 PM, Ista Pouss wrote:
>>
>>> 2009/12/31 Daniel Dekany <[hidden email]>:
>>>> Wednesday, December 30, 2009, 3:57:36 PM, Ista Pouss wrote:
>>>>
>>>> As far as FreeMarker is concerned, yes, but it's always a question if
>>>> the framework your are using gives sufficiently low-level access to
>>>> FreeMarker... Anyway, if it does, since "term" is a top-level data,
>>>> you could use a custom TemplateHashModel implementation that does
>>>> this. (If are using a java.util.Map as the data-model root, you could
>>>> wrap it into your TemplateHashModel implementation just before passing
>>>> to the template.process call)
>>>>
>>>
>>> Yes my root data model is a Map, so You say I do something like
>>>
>>> template.process(new CustomTemplateHashModel(map), output);
>>>
>>> and, in my Custom...
>>>
>>> TemplateModel get(String key)
>>> {
>>>  if (deprecated(key))
>>>    System.out.println("Damned! Deprecated!");
>>>  return super.get(key);
>>> }
>>>
>>> Is it OK ?
>>
>> Yes, something like that.
>>
>>> But what's append if the deprecated term is, from root, thing in
>>> "foo.bar.thing" ?
>>
>> The basic idea is that the TemplateModel that you return with
>> get(String) must also be of a custom class so that it will be aware of
>> the name (path) of its parent and also of the whole deprecation
>> checking thing. More precisely, using a custom class for the return
>> value is only required if (a) the returned value itself is a hash (so
>> it can create further TemplateModel-s; you want to monitor that) (b)
>> you are still on a path that can lead to a deprecated object.
>>
>> As of the implementation... I would write a custom ObjectWrapper by
>> extending BeansWrapper or DefaultObjectWrapper (whichever you plan to
>> use). Then I would configure FreeMarker to use that wrapper
>> (Configuration.setObjectWrapper or the "object_wrapper" property).
>>
>> What should the custom implementation do? I would override the
>> wrap(Object) method, which would just call super.wrap, except if the
>> object to wrap is an instance of com.yourcompany.MapWithDeprecations,
>> in which case it would wrap it with
>> com.yourcompany.DeprecationAwareTemplateHashModel.
>> DeprecationAwareTemplateHashModel would be the extension of the class
>> that the ObjectWrapper you extended normally uses for maps (so if
>> those have any fancy extra features, yours will have them too).
>>
>> MapWithDeprecations would be something that extends HashMap class. You
>> would instantiate it somehow like "new MapWithDeprecations(dataModel,
>> deprecations)", and that's what you pass to Template.process. So I
>> simply made the deprecations the part of the data-model, and made the
>> ObjectWrapper be aware of that information. If somewhere you just pass
>> in a plain HashMap as the data-model, it will still work, only without
>> the deprecation warnings. (Or if you pass in a MapWithDeprecations,
>> but you are using a standard ObjectWrapper, it will still work, just
>> again without deprecation warnings. Robust...)
>>
>>> Thanks.
>>
>> --
>> Best regards,
>>  Daniel Dekany
>>
>>
>> ------------------------------------------------------------------------------
>> This SF.Net email is sponsored by the Verizon Developer Community
>> Take advantage of Verizon's best-in-class app development support
>> A streamlined, 14 day to market process makes app distribution fast and easy
>> Join now and get one step closer to millions of Verizon customers
>> http://p.sf.net/sfu/verizon-dev2dev
>> _______________________________________________
>> FreeMarker-user mailing list
>> [hidden email]
>> https://lists.sourceforge.net/lists/listinfo/freemarker-user
>>
>
> ------------------------------------------------------------------------------
> This SF.Net email is sponsored by the Verizon Developer Community
> Take advantage of Verizon's best-in-class app development support
> A streamlined, 14 day to market process makes app distribution fast and easy
> Join now and get one step closer to millions of Verizon customers
> http://p.sf.net/sfu/verizon-dev2dev 
> _______________________________________________
> FreeMarker-user mailing list
> [hidden email]
> https://lists.sourceforge.net/lists/listinfo/freemarker-user
>

--
Best regards,
 Daniel Dekany


------------------------------------------------------------------------------
This SF.Net email is sponsored by the Verizon Developer Community
Take advantage of Verizon's best-in-class app development support
A streamlined, 14 day to market process makes app distribution fast and easy
Join now and get one step closer to millions of Verizon customers
http://p.sf.net/sfu/verizon-dev2dev 
_______________________________________________
FreeMarker-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/freemarker-user