001: /*
002: * Copyright (c) 2001 - 2005 ivata limited.
003: * All rights reserved.
004: * -----------------------------------------------------------------------------
005: * ivata groupware may be redistributed under the GNU General Public
006: * License as published by the Free Software Foundation;
007: * version 2 of the License.
008: *
009: * These programs are free software; you can redistribute them and/or
010: * modify them under the terms of the GNU General Public License
011: * as published by the Free Software Foundation; version 2 of the License.
012: *
013: * These programs are distributed in the hope that they will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
016: *
017: * See the GNU General Public License in the file LICENSE.txt for more
018: * details.
019: *
020: * If you would like a copy of the GNU General Public License write to
021: *
022: * Free Software Foundation, Inc.
023: * 59 Temple Place - Suite 330
024: * Boston, MA 02111-1307, USA.
025: *
026: *
027: * To arrange commercial support and licensing, contact ivata at
028: * http://www.ivata.com/contact.jsp
029: * -----------------------------------------------------------------------------
030: * $Log: SettingDateFormatter.java,v $
031: * Revision 1.5 2005/10/12 18:36:18 colinmacleod
032: * Standardized format of Logger declaration - to make it easier to find instances
033: * which are not both static and final.
034: *
035: * Revision 1.4 2005/10/11 18:57:17 colinmacleod
036: * Fixed some checkstyle and javadoc issues.
037: *
038: * Revision 1.3 2005/10/03 10:21:15 colinmacleod
039: * Fixed some style and javadoc issues.
040: *
041: * Revision 1.2 2005/10/02 14:08:59 colinmacleod
042: * Added/improved log4j logging.
043: *
044: * Revision 1.1 2005/09/29 13:07:49 colinmacleod
045: * First version of setting subproject.
046: * Existing classes restructured, new setting user interface created.
047: * Flexible XML UI configuration makes it easy to reuse the same web pages in
048: * other projects.
049: * Web files work as stand-alone webapp for testing.
050: *
051: * Revision 1.3 2005/09/14 16:10:22 colinmacleod
052: * Removed unused local and class variables.
053: * Added serialVersionUID.
054: *
055: * Revision 1.2 2005/04/09 17:19:58 colinmacleod
056: * Changed copyright text to GPL v2 explicitly.
057: *
058: * Revision 1.1.1.1 2005/03/10 17:51:45 colinmacleod
059: * Restructured ivata op around Hibernate/PicoContainer.
060: * Renamed ivata groupware.
061: *
062: * Revision 1.3 2004/11/12 15:57:20 colinmacleod
063: * Removed dependencies on SSLEXT.
064: * Moved Persistence classes to ivata masks.
065: *
066: * Revision 1.2 2004/11/03 16:10:13 colinmacleod
067: * Changed todo comments to TODO: all caps.
068: *
069: * Revision 1.1 2004/09/30 15:16:04 colinmacleod
070: * Split off addressbook elements into security subproject.
071: *
072: * Revision 1.3 2004/07/13 19:41:17 colinmacleod
073: * Moved project to POJOs from EJBs.
074: * Applied PicoContainer to services layer (replacing session EJBs).
075: * Applied Hibernate to persistence layer (replacing entity EJBs).
076: *
077: * Revision 1.2 2004/03/21 21:16:19 colinmacleod
078: * Shortened name to ivata op.
079: *
080: * Revision 1.1.1.1 2004/01/27 20:58:00 colinmacleod
081: * Moved ivata openportal to SourceForge..
082: *
083: * Revision 1.2 2003/10/17 12:36:13 jano
084: * fixing problems with building
085: * converting intranet -> portal
086: * Eclipse building
087: *
088: * Revision 1.1.1.1 2003/10/13 20:50:15 colin
089: * Restructured portal into subprojects
090: *
091: * Revision 1.19 2003/06/02 06:03:31 peter
092: * userName check commented out
093: *
094: * Revision 1.18 2003/02/25 16:57:20 peter
095: * fixed bugs: mistyped variable names
096: *
097: * Revision 1.17 2003/02/24 19:27:31 colin
098: * restructured file paths
099: *
100: * Revision 1.16 2003/02/21 16:22:05 peter
101: * serializable now
102: *
103: * Revision 1.15 2003/02/20 16:21:19 peter
104: * added input format for date/time
105: *
106: * Revision 1.14 2003/02/20 14:25:28 peter
107: * 24H time formats removed
108: *
109: * Revision 1.13 2003/02/20 07:47:41 colin
110: * changed name of setting from timeZone to i18nTimeZone
111: *
112: * Revision 1.12 2003/02/04 17:43:52 colin
113: * copyright notice
114: *
115: * Revision 1.10 2003/01/30 16:40:39 peter
116: * time zone awareness added
117: *
118: * Revision 1.9 2003/01/15 10:58:44 jano
119: * fixing bug with language
120: *
121: * Revision 1.8 2002/12/18 13:14:26 peter
122: * the locale information read from db, moved to
123: * SimpleDateFormat's locale aware constructor
124: *
125: * Revision 1.6 2002/09/23 11:47:32 colin
126: * Split date formatter constants off into separate file.
127: *
128: * Revision 1.5 2002/08/29 16:40:42 colin
129: * improved error handling of missing settings
130: *
131: * Revision 1.4 2002/07/30 14:12:27 jano
132: * set lenient to FALSE of format when is DateFormater created
133: *
134: * Revision 1.3 2002/07/15 14:59:32 jano
135: * added format time for 24H
136: *
137: * Revision 1.2 2002/07/10 13:16:43 colin
138: * bug fixes
139: * completed implementation of SettingDateFormatter
140: * -----------------------------------------------------------------------------
141: */
142: package com.ivata.groupware.util;
143:
144: import java.io.Serializable;
145: import java.text.MessageFormat;
146: import java.text.ParseException;
147: import java.text.SimpleDateFormat;
148: import java.util.Calendar;
149: import java.util.Date;
150: import java.util.GregorianCalendar;
151: import java.util.Locale;
152: import java.util.TimeZone;
153:
154: import org.apache.log4j.Logger;
155:
156: import com.ivata.groupware.admin.security.server.SecuritySession;
157: import com.ivata.groupware.admin.setting.Settings;
158: import com.ivata.groupware.admin.setting.SettingsInitializationException;
159: import com.ivata.mask.util.SystemException;
160: import com.ivata.mask.web.format.DateFormatter;
161: import com.ivata.mask.web.format.DateFormatterConstants;
162: import com.ivata.mask.web.format.DateFormatterException;
163:
164: /**
165: * <p>Handles conversion of dates to/from strings in a unified way
166: * throughout the intranet system.</p>
167: *
168: * @author Colin MacLeod
169: * <a href='mailto:colin.macleod@ivata.com'>colin.macleod@ivata.com</a>
170: * @version $Revision: 1.5 $
171: * @since ivata groupware 0.9 (2002-06-22)
172: * TODO: the <code>DATE_FORMAT_RELATIVE</code> handling could be
173: * extended to include future dates
174: */
175: public class SettingDateFormatter implements Serializable,
176: DateFormatter {
177: /**
178: * All times after <code>HOUR_MORNING</code> but before this hour are
179: * considered afternoon.
180: */
181: private static final int HOUR_AFTERNOON = 18;
182: /**
183: * All times before this hour are considered morning.
184: */
185: private static final int HOUR_MORNING = 12;
186: /**
187: * Logger for this class.
188: */
189: private static final Logger logger = Logger
190: .getLogger(SettingDateFormatter.class);
191: /**
192: * Serialization version (for <code>Serializable</code> interface).
193: */
194: private static final long serialVersionUID = 1L;
195: /**
196: * <p>Set this to one of the
197: * <code>DateFormatterConstants.DATE_FORMAT_.</code> constants to use
198: * that date format.</p>
199: */
200: private int dateFormat = DateFormatterConstants.DATE_LONG;
201: /**
202: * <p>This is the pattern string which is passed to the
203: * <code>SimpleDateFormat</code> which is used internally. Used to
204: * display error texts.</p>
205: */
206: private String dateFormatString = null;
207: /**
208: * <p>Stores how the date and time are used in the output. Change this
209: * text to
210: * restrict the output to just date or just time, or to change the
211: * text between
212: * them.</p>
213: *
214: * <p>The format used is the same as the format for
215: * <code>java.text.MessageFormat</code> and the string
216: * <code>{0}</code> will be
217: * replaced with the date format chosen, <code>{1}</code> is replaced
218: * with the
219: * time format chosen.</p>
220: */
221: private String dateTimeText = "{0}, ''at'' {1}";
222: /**
223: * <p>This member is used to do the actual date conversions.</p>
224: */
225: private SimpleDateFormat format;
226:
227: /**
228: * <p>Used to form the string which connects the date format with the
229: * time
230: * format.</p>
231: */
232: private MessageFormat messageFormat;
233: /**
234: * <p>This is the pattern string which is passed to the
235: * <code>SimpleDateFormat</code> which is used internally. Used to
236: * display error texts.</p>
237: */
238: private String pattern = null;
239: /**
240: * <p>
241: * Each date formatter can only apply to one security session. This is used
242: * to retrieve settings for the current user.
243: * </p>
244: */
245: private SecuritySession securitySession;
246: /**
247: * <p>Used to access the date formats from the system settings.</p>
248: */
249: private Settings settings;
250: /**
251: * <p>Set this to one of the
252: * <code>DateFormatterConstants.TIME_FORMAT_.</code> to use that time
253: * format.</p>
254: */
255: private int timeFormat = DateFormatterConstants.TIME_SHORT;
256:
257: /**
258: * <p>This is the pattern string which is passed to the
259: * <code>SimpleDateFormat</code> which is used internally. Used to
260: * display error texts.</p>
261: */
262: private String timeFormatString = null;
263:
264: /**
265: * <p>Holds the time zone used in this formatter to return dates
266: * specific to user's geographic location.</p>
267: */
268: private TimeZone timeZone;
269: /**
270: * <p>Date format settings (as with all other settings in
271: * ivata groupware) can be
272: * made specific to each user. This user name identifies the user
273: * whose
274: * individual preferences will be applied </p>
275: *
276: * <p>Leave this setting <code>null</code> (the default) to use the
277: * standard,
278: * system-wide settings.</p>
279: */
280: private String userName = null;
281:
282: /**
283: * Construct a date formatter.
284: *
285: * @param securitySessionParam Used to retrieve settings for the current
286: * user.
287: * @param settingsParam Used to access the date formats from the system
288: * settings.
289: */
290: public SettingDateFormatter(
291: final SecuritySession securitySessionParam,
292: final Settings settingsParam) {
293: this .securitySession = securitySessionParam;
294: this .settings = settingsParam;
295: }
296:
297: /**
298: * <p>Used by the class internally to initialize the
299: * <code>SimpleDateFormat</code> instance used when the format
300: * changes.</p>
301: *
302: * @param date for relative date formats, the returned string is
303: * dependent upon
304: * the date being formatted. In these cases, this date is used to
305: * create a
306: * relative format.
307: * @throws SettingsInitializationException if the settings for this
308: * formatter
309: * have not yet been set.
310: * @throws DateFormatterException if the settings for this date format
311: *
312: * are not set, or not set correctly
313: */
314: private void createFormat(final Date date)
315: throws SettingsInitializationException,
316: DateFormatterException {
317: if (logger.isDebugEnabled()) {
318: logger.debug("createFormat(Date date = " + date
319: + ") - start");
320: }
321:
322: // prerequisites: check that the security and settings are not null
323: assert (settings != null);
324: assert (securitySession != null);
325:
326: try {
327: if (messageFormat == null) {
328: messageFormat = new MessageFormat(dateTimeText);
329: }
330: // now work out the format to use
331: // if the date is relative, there is nothing we can do here without
332: // a date object
333: if (((dateFormat == DateFormatterConstants.DATE_RELATIVE) || (dateFormat == DateFormatterConstants.DATE_SHORT_RELATIVE))
334: && (date == null)) {
335: format = null;
336:
337: if (logger.isDebugEnabled()) {
338: logger.debug("createFormat() - end");
339: }
340: return;
341: }
342: // other date formats are constant
343: String dateFormatSetting = getDateFormatSetting(date);
344: dateFormatString = settings.getStringSetting(
345: securitySession, dateFormatSetting, securitySession
346: .getUser());
347:
348: String timeFormatSetting = getTimeFormatSetting(date);
349: timeFormatString = settings.getStringSetting(
350: securitySession, timeFormatSetting, securitySession
351: .getUser());
352:
353: // now just format the dateTimeText and use the result to create the
354: // simple date format
355: Object[] arguments = { dateFormatString, timeFormatString };
356: Locale locale = new Locale(settings.getStringSetting(
357: securitySession, "i18nLocaleLanguage",
358: securitySession.getUser()), settings
359: .getStringSetting(securitySession,
360: "i18nLocaleCountry", securitySession
361: .getUser()));
362:
363: pattern = MessageFormat.format(dateTimeText, arguments);
364: format = new SimpleDateFormat(pattern, locale);
365: format.setLenient(false);
366: format.setTimeZone(getTimeZone());
367: } catch (com.ivata.mask.util.SystemException e) {
368: logger.error("createFormat - " + e.getClass(), e);
369: throw new DateFormatterException(
370: "Error in SettingDateFormatter.createFormat().", e);
371: }
372:
373: if (logger.isDebugEnabled()) {
374: logger.debug("createFormat() - end");
375: }
376: }
377:
378: /**
379: * <p>Format the date provided as a string, using the date format from
380: * the settings.</p>
381: *
382: * @param date the date to convert into a string.
383: * @return date string, converted to a string, using the requested
384: * format.
385: * @throws DateFormatterException if there is a problem creating the
386: * string because of an incorrect format pattern, for example.
387: */
388: public String format(final Date date) throws DateFormatterException {
389: if (logger.isDebugEnabled()) {
390: logger.debug("format(Date date = " + date + ") - start");
391: }
392:
393: if ((format == null)
394: || (dateFormat == DateFormatterConstants.DATE_RELATIVE)
395: || (dateFormat == DateFormatterConstants.DATE_SHORT_RELATIVE)) {
396: try {
397: createFormat(date);
398: } catch (SettingsInitializationException e1) {
399: logger.error("format - creating the format.");
400: throw new DateFormatterException(e1);
401: }
402: }
403: String returnString = "";
404:
405: try {
406: returnString = format.format(date);
407: } catch (Exception e) {
408: String message = "ERROR in SettingDateFormatter: format threw "
409: + e.getClass()
410: + " formatting '"
411: + date
412: + "', using date format '"
413: + dateFormatString
414: + "', time format '" + timeFormatString + "'";
415: logger.error(message, e);
416: throw new DateFormatterException(message, e);
417: }
418:
419: if (logger.isDebugEnabled()) {
420: logger.debug("format() - end - return value = "
421: + returnString);
422: }
423: return returnString;
424: }
425:
426: /**
427: * <p>Get the number of the date format used in this object. This
428: * should
429: * correspond to one of the <code>DATE_FORMAT_...</code>
430: * constants.</p>
431: *
432: * @return the current value of the date format used.
433: */
434: public int getDateFormat() {
435: if (logger.isDebugEnabled()) {
436: logger.debug("getDateFormat() - start");
437: }
438:
439: if (logger.isDebugEnabled()) {
440: logger.debug("getDateFormat() - end - return value = "
441: + dateFormat);
442: }
443: return dateFormat;
444: }
445:
446: /**
447: * Get the system setting to use for the date, given the numeric date format
448: * we should use.
449: *
450: * @param date The date for which to return the setting.
451: * @return The name of the system setting to use to get the
452: * <code>SimpleDateFormat</code> date pattern.
453: * @throws SystemException If the date format is unrecognized.
454: */
455: private String getDateFormatSetting(final Date date)
456: throws SystemException {
457: if (logger.isDebugEnabled()) {
458: logger.debug("getDateFormatSetting(Date date = " + date
459: + ") - start");
460: }
461:
462: String dateFormatSetting;
463: switch (dateFormat) {
464: default:
465: String message = "createFormat - unrecognized date format '"
466: + dateFormat + "'";
467: logger.error(message);
468: throw new SystemException(message);
469:
470: case DateFormatterConstants.DATE_LONG:
471: dateFormatSetting = "i18nDateLong";
472: break;
473:
474: case DateFormatterConstants.DATE_LONG_YEAR:
475: dateFormatSetting = "i18nDateLongYear";
476: break;
477:
478: case DateFormatterConstants.DATE_LONG_DAY:
479: dateFormatSetting = "i18nDateLongDay";
480: break;
481:
482: case DateFormatterConstants.DATE_SHORT:
483: dateFormatSetting = "i18nDateShort";
484: break;
485:
486: case DateFormatterConstants.DATE_SHORT_YEAR:
487: dateFormatSetting = "i18nDateShortYear";
488: break;
489:
490: case DateFormatterConstants.DATE_INPUT:
491: dateFormatSetting = "i18nDateInput";
492: break;
493:
494: case DateFormatterConstants.DATE_INPUT_DISPLAY:
495: dateFormatSetting = "i18nDateInputDisplay";
496: break;
497:
498: case DateFormatterConstants.DATE_SHORT_RELATIVE:
499: case DateFormatterConstants.DATE_RELATIVE:
500: GregorianCalendar now = new GregorianCalendar();
501:
502: now.setTime(new Date());
503: GregorianCalendar yesterday = new GregorianCalendar();
504:
505: yesterday.setTime(new Date());
506: yesterday.roll(GregorianCalendar.DATE, false);
507: GregorianCalendar lastWeek = new GregorianCalendar();
508:
509: lastWeek.setTime(new Date());
510: lastWeek.roll(GregorianCalendar.WEEK_OF_YEAR, false);
511: GregorianCalendar compare = new GregorianCalendar();
512:
513: compare.setTime(date);
514: // is it today?
515: if ((now.get(GregorianCalendar.YEAR) == compare
516: .get(GregorianCalendar.YEAR))
517: && (now.get(GregorianCalendar.DAY_OF_YEAR) == compare
518: .get(GregorianCalendar.DAY_OF_YEAR))) {
519: dateFormatSetting = getTodayFormatSetting(compare);
520: } else if ((now.get(GregorianCalendar.YEAR) == compare
521: .get(GregorianCalendar.YEAR))
522: && (yesterday.get(GregorianCalendar.DAY_OF_YEAR) == compare
523: .get(GregorianCalendar.DAY_OF_YEAR))) {
524: dateFormatSetting = getYesterdayFormatSetting(compare);
525: } else if ((now.get(GregorianCalendar.YEAR) == compare
526: .get(GregorianCalendar.YEAR))
527: && (now.get(GregorianCalendar.WEEK_OF_YEAR) == compare
528: .get(GregorianCalendar.WEEK_OF_YEAR))) {
529: // so it this week
530: dateFormatSetting = "i18nDateWeekDay";
531: } else if (now.get(GregorianCalendar.YEAR) == compare
532: .get(GregorianCalendar.YEAR)) {
533: // it is this year
534: if (dateFormat == DateFormatterConstants.DATE_SHORT_RELATIVE) {
535: dateFormatSetting = "i18nDateShort";
536: } else {
537: dateFormatSetting = "i18nDateLong";
538: }
539: } else {
540: // everything else is long year format
541: if (dateFormat == DateFormatterConstants.DATE_SHORT_RELATIVE) {
542: dateFormatSetting = "i18nDateShortYear";
543: } else {
544: dateFormatSetting = "i18nDateLongYear";
545: }
546: }
547: break;
548: }
549:
550: if (logger.isDebugEnabled()) {
551: logger
552: .debug("getDateFormatSetting() - end - return value = "
553: + dateFormatSetting);
554: }
555: return dateFormatSetting;
556: }
557:
558: /**
559: * <p>Get how the date and time are used in the output.</p>
560: *
561: * <p>The format used is the same as the format for
562: * <code>java.text.MessageFormat</code> and the string
563: * <code>{0}</code> will be
564: * replaced with the date format chosen, <code>{1}</code> is replaced
565: * with the
566: * time format chosen.</p>
567: *
568: * @return the current text used to combine date and time formats.
569: */
570: public String getDateTimeText() {
571: if (logger.isDebugEnabled()) {
572: logger.debug("getDateTimeText() - start");
573: }
574:
575: if (logger.isDebugEnabled()) {
576: logger.debug("getDateTimeText() - end - return value = "
577: + dateTimeText);
578: }
579: return dateTimeText;
580: }
581:
582: /**
583: * <p>Get the number of the time format used in this object. This
584: * should
585: * correspond to one of the <code>TIME_FORMAT_...</code>
586: * constants.</p>
587: *
588: * @return the current value of the time format used.
589: */
590: public int getTimeFormat() {
591: if (logger.isDebugEnabled()) {
592: logger.debug("getTimeFormat() - start");
593: }
594:
595: if (logger.isDebugEnabled()) {
596: logger.debug("getTimeFormat() - end - return value = "
597: + timeFormat);
598: }
599: return timeFormat;
600: }
601:
602: /**
603: * Get the system setting to use for the time, given the numeric date format
604: * we should use.
605: *
606: * @param date The date for which to return the setting.
607: * @return The name of the system setting to use to get the
608: * <code>SimpleDateFormat</code> date pattern.
609: * @throws SystemException If the date format is unrecognized.
610: */
611: private String getTimeFormatSetting(final Date date)
612: throws SystemException {
613: if (logger.isDebugEnabled()) {
614: logger.debug("getTimeFormatSetting(Date date = " + date
615: + ") - start");
616: }
617:
618: String timeFormatSetting;
619: // times are simpler
620: switch (timeFormat) {
621: default:
622: throw new SystemException("Unrecognized time format '"
623: + timeFormat + "'");
624: case DateFormatterConstants.TIME_LONG:
625: timeFormatSetting = "i18nTimeLong";
626: break;
627:
628: case DateFormatterConstants.TIME_SHORT:
629: timeFormatSetting = "i18nTimeShort";
630: break;
631:
632: case DateFormatterConstants.TIME_INPUT:
633: timeFormatSetting = "i18nTimeInput";
634: break;
635:
636: case DateFormatterConstants.TIME_INPUT_DISPLAY:
637: timeFormatSetting = "i18nTimeInputDisplay";
638: break;
639:
640: }
641:
642: if (logger.isDebugEnabled()) {
643: logger
644: .debug("getTimeFormatSetting() - end - return value = "
645: + timeFormatSetting);
646: }
647: return timeFormatSetting;
648: }
649:
650: /**
651: * <p>Get the private variable timeZone, when not set yet,
652: * fetches it from settings first.</p>
653: *
654: * @return The time zone.
655: * @exception DateFormatterException if there is a remote exception
656: * accessing the settings, or the settings is of an unexpected data
657: * type.
658: */
659: private TimeZone getTimeZone() throws DateFormatterException {
660: if (logger.isDebugEnabled()) {
661: logger.debug("getTimeZone() - start");
662: }
663:
664: assert (securitySession != null);
665: if (this .timeZone == null) {
666: try {
667: String timeZoneID = settings.getStringSetting(
668: securitySession, "i18nTimeZone",
669: securitySession.getUser());
670: timeZone = TimeZone.getTimeZone(timeZoneID);
671: } catch (SystemException e) {
672: String message = "getTimeZone - Error in SettingDateFormatter "
673: + "getting system setting 'i18nTimeZone.";
674: logger.error(message, e);
675: throw new DateFormatterException(message, e);
676: }
677: }
678:
679: if (logger.isDebugEnabled()) {
680: logger.debug("getTimeZone() - end - return value = "
681: + timeZone);
682: }
683: return timeZone;
684: }
685:
686: /**
687: * Helper, called from <code>getDateFormatSetting</code>. Get the correct
688: * setting name, for the pattern for a date format when the date happens
689: * today.
690: *
691: * @param compare Date and time to compare against.
692: * @return pattern string for this date format
693: */
694: private String getTodayFormatSetting(final Calendar compare) {
695: if (logger.isDebugEnabled()) {
696: logger.debug("getTodayFormatSetting(Calendar compare = "
697: + compare + ") - start");
698: }
699:
700: String dateFormatSetting;
701: if (dateFormat == DateFormatterConstants.DATE_SHORT_RELATIVE) {
702: dateFormatSetting = "i18nDateShortToday";
703: } else {
704: // it is today: now we need to compare the time
705: int hour = compare.get(GregorianCalendar.HOUR_OF_DAY);
706:
707: if (hour < HOUR_MORNING) {
708: dateFormatSetting = "i18nDateThisMorning";
709: } else if (hour < HOUR_AFTERNOON) {
710: dateFormatSetting = "i18nDateThisAfternoon";
711: } else {
712: dateFormatSetting = "i18nDateThisEvening";
713: }
714: }
715:
716: if (logger.isDebugEnabled()) {
717: logger
718: .debug("getTodayFormatSetting() - end - return value = "
719: + dateFormatSetting);
720: }
721: return dateFormatSetting;
722: }
723:
724: /**
725: * <p>Get the user name used for date/time system settings.</p>
726: *
727: * <p>Date format settings (as with all other settings in
728: * ivata groupware) can be
729: * made specific to each user. This user name identifies the user
730: * whose
731: * indifvidual preferences will be applied </p>
732: *
733: * @return the current value of the user name used for settings.
734: */
735: public String getUserName() {
736: if (logger.isDebugEnabled()) {
737: logger.debug("getUserName() - start");
738: }
739:
740: if (logger.isDebugEnabled()) {
741: logger.debug("getUserName() - end - return value = "
742: + userName);
743: }
744: return userName;
745: }
746:
747: /**
748: * Helper, called from <code>getDateFormatSetting</code>. Get the correct
749: * setting name, for the pattern for a date format when the date happens
750: * yesterday.
751: *
752: * @param compare Current date and time to compare against.
753: * @return pattern string for this date format
754: */
755: private String getYesterdayFormatSetting(final Calendar compare) {
756: if (logger.isDebugEnabled()) {
757: logger
758: .debug("getYesterdayFormatSetting(Calendar compare = "
759: + compare + ") - start");
760: }
761:
762: String dateFormatSetting;
763: if (dateFormat == DateFormatterConstants.DATE_SHORT_RELATIVE) {
764: dateFormatSetting = "i18nDateShortYesterday";
765: } else {
766: // it is yesterday: now we need to compare the time
767: int hour = compare.get(GregorianCalendar.HOUR_OF_DAY);
768:
769: if (hour < HOUR_MORNING) {
770: dateFormatSetting = "i18nDateYesterdayMorning";
771: } else if (hour < HOUR_AFTERNOON) {
772: dateFormatSetting = "i18nDateYesterdayAfternoon";
773: } else {
774: dateFormatSetting = "i18nDateYesterdayEvening";
775: }
776: }
777:
778: if (logger.isDebugEnabled()) {
779: logger
780: .debug("getYesterdayFormatSetting() - end - return value = "
781: + dateFormatSetting);
782: }
783: return dateFormatSetting;
784: }
785:
786: /**
787: * <p>Parse the given string to a date, using the current date
788: * format.</p>
789: *
790: * @param formatString the string to convert into a date.
791: * @return date parsed from the string provided.
792: * @throws ParseException if the string provided does not match the
793: * date/time format.
794: * @throws DateFormatterException if the settings for this date format
795: *
796: * are not set, or not set correctly
797: */
798: public Date parse(final String formatString) throws ParseException,
799: DateFormatterException {
800: if (logger.isDebugEnabled()) {
801: logger.debug("parse(String formatString = " + formatString
802: + ") - start");
803: }
804:
805: if ((dateFormat == DateFormatterConstants.DATE_RELATIVE)
806: || (dateFormat == DateFormatterConstants.DATE_SHORT_RELATIVE)) {
807: // TODO: go through all of the possible date formats and try to
808: // parse each one
809:
810: if (logger.isDebugEnabled()) {
811: logger.debug("parse() - end - return value = " + null);
812: }
813: return null;
814: }
815: if (format == null) {
816: try {
817: createFormat(null);
818: } catch (SettingsInitializationException e1) {
819: logger.error("parse() - error creating the format", e1);
820: throw new DateFormatterException(e1);
821: }
822: }
823: Date returnDate = format.parse(formatString);
824: if (logger.isDebugEnabled()) {
825: logger
826: .debug("parse() - end - return value = "
827: + returnDate);
828: }
829: return returnDate;
830: }
831:
832: /**
833: * <p>Set the number of the date format used in this object. This
834: * should
835: * correspond to one of the <code>DATE_FORMAT_...</code>
836: * constants.</p>
837: *
838: * @param dateFormatParam the new value of the date format used.
839: * @throws DateFormatterException if the settings for this date format
840: * are not set, or not set correctly
841: */
842: public void setDateFormat(final int dateFormatParam)
843: throws DateFormatterException {
844: if (logger.isDebugEnabled()) {
845: logger.debug("setDateFormat(int dateFormat = "
846: + dateFormatParam + ") - start");
847: }
848:
849: this .dateFormat = dateFormatParam;
850: try {
851: // date format has changed, create the format
852: createFormat(null);
853: } catch (SettingsInitializationException e) {
854: logger.error(
855: "setDateFormat() - error creating the format.", e);
856: throw new DateFormatterException(e);
857: }
858:
859: if (logger.isDebugEnabled()) {
860: logger.debug("setDateFormat() - end");
861: }
862: }
863:
864: /**
865: * <p>Set this text to restrict the output to just date or just time,
866: * or to
867: * change the text between
868: * them.</p>
869: *
870: * <p>The format used is the same as the format for
871: * <code>java.text.MessageFormat</code> and the string
872: * <code>{0}</code> will be
873: * replaced with the date format chosen, <code>{1}</code> is replaced
874: * with the
875: * time format chosen.</p>
876: *
877: * @param dateTimeTextParam the new value of the text used to combine date
878: * and time
879: * formats.
880: * @throws DateFormatterException if the settings for this date format
881: * are not set, or not set correctly
882: */
883: public void setDateTimeText(final String dateTimeTextParam)
884: throws DateFormatterException {
885: if (logger.isDebugEnabled()) {
886: logger.debug("setDateTimeText(String dateTimeText = "
887: + dateTimeTextParam + ") - start");
888: }
889:
890: this .dateTimeText = dateTimeTextParam;
891: // this affects the message format: force a new one
892: messageFormat = null;
893: try {
894: createFormat(null);
895: } catch (SettingsInitializationException e) {
896: logger.error(
897: "setDateTimeText - error creating the format.", e);
898: throw new DateFormatterException(e);
899: }
900:
901: if (logger.isDebugEnabled()) {
902: logger.debug("setDateTimeText() - end");
903: }
904: }
905:
906: /**
907: * <p>Set the number of the time format used in this object. This
908: * should
909: * correspond to one of the <code>TIME_FORMAT_...</code>
910: * constants.</p>
911: *
912: * @param timeFormatParam the new value of the time format used.
913: * @throws DateFormatterException if the settings for this date format
914: * are not set, or not set correctly
915: */
916: public void setTimeFormat(final int timeFormatParam)
917: throws DateFormatterException {
918: if (logger.isDebugEnabled()) {
919: logger.debug("setTimeFormat(int timeFormat = "
920: + timeFormatParam + ") - start");
921: }
922:
923: this .timeFormat = timeFormatParam;
924: try {
925: // time format has changed, create the format
926: createFormat(null);
927: } catch (SettingsInitializationException e) {
928: logger.error("setTimeFormat - error creating the format.",
929: e);
930: throw new DateFormatterException(e);
931: }
932:
933: if (logger.isDebugEnabled()) {
934: logger.debug("setTimeFormat() - end");
935: }
936: }
937:
938: /**
939: * <p>Set the user name used for date/time system settings.</p>
940: *
941: * <p>Date format settings (as with all other settings in
942: * ivata groupware) can be
943: * made specific to each user. This user name identifies the user
944: * whose
945: * individual preferences will be applied </p>
946: *
947: * <p>Leave this setting <code>null</code> (the default) to use the
948: * standard,
949: * system-wide settings.</p>
950: *
951: * @param userNameParam the new value of the user name used for system
952: * settings.
953: * @throws SettingsInitializationException if the settings for this
954: * formatter
955: * have not yet been set.
956: * @throws DateFormatterException if the settings for this date format
957: * are not set, or not set correctly
958: */
959: public void setUserName(final String userNameParam)
960: throws SettingsInitializationException,
961: DateFormatterException {
962: if (logger.isDebugEnabled()) {
963: logger.debug("setUserName(String userName = "
964: + userNameParam + ") - start");
965: }
966:
967: this .userName = userNameParam;
968: // user has changed, create the format
969: createFormat(null);
970:
971: if (logger.isDebugEnabled()) {
972: logger.debug("setUserName() - end");
973: }
974: }
975: }
|