Say I create an extension of the freemarker.template.SimpleDate object. Is
there an environmental setting that I can use to tell FreeMarker to always
use my custom class as the date wrapper as opposed to the
freemarker.template.SimpleDate class? This sounds like the best idea for
me. Thanks.
Joe
-----Original Message-----
From: freemarker-user-***@lists.sourceforge.net
[mailto:freemarker-user-***@lists.sourceforge.net] On Behalf Of Jonathan
Revusky
Sent: Tuesday, June 07, 2005 10:49 AM
To: freemarker-***@lists.sourceforge.net
Subject: Re: [FreeMarker-user] Re: how to call java.util.Date.getTime()
Post by Joe HudsonHi Jonathan, I will try to stop bothering you real soon, I promise!
No problem. This list exists for this purpose.
Post by Joe HudsonIn regard to this answer, I really like the "built in" functionality that
I
Post by Joe Hudsonwould loose if I used the bean wrapper. Is there any way I can extend the
TemplateDateModel (and tell freemarker to use my class for date objects)
to
Post by Joe Hudsonadd the functionality that I need but keep the cool functionality that
already exists? Thanks.
Well, I'm going to give you various long-winded answers, more than you
actually need, to help you get a conceptual model of how FM works and
how to solve such problems.
The first answer to your question is that if you want the methods on the
object to be exposed (IMO, you should only do this if necessary because
you should try to keep your template's underlying data model simple and
exposing a boatload of java API to it runs against that) you can use
certain parallel objects in the freemarker.ext.beans package. For
example, by default, when you expose a date to a freemarker template, it
is an instance of freemarker.template.SimpleDate, but you could
alternatively use freemarker.ext.beans.DateModel. See:
http://freemarker.org/docs/api/freemarker/ext/beans/DateModel.html
You'll actually get vended one if you use the BeansWrapper, so you can go:
TemplateModel myDate = BeansWrapper.getDefaultInstance().wrap(new Date());
dataModel.put("myDate", myDate);
and in the template ${date.getTime()) or ${date.time} should work.
In general, note that there are parallel implementations of the core
freemarker interfaces in freemarker.ext.beans that tend to expose full
java API as opposed to the SimpleXXX implementations in freemarker.template.
That's the first answer and the easiest, because it's a ready-made
out-of-the-box solution.
Here's a second answer. Preamble: FreeMarker's design is such that the
type system in the template language is based on a set of interfaces in
the freemarker.template package, the classnames following the naming
convention TemplateXXXModel. These tend to be very lean interfaces.
TemplateDateModel, for example, only has two methods. If you want
something to be interpretable as a hash in the right context, you can
have it implement TemplateHashModel. So, let's say you write your
own little class that is a FreeMarker SimpleDate but also has a hashkey
called "timeStamp". Really quite easy.
public class MyDate extends SimpleDate implements TemplateHashModel {
public MyDate(Date d) {
super(d);
}
public TemplateHashModel get(String key) throws
TemplateModelException {
if ("timeStamp".equals(key)) {
return new SimpleScalar(""+ this.getAsDate().getTime());
}
throw new TemplateModelException("only accepts 'timeStamp' as
key");
}
}
And then:
dateModel.put("myDate", new MyDate(new Date()));
and in the template:
${myDate.timeStamp}
should work, myDate.timeStamp will be a string like "1118155003281" or
something.
Now, here is a third way to get what you want: Stick a helper method in
the context that gets the timestamp you want. It would have to implement
TemplateMethodModel.
class TimeStampExtractor implements TemplateMethodModelEx {
public Object exec(List args) throws TemplateModelException {
if (args.size() != 1) throw new
TemplateModelException("expecting 1 arg");
Object arg = args.get(0);
if (!(arg instanceof TemplateDateModel)) throw new
TemplateModelException("This method only deals with dates. You passed in
a " + arg.getClass().getName());
TemplateDateModel tdm = (TemplateDateModel) arg;
long t = tdm.getAsDate().getTime();
return new SimpleScalar("" + t);
// or possibly: return new SimpleNumber(new Long(t));
// This would return a number rather than a string.
// YOu probably just want a string for your purposes though.
}
}
dataModel.put("extractTimeStamp", new TimeStampExtractor());
and then in the template:
${extractTimeStamp(myDate)}
would work just fine.
I hope that's helpful. All you needed was the first answer, but the
second two answers give you tools to resolve things when there is not an
immediate out-of-the-box solution.
Jonathan
Post by Joe HudsonJoe
-----Original Message-----
Revusky
Sent: Tuesday, June 07, 2005 8:44 AM
Subject: [FreeMarker-user] Re: how to call java.util.Date.getTime()
Post by Joe HudsonHello, I am unable to figure out how to call getTime() on a Date object.
Joe,
FreeMarker has a different approach in that it is not based on simply
dropping in Java API to the template layer. In fact, when working on a
FreeMarker template, you should try to temporarily forget that you are a
java programmer and know anything about a java API. So, a FreeMarker
data object is not a java.util.Date.
(Note that a java.util.Date is just a very thin wrapper around a long
that contains the number of milliseconds elapsed since the new year of
1970, UTC. (What should actually be called Date probably is
java.util.Calendar. The whole java API regarding time/date is not well
designed or well named...))
Anyway, Date.getTime() just returns the number of milliseconds since
1/1/70. Why would a template writer want that?
We try to expose generally useful built-ins that people would use when
producing web pages or other human readable output. So, while exposing
Date.getTime() would be very easy, would anybody want it? Or really,
getting to first principles, isn't a template about converting
computerized data into a format that is readable to humans -- as opposed
to the other way round????
Actually, why do you want it? (If you want it for sorting/comparison
purposes, which is the only thing that occurs to me, we have
sorting/comparison on dates working anyway.)
Of course, if you really do need this, you can expose any java object
directly to the template by explicitly using the beanswrapper for this
model.expose("myDate", BeansWrapper.getDefaultInstance().wrap(new
Date()));
Post by Joe HudsonAnd then date.getTime() or more simply date.time would provide the
number of milliseconds since 1/1/70.
Regards,
Jonathan Revusky
Post by Joe HudsonI have tried ${date.time} which produces an error.
I see no reference to do this on
http://www.freemarker.org/docs/ref_builtins_date.html
Could somebody please tell me how this can be done? Thank you very much.
Joe
-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games. How far can you
shotput
a projector? How fast can you ride your desk chair down the office luge
track?
If you want to score the big prize, get to know the little guy.
Play to win an NEC 61" plasma display: http://www.necitguy.com/?r=20
_______________________________________________
FreeMarker-user mailing list
https://lists.sourceforge.net/lists/listinfo/freemarker-user
-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games. How far can you
shotput
Post by Joe Hudsona projector? How fast can you ride your desk chair down the office luge
track?
Post by Joe HudsonIf you want to score the big prize, get to know the little guy.
Play to win an NEC 61" plasma display: http://www.necitguy.com/?r=20
_______________________________________________
FreeMarker-user mailing list
https://lists.sourceforge.net/lists/listinfo/freemarker-user
-------------------------------------------------------
This SF.Net email is sponsored by: NEC IT Guy Games. How far can you
shotput
a projector? How fast can you ride your desk chair down the office luge
track?
If you want to score the big prize, get to know the little guy.
Play to win an NEC 61" plasma display: http://www.necitguy.com/?r=20