View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.commons.converter;
21  
22  import java.text.DateFormat;
23  import java.text.ParseException;
24  import java.text.SimpleDateFormat;
25  import java.util.Date;
26  import java.util.HashMap;
27  import java.util.Iterator;
28  import java.util.Locale;
29  import java.util.Map;
30  import java.util.TimeZone;
31  
32  import javax.faces.application.FacesMessage;
33  import javax.faces.application.FacesMessage.Severity;
34  import javax.faces.component.UIComponent;
35  import javax.faces.context.FacesContext;
36  import javax.faces.convert.ConverterException;
37  import javax.faces.el.ValueBinding;
38  
39  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFConverter;
40  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
41  import org.apache.myfaces.commons.util.MessageUtils;
42  
43  /**
44   * Simple convert that overrides the spec DateTimeConverter and uses TimeZone.getDefault() as the 
45   * base timezone, rather than GMT.
46   *
47   * Convert date time using normal system timezone like it should
48   *
49   * User: treeder
50   * Date: Oct 28, 2005
51   * Time: 7:19:01 PM
52   */
53  @JSFConverter(
54     name = "mcc:convertDateTime",
55     tagClass = "org.apache.myfaces.commons.converter.ConvertDateTimeTag",
56     tagHandler = "org.apache.myfaces.commons.converter.ConvertDateTimeTagHandler",
57     tagSuperclass = "javax.faces.webapp.ConverterTag",
58     evaluateELOnExecution=true)
59  public class DateTimeConverter extends javax.faces.convert.DateTimeConverter
60  {
61      public static final String CONVERTER_ID = "org.apache.myfaces.custom.convertDateTime.DateTimeConverter";
62      
63      // internal constants
64      private static final String CONVERSION_MESSAGE_ID = "javax.faces.convert.DateTimeConverter.CONVERSION";
65      private static final String TYPE_DATE = "date";
66      private static final String TYPE_TIME = "time";
67      private static final String TYPE_BOTH = "both";
68      private static final String STYLE_DEFAULT = "default";
69      private static final String STYLE_MEDIUM = "medium";
70      private static final String STYLE_SHORT = "short";
71      private static final String STYLE_LONG = "long";
72      private static final String STYLE_FULL = "full";
73      private static final TimeZone TIMEZONE_DEFAULT = TimeZone.getTimeZone("GMT");
74  
75      // CONSTRUCTORS
76      public DateTimeConverter()
77      {
78          //setTimeZone(TimeZone.getDefault());
79      }
80      
81      private String _dateStyle;
82      private Locale _locale;
83      private String _pattern;
84      private String _timeStyle;
85      private TimeZone _timeZone;
86      private String _type;
87      private boolean _transient;
88      
89      private transient FacesContext _facesContext;
90  
91      // METHODS
92      public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String value)
93      {
94          if (facesContext == null) throw new NullPointerException("facesContext");
95          if (uiComponent == null) throw new NullPointerException("uiComponent");
96  
97          if (value != null)
98          {
99              value = value.trim();
100             if (value.length() > 0)
101             {
102                 DateFormat format = getDateFormat();
103                 TimeZone tz = getTimeZone();
104                 if( tz != null )
105                     format.setTimeZone( tz );
106                 try
107                 {
108                     return format.parse(value);
109                 }
110                 catch (ParseException e)
111                 {
112                     throw new ConverterException(
113                             MessageUtils.getMessage(FacesMessage.FACES_MESSAGES, FacesMessage.SEVERITY_ERROR, CONVERSION_MESSAGE_ID,
114                                     new Object[] {value, uiComponent.getId()}, facesContext), e);
115                 }
116             }
117         }
118         return null;
119     }
120 
121     public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value)
122     {
123         if (facesContext == null) throw new NullPointerException("facesContext");
124         if (uiComponent == null) throw new NullPointerException("uiComponent");
125 
126         if (value == null)
127         {
128             return "";
129         }
130         if (value instanceof String)
131         {
132             return (String)value;
133         }
134 
135         DateFormat format = getDateFormat();
136         TimeZone tz = getTimeZone(); 
137         if (tz != null)
138         {
139             format.setTimeZone(tz);
140         }
141         try
142         {
143             return format.format(value);
144         }
145         catch (Exception e)
146         {
147             throw new ConverterException(e);
148         }
149     }
150 
151     private DateFormat getDateFormat()
152     {
153         String type = getType();
154         DateFormat format;
155         if (_pattern != null)
156         {
157             try 
158             {
159                 format = new SimpleDateFormat(_pattern, getLocale());
160             } 
161                 catch (IllegalArgumentException iae)
162             {
163                 throw new ConverterException("Invalid pattern", iae);    
164             }
165         }
166         else if (type.equals(TYPE_DATE))
167         {
168             format = DateFormat.getDateInstance(calcStyle(getDateStyle()), getLocale());
169         }
170         else if (type.equals(TYPE_TIME))
171         {
172             format = DateFormat.getTimeInstance(calcStyle(getTimeStyle()), getLocale());
173         }
174         else if (type.equals(TYPE_BOTH))
175         {
176             format = DateFormat.getDateTimeInstance(calcStyle(getDateStyle()),
177                                                     calcStyle(getTimeStyle()),
178                                                     getLocale());
179         }
180         else
181         {
182             throw new ConverterException("invalid type '" + _type + "'");
183         }
184         
185         // format cannot be lenient (JSR-127)
186         format.setLenient(false);
187         return format;
188     }
189 
190     private int calcStyle(String name)
191     {
192         if (name.equals(STYLE_DEFAULT))
193         {
194             return DateFormat.DEFAULT;
195         }
196         if (name.equals(STYLE_MEDIUM))
197         {
198             return DateFormat.MEDIUM;
199         }
200         if (name.equals(STYLE_SHORT))
201         {
202             return DateFormat.SHORT;
203         }
204         if (name.equals(STYLE_LONG))
205         {
206             return DateFormat.LONG;
207         }
208         if (name.equals(STYLE_FULL))
209         {
210             return DateFormat.FULL;
211         }
212 
213         throw new ConverterException("invalid style '" + name + "'");
214     }
215 
216     // STATE SAVE/RESTORE
217     public void restoreState(FacesContext facesContext, Object state)
218     {
219         Object[] values = (Object[])state;
220         _dateStyle = (String)values[0];
221         _locale = (Locale)values[1];
222         _pattern = (String)values[2];
223         _timeStyle = (String)values[3];
224         _timeZone = (TimeZone)values[4];
225         _type = (String)values[5];
226         restoreValueBindingMap(facesContext, values[6]);
227         
228     }
229 
230     public Object saveState(FacesContext facesContext)
231     {
232         Object[] values = new Object[7];
233         values[0] = _dateStyle;
234         values[1] = _locale;
235         values[2] = _pattern;
236         values[3] = _timeStyle;
237         values[4] = _timeZone;
238         values[5] = _type;
239         values[6] = saveValueBindingMap(facesContext);
240         return values;
241     }
242     
243     // --------------------- borrowed from UIComponentBase ------------
244 
245     private Map _valueBindingMap = null;
246 
247     public ValueBinding getValueBinding(String name)
248     {
249         if (name == null) throw new NullPointerException("name");
250         if (_valueBindingMap == null)
251         {
252             return null;
253         }
254         else
255         {
256             return (ValueBinding)_valueBindingMap.get(name);
257         }
258     }
259 
260     public void setValueBinding(String name,
261                                 ValueBinding binding)
262     {
263         if (name == null) throw new NullPointerException("name");
264         if (_valueBindingMap == null)
265         {
266             _valueBindingMap = new HashMap();
267         }
268         _valueBindingMap.put(name, binding);
269     }
270 
271     private Object saveValueBindingMap(FacesContext context)
272     {
273         if (_valueBindingMap != null)
274         {
275             int initCapacity = (_valueBindingMap.size() * 4 + 3) / 3;
276             HashMap stateMap = new HashMap(initCapacity);
277             for (Iterator it = _valueBindingMap.entrySet().iterator(); it.hasNext(); )
278             {
279                 Map.Entry entry = (Map.Entry)it.next();
280                 stateMap.put(entry.getKey(),
281                              ConverterBase.saveAttachedState(context, entry.getValue()));
282             }
283             return stateMap;
284         }
285         else
286         {
287             return null;
288         }
289     }
290 
291     private void restoreValueBindingMap(FacesContext context, Object stateObj)
292     {
293         if (stateObj != null)
294         {
295             Map stateMap = (Map)stateObj;
296             int initCapacity = (stateMap.size() * 4 + 3) / 3;
297             _valueBindingMap = new HashMap(initCapacity);
298             for (Iterator it = stateMap.entrySet().iterator(); it.hasNext(); )
299             {
300                 Map.Entry entry = (Map.Entry)it.next();
301                 _valueBindingMap.put(entry.getKey(),
302                         ConverterBase.restoreAttachedState(context, entry.getValue()));
303             }
304         }
305         else
306         {
307             _valueBindingMap = null;
308         }
309     }
310     protected FacesContext getFacesContext()
311     {
312         if (_facesContext == null)
313         {
314             return FacesContext.getCurrentInstance();
315         }
316         else
317         {
318             return _facesContext;
319         }
320     }
321     
322     boolean isCachedFacesContext()
323     {
324         return _facesContext != null;
325     }
326     
327     void setCachedFacesContext(FacesContext facesContext)
328     {
329         _facesContext = facesContext;
330     }
331     
332 
333     // GETTER & SETTER
334     
335     /**
336      * The style of the date.  Values include: default, short, medium, 
337      * long, and full.
338      * 
339      */
340     @JSFProperty(inheritedTag = false)
341     public String getDateStyle()
342     {
343         if (_dateStyle != null)
344         {
345             return _dateStyle;
346         }
347         ValueBinding vb = getValueBinding("dateStyle");
348         if (vb != null)
349         {
350             return (String) vb.getValue(getFacesContext());
351         }
352         return STYLE_DEFAULT;
353     }
354 
355     public void setDateStyle(String dateStyle)
356     {
357         _dateStyle = dateStyle;
358     }
359 
360     /**
361      * The name of the locale to be used, instead of the default.
362      * 
363      */
364     @JSFProperty(inheritedTag = false)
365     public Locale getLocale()
366     {        
367         if (_locale != null)
368         {
369             return _locale;
370         }
371         ValueBinding vb = getValueBinding("locale");
372         if (vb != null)
373         {
374             Object _localeValue = vb.getValue(getFacesContext());
375             if (_localeValue instanceof String)
376             {
377                 _localeValue = org.apache.myfaces.commons.util.TagUtils.getLocale((String)_localeValue);
378             }
379             return (java.util.Locale)_localeValue;
380         }
381         FacesContext context = FacesContext.getCurrentInstance();
382         return context.getViewRoot().getLocale();
383     }
384 
385     public void setLocale(Locale locale)
386     {
387         _locale = locale;
388     }
389 
390     /**
391      * A custom Date formatting pattern, in the format used by java.text.SimpleDateFormat.
392      * 
393      */
394     @JSFProperty(inheritedTag = false)
395     public String getPattern()
396     {
397         if (_pattern != null)
398         {
399             return _pattern;
400         }
401         ValueBinding vb = getValueBinding("pattern");
402         if (vb != null)
403         {
404             return (String) vb.getValue(getFacesContext()).toString();
405         }
406         return null;
407     }
408 
409     public void setPattern(String pattern)
410     {
411         _pattern = pattern;
412     }
413 
414     /**
415      * The style of the time.  Values include:  default, short, medium, long, 
416      * and full.
417      * 
418      */
419     @JSFProperty(inheritedTag = false)
420     public String getTimeStyle()
421     {
422         if (_timeStyle != null)
423         {
424             return _timeStyle;
425         }
426         ValueBinding vb = getValueBinding("timeStyle");
427         if (vb != null)
428         {
429             return (String) vb.getValue(getFacesContext()).toString();
430         }
431         return STYLE_DEFAULT;
432     }
433 
434     public void setTimeStyle(String timeStyle)
435     {
436         _timeStyle = timeStyle;
437     }
438 
439     /**
440      * The time zone to use instead of GMT (the default timezone). When
441      * this value is a value-binding to a TimeZone instance, that
442      * timezone is used. Otherwise this value is treated as a String
443      * containing a timezone id, ie as the ID parameter of method
444      * java.util.TimeZone.getTimeZone(String).
445      * 
446      */
447     @JSFProperty(inheritedTag = false)
448     public TimeZone getTimeZone()
449     {
450         //return _timeZone != null ? _timeZone : TIMEZONE_DEFAULT;
451         if (_timeZone != null)
452         {
453             return _timeZone;
454         }
455         ValueBinding vb = getValueBinding("timeZone");
456         if (vb != null)
457         {
458             Object _timeZoneValue = vb.getValue(getFacesContext());
459             if(_timeZoneValue instanceof java.util.TimeZone)
460             {
461                 return (java.util.TimeZone) _timeZoneValue;
462             }
463             else
464             {
465                 return java.util.TimeZone.getTimeZone(_timeZoneValue.toString());
466             }
467         }
468         return TimeZone.getDefault(); //TIMEZONE_DEFAULT
469     }
470 
471     public void setTimeZone(TimeZone timeZone)
472     {
473         _timeZone = timeZone;
474     }
475 
476     /**
477      * Specifies whether the date, time, or both should be 
478      * parsed/formatted.  Values include:  date, time, and both.
479      * Default based on setting of timeStyle and dateStyle.
480      * 
481      */
482     @JSFProperty(inheritedTag = false)
483     public String getType()
484     {
485         if (_type != null)
486         {
487             return _type;
488         }
489         ValueBinding vb = getValueBinding("type");
490         if (vb != null)
491         {
492             return (String) vb.getValue(getFacesContext()).toString();
493         }
494         return TYPE_DATE;
495     }
496 
497     public void setType(String type)
498     {
499         _type = type;
500     }
501 }