KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > bridge > jsp > taglib > TimeTag


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9  */

10 package org.mmbase.bridge.jsp.taglib;
11 import org.mmbase.bridge.jsp.taglib.util.Attribute;
12
13 import java.util.*;
14 import java.text.*;
15 import org.mmbase.util.logging.*;
16 import org.mmbase.util.*;
17 import javax.servlet.jsp.JspTagException JavaDoc;
18 import javax.servlet.jsp.JspException JavaDoc;
19
20 /**
21  * The time taglib provides you easy functionality for using times in your web pages.
22  *
23  * @author Rob Vermeulen (VPRO)
24  * @author Michiel Meeuwissen
25  * @since MMBase-1.6
26  * @version $Id: TimeTag.java,v 1.57 2006/08/22 11:21:42 michiel Exp $
27  */

28 public class TimeTag extends ContextReferrerTag implements Writer, WriterReferrer {
29
30     private static final Logger log = Logging.getLoggerInstance(TimeTag.class);
31
32     private Attribute time = Attribute.NULL;
33     private Attribute inputFormat = Attribute.NULL;
34     private Attribute offset = Attribute.NULL;
35
36     private Attribute precision = Attribute.NULL;
37     private Attribute relevance = Attribute.NULL;
38
39     private Attribute timezone = Attribute.NULL;
40
41     private final static int PRECISION_UNSET = -1;
42     private final static int PRECISION_SECONDS = 1;
43     private final static int PRECISION_MINUTES = 2;
44     private final static int PRECISION_HOURS = 3;
45     private final static int PRECISION_DAYS = 4;
46     private final static int PRECISION_WEEKS = 5;
47     private final static int PRECISION_MONTHS = 6;
48     private final static int PRECISION_YEARS = 7;
49     private final static int PRECISION_PARSE = 100;
50
51
52     /**
53      * Format attribute used for displaying the dates.
54      */

55     private Attribute dateFormat = Attribute.NULL;
56
57     /**
58      * @since MMBase-1.7.1
59      */

60     protected Date _date;
61
62     // Attributes
63
public void setTime(String JavaDoc time) throws JspTagException JavaDoc {
64         this.time = getAttribute(time);
65     }
66
67     public void setFormat(String JavaDoc f) throws JspTagException JavaDoc {
68         dateFormat = getAttribute(f);
69     }
70
71     public void setPrecision(String JavaDoc p) throws JspTagException JavaDoc {
72         precision = getAttribute(p);
73     }
74
75     protected static int getPrecisionConstant(String JavaDoc p) throws JspTagException JavaDoc {
76         if (p.equals("")) {
77             return PRECISION_UNSET;
78         } else if (p.equals("seconds")) {
79             return PRECISION_SECONDS;
80         } else if (p.equals("minutes")) {
81             return PRECISION_MINUTES;
82         } else if (p.equals("hours")) {
83             return PRECISION_HOURS;
84         } else if (p.equals("days")) {
85             return PRECISION_DAYS;
86         } else if (p.equals("weeks")) {
87             return PRECISION_WEEKS;
88         } else if (p.equals("months")) {
89             return PRECISION_MONTHS;
90         } else if (p.equals("years")) {
91             return PRECISION_YEARS;
92         } else {
93             return PRECISION_PARSE;
94         }
95     }
96
97     private int getPrecision() throws JspTagException JavaDoc {
98         String JavaDoc p = precision.getString(this).toLowerCase();
99         return getPrecisionConstant(p);
100
101     }
102
103     public void setRelevance(String JavaDoc p) throws JspTagException JavaDoc {
104         relevance = getAttribute(p);
105     }
106
107     private int getRelevance() throws JspTagException JavaDoc {
108         String JavaDoc p = relevance.getString(this).toLowerCase();
109         return getPrecisionConstant(p);
110     }
111
112     public TimeZone getTimeZone() {
113         try {
114             String JavaDoc tz = timezone.getString(this);
115             if (tz != null && !"".equals(tz)) {
116                 return TimeZone.getTimeZone(tz);
117             } else {
118                 return super.getTimeZone();
119             }
120         } catch (JspTagException JavaDoc jte) {
121             return super.getTimeZone();
122         }
123     }
124
125     protected DateFormat getFormat() throws JspTagException JavaDoc {
126         if (log.isDebugEnabled()) {
127             log.debug("format: '" + dateFormat + "'");
128         }
129         return org.mmbase.util.DateFormats.getInstance(dateFormat.getString(this), getTimeZone().getID(), getLocale());
130     }
131
132
133     public void setInputformat(String JavaDoc inputformat) throws JspTagException JavaDoc {
134         this.inputFormat = getAttribute(inputformat);
135     }
136
137     public void setOffset(String JavaDoc offset) throws JspTagException JavaDoc {
138         this.offset = getAttribute(offset);
139     }
140
141     public void setTimezone(String JavaDoc tz) throws JspTagException JavaDoc {
142         timezone = getAttribute(tz);
143     }
144
145     /**
146      * You could implement a tag for the body of time-tag, which can then receive the date-object.
147      * @todo Don't we use getCalendar (to get Locales right)
148      * @since MMBase-1.7.1
149      */

150     public Date getDate() {
151         return _date;
152     }
153
154     public int doStartTag() throws JspTagException JavaDoc {
155         log.debug("Start-tag of mm:time ");
156         try {
157             _date = evaluateTime();
158         } catch (ParseException pe) {
159             throw new TaglibException(pe);
160         }
161         if (log.isDebugEnabled()) {
162             log.debug("Using date " + _date);
163         }
164         if (helper.getVartype() == WriterHelper.TYPE_DATE) {
165             helper.setValue(_date);
166         } else {
167             String JavaDoc formattedDate = format(_date);
168             if (log.isDebugEnabled()) {
169                 log.debug("Formatteddate " + formattedDate);
170             }
171             helper.setValue(formattedDate);
172         }
173
174         if (getId() != null) {
175             if (helper.getVartype() == WriterHelper.TYPE_DATE) {
176                 getContextProvider().getContextContainer().register(getId(), _date);
177             } else {
178                 getContextProvider().getContextContainer().register(getId(), helper.getValue());
179             }
180         }
181         return EVAL_BODY_BUFFERED;
182     }
183
184     public int doAfterBody() throws JspException JavaDoc {
185         return helper.doAfterBody();
186     }
187
188     public int doEndTag() throws JspTagException JavaDoc {
189         helper.doEndTag();
190         return super.doEndTag();
191     }
192
193     public void doFinally() {
194         inputFormat = Attribute.NULL;
195         offset = Attribute.NULL;
196         dateFormat = Attribute.NULL;
197         super.doFinally();
198     }
199
200     /**
201      * Evaluate the time attribute.
202      * @javadoc
203      */

204     private Date evaluateTime() throws JspTagException JavaDoc, ParseException {
205         if (log.isDebugEnabled()) {
206             log.debug("time: '" + time + "' offset: '" + offset + "' format: '" + dateFormat + "' inputformat: '" + inputFormat + "'");
207         }
208
209         String JavaDoc useTime = null;
210         Date date = null;
211         // If the time attribute is not set, check if referid is used, otherwise check if the parent set the time.
212
// Otherwise use current time
213
if (time == Attribute.NULL) {
214             if (getReferid() != null) { // try to get it from other time tag
215
Object JavaDoc object = getObject(getReferid());
216                 if (object instanceof Date) {
217                     date = (Date) object;
218                 } else {
219                     try {
220                         useTime = Casting.toString(object);
221                     } catch (Error JavaDoc e) {
222                         log.debug(e);
223                         useTime = null;
224                     }
225                 }
226             } else { // try to get it from parent writer.
227
Writer w = findWriter(false);
228                 if (w != null) {
229                     Object JavaDoc object = w.getWriterValue();
230                     if (object instanceof Date) {
231                         date = (Date) object;
232                     } else {
233                         useTime = "" + object;
234                     }
235
236                 }
237             }
238
239             if (useTime == null && date == null) { // still not found
240
throw new JspTagException JavaDoc("Cannot evaluate time. No time attribute given, no referid attribute set, and no writer parent tag found.");
241             }
242         } else {
243             useTime = time.getString(this);
244         }
245
246         TimeZone tz = getTimeZone();
247         String JavaDoc iformat = inputFormat.getString(this);
248         if (iformat.equals("")) {
249             if (date == null) {
250                 try {
251                     String JavaDoc tzTime = useTime.startsWith("TZ") ? useTime : ("TZ" + tz.getID() + " " + useTime);
252                     date = DynamicDate.eval(DynamicDate.getInstance(tzTime));
253                 } catch (Throwable JavaDoc e) {
254                     log.debug(e);
255                     // Try to parse it in three standard ways, this can be considered Legacy, because DynamicDate.getInstance can handle everything already.
256
date = parseTime(useTime);
257                 }
258             }
259         } else { // The input format is provided. We use that to parse the time attribute
260
try {
261                 // nothing to do with TIMEZONE?
262
SimpleDateFormat format = getDateFormat();
263                 format.applyPattern(iformat);
264                 date = format.parse(useTime);
265             } catch (java.text.ParseException JavaDoc e) {
266                 throw new TaglibException(e);
267             }
268
269         }
270
271         if (log.isDebugEnabled()) {
272             log.debug("date: '" + date + "'");
273         }
274
275         if (date == null) { // date fields can be null.
276
date = new Date(0);
277         }
278
279         date = handleOffset(date);
280         try {
281             date = handlePrecision(date);
282         } catch (org.mmbase.util.dateparser.ParseException pe) {
283             throw new TaglibException(pe);
284         }
285         date = handleRelevance(date);
286         return date;
287     }
288
289
290     private String JavaDoc format(Date date) throws JspTagException JavaDoc {
291         if (dateFormat == Attribute.NULL) {
292             // If no format is specified, we return the time in second from EPOC (UTC)
293
return "" + date.getTime() / 1000;
294         } else {
295             return getFormat().format(date);
296         }
297     }
298     
299     private Date handleOffset(Date date) throws JspTagException JavaDoc {
300         // Calculate the offset
301
if (offset != Attribute.NULL) {
302             long calculatedDate = date.getTime();
303             long os;
304             String JavaDoc off = offset.getString(this);
305             try {
306                 os = Long.parseLong(off) * 1000;
307             } catch (NumberFormatException JavaDoc nfe) {
308                 os = new Double JavaDoc(off).longValue() * 1000;
309             }
310             date = new Date(calculatedDate + os);
311         }
312         return date;
313     }
314     
315     private Date handlePrecision(Date date) throws JspTagException JavaDoc, org.mmbase.util.dateparser.ParseException {
316         // precision sets fields of date opbject to 0 starting with least relevant bits (for caching purposes)
317
if (precision != Attribute.NULL) {
318             Calendar cal = Calendar.getInstance(getTimeZone(), getLocale());
319             cal.setTime(date);
320             int prec = getPrecision();
321             switch (prec) {
322             case PRECISION_PARSE:
323                 long p = DynamicDate.getInstance("duration + " + precision.getString(this)).getTime();
324                 cal.setTime(new Date((date.getTime() / p) * p));
325                 break;
326             case PRECISION_YEARS :
327                 cal.set(Calendar.MONTH, Calendar.JANUARY);
328             case PRECISION_MONTHS :
329                 cal.set(Calendar.DAY_OF_MONTH, 1);
330             case PRECISION_DAYS :
331                 cal.set(Calendar.HOUR_OF_DAY, 0);
332             case PRECISION_HOURS :
333                 cal.set(Calendar.MINUTE, 0);
334             case PRECISION_MINUTES :
335                 cal.set(Calendar.SECOND, 0);
336             case PRECISION_SECONDS :
337             default :
338                 cal.set(Calendar.MILLISECOND, 0);
339             }
340             if (prec == PRECISION_WEEKS) {
341                 // this can not be done in above fall-through mechanism, because should not be done if >= PRECION_WEEKS
342
cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
343                 cal.set(Calendar.HOUR_OF_DAY, 0);
344                 cal.set(Calendar.MINUTE, 0);
345                 cal.set(Calendar.SECOND, 0);
346                 cal.set(Calendar.MILLISECOND, 0);
347             }
348             date = cal.getTime();
349         }
350         return date;
351     }
352     private Date handleRelevance(Date date) throws JspTagException JavaDoc {
353         // relevance (which is not in tld (yet), works the other way around. It sets the 'maximum
354
// relevance bit'. If for example you set it to 'months', then the year is set to 0 and can
355
// be ignored. In this way you can e.g. check if it january, or if it is somebody's birthday.
356
if (relevance != Attribute.NULL) {
357             Calendar cal = Calendar.getInstance(getTimeZone(), getLocale());
358             cal.setTime(date);
359             int rel = getRelevance();
360             switch (rel) {
361                 case PRECISION_SECONDS :
362                     cal.set(Calendar.MINUTE, 0);
363                 case PRECISION_MINUTES :
364                     cal.set(Calendar.HOUR, 0);
365                 case PRECISION_HOURS :
366                     cal.set(Calendar.DAY_OF_MONTH, 0);
367                 case PRECISION_WEEKS :
368                     ;
369                 case PRECISION_DAYS :
370                     cal.set(Calendar.MONTH, Calendar.JANUARY);
371                 case PRECISION_MONTHS :
372                     cal.set(Calendar.YEAR, 0);
373                 case PRECISION_YEARS :
374                 default :
375                     }
376             date = cal.getTime();
377         }
378         return date;
379     }
380
381     /**
382      * LEGACY.
383      *
384      * The time is giving in a standard format i.e. yyyy/mm/dd
385      * hh:mm:ss, yyyy/mm/dd, or hh:mm:ss. This function parses and
386      * returns the corresponding Date object, or throws an exception
387      * if unsuccessful.
388      * So, it parses the 'time' attribute without the use of 'inputformat'.
389      *
390      */

391     private Date parseTime(String JavaDoc t) throws ParseException, JspTagException JavaDoc {
392
393         Date date = new Date();
394         if (t.length() == 10) {
395             SimpleDateFormat format = getDateFormat();
396             format.applyPattern("yyyy/MM/dd");
397             date = format.parse(t);
398         } else if (t.length() == 8) {
399             SimpleDateFormat format = getDateFormat();
400             format.applyPattern("HH:mm:ss");
401             date = format.parse(t);
402         } else if (t.length() == 19) {
403             SimpleDateFormat format = getDateFormat();
404             format.applyPattern("yyyy/MM/dd HH:mm:ss");
405             date = format.parse(t);
406         } else {
407             throw new ParseException("Time '" + t + "' could not be parsed according to yyyy/MM/dd, HH:mm:ss or yyyy/MM/dd HH:mm:ss", 0);
408         }
409
410         return date;
411
412     }
413
414
415     /**
416      * DateFormat used for parsing dates.
417      */

418     protected SimpleDateFormat getDateFormat() throws JspTagException JavaDoc {
419         return new SimpleDateFormat("", getLocale());
420     }
421 }
422
Popular Tags