View Javadoc

1   /*
2    * $Id: DateTimePicker.java 512578 2007-02-28 02:44:58Z musachy $
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   *
47   * <p>
48   * It is possible to customize the user-visible formatting with either the
49   * 'formatLength' (long, short, medium or full) or 'displayFormat' attributes. By defaulty current
50   * locale will be used.</p>
51   * </p>
52   * 
53   * Syntax supported by 'displayFormat' is (http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns):-
54   * <table border="1">
55   *   <tr>
56   *      <td>Format</td>
57   *      <td>Description</td>
58   *   </tr>
59   *   <tr>
60   *      <td>d</td>
61   *      <td>Day of the month</td>
62   *   </tr>
63   *   <tr>
64   *      <td>D</td>
65   *      <td>Day of year</td>
66   *   </tr>
67   *   <tr>
68   *      <td>M</td>
69   *      <td>Month - Use one or two for the numerical month, three for the abbreviation, or four for the full name, or 5 for the narrow name.</td>
70   *   </tr>
71   *   <tr>
72   *      <td>h</td>
73   *      <td>Hour [1-12].</td>
74   *   </tr>
75   *   <tr>
76   *      <td>H</td>
77   *      <td>Hour [0-23].</td>
78   *   </tr>
79   *   <tr>
80   *      <td>m</td>
81   *      <td>Minute. Use one or two for zero padding.</td>
82   *   </tr>
83   *   <tr>
84   *      <td>s</td>
85   *      <td>Second. Use one or two for zero padding.</td>
86   *   </tr>
87   * </table>
88   * 
89   * <p>
90   * The value sent to the server is
91   * typically a locale-independent value in a hidden field as defined by the name
92   * attribute. RFC3339 representation is the format used.
93   * </p>
94   *
95   * <p/>
96   *
97   * <!-- END SNIPPET: javadoc -->
98   *
99   * <b>Examples</b>
100  *
101  * <pre>
102  * <!-- START SNIPPET: expl1 -->
103  *
104  * Example 1:
105  *     &lt;s:datetimepicker name="order.date" label="Order Date" /&gt;
106  * Example 2:
107  *     &lt;s:datetimepicker name="delivery.date" label="Delivery Date" format="yyyy-MM-dd"  /&gt;
108  *
109  * <!-- END SNIPPET: expl1 -->
110  * </pre>
111  * <p/>
112  *
113  * <!-- START SNIPPET: expldesc2 -->
114  *
115  * The css could be changed by using the following :-
116  *
117  * <!-- END SNIPPET: expldesc2 -->
118  *
119  * <pre>
120  * <!-- START SNIPPET: expl2 -->
121  *
122  * &lt;s:datetimepicker name="birthday" label="Birthday" templateCss="...." /&gt;
123  *
124  * <!-- END SNIPPET: expl2 -->
125  * </pre>
126  *
127  */
128 @StrutsTag(name="datetimepicker", tldTagClass="org.apache.struts2.views.jsp.ui.DateTimePickerTag", description="Render datetimepicker")
129 public class DateTimePicker extends UIBean {
130 
131     final public static String TEMPLATE = "datetimepicker";
132     final private static SimpleDateFormat RFC3339_FORMAT = new SimpleDateFormat(
133     "yyyy-MM-dd'T'HH:mm:ss");
134     final protected static Log LOG = LogFactory.getLog(DateTimePicker.class);
135     
136     protected String iconPath;
137     protected String formatLength;
138     protected String displayFormat;
139     protected String toggleType;
140     protected String toggleDuration;
141     protected String type;
142 
143     protected String displayWeeks;
144     protected String adjustWeeks;
145     protected String startDate;
146     protected String endDate;
147     protected String weekStartsOn;
148     protected String staticDisplay;
149     protected String dayWidth;
150     protected String language;
151     protected String templateCssPath;
152 
153     public DateTimePicker(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
154         super(stack, request, response);
155     }
156 
157     protected String getDefaultTemplate() {
158         return TEMPLATE;
159     }
160 
161     public void evaluateParams() {
162         super.evaluateParams();
163 
164         if(displayWeeks != null)
165             addParameter("displayWeeks", findString(displayWeeks));
166         if(adjustWeeks != null)
167             addParameter("adjustWeeks", findValue(adjustWeeks, Boolean.class));
168         if(startDate != null)
169             addParameter("startDate", findString(startDate));
170         if(endDate != null)
171             addParameter("endDate", findString(endDate));
172         if(weekStartsOn != null)
173             addParameter("weekStartsOn", findString(weekStartsOn));
174         if(staticDisplay != null)
175             addParameter("staticDisplay", findValue(staticDisplay, Boolean.class));
176         if(dayWidth != null)
177             addParameter("dayWidth", findValue(dayWidth, Integer.class));
178         if(language != null)
179             addParameter("language", findString(language));
180         if(value != null)
181             addParameter("value", findString(value));
182         if(iconPath != null)
183             addParameter("iconPath", findString(iconPath));
184         if(formatLength != null)
185             addParameter("formatLength", findString(formatLength));
186         if(displayFormat != null)
187             addParameter("displayFormat", findString(displayFormat));
188         if(toggleType != null)
189             addParameter("toggleType", findString(toggleType));
190         if(toggleDuration != null)
191             addParameter("toggleDuration", findValue(toggleDuration,
192                     Integer.class));
193         if(type != null)
194             addParameter("type", findString(type));
195         else
196             addParameter("type", "date");
197         if(templateCssPath != null)
198             addParameter("templateCssPath", findString(templateCssPath));
199         
200         // format the value to RFC 3399
201         if(parameters.containsKey("value")) {
202             parameters.put("nameValue", format(parameters.get("value")));
203         } else {
204             if(name != null) {
205                 String expr = name;
206                 if(altSyntax()) {
207                     expr = "%{" + expr + "}";
208                 }
209                 addParameter("nameValue", format(findValue(expr)));
210             }
211         }
212     }
213 
214     @StrutsTagAttribute(description="If true, weekly size of calendar changes to acomodate the month if false," +
215                 " 42 day format is used", type="Boolean", defaultValue="false")
216     public void setAdjustWeeks(String adjustWeeks) {
217         this.adjustWeeks = adjustWeeks;
218     }
219 
220     @StrutsTagAttribute(description="How to render the names of the days in the header(narrow, abbr or wide)", defaultValue="narrow")
221     public void setDayWidth(String dayWidth) {
222         this.dayWidth = dayWidth;
223     }
224 
225     @StrutsTagAttribute(description="Total weeks to display", type="Integer", defaultValue="6")
226     public void setDisplayWeeks(String displayWeeks) {
227         this.displayWeeks = displayWeeks;
228     }
229 
230     @StrutsTagAttribute(description="Last available date in the calendar set", type="Date", defaultValue="2941-10-12")
231     public void setEndDate(String endDate) {
232         this.endDate = endDate;
233     }
234 
235     @StrutsTagAttribute(description="First available date in the calendar set", type="Date", defaultValue="1492-10-12")
236     public void setStartDate(String startDate) {
237         this.startDate = startDate;
238     }
239 
240     @StrutsTagAttribute(description="Disable all incremental controls, must pick a date in the current display", type="Boolean", defaultValue="false")
241     public void setStaticDisplay(String staticDisplay) {
242         this.staticDisplay = staticDisplay;
243     }
244 
245     @StrutsTagAttribute(description="Adjusts the first day of the week 0==Sunday..6==Saturday", type="Integer", defaultValue="0")
246     public void setWeekStartsOn(String weekStartsOn) {
247         this.weekStartsOn = weekStartsOn;
248     }
249 
250     @StrutsTagAttribute(description="Language to display this widget in", defaultValue="brower's specified preferred language")
251     public void setLanguage(String language) {
252         this.language = language;
253     }
254     
255     @StrutsTagAttribute(description="A pattern used for the visual display of the formatted date, e.g. dd/MM/yyyy")
256     public void setDisplayFormat(String displayFormat) {
257         this.displayFormat = displayFormat;
258     }
259 
260     @StrutsTagAttribute(description="Type of formatting used for visual display. Possible values are " +
261                 "long, short, medium or full", defaultValue="short")
262     public void setFormatLength(String formatLength) {
263         this.formatLength = formatLength;
264     }
265 
266     @StrutsTagAttribute(description="Path to icon used for the dropdown")
267     public void setIconPath(String iconPath) {
268         this.iconPath = iconPath;
269     }
270 
271     @StrutsTagAttribute(description="Duration of toggle in milliseconds", type="Integer", defaultValue="100")
272     public void setToggleDuration(String toggleDuration) {
273         this.toggleDuration = toggleDuration;
274     }
275 
276     @StrutsTagAttribute(description="Defines the type of the picker on the dropdown. Possible values are 'date'" +
277                 " for a DateTimePicker, and 'time' for a timePicker", defaultValue="date")
278     public void setType(String type) {
279         this.type = type;
280     }
281 
282     @StrutsTagAttribute(description="oggle type of the dropdown. Possible values are plain,wipe,explode,fade", defaultValue="plain")
283     public void setToggleType(String toggleType) {
284         this.toggleType = toggleType;
285     }
286     
287     @StrutsTagAttribute(description="Template css path")
288     public void setTemplateCssPath(String templateCssPath) {
289         this.templateCssPath = templateCssPath;
290     }
291     
292     private String format(Object obj) {
293         if(obj == null)
294             return null;
295 
296         if(obj instanceof Date) {
297             return RFC3339_FORMAT.format((Date) obj);
298         } else {
299             // try to parse a date
300             String dateStr = obj.toString();
301             if(dateStr.equalsIgnoreCase("today"))
302                 return RFC3339_FORMAT.format(new Date());
303 
304             try {
305                 Date date = null;
306                 if(this.displayFormat != null) {
307                     SimpleDateFormat format = new SimpleDateFormat(
308                             (String) getParameters().get("displayFormat"));
309                     date = format.parse(dateStr);
310                     return RFC3339_FORMAT.format(date);
311                 } else {
312                     // last resource to assume already in correct/default format
313                     return dateStr;
314                 }
315             } catch (ParseException e) {
316                 LOG.error("Could not parse date", e);
317                 return dateStr;
318             }
319         }
320     }
321 
322 }