View Javadoc

1   /*
2    * $Id: DateTimePicker.java 497654 2007-01-19 00:21:57Z rgielen $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts2.components;
22  
23  import java.text.ParseException;
24  import java.text.SimpleDateFormat;
25  import java.util.Date;
26  
27  import javax.servlet.http.HttpServletRequest;
28  import javax.servlet.http.HttpServletResponse;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.struts2.views.annotations.StrutsTag;
33  import org.apache.struts2.views.annotations.StrutsTagAttribute;
34  
35  import com.opensymphony.xwork2.util.ValueStack;
36  
37  /***
38   * <!-- START SNIPPET: javadoc -->
39   * <p>
40   * Renders a date/time picker in a dropdown container.
41   * </p>
42   * <p>
43   * A stand-alone DateTimePicker widget that makes it easy to select a date/time, or increment by week, month,
44   * and/or year.
45   * </p>
46   * Dates attributes passed in the `RFC 3339` format:
47   *
48   * Renders date/time picker element.</p>
49   * Format supported by this component are:-
50   * <table border="1">
51   *   <tr>
52   *      <td>Format</td>
53   *      <td>Description</td>
54   *   </tr>
55   *   <tr>
56   *      <td>#dd</td>
57   *      <td>Display day in two digits format</td>
58   *   </tr>
59   *   <tr>
60   *      <td>#d</td>
61   *      <td>Try to display day in one digit format, if cannot use 2 digit format</td>
62   *   </tr>
63   *   <tr>
64   *      <td>#MM</td>
65   *      <td>Display month in two digits format</td>
66   *   </tr>
67   *   <tr>
68   *      <td>#M</td>
69   *      <td>Try to display month in one digits format, if cannot use 2 digit format</td>
70   *   </tr>
71   *   <tr>
72   *      <td>#yyyy</td>
73   *      <td>Display year in four digits format</td>
74   *   </tr>
75   *   <tr>
76   *      <td>#yy</td>
77   *      <td>Display the last two digits of the yaer</td>
78   *   </tr>
79   *   <tr>
80   *      <td>#y</td>
81   *      <td>Display the last digits of the year</td>
82   *   </tr>
83   * </table>
84   * 
85   * <p>
86   * It is possible to customize the user-visible formatting with either the
87   * formatLength or displayFormat attributes. The value sent to the server is
88   * typically a locale-independent value in a hidden field as defined by the name
89   * attribute. RFC3339 representation is used by default, but other options are
90   * available with saveFormat
91   * </p>
92   *
93   * <p/>
94   *
95   * <!-- END SNIPPET: javadoc -->
96   *
97   * <b>Examples</b>
98   *
99   * <pre>
100  * <!-- START SNIPPET: expl1 -->
101  *
102  * Example 1:
103  *     &lt;s:datetimepicker name="order.date" label="Order Date" /&gt;
104  * Example 2:
105  *     &lt;s:datetimepicker name="delivery.date" label="Delivery Date" format="#yyyy-#MM-#dd"  /&gt;
106  *
107  * <!-- END SNIPPET: expl1 -->
108  * </pre>
109  * <p/>
110  *
111  * <!-- START SNIPPET: expldesc2 -->
112  *
113  * The css could be changed by using the following :-
114  *
115  * <!-- END SNIPPET: expldesc2 -->
116  *
117  * <pre>
118  * <!-- START SNIPPET: expl2 -->
119  *
120  * &lt;s:datetimepicker name="birthday" label="Birthday" templateCss="...." /&gt;
121  *
122  * <!-- END SNIPPET: expl2 -->
123  * </pre>
124  *
125  */
126 @StrutsTag(name="datetimepicker", tldTagClass="org.apache.struts2.views.jsp.ui.DateTimePickerTag", description="Render datetimepicker")
127 public class DateTimePicker extends UIBean {
128 
129     final public static String TEMPLATE = "datetimepicker";
130     final private static SimpleDateFormat RFC3399_FORMAT = new SimpleDateFormat(
131     "yyyy-MM-dd'T'HH:mm:ss");
132     final protected static Log LOG = LogFactory.getLog(DateTimePicker.class);
133     
134     protected String iconPath;
135     protected String formatLength;
136     protected String displayFormat;
137     protected String toggleType;
138     protected String toggleDuration;
139     protected String type;
140 
141     protected String displayWeeks;
142     protected String adjustWeeks;
143     protected String startDate;
144     protected String endDate;
145     protected String weekStartsOn;
146     protected String staticDisplay;
147     protected String dayWidth;
148     protected String language;
149 
150     public DateTimePicker(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
151         super(stack, request, response);
152     }
153 
154     protected String getDefaultTemplate() {
155         return TEMPLATE;
156     }
157 
158     public void evaluateParams() {
159         super.evaluateParams();
160 
161         if(displayWeeks != null)
162             addParameter("displayWeeks", findString(displayWeeks));
163         if(adjustWeeks != null)
164             addParameter("adjustWeeks", findValue(adjustWeeks, Boolean.class));
165         if(startDate != null)
166             addParameter("startDate", findString(startDate));
167         if(endDate != null)
168             addParameter("endDate", findString(endDate));
169         if(weekStartsOn != null)
170             addParameter("weekStartsOn", findString(weekStartsOn));
171         if(staticDisplay != null)
172             addParameter("staticDisplay", findValue(staticDisplay, Boolean.class));
173         if(dayWidth != null)
174             addParameter("dayWidth", findValue(dayWidth, Integer.class));
175         if(language != null)
176             addParameter("language", findString(language));
177         if(value != null)
178             addParameter("value", findString(value));
179         if(iconPath != null)
180             addParameter("iconPath", iconPath);
181         if(formatLength != null)
182             addParameter("formatLength", findString(formatLength));
183         if(displayFormat != null)
184             addParameter("displayFormat", findString(displayFormat));
185         if(toggleType != null)
186             addParameter("toggleType", findString(toggleType));
187         if(toggleDuration != null)
188             addParameter("toggleDuration", findValue(toggleDuration,
189                     Integer.class));
190         if(type != null)
191             addParameter("type", findString(type));
192         else
193             addParameter("type", "date");
194 
195         // format the value to RFC 3399
196         if(parameters.containsKey("value")) {
197             parameters.put("nameValue", format(parameters.get("value")));
198         } else {
199             if(name != null) {
200                 String expr = name;
201                 if(altSyntax()) {
202                     expr = "%{" + expr + "}";
203                 }
204                 addParameter("nameValue", format(findValue(expr)));
205             }
206         }
207     }
208 
209     @StrutsTagAttribute(description="If true, weekly size of calendar changes to acomodate the month if false," +
210                 " 42 day format is used", type="Boolean", defaultValue="false")
211     public void setAdjustWeeks(String adjustWeeks) {
212         this.adjustWeeks = adjustWeeks;
213     }
214 
215     @StrutsTagAttribute(description="How to render the names of the days in the header(narrow, abbr or wide)", defaultValue="narrow")
216     public void setDayWidth(String dayWidth) {
217         this.dayWidth = dayWidth;
218     }
219 
220     @StrutsTagAttribute(description="Total weeks to display", type="Integer", defaultValue="6")
221     public void setDisplayWeeks(String displayWeeks) {
222         this.displayWeeks = displayWeeks;
223     }
224 
225     @StrutsTagAttribute(description="Last available date in the calendar set", type="Date", defaultValue="2941-10-12")
226     public void setEndDate(String endDate) {
227         this.endDate = endDate;
228     }
229 
230     @StrutsTagAttribute(description="First available date in the calendar set", type="Date", defaultValue="1492-10-12")
231     public void setStartDate(String startDate) {
232         this.startDate = startDate;
233     }
234 
235     @StrutsTagAttribute(description="Disable all incremental controls, must pick a date in the current display", type="Boolean", defaultValue="false")
236     public void setStaticDisplay(String staticDisplay) {
237         this.staticDisplay = staticDisplay;
238     }
239 
240     @StrutsTagAttribute(description="Adjusts the first day of the week 0==Sunday..6==Saturday", type="Integer", defaultValue="0")
241     public void setWeekStartsOn(String weekStartsOn) {
242         this.weekStartsOn = weekStartsOn;
243     }
244 
245     @StrutsTagAttribute(description="Language to display this widget in", defaultValue="brower's specified preferred language")
246     public void setLanguage(String language) {
247         this.language = language;
248     }
249     
250     @StrutsTagAttribute(description="A pattern used for the visual display of the formatted date, e.g. dd/MM/yyyy")
251     public void setDisplayFormat(String displayFormat) {
252         this.displayFormat = displayFormat;
253     }
254 
255     @StrutsTagAttribute(description="Type of formatting used for visual display. Possible values are " +
256                 "long, short, medium or full", defaultValue="short")
257     public void setFormatLength(String formatLength) {
258         this.formatLength = formatLength;
259     }
260 
261     @StrutsTagAttribute(description=" Path to icon used for the dropdown")
262     public void setIconPath(String iconPath) {
263         this.iconPath = iconPath;
264     }
265 
266     @StrutsTagAttribute(description="Duration of toggle in milliseconds", type="Integer", defaultValue="100")
267     public void setToggleDuration(String toggleDuration) {
268         this.toggleDuration = toggleDuration;
269     }
270 
271     @StrutsTagAttribute(description="Defines the type of the picker on the dropdown. Possible values are 'date'" +
272                 " for a DateTimePicker, and 'time' for a timePicker", defaultValue="date")
273     public void setType(String type) {
274         this.type = type;
275     }
276 
277     @StrutsTagAttribute(description="oggle type of the dropdown. Possible values are plain,wipe,explode,fade", defaultValue="plain")
278     public void setToggleType(String toggleType) {
279         this.toggleType = toggleType;
280     }
281     
282     private String format(Object obj) {
283         if(obj == null)
284             return null;
285 
286         if(obj instanceof Date) {
287             return RFC3399_FORMAT.format((Date) obj);
288         } else {
289             // try to parse a date
290             String dateStr = obj.toString();
291             if(dateStr.equalsIgnoreCase("today"))
292                 return  RFC3399_FORMAT.format(new Date());
293 
294             try {
295                 Date date = null;
296                 if(this.displayFormat != null) {
297                     SimpleDateFormat format = new SimpleDateFormat(
298                             this.displayFormat);
299                     date = format.parse(dateStr);
300                     return RFC3399_FORMAT.format(date);
301                 } else {
302                     // last resource to assume already in correct/default format
303                     return dateStr;
304                 }
305             } catch (ParseException e) {
306                 LOG.error("Could not parse date", e);
307                 return dateStr;
308             }
309         }
310     }
311 
312 }