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  package javax.faces.convert;
20  
21  import java.text.DateFormat;
22  import java.text.ParseException;
23  import java.text.SimpleDateFormat;
24  import java.util.Date;
25  import java.util.Locale;
26  import java.util.TimeZone;
27  
28  import javax.faces.component.StateHolder;
29  import javax.faces.component.UIComponent;
30  import javax.faces.context.FacesContext;
31  
32  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFConverter;
33  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
34  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
35  
36  /**
37   * This tag associates a date time converter with the nearest parent UIComponent.
38   * 
39   * Unless otherwise specified, all attributes accept static values or EL expressions.
40   * 
41   * see Javadoc of <a href="http://java.sun.com/javaee/javaserverfaces/1.2/docs/api/index.html">JSF Specification</a>
42   *
43   * @author Thomas Spiegl (latest modification by $Author: lu4242 $)
44   * @version $Revision: 693358 $ $Date: 2008-09-08 22:54:29 -0500 (Mon, 08 Sep 2008) $
45   */
46  @JSFConverter(
47      name="f:convertDateTime",
48      bodyContent="empty",
49      tagClass="org.apache.myfaces.taglib.core.ConvertDateTimeTag")
50  @JSFJspProperty(
51      name="binding", 
52      returnType = "javax.faces.convert.DateTimeConverter",
53      longDesc = "A ValueExpression that evaluates to a DateTimeConverter.")
54  public class DateTimeConverter
55          implements Converter, StateHolder
56  {
57  
58      // API field
59      public static final String CONVERTER_ID = "javax.faces.DateTime";
60      public static final String DATE_ID = "javax.faces.converter.DateTimeConverter.DATE";
61      public static final String DATETIME_ID = "javax.faces.converter.DateTimeConverter.DATETIME";
62      public static final String STRING_ID = "javax.faces.converter.STRING";
63      public static final String TIME_ID = "javax.faces.converter.DateTimeConverter.TIME";
64  
65      // internal constants
66      private static final String TYPE_DATE = "date";
67      private static final String TYPE_TIME = "time";
68      private static final String TYPE_BOTH = "both";
69      private static final String STYLE_DEFAULT = "default";
70      private static final String STYLE_MEDIUM = "medium";
71      private static final String STYLE_SHORT = "short";
72      private static final String STYLE_LONG = "long";
73      private static final String STYLE_FULL = "full";
74      private static final TimeZone TIMEZONE_DEFAULT = TimeZone.getTimeZone("GMT");
75  
76      private String _dateStyle;
77      private Locale _locale;
78      private String _pattern;
79      private String _timeStyle;
80      private TimeZone _timeZone;
81      private String _type;
82      private boolean _transient;
83  
84      // CONSTRUCTORS
85      public DateTimeConverter()
86      {
87      }
88  
89      // METHODS
90      public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String value)
91      {
92          if (facesContext == null) throw new NullPointerException("facesContext");
93          if (uiComponent == null) throw new NullPointerException("uiComponent");
94  
95          if (value != null)
96          {
97              value = value.trim();
98              if (value.length() > 0)
99              {
100                 DateFormat format = getDateFormat();
101                 TimeZone tz = getTimeZone();
102                 if( tz != null )
103                     format.setTimeZone( tz );
104                 try
105                 {
106                     return format.parse(value);
107                 }
108                 catch (ParseException e)
109                 {
110                     String type = getType();
111                     Object[] args = new Object[]{value,format.format(new Date()),_MessageUtils.getLabel(facesContext, uiComponent)};
112                     
113                     if(type.equals(TYPE_DATE))
114                         throw new ConverterException(_MessageUtils.getErrorMessage(facesContext,DATE_ID,args));
115                     else if (type.equals(TYPE_TIME))
116                         throw new ConverterException(_MessageUtils.getErrorMessage(facesContext,TIME_ID,args));
117                     else if (type.equals(TYPE_BOTH))
118                         throw new ConverterException(_MessageUtils.getErrorMessage(facesContext,DATETIME_ID,args));
119                     else
120                         throw new ConverterException("invalid type '" + _type + "'");
121                 }
122             }
123         }
124         return null;
125     }
126 
127     public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value)
128     {
129         if (facesContext == null) throw new NullPointerException("facesContext");
130         if (uiComponent == null) throw new NullPointerException("uiComponent");
131 
132         if (value == null)
133         {
134             return "";
135         }
136         if (value instanceof String)
137         {
138             return (String)value;
139         }
140 
141         DateFormat format = getDateFormat();
142         TimeZone tz = getTimeZone(); 
143         if (tz != null)
144         {
145             format.setTimeZone(tz);
146         }
147         try
148         {
149             return format.format(value);
150         }
151         catch (Exception e)
152         {
153             throw new ConverterException(_MessageUtils.getErrorMessage(facesContext, STRING_ID, new Object[]{value,_MessageUtils.getLabel(facesContext, uiComponent)}),e);
154         }
155     }
156 
157     private DateFormat getDateFormat()
158     {
159         String type = getType();
160         DateFormat format;
161         if (_pattern != null)
162         {
163             try 
164             {
165                 format = new SimpleDateFormat(_pattern, getLocale());
166             } 
167                 catch (IllegalArgumentException iae)
168             {
169                 throw new ConverterException("Invalid pattern", iae);    
170             }
171         }
172         else if (type.equals(TYPE_DATE))
173         {
174             format = DateFormat.getDateInstance(calcStyle(getDateStyle()), getLocale());
175         }
176         else if (type.equals(TYPE_TIME))
177         {
178             format = DateFormat.getTimeInstance(calcStyle(getTimeStyle()), getLocale());
179         }
180         else if (type.equals(TYPE_BOTH))
181         {
182             format = DateFormat.getDateTimeInstance(calcStyle(getDateStyle()),
183                                                     calcStyle(getTimeStyle()),
184                                                     getLocale());
185         }
186         else
187         {
188             throw new ConverterException("invalid type '" + _type + "'");
189         }
190         
191         // format cannot be lenient (JSR-127)
192         format.setLenient(false);
193         return format;
194     }
195 
196     private int calcStyle(String name)
197     {
198         if (name.equals(STYLE_DEFAULT))
199         {
200             return DateFormat.DEFAULT;
201         }
202         if (name.equals(STYLE_MEDIUM))
203         {
204             return DateFormat.MEDIUM;
205         }
206         if (name.equals(STYLE_SHORT))
207         {
208             return DateFormat.SHORT;
209         }
210         if (name.equals(STYLE_LONG))
211         {
212             return DateFormat.LONG;
213         }
214         if (name.equals(STYLE_FULL))
215         {
216             return DateFormat.FULL;
217         }
218 
219         throw new ConverterException("invalid style '" + name + "'");
220     }
221 
222     // STATE SAVE/RESTORE
223     public void restoreState(FacesContext facesContext, Object state)
224     {
225         Object[] values = (Object[])state;
226         _dateStyle = (String)values[0];
227         _locale = (Locale)values[1];
228         _pattern = (String)values[2];
229         _timeStyle = (String)values[3];
230         _timeZone = (TimeZone)values[4];
231         _type = (String)values[5];
232     }
233 
234     public Object saveState(FacesContext facesContext)
235     {
236         Object[] values = new Object[6];
237         values[0] = _dateStyle;
238         values[1] = _locale;
239         values[2] = _pattern;
240         values[3] = _timeStyle;
241         values[4] = _timeZone;
242         values[5] = _type;
243         return values;
244     }
245 
246     // GETTER & SETTER
247     
248     /**
249      * The style of the date.  Values include: default, short, medium, 
250      * long, and full.
251      * 
252      */
253     @JSFProperty
254     public String getDateStyle()
255     {
256         return _dateStyle != null ? _dateStyle : STYLE_DEFAULT;
257     }
258 
259     public void setDateStyle(String dateStyle)
260     {
261         //TODO: validate timeStyle
262         _dateStyle = dateStyle;
263     }
264 
265     /**
266      * The name of the locale to be used, instead of the default.
267      * 
268      */
269     @JSFProperty
270     public Locale getLocale()
271     {
272         if (_locale != null) return _locale;
273         FacesContext context = FacesContext.getCurrentInstance();
274         return context.getViewRoot().getLocale();
275     }
276 
277     public void setLocale(Locale locale)
278     {
279         _locale = locale;
280     }
281 
282     /**
283      * A custom Date formatting pattern, in the format used by java.text.SimpleDateFormat.
284      * 
285      */
286     @JSFProperty
287     public String getPattern()
288     {
289         return _pattern;
290     }
291 
292     public void setPattern(String pattern)
293     {
294         _pattern = pattern;
295     }
296 
297     /**
298      * The style of the time.  Values include:  default, short, medium, long, 
299      * and full.
300      * 
301      */
302     @JSFProperty
303     public String getTimeStyle()
304     {
305         return _timeStyle != null ? _timeStyle : STYLE_DEFAULT;
306     }
307 
308     public void setTimeStyle(String timeStyle)
309     {
310         //TODO: validate timeStyle
311         _timeStyle = timeStyle;
312     }
313 
314     /**
315      * The time zone to use instead of GMT (the default timezone). When
316      * this value is a value-binding to a TimeZone instance, that
317      * timezone is used. Otherwise this value is treated as a String
318      * containing a timezone id, ie as the ID parameter of method
319      * java.util.TimeZone.getTimeZone(String).
320      * 
321      */
322     @JSFProperty
323     public TimeZone getTimeZone()
324     {
325         return _timeZone != null ? _timeZone : TIMEZONE_DEFAULT;
326     }
327 
328     public void setTimeZone(TimeZone timeZone)
329     {
330         _timeZone = timeZone;
331     }
332 
333     public boolean isTransient()
334     {
335         return _transient;
336     }
337 
338     public void setTransient(boolean aTransient)
339     {
340         _transient = aTransient;
341     }
342 
343     /**
344      * Specifies whether the date, time, or both should be 
345      * parsed/formatted.  Values include:  date, time, and both.
346      * Default based on setting of timeStyle and dateStyle.
347      * 
348      */
349     @JSFProperty
350     public String getType()
351     {
352         return _type != null ? _type : TYPE_DATE;
353     }
354 
355     public void setType(String type)
356     {
357         //TODO: validate type
358         _type = type;
359     }
360 }