    001package org.apache.turbine.util;
    002
    003
    004/*
    005 * Licensed to the Apache Software Foundation (ASF) under one
    006 * or more contributor license agreements.  See the NOTICE file
    007 * distributed with this work for additional information
    008 * regarding copyright ownership.  The ASF licenses this file
    009 * to you under the Apache License, Version 2.0 (the
    010 * "License"); you may not use this file except in compliance
    011 * with the License.  You may obtain a copy of the License at
    012 *
    013 *   http://www.apache.org/licenses/LICENSE-2.0
    014 *
    015 * Unless required by applicable law or agreed to in writing,
    016 * software distributed under the License is distributed on an
    017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    018 * KIND, either express or implied.  See the License for the
    019 * specific language governing permissions and limitations
    020 * under the License.
    021 */
    022
    023
    024import java.text.DateFormatSymbols;
    025import java.util.Calendar;
    026
    027import org.apache.ecs.ConcreteElement;
    028import org.apache.ecs.ElementContainer;
    029import org.apache.ecs.html.Input;
    030import org.apache.ecs.html.Option;
    031import org.apache.ecs.html.Select;
    032
    033/**
    034 * DateSelector is a utility class to handle the creation of a set of
    035 * date popup menus.  The code is broken into a set of static methods
    036 * for quick and easy access to the individual select objects:
    037 *
    038 *  <pre>
    039 *  ElementContainer ec dateSelect = new ElementContainer();
    040 *  String myName = "mydate";
    041 *  ec.addElement(DateSelector.getMonthSelector(myName));
    042 *  ec.addElement(DateSelector.getDaySelector(myName));
    043 *  ec.addElement(DateSelector.getYearSelector(myName));
    044 *  </pre>
    045 *
    046 * There are also methods which will use attributes to build a
    047 * complete month,day,year selector:
    048 *
    049 *  <pre>
    050 *  DateSelector ds = new DateSelector(myName);
    051 *  dateSelect = ds.ecsOutput();
    052 *  </pre>
    053 *
    054 * The above element container would use the onChange setting and may
    055 * hide the selected day if set via showDays().<br>
    056 *
    057 * @author <a href="mailto:ekkerbj@netscape.net">Jeffrey D. Brekke</a>
    058 * @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a>
    059 * @author <a href="mailto:leon@clearink.com">Leon Atkinson</a>
    060 * @version $Id: DateSelector.java 1706239 2015-10-01 13:18:35Z tv $
    061 */
    062public class DateSelector
    063{
    064    /** Prefix for date names. */
    065    public static final String DEFAULT_PREFIX = "DateSelector";
    066
    067    /** Suffix for day parameter. */
    068    public static final String DAY_SUFFIX = "_day";
    069
    070    /** Suffix for month parameter. */
    071    public static final String MONTH_SUFFIX = "_month";
    072
    073    /** Suffix for year parameter. */
    074    public static final String YEAR_SUFFIX = "_year";
    075
    076    private Calendar useDate = null;
    077    private String selName = null;
    078    private static final String[] monthName =
    079            new DateFormatSymbols().getMonths();
    080    private String onChange = null;
    081    private boolean onChangeSet = false;
    082    private boolean showDays = true;
    083    private int setDay = 0;
    084    private boolean useYears = false;
    085    private int firstYear = 0;
    086    private int lastYear = 0;
    087    private int selectedYear = 0;
    088
    089    /**
    090     * Constructor defaults to current date and uses the default
    091     * prefix: <pre>DateSelector.DEFAULT</pre>
    092     */
    093    public DateSelector()
    094    {
    095        this(DEFAULT_PREFIX);
    096    }
    097
    098    /**
    099     * Constructor defaults to current date.
    100     *
    101     * @param selName A String with the selector name.
    102     */
    103    public DateSelector(String selName)
    104    {
    105        this(selName, Calendar.getInstance());
    106    }
    107
    108    /**
    109     * Constructor, uses the date set in a calendar that has been
    110     * already passed in (with the date set correctly).
    111     *
    112     * @param selName A String with the selector name.
    113     * @param useDate A Calendar with a date.
    114     */
    115    public DateSelector(String selName, Calendar useDate)
    116    {
    117        this.useDate = useDate;
    118        this.selName = selName;
    119    }
    120
    121    /**
    122     * Adds the onChange to all of &lt;SELECT&gt; tags.  This is limited to
    123     * one function for all three popups and is only used when the
    124     * output() methods are used.  Individual getMonth, getDay,
    125     * getYear static methods will not use this setting.
    126     *
    127     * @param onChange A String to use for onChange attribute.  If null,
    128     * then nothing will be set.
    129     * @return A DateSelector (self).
    130     */
    131    public DateSelector setOnChange(String onChange)
    132    {
    133        if (onChange != null)
    134        {
    135            this.onChange = onChange;
    136            this.onChangeSet = true;
    137        }
    138        else
    139        {
    140            this.onChange = null;
    141            this.onChangeSet = false;
    142        }
    143        return this;
    144    }
    145
    146    /**
    147     * Select the day to be selected if the showDays(false) behavior
    148     * is used.  Individual getMonth, getDay, getYear static methods
    149     * will not use this setting.
    150     *
    151     * @param day The day.
    152     * @return A DateSelector (self).
    153     */
    154    public DateSelector setDay(int day)
    155    {
    156        this.setDay = day;
    157        this.showDays = false;
    158        return this;
    159    }
    160
    161    /**
    162     * Whether or not to show the days as a popup menu.  The days will
    163     * be a hidden parameter and the value set with setDay is used.
    164     * Individual getMonth, getDay, getYear static methods will not
    165     * use this setting.
    166     *
    167     * @param show True if the day should be shown.
    168     * @return A DateSelector (self).
    169     */
    170    public DateSelector setShowDay(boolean show)
    171    {
    172        this.showDays = false;
    173        return this;
    174    }
    175
    176    /**
    177     * Set the selector name prefix.  Individual getMonth, getDay,
    178     * getYear static methods will not use this setting.
    179     *
    180     * @param selName A String with the select name prefix.
    181     */
    182    public void setSelName(String selName)
    183    {
    184        this.selName = selName;
    185    }
    186
    187    /**
    188     * Get the selector name prefix.
    189     *
    190     * @return A String with the select name prefix.
    191     */
    192    public String getSelName()
    193    {
    194        return selName;
    195    }
    196
    197    /**
    198     * Return a month selector.
    199     *
    200     * @param name The name to use for the selected month.
    201     * @return A select object with all the months.
    202     */
    203    public static Select getMonthSelector(String name)
    204    {
    205        return (getMonthSelector(name, Calendar.getInstance()));
    206    }
    207
    208    /**
    209     * Return a month selector.
    210     *
    211     * Note: The values of the month placed into the select list are
    212     * the month integers starting at 0 (ie: if the user selects
    213     * February, the selected value will be 1).
    214     *
    215     * @param name The name to use for the selected month.
    216     * @param now Calendar to start with.
    217     * @return A select object with all the months.
    218     */
    219    public static Select getMonthSelector(String name, Calendar now)
    220    {
    221        Select monthSelect = new Select().setName(name);
    222
    223        for (int curMonth = 0; curMonth <= 11; curMonth++)
    224        {
    225            Option o = new Option();
    226            o.addElement(monthName[curMonth]);
    227            o.setValue(curMonth);
    228            if ((now.get(Calendar.MONTH)) == curMonth)
    229            {
    230                o.setSelected(true);
    231            }
    232            monthSelect.addElement(o);
    233        }
    234        return (monthSelect);
    235    }
    236
    237    /**
    238     * Return a day selector.
    239     *
    240     * @param name The name to use for the selected day.
    241     * @return A select object with all the days in a month.
    242     */
    243    public static Select getDaySelector(String name)
    244    {
    245        return (getDaySelector(name, Calendar.getInstance()));
    246    }
    247
    248    /**
    249     * Return a day selector.
    250     *
    251     * @param name The name to use for the selected day.
    252     * @param now Calendar to start with.
    253     * @return A select object with all the days in a month.
    254     */
    255    public static Select getDaySelector(String name, Calendar now)
    256    {
    257        Select daySelect = new Select().setName(name);
    258
    259        for (int currentDay = 1; currentDay <= 31; currentDay++)
    260        {
    261            Option o = new Option();
    262            o.addElement(Integer.toString(currentDay));
    263            o.setValue(currentDay);
    264            if (now.get(Calendar.DAY_OF_MONTH) == currentDay)
    265            {
    266                o.setSelected(true);
    267            }
    268            daySelect.addElement(o);
    269        }
    270        return (daySelect);
    271    }
    272
    273    /**
    274     * Return a year selector.
    275     *
    276     * @param name The name to use for the selected year.
    277     * @return A select object with all the years starting five years
    278     * from now and five years before this year.
    279     */
    280    public static Select getYearSelector(String name)
    281    {
    282        return (getYearSelector(name, Calendar.getInstance()));
    283    }
    284
    285    /**
    286     * Return a year selector.
    287     *
    288     * @param name The name to use for the selected year.
    289     * @param now Calendar to start with.
    290     * @return A select object with all the years starting five years
    291     * from now and five years before this year.
    292     */
    293    public static Select getYearSelector(String name, Calendar now)
    294    {
    295        int startYear = now.get(Calendar.YEAR);
    296        return (getYearSelector(name, startYear - 5, startYear + 5, startYear));
    297    }
    298
    299    /**
    300     * Return a year selector.
    301     *
    302     * @param name The name to use for the selected year.
    303     * @param firstYear the first (earliest) year in the selector.
    304     * @param lastYear the last (latest) year in the selector.
    305     * @param selectedYear the year initially selected in the Select html.
    306     * @return A select object with all the years from firstyear
    307     * to lastyear..
    308     */
    309    public static Select getYearSelector(String name,
    310                                         int firstYear, int lastYear,
    311                                         int selectedYear)
    312    {
    313        Select yearSelect = new Select().setName(name);
    314
    315        for (int currentYear = firstYear;
    316             currentYear <= lastYear;
    317
    318             currentYear++)
    319        {
    320            Option o = new Option();
    321            o.addElement(Integer.toString(currentYear));
    322            o.setValue(currentYear);
    323            if (currentYear == selectedYear)
    324            {
    325                o.setSelected(true);
    326            }
    327            yearSelect.addElement(o);
    328        }
    329        return (yearSelect);
    330    }
    331
    332    /**
    333     * Set a year range to be displayed
    334     * @param firstYear start of year range
    335     * @param lastYear end of year range
    336     * @param selectedYear entry to select
    337     * @return true if the range settings are valid
    338     */
    339    public boolean setYear(int firstYear, int lastYear, int selectedYear)
    340    {
    341        if (firstYear <= lastYear && firstYear <= selectedYear
    342                && selectedYear <= lastYear)
    343        {
    344            this.useYears = true;
    345            this.firstYear = firstYear;
    346            this.lastYear = lastYear;
    347            this.selectedYear = selectedYear;
    348            return true;
    349        }
    350        else
    351        {
    352            return false;
    353        }
    354    }
    355
    356    /**
    357     * Used to build the popupmenu in HTML.  The properties set in the
    358     * object are used to generate the correct HTML.  The selName
    359     * attribute is used to seed the names of the select lists.  The
    360     * names will be generated as follows:
    361     *
    362     * <ul>
    363     *  <li>selName + "_month"</li>
    364     *  <li>selName + "_day"</li>
    365     *  <li>selName + "_year"</li>
    366     * </ul>
    367     *
    368     * If onChange was set it is also used in the generation of the
    369     * output.  The output HTML will list the select lists in the
    370     * following order: month day year.
    371     *
    372     * @return A String with the correct HTML for the date selector.
    373     */
    374    public String output()
    375    {
    376        return (ecsOutput().toString());
    377    }
    378
    379    /**
    380     * Used to build the popupmenu in HTML.  The properties set in the
    381     * object are used to generate the correct HTML.  The selName
    382     * attribute is used to seed the names of the select lists.  The
    383     * names will be generated as follows:
    384     *
    385     * <ul>
    386     *  <li>selName + "_month"</li>
    387     *  <li>selName + "_day"</li>
    388     *  <li>selName + "_year"</li>
    389     * </ul>
    390     *
    391     * The output HTML will list the select lists in the following
    392     * order: month day year.
    393     *
    394     * @return A String with the correct HTML for the date selector.
    395     */
    396    @Override
    397    public String toString()
    398    {
    399        return (ecsOutput().toString());
    400    }
    401
    402    /**
    403     * Return an ECS container with the month, day, and year select
    404     * objects inside.
    405     *
    406     * @return An ECS container.
    407     */
    408    public ElementContainer ecsOutput()
    409    {
    410        if (this.useDate == null)
    411        {
    412            this.useDate = Calendar.getInstance();
    413        }
    414
    415        Select monthSelect = getMonthSelector(selName + MONTH_SUFFIX, useDate);
    416        ConcreteElement daySelect = null;
    417        if (!showDays)
    418        {
    419            daySelect = new Input(Input.hidden, selName + DAY_SUFFIX, setDay);
    420        }
    421        else
    422        {
    423            Select tmp = getDaySelector(selName + DAY_SUFFIX, useDate);
    424            if (onChangeSet)
    425            {
    426                tmp.setOnChange(onChange);
    427            }
    428            daySelect = tmp;
    429        }
    430        Select yearSelect = null;
    431        if (useYears)
    432        {
    433            yearSelect = getYearSelector(selName + YEAR_SUFFIX,
    434                    firstYear, lastYear, selectedYear);
    435        }
    436        else
    437        {
    438            yearSelect = getYearSelector(selName + YEAR_SUFFIX, useDate);
    439        }
    440        if (onChangeSet)
    441        {
    442            monthSelect.setOnChange(onChange);
    443            yearSelect.setOnChange(onChange);
    444        }
    445        ElementContainer ec = new ElementContainer();
    446        // ec.addElement(new Comment("== BEGIN org.apache.turbine.util.DateSelector.ecsOutput() =="));
    447        ec.addElement(monthSelect);
    448        ec.addElement(daySelect);
    449        ec.addElement(yearSelect);
    450        // ec.addElement(new Comment("== END org.apache.turbine.util.DateSelector.ecsOutput() =="));
    451        return (ec);
    452    }
    453}