View Javadoc

    1   /*
    2    * $Id: DateTimePicker.java 508631 2007-02-16 22:48:10Z 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   * 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 RFC3339_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     protected String templateCssPath;
    150
    151     public DateTimePicker(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
    152         super(stack, request, response);
    153     }
    154
    155     protected String getDefaultTemplate() {
    156         return TEMPLATE;
    157     }
    158
    159     public void evaluateParams() {
    160         super.evaluateParams();
    161
    162         if(displayWeeks != null)
    163             addParameter("displayWeeks", findString(displayWeeks));
    164         if(adjustWeeks != null)
    165             addParameter("adjustWeeks", findValue(adjustWeeks, Boolean.class));
    166         if(startDate != null)
    167             addParameter("startDate", findString(startDate));
    168         if(endDate != null)
    169             addParameter("endDate", findString(endDate));
    170         if(weekStartsOn != null)
    171             addParameter("weekStartsOn", findString(weekStartsOn));
    172         if(staticDisplay != null)
    173             addParameter("staticDisplay", findValue(staticDisplay, Boolean.class));
    174         if(dayWidth != null)
    175             addParameter("dayWidth", findValue(dayWidth, Integer.class));
    176         if(language != null)
    177             addParameter("language", findString(language));
    178         if(value != null)
    179             addParameter("value", findString(value));
    180         if(iconPath != null)
    181             addParameter("iconPath", findString(iconPath));
    182         if(formatLength != null)
    183             addParameter("formatLength", findString(formatLength));
    184         if(displayFormat != null)
    185             addParameter("displayFormat", findString(displayFormat));
    186         if(toggleType != null)
    187             addParameter("toggleType", findString(toggleType));
    188         if(toggleDuration != null)
    189             addParameter("toggleDuration", findValue(toggleDuration,
    190                     Integer.class));
    191         if(type != null)
    192             addParameter("type", findString(type));
    193         else
    194             addParameter("type", "date");
    195         if(templateCssPath != null)
    196             addParameter("templateCssPath", findString(templateCssPath));
    197
    198         // format the value to RFC 3399
    199         if(parameters.containsKey("value")) {
    200             parameters.put("nameValue", format(parameters.get("value")));
    201         } else {
    202             if(name != null) {
    203                 String expr = name;
    204                 if(altSyntax()) {
    205                     expr = "%{" + expr + "}";
    206                 }
    207                 addParameter("nameValue", format(findValue(expr)));
    208             }
    209         }
    210     }
    211
    212     @StrutsTagAttribute(description="If true, weekly size of calendar changes to acomodate the month if false," +
    213                 " 42 day format is used", type="Boolean", defaultValue="false")
    214     public void setAdjustWeeks(String adjustWeeks) {
    215         this.adjustWeeks = adjustWeeks;
    216     }
    217
    218     @StrutsTagAttribute(description="How to render the names of the days in the header(narrow, abbr or wide)", defaultValue="narrow")
    219     public void setDayWidth(String dayWidth) {
    220         this.dayWidth = dayWidth;
    221     }
    222
    223     @StrutsTagAttribute(description="Total weeks to display", type="Integer", defaultValue="6")
    224     public void setDisplayWeeks(String displayWeeks) {
    225         this.displayWeeks = displayWeeks;
    226     }
    227
    228     @StrutsTagAttribute(description="Last available date in the calendar set", type="Date", defaultValue="2941-10-12")
    229     public void setEndDate(String endDate) {
    230         this.endDate = endDate;
    231     }
    232
    233     @StrutsTagAttribute(description="First available date in the calendar set", type="Date", defaultValue="1492-10-12")
    234     public void setStartDate(String startDate) {
    235         this.startDate = startDate;
    236     }
    237
    238     @StrutsTagAttribute(description="Disable all incremental controls, must pick a date in the current display", type="Boolean", defaultValue="false")
    239     public void setStaticDisplay(String staticDisplay) {
    240         this.staticDisplay = staticDisplay;
    241     }
    242
    243     @StrutsTagAttribute(description="Adjusts the first day of the week 0==Sunday..6==Saturday", type="Integer", defaultValue="0")
    244     public void setWeekStartsOn(String weekStartsOn) {
    245         this.weekStartsOn = weekStartsOn;
    246     }
    247
    248     @StrutsTagAttribute(description="Language to display this widget in", defaultValue="brower's specified preferred language")
    249     public void setLanguage(String language) {
    250         this.language = language;
    251     }
    252
    253     @StrutsTagAttribute(description="A pattern used for the visual display of the formatted date, e.g. dd/MM/yyyy")
    254     public void setDisplayFormat(String displayFormat) {
    255         this.displayFormat = displayFormat;
    256     }
    257
    258     @StrutsTagAttribute(description="Type of formatting used for visual display. Possible values are " +
    259                 "long, short, medium or full", defaultValue="short")
    260     public void setFormatLength(String formatLength) {
    261         this.formatLength = formatLength;
    262     }
    263
    264     @StrutsTagAttribute(description="Path to icon used for the dropdown")
    265     public void setIconPath(String iconPath) {
    266         this.iconPath = iconPath;
    267     }
    268
    269     @StrutsTagAttribute(description="Duration of toggle in milliseconds", type="Integer", defaultValue="100")
    270     public void setToggleDuration(String toggleDuration) {
    271         this.toggleDuration = toggleDuration;
    272     }
    273
    274     @StrutsTagAttribute(description="Defines the type of the picker on the dropdown. Possible values are 'date'" +
    275                 " for a DateTimePicker, and 'time' for a timePicker", defaultValue="date")
    276     public void setType(String type) {
    277         this.type = type;
    278     }
    279
    280     @StrutsTagAttribute(description="oggle type of the dropdown. Possible values are plain,wipe,explode,fade", defaultValue="plain")
    281     public void setToggleType(String toggleType) {
    282         this.toggleType = toggleType;
    283     }
    284
    285     @StrutsTagAttribute(description="Template css path")
    286     public void setTemplateCssPath(String templateCssPath) {
    287         this.templateCssPath = templateCssPath;
    288     }
    289
    290     private String format(Object obj) {
    291         if(obj == null)
    292             return null;
    293
    294         if(obj instanceof Date) {
    295             return RFC3339_FORMAT.format((Date) obj);
    296         } else {
    297             // try to parse a date
    298             String dateStr = obj.toString();
    299             if(dateStr.equalsIgnoreCase("today"))
    300                 return  RFC3339_FORMAT.format(new Date());
    301
    302             try {
    303                 Date date = null;
    304                 if(this.displayFormat != null) {
    305                     SimpleDateFormat format = new SimpleDateFormat(
    306                             this.displayFormat);
    307                     date = format.parse(dateStr);
    308                     return RFC3339_FORMAT.format(date);
    309                 } else {
    310                     // last resource to assume already in correct/default format
    311                     return dateStr;
    312                 }
    313             } catch (ParseException e) {
    314                 LOG.error("Could not parse date", e);
    315                 return dateStr;
    316             }
    317         }
    318     }
    319
    320 }