1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.jelly.tags.fmt;
17
18 import org.apache.commons.jelly.JellyTagException;
19 import org.apache.commons.jelly.XMLOutput;
20 import org.apache.commons.jelly.Tag;
21 import org.apache.commons.jelly.TagSupport;
22 import org.apache.commons.jelly.expression.Expression;
23
24 import org.xml.sax.SAXException;
25
26 import java.text.DateFormat;
27 import java.text.SimpleDateFormat;
28 import java.util.Date;
29 import java.util.Locale;
30 import java.util.TimeZone;
31
32
33 /***
34 * Support for tag handlers for <formatDate>, the date and time formatting
35 * tag in JSTL.
36 * @author <a href="mailto:willievu@yahoo.com">Willie Vu</a>
37 * @version $Revision: 155420 $
38 * @task i18n exception message
39 */
40 public class FormatDateTag extends TagSupport {
41
42 private static final String DEFAULT = "default";
43 private static final String SHORT = "short";
44 private static final String MEDIUM = "medium";
45 private static final String LONG = "long";
46 private static final String FULL = "full";
47
48 private static final String DATE = "date";
49 private static final String TIME = "time";
50 private static final String DATETIME = "both";
51
52 /*** Holds value of property value. */
53 private Expression value;
54
55 /*** Holds value of property type. */
56 private Expression type;
57
58 /*** Holds value of property dataStyle. */
59 private Expression dateStyle;
60
61 /*** Holds value of property timeStyle. */
62 private Expression timeStyle;
63
64 /*** Holds value of property pattern. */
65 private Expression pattern;
66
67 /*** Holds value of property timeZone. */
68 private Expression timeZone;
69
70 /*** Holds value of property var. */
71 private String var;
72
73 /*** Holds value of property scope. */
74 private String scope;
75
76 /*** Evaluated type */
77 private String etype;
78 /*** Evaluated dateStyle */
79 private String edateStyle;
80 /*** Evaluated timeStyle */
81 private String etimeStyle;
82
83 /*** Creates a new instance of FormatDateTag */
84 public FormatDateTag() {
85 }
86
87 /***
88 * Evaluates this tag after all the tags properties have been initialized.
89 *
90 */
91 public void doTag(XMLOutput output) throws JellyTagException {
92
93 if (scope != null && var == null) {
94 throw new JellyTagException(
95 "If 'scope' is specified, 'var' must be defined for this tag" );
96 }
97
98 Object valueInput = null;
99 if (this.value != null) {
100 valueInput = this.value.evaluate(context);
101 }
102
103 Date date = null;
104 if (valueInput != null && valueInput instanceof Date) {
105 date = (Date) valueInput;
106 }
107
108 if (date == null && var != null) {
109 if (scope != null) {
110 context.removeVariable(var, scope);
111 }
112 else {
113 context.removeVariable(var);
114 }
115 }
116
117 etype = DATE;
118 if (this.type != null) {
119 etype = (String) this.type.evaluate(context);
120 }
121
122 edateStyle = DEFAULT;
123 if (this.dateStyle != null) {
124 edateStyle = (String) this.dateStyle.evaluate(context);
125 }
126
127 etimeStyle = DEFAULT;
128 if (this.timeStyle != null) {
129 etimeStyle = (String) this.timeStyle.evaluate(context);
130 }
131
132 String epattern = null;
133 if (this.pattern != null) {
134 epattern = (String) this.pattern.evaluate(context);
135 }
136
137 Object etimeZone = null;
138 if (this.timeZone != null) {
139 etimeZone = this.timeZone.evaluate(context);
140 }
141
142
143 Locale locale = SetLocaleTag.getFormattingLocale(
144 context,
145 this,
146 true,
147 DateFormat.getAvailableLocales());
148
149 String formatted = null;
150 if (locale != null) {
151 DateFormat formatter = createFormatter(locale);
152
153
154 if (pattern != null) {
155 try {
156 ((SimpleDateFormat) formatter).applyPattern(epattern);
157 } catch (ClassCastException cce) {
158 formatter = new SimpleDateFormat(epattern, locale);
159 }
160 }
161
162
163 TimeZone tz = null;
164 if ((etimeZone instanceof String)
165 && ((String) etimeZone).equals("")) {
166 etimeZone = null;
167 }
168 if (etimeZone != null) {
169 if (etimeZone instanceof String) {
170 tz = TimeZone.getTimeZone((String) etimeZone);
171 } else if (etimeZone instanceof TimeZone) {
172 tz = (TimeZone) etimeZone;
173 } else {
174 throw new JellyTagException("Bad time zone");
175 }
176 } else {
177 tz = TimeZoneTag.getTimeZone(context, this);
178 }
179 if (tz != null) {
180 formatter.setTimeZone(tz);
181 }
182 formatted = formatter.format(date);
183 } else {
184
185 formatted = date.toString();
186 }
187
188 if (var != null) {
189 if (scope != null) {
190 context.setVariable(var, scope, formatted);
191 }
192 else {
193 context.setVariable(var, formatted);
194 }
195 }
196 else {
197 try {
198
199 output.write(formatted);
200 } catch (SAXException e) {
201 throw new JellyTagException("could not write formatted text",e);
202 }
203 }
204 }
205
206 /*** Setter for property value.
207 * @param value New value of property value.
208 *
209 */
210 public void setValue(Expression value) {
211 this.value = value;
212 }
213
214 /*** Setter for property type.
215 * @param type New value of property type.
216 *
217 */
218 public void setType(Expression type) {
219 this.type = type;
220 }
221
222 /*** Setter for property dataStyle.
223 * @param dataStyle New value of property dataStyle.
224 *
225 */
226 public void setDateStyle(Expression dateStyle) {
227 this.dateStyle = dateStyle;
228 }
229
230 /*** Setter for property timeStyle.
231 * @param timeStyle New value of property timeStyle.
232 *
233 */
234 public void setTimeStyle(Expression timeStyle) {
235 this.timeStyle = timeStyle;
236 }
237
238 /*** Setter for property pattern.
239 * @param pattern New value of property pattern.
240 *
241 */
242 public void setPattern(Expression pattern) {
243 this.pattern = pattern;
244 }
245
246 /*** Setter for property timeZone.
247 * @param timeZone New value of property timeZone.
248 *
249 */
250 public void setTimeZone(Expression timeZone) {
251 this.timeZone = timeZone;
252 }
253
254 /*** Setter for property var.
255 * @param var New value of property var.
256 *
257 */
258 public void setVar(String var) {
259 this.var = var;
260 }
261
262 /*** Setter for property scope.
263 * @param scope New value of property scope.
264 *
265 */
266 public void setScope(String scope) {
267 this.scope = scope;
268 }
269
270 //**********************************************************************
271 // Private utility methods
272
273 private DateFormat createFormatter(Locale loc) throws JellyTagException {
274 DateFormat formatter = null;
275
276 if ((etype == null) || DATE.equalsIgnoreCase(etype)) {
277 formatter = DateFormat.getDateInstance(
278 getStyle(edateStyle, "FORMAT_DATE_INVALID_DATE_STYLE"),
279 loc);
280 } else if (TIME.equalsIgnoreCase(etype)) {
281 formatter = DateFormat.getTimeInstance(
282 getStyle(etimeStyle, "FORMAT_DATE_INVALID_TIME_STYLE"),
283 loc);
284 } else if (DATETIME.equalsIgnoreCase(etype)) {
285 formatter = DateFormat.getDateTimeInstance(
286 getStyle(edateStyle, "FORMAT_DATE_INVALID_DATE_STYLE"),
287 getStyle(etimeStyle, "FORMAT_DATE_INVALID_TIME_STYLE"),
288 loc);
289 } else {
290 throw new JellyTagException("Date format invalue");
291 }
292
293 return formatter;
294 }
295
296 /*
297 * Converts the given string description of a formatting style for
298 * dates and times to the corresponding java.util.DateFormat constant.
299 *
300 * @param style String description of formatting style for dates and times
301 * @param errCode Error code to throw if given style is invalid
302 *
303 * @return java.util.DateFormat constant corresponding to given style
304 *
305 * @throws JellyException if the given style is invalid
306 */
307 public static int getStyle(String style, String errCode)
308 throws JellyTagException {
309 int ret = DateFormat.DEFAULT;
310
311 if (style != null) {
312 if (DEFAULT.equalsIgnoreCase(style)) {
313 ret = DateFormat.DEFAULT;
314 } else if (SHORT.equalsIgnoreCase(style)) {
315 ret = DateFormat.SHORT;
316 } else if (MEDIUM.equalsIgnoreCase(style)) {
317 ret = DateFormat.MEDIUM;
318 } else if (LONG.equalsIgnoreCase(style)) {
319 ret = DateFormat.LONG;
320 } else if (FULL.equalsIgnoreCase(style)) {
321 ret = DateFormat.FULL;
322 } else {
323 throw new JellyTagException("Invalid style " + errCode);
324 }
325 }
326
327 return ret;
328 }
329
330 }