View Javadoc

1   package org.apache.turbine.util;
2   
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  
22  import java.text.NumberFormat;
23  import java.util.Calendar;
24  import java.util.Date;
25  
26  import org.apache.ecs.ConcreteElement;
27  import org.apache.ecs.ElementContainer;
28  import org.apache.ecs.html.Comment;
29  import org.apache.ecs.html.Input;
30  import org.apache.ecs.html.Option;
31  import org.apache.ecs.html.Select;
32  
33  /**
34   * TimeSelector is a utility class to handle the creation of a set of
35   * time drop-down menus.  The code is broken into a set of static methods
36   * for quick and easy access to the individual select objects:
37   *
38   *  <pre>
39   *  ElementContainer ec timeSelect = new ElementContainer();
40   *  String myName = "mytime";
41   *  ec.addElement(TimeSelector.getHourSelector(myName));
42   *  ec.addElement(TimeSelector.getMinuteSelector(myName));
43   *  ec.addElement(TimeSelector.getAMPMSelector(myName));
44   *  </pre>
45   *
46   * There are also methods which will use attributes to build a
47   * complete time selector in the default 12hr format (eg HH:MM am/pm):
48   *
49   *  <pre>
50   *  TimeSelector ts = new TimeSelector(myName);
51   *  timeSelect = ts.ecsOutput();
52   *  </pre>
53   *
54   * Minutes/Seconds are by default rounded to the nearest 5 units
55   * although this can be easily changed.
56   *
57   * 24hr TimeSelectors can also be produced. The following example
58   * creates a full precision TimeSelector (eg HH:MM:SS):
59   *
60   *  <pre>
61   *  TimeSelector ts = new TimeSelector(myName);
62   *  ts.setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR);
63   *  ts.setMinuteInterval(1);
64   *  ts.setSecondInterval(1);
65   *  ts.setShowSeconds(true);
66   *  timeSelect = ts.toString();
67   *  </pre>
68   *
69   * @author <a href="mailto:ekkerbj@netscape.net">Jeffrey D. Brekke</a>
70   * @author <a href="mailto:rich@thenetrevolution.com">Rich Aston</a>
71   * @version $Id: TimeSelector.java 1706239 2015-10-01 13:18:35Z tv $
72   */
73  public class TimeSelector
74  {
75      /** Prefix for time names. */
76      public static final String DEFAULT_PREFIX = "TimeSelector";
77  
78      /** Suffix for hour parameter. */
79      public static final String HOUR_SUFFIX = "_hour";
80  
81      /** Suffix for minute parameter. */
82      public static final String MINUTE_SUFFIX = "_minute";
83  
84      /** Suffix for second parameter. */
85      public static final String SECOND_SUFFIX = "_second";
86  
87      /** Suffix for am/pm parameter. */
88      public static final String AMPM_SUFFIX = "_ampm";
89  
90      /** Constant for 12hr format */
91      public static final int TWELVE_HOUR = 0;
92  
93      /** Constant for 24hr format */
94      public static final int TWENTY_FOUR_HOUR = 1;
95  
96      /** TODO: Add ability to specify Locale. */
97      private static final NumberFormat nbrFmt;
98  
99      private static final int DEFAULT_MINUTE_INTERVAL = 5;
100     private static final int DEFAULT_SECOND_INTERVAL = 5;
101     private static final int DEFAULT_TIME_FORMAT = TWELVE_HOUR;
102 
103     private int timeFormat = DEFAULT_TIME_FORMAT;
104     private int minuteInterval = DEFAULT_MINUTE_INTERVAL;
105     private int secondInterval = DEFAULT_SECOND_INTERVAL;
106 
107     private Calendar useDate = null;
108     private String selName = null;
109     private String onChange = null;
110     private boolean onChangeSet = false;
111     private boolean showSeconds = false;
112     private int setSeconds = 0;
113 
114     static
115     {
116         nbrFmt = NumberFormat.getInstance();
117         nbrFmt.setMinimumIntegerDigits(2);
118         nbrFmt.setMaximumIntegerDigits(2);
119     }
120 
121     /**
122      * Constructor defaults to current date/time and uses the default
123      * prefix: <pre>TimeSelector.DEFAULT</pre>
124      */
125     public TimeSelector()
126     {
127         this.selName = DEFAULT_PREFIX;
128         this.useDate = Calendar.getInstance();
129         this.useDate.setTime(new Date());
130     }
131 
132     /**
133      * Constructor, uses the date/time set in the calendar
134      * passed in (with the date/time set correctly).
135      *
136      * @param selName A String with the selector name.
137      * @param useDate A Calendar with a date/time.
138      */
139     public TimeSelector(String selName, Calendar useDate)
140     {
141         this.useDate = useDate;
142         this.selName = selName;
143     }
144 
145     /**
146      * Constructor defaults to current date/time.
147      *
148      * @param selName A String with the selector name.
149      */
150     public TimeSelector(String selName)
151     {
152         this.selName = selName;
153         this.useDate = Calendar.getInstance();
154         this.useDate.setTime(new Date());
155     }
156 
157     /**
158      * Adds the onChange to all of <code>&lt;SELECT&gt;</code> tags.
159      * This is limited to one function for all three popups and is only
160      * used when the output() methods are used.  Individual getHour,
161      * getMinute, getSecond, getAMPM static methods will not use this
162      * setting.
163      *
164      * @param onChange A String to use for onChange attribute.  If null,
165      * then nothing will be set.
166      * @return A TimeSelector (self).
167      */
168     public TimeSelector setOnChange(String onChange)
169     {
170         if (onChange != null)
171         {
172             this.onChange = onChange;
173             this.onChangeSet = true;
174         }
175         else
176         {
177             this.onChange = null;
178             this.onChangeSet = false;
179         }
180         return this;
181     }
182 
183     /**
184      * Select the second to be selected if the showSeconds(false) behavior
185      * is used.  Individual getHour, getMinute, getSecond, getAMPM
186      * static methods will not use this setting.
187      *
188      * @param seconds The second.
189      * @return A TimeSelector (self).
190      */
191     public TimeSelector setSeconds(int seconds)
192     {
193         this.setSeconds = seconds;
194         this.showSeconds = false;
195         return this;
196     }
197 
198     /**
199      * Set the interval between options in the minute select box.
200      * Individual getHour, getMinute, getSecond, getAMPM static methods
201      * will not use this setting.
202      *
203      * @param minutes Interval in minutes.
204      * @return A TimeSelector (self).
205      */
206     public TimeSelector setMinuteInterval(int minutes)
207     {
208         this.minuteInterval = minutes;
209         return this;
210     }
211 
212     /**
213      * Set the interval between options in the second select box.
214      * Individual getHour, getMinute, getSecond, getAMPM static methods
215      * will not use this setting.
216      *
217      * @param seconds Interval in seconds.
218      * @return A TimeSelector (self).
219      */
220     public TimeSelector setSecondInterval(int seconds)
221     {
222         this.secondInterval = seconds;
223         return this;
224     }
225 
226     /**
227      * Set the time format to 12 or 24 hour. Individual getHour,
228      * getMinute, getSecond, getAMPM static methods
229      * will not use this setting.
230      *
231      * @param format Time format.
232      * @return A TimeSelector (self).
233      */
234     public TimeSelector setTimeFormat(int format)
235     {
236         this.timeFormat = format;
237         return this;
238     }
239 
240     /**
241      * Whether or not to show the seconds as a popup menu.  The seconds will
242      * be a hidden parameter and the value set with setSeconds is used.
243      * Individual getHour, getMinute, getSecond, getAMPM static methods
244      * will not use this setting.
245      *
246      * @param show True if the second should be shown.
247      * @return A TimeSelector (self).
248      */
249     public TimeSelector setShowSeconds(boolean show)
250     {
251         this.showSeconds = show;
252         return this;
253     }
254 
255     /**
256      * Set the selector name prefix.  Individual getHour, getMinute,
257      * getSeconds, getAMPM static methods will not use this setting.
258      *
259      * @param selName A String with the select name prefix.
260      */
261     public void setSelName(String selName)
262     {
263         this.selName = selName;
264     }
265 
266     /**
267      * Get the selector name prefix.
268      *
269      * @return A String with the select name prefix.
270      */
271     public String getSelName()
272     {
273         return selName;
274     }
275 
276     /**
277      * Return a second selector.
278      *
279      * @param name The name to use for the selected second.
280      * @return A select object with second options.
281      */
282     public static Select getSecondSelector(String name)
283     {
284         return (getSecondSelector(name, Calendar.getInstance()));
285     }
286 
287     /**
288      * Return a second selector.
289      *
290      * @param name The name to use for the selected second.
291      * @param now Calendar to start with.
292      * @return A select object with second options.
293      */
294     public static Select getSecondSelector(String name, Calendar now)
295     {
296         return (getSecondSelector(name, Calendar.getInstance(),
297                 DEFAULT_SECOND_INTERVAL));
298     }
299 
300     /**
301      * Return a second selector.
302      *
303      * @param name The name to use for the selected second.
304      * @param now Calendar to start with.
305      * @param interval Interval between options.
306      * @return A select object with second options.
307      */
308     public static Select getSecondSelector(String name, Calendar now,
309                                            int interval)
310     {
311         Select secondSelect = new Select().setName(name);
312 
313         for (int currentSecond = 0; currentSecond <= 59; currentSecond += interval)
314         {
315             Option o = new Option();
316             o.addElement(nbrFmt.format(currentSecond));
317             o.setValue(currentSecond);
318             int nearestSecond =
319                     ((now.get(Calendar.SECOND) / interval) * interval);
320 
321             if (nearestSecond == currentSecond)
322             {
323                 o.setSelected(true);
324             }
325             secondSelect.addElement(o);
326         }
327         return (secondSelect);
328     }
329 
330     /**
331      * Return a minute selector.
332      *
333      * @param name The name to use for the selected minute.
334      * @return A select object with minute options.
335      */
336     public static Select getMinuteSelector(String name)
337     {
338         return (getMinuteSelector(name, Calendar.getInstance()));
339     }
340 
341     /**
342      * Return a minute selector.
343      *
344      * @param name The name to use for the selected minute.
345      * @param now Calendar to start with.
346      * @return A select object with minute options.
347      */
348     public static Select getMinuteSelector(String name, Calendar now)
349     {
350         return (getMinuteSelector(name, now, DEFAULT_MINUTE_INTERVAL));
351     }
352 
353     /**
354      * Return a minute selector.
355      *
356      * @param name The name to use for the selected minute.
357      * @param now Calendar to start with.
358      * @param interval Interval between options.
359      * @return A select object with minute options.
360      */
361     public static Select getMinuteSelector(String name, Calendar now,
362                                            int interval)
363     {
364         Select minuteSelect = new Select().setName(name);
365 
366         for (int curMinute = 0; curMinute <= 59; curMinute += interval)
367         {
368             Option o = new Option();
369             o.addElement(nbrFmt.format(curMinute));
370             o.setValue(curMinute);
371             int nearestMinute =
372                     ((now.get(Calendar.MINUTE)) / interval) * interval;
373 
374             if (nearestMinute == curMinute)
375             {
376                 o.setSelected(true);
377             }
378             minuteSelect.addElement(o);
379         }
380         return (minuteSelect);
381     }
382 
383     /**
384      * Return an 12 hour selector.
385      *
386      * @param name The name to use for the selected hour.
387      * @return A select object with all the hours.
388      */
389     public static Select getHourSelector(String name)
390     {
391         return (getHourSelector(name, Calendar.getInstance()));
392     }
393 
394     /**
395      * Return an 12 hour selector.
396      *
397      * @param name The name to use for the selected hour.
398      * @param now Calendar to start with.
399      * @return A select object with all the hours.
400      */
401     public static Select getHourSelector(String name, Calendar now)
402     {
403         return (getHourSelector(name, Calendar.getInstance(), TWELVE_HOUR));
404     }
405 
406     /**
407      * Return an hour selector (either 12hr or 24hr depending on
408      * <code>format</code>.
409      *
410      * @param name The name to use for the selected hour.
411      * @param now Calendar to start with.
412      * @param format Time format.
413      * @return A select object with all the hours.
414      */
415     public static Select getHourSelector(String name, Calendar now, int format)
416     {
417         Select hourSelect = new Select().setName(name);
418 
419         if (format == TWENTY_FOUR_HOUR)
420         {
421             for (int currentHour = 0; currentHour <= 23; currentHour++)
422             {
423                 Option o = new Option();
424                 o.addElement(nbrFmt.format(currentHour));
425                 o.setValue(currentHour);
426                 if (now.get(Calendar.HOUR_OF_DAY) == currentHour)
427                 {
428                     o.setSelected(true);
429                 }
430                 hourSelect.addElement(o);
431             }
432         }
433         else
434         {
435             for (int curHour = 1; curHour <= 12; curHour++)
436             {
437                 Option o = new Option();
438 
439                 o.addElement(nbrFmt.format(curHour));
440                 o.setValue(curHour);
441                 if (now.get(Calendar.AM_PM) == Calendar.AM)
442                 {
443                     if (((now.get(Calendar.HOUR_OF_DAY)) == 0) &&
444                             (curHour == 12))
445                     {
446                         o.setSelected(true);
447                     }
448                     else
449                     {
450                         if (now.get(Calendar.HOUR_OF_DAY) == curHour)
451                         {
452                             o.setSelected(true);
453                         }
454                     }
455                 }
456                 else
457                 {
458                     if (((now.get(Calendar.HOUR_OF_DAY)) == 12) &&
459                             (curHour == 12))
460                     {
461                         o.setSelected(true);
462                     }
463                     else
464                     {
465                         if (now.get(Calendar.HOUR_OF_DAY) == curHour + 12)
466                         {
467                             o.setSelected(true);
468                         }
469                     }
470                 }
471                 hourSelect.addElement(o);
472             }
473         }
474         return (hourSelect);
475     }
476 
477     /**
478      * Return an am/pm selector.
479      *
480      * @param name The name to use for the selected am/pm.
481      * @return A select object with am/pm
482      */
483     public static Select getAMPMSelector(String name)
484     {
485         Calendar c = Calendar.getInstance();
486         c.setTime(new Date());
487         return (getAMPMSelector(name, c));
488     }
489 
490     /**
491      * Return an am/pm selector.
492      *
493      * @param name The name to use for the selected am/pm.
494      * @param now Calendar to start with.
495      * @return A select object with am/pm.
496      */
497     public static Select getAMPMSelector(String name,
498                                          Calendar now)
499     {
500         Select ampmSelect = new Select().setName(name);
501 
502         Option o = new Option();
503         o.addElement("am");
504         o.setValue(Calendar.AM);
505         if (now.get(Calendar.AM_PM) == Calendar.AM)
506         {
507             o.setSelected(true);
508         }
509         ampmSelect.addElement(o);
510 
511         o = new Option();
512         o.addElement("pm");
513         o.setValue(Calendar.PM);
514         if (now.get(Calendar.AM_PM) == Calendar.PM)
515         {
516             o.setSelected(true);
517         }
518         ampmSelect.addElement(o);
519 
520         return (ampmSelect);
521     }
522 
523     /**
524      * Used to build the popupmenu in HTML.  The properties set in the
525      * object are used to generate the correct HTML.  The selName
526      * attribute is used to seed the names of the select lists.  The
527      * names will be generated as follows:
528      *
529      * <ul>
530      *  <li>selName + "_hour"</li>
531      *  <li>selName + "_minute"</li>
532      *  <li>selName + "_ampm"</li>
533      * </ul>
534      *
535      * If onChange was set it is also used in the generation of the
536      * output.  The output HTML will list the select lists in the
537      * following order: hour minute ampm.
538      *
539      * If setShowSeconds(true) is used then an addition second select box
540      * is produced after the minute select box.
541      *
542      * If setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR) is used then
543      * the ampm select box is omitted.
544      *
545      * @return A String with the correct HTML for the date selector.
546      */
547     public String output()
548     {
549         return (ecsOutput().toString());
550     }
551 
552     /**
553      * Used to build the popupmenu in HTML.  The properties set in the
554      * object are used to generate the correct HTML.  The selName
555      * attribute is used to seed the names of the select lists.  The
556      * names will be generated as follows:
557      *
558      * <ul>
559      *  <li>selName + "_hour"</li>
560      *  <li>selName + "_minute"</li>
561      *  <li>selName + "_ampm"</li>
562      * </ul>
563      *
564      * If onChange was set it is also used in the generation of the
565      * output.  The output HTML will list the select lists in the
566      * following order: hour minute ampm.
567      *
568      * If setShowSeconds(true) is used then an addition second select box
569      * is produced after the minute select box.
570      *
571      * If setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR) is used then
572      * the ampm select box is omitted.
573      *
574      * @return A String with the correct HTML for the date selector.
575      */
576     @Override
577     public String toString()
578     {
579         return (ecsOutput().toString());
580     }
581 
582     /**
583      * Return an ECS container with the select objects inside.
584      *
585      * @return An ECS container.
586      */
587     public ElementContainer ecsOutput()
588     {
589         if (this.useDate == null)
590         {
591             this.useDate = Calendar.getInstance();
592             this.useDate.setTime(new Date());
593         }
594 
595         ConcreteElement secondSelect = null;
596 
597         Select ampmSelect = getAMPMSelector(selName + AMPM_SUFFIX, useDate);
598 
599         Select hourSelect = getHourSelector(selName + HOUR_SUFFIX,
600                 useDate, this.timeFormat);
601 
602         Select minuteSelect = getMinuteSelector(selName + MINUTE_SUFFIX,
603                 useDate, this.minuteInterval);
604 
605         if (this.showSeconds)
606         {
607             Select tmp = getSecondSelector(selName + SECOND_SUFFIX, useDate,
608                     this.secondInterval);
609             if (onChangeSet)
610             {
611                 tmp.setOnChange(onChange);
612             }
613             secondSelect = tmp;
614         }
615         else
616         {
617             secondSelect = new Input(Input.hidden,
618                     selName + SECOND_SUFFIX,
619                     setSeconds);
620         }
621 
622         if (onChangeSet)
623         {
624             hourSelect.setOnChange(onChange);
625             minuteSelect.setOnChange(onChange);
626             ampmSelect.setOnChange(onChange);
627         }
628 
629         ElementContainer ec = new ElementContainer();
630         ec.addElement(new Comment(
631                 "== BEGIN org.apache.turbine.util.TimeSelector.ecsOutput() =="));
632         ec.addElement(hourSelect);
633         ec.addElement(":");
634         ec.addElement(minuteSelect);
635         if (this.showSeconds == true)
636         {
637             ec.addElement(":");
638         }
639         ec.addElement(secondSelect);
640         if (this.timeFormat == TimeSelector.TWELVE_HOUR)
641         {
642             ec.addElement(ampmSelect);
643         }
644         ec.addElement(new Comment(
645                 "== END org.apache.turbine.util.TimeSelector.ecsOutput() =="));
646         return (ec);
647     }
648 }