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 534527 2007-05-02 16:10:59Z 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      * @return A select object with minute options.
346      */
347     public static Select getMinuteSelector(String name, Calendar now)
348     {
349         return (getMinuteSelector(name, now, DEFAULT_MINUTE_INTERVAL));
350     }
351 
352     /***
353      * Return a minute selector.
354      *
355      * @param name The name to use for the selected minute.
356      * @param now Calendar to start with.
357      * @param interval Interval between options.
358      * @return A select object with minute options.
359      */
360     public static Select getMinuteSelector(String name, Calendar now,
361                                            int interval)
362     {
363         Select minuteSelect = new Select().setName(name);
364 
365         for (int curMinute = 0; curMinute <= 59; curMinute += interval)
366         {
367             Option o = new Option();
368             o.addElement(nbrFmt.format(curMinute));
369             o.setValue(curMinute);
370             int nearestMinute =
371                     ((now.get(Calendar.MINUTE)) / interval) * interval;
372 
373             if (nearestMinute == curMinute)
374             {
375                 o.setSelected(true);
376             }
377             minuteSelect.addElement(o);
378         }
379         return (minuteSelect);
380     }
381 
382     /***
383      * Return an 12 hour selector.
384      *
385      * @param name The name to use for the selected hour.
386      * @return A select object with all the hours.
387      */
388     public static Select getHourSelector(String name)
389     {
390         return (getHourSelector(name, Calendar.getInstance()));
391     }
392 
393     /***
394      * Return an 12 hour selector.
395      *
396      * @param name The name to use for the selected hour.
397      * @param now Calendar to start with.
398      * @return A select object with all the hours.
399      */
400     public static Select getHourSelector(String name, Calendar now)
401     {
402         return (getHourSelector(name, Calendar.getInstance(), TWELVE_HOUR));
403     }
404 
405     /***
406      * Return an hour selector (either 12hr or 24hr depending on
407      * <code>format</code>.
408      *
409      * @param name The name to use for the selected hour.
410      * @param now Calendar to start with.
411      * @param format Time format.
412      * @return A select object with all the hours.
413      */
414     public static Select getHourSelector(String name, Calendar now, int format)
415     {
416         Select hourSelect = new Select().setName(name);
417 
418         if (format == TWENTY_FOUR_HOUR)
419         {
420             for (int currentHour = 0; currentHour <= 23; currentHour++)
421             {
422                 Option o = new Option();
423                 o.addElement(nbrFmt.format(currentHour));
424                 o.setValue(currentHour);
425                 if (now.get(Calendar.HOUR_OF_DAY) == currentHour)
426                 {
427                     o.setSelected(true);
428                 }
429                 hourSelect.addElement(o);
430             }
431         }
432         else
433         {
434             for (int curHour = 1; curHour <= 12; curHour++)
435             {
436                 Option o = new Option();
437 
438                 o.addElement(nbrFmt.format((long) curHour));
439                 o.setValue(curHour);
440                 if (now.get(Calendar.AM_PM) == Calendar.AM)
441                 {
442                     if (((now.get(Calendar.HOUR_OF_DAY)) == 0) &&
443                             (curHour == 12))
444                     {
445                         o.setSelected(true);
446                     }
447                     else
448                     {
449                         if (now.get(Calendar.HOUR_OF_DAY) == curHour)
450                         {
451                             o.setSelected(true);
452                         }
453                     }
454                 }
455                 else
456                 {
457                     if (((now.get(Calendar.HOUR_OF_DAY)) == 12) &&
458                             (curHour == 12))
459                     {
460                         o.setSelected(true);
461                     }
462                     else
463                     {
464                         if (now.get(Calendar.HOUR_OF_DAY) == curHour + 12)
465                         {
466                             o.setSelected(true);
467                         }
468                     }
469                 }
470                 hourSelect.addElement(o);
471             }
472         }
473         return (hourSelect);
474     }
475 
476     /***
477      * Return an am/pm selector.
478      *
479      * @param name The name to use for the selected am/pm.
480      * @return A select object with am/pm
481      */
482     public static Select getAMPMSelector(String name)
483     {
484         Calendar c = Calendar.getInstance();
485         c.setTime(new Date());
486         return (getAMPMSelector(name, c));
487     }
488 
489     /***
490      * Return an am/pm selector.
491      *
492      * @param name The name to use for the selected am/pm.
493      * @param now Calendar to start with.
494      * @return A select object with am/pm.
495      */
496     public static Select getAMPMSelector(String name,
497                                          Calendar now)
498     {
499         Select ampmSelect = new Select().setName(name);
500 
501         Option o = new Option();
502         o.addElement("am");
503         o.setValue(Calendar.AM);
504         if (now.get(Calendar.AM_PM) == Calendar.AM)
505         {
506             o.setSelected(true);
507         }
508         ampmSelect.addElement(o);
509 
510         o = new Option();
511         o.addElement("pm");
512         o.setValue(Calendar.PM);
513         if (now.get(Calendar.AM_PM) == Calendar.PM)
514         {
515             o.setSelected(true);
516         }
517         ampmSelect.addElement(o);
518 
519         return (ampmSelect);
520     }
521 
522     /***
523      * Used to build the popupmenu in HTML.  The properties set in the
524      * object are used to generate the correct HTML.  The selName
525      * attribute is used to seed the names of the select lists.  The
526      * names will be generated as follows:
527      *
528      * <ul>
529      *  <li>selName + "_hour"</li>
530      *  <li>selName + "_minute"</li>
531      *  <li>selName + "_ampm"</li>
532      * </ul>
533      *
534      * If onChange was set it is also used in the generation of the
535      * output.  The output HTML will list the select lists in the
536      * following order: hour minute ampm.
537      *
538      * If setShowSeconds(true) is used then an addition second select box
539      * is produced after the minute select box.
540      *
541      * If setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR) is used then
542      * the ampm select box is omitted.
543      *
544      * @return A String with the correct HTML for the date selector.
545      */
546     public String output()
547     {
548         return (ecsOutput().toString());
549     }
550 
551     /***
552      * Used to build the popupmenu in HTML.  The properties set in the
553      * object are used to generate the correct HTML.  The selName
554      * attribute is used to seed the names of the select lists.  The
555      * names will be generated as follows:
556      *
557      * <ul>
558      *  <li>selName + "_hour"</li>
559      *  <li>selName + "_minute"</li>
560      *  <li>selName + "_ampm"</li>
561      * </ul>
562      *
563      * If onChange was set it is also used in the generation of the
564      * output.  The output HTML will list the select lists in the
565      * following order: hour minute ampm.
566      *
567      * If setShowSeconds(true) is used then an addition second select box
568      * is produced after the minute select box.
569      *
570      * If setTimeFormat(TimeSelector.TWENTY_FOUR_HOUR) is used then
571      * the ampm select box is omitted.
572      *
573      * @return A String with the correct HTML for the date selector.
574      */
575     public String toString()
576     {
577         return (ecsOutput().toString());
578     }
579 
580     /***
581      * Return an ECS container with the select objects inside.
582      *
583      * @return An ECS container.
584      */
585     public ElementContainer ecsOutput()
586     {
587         if (this.useDate == null)
588         {
589             this.useDate = Calendar.getInstance();
590             this.useDate.setTime(new Date());
591         }
592 
593         ConcreteElement secondSelect = null;
594 
595         Select ampmSelect = getAMPMSelector(selName + AMPM_SUFFIX, useDate);
596 
597         Select hourSelect = getHourSelector(selName + HOUR_SUFFIX,
598                 useDate, this.timeFormat);
599 
600         Select minuteSelect = getMinuteSelector(selName + MINUTE_SUFFIX,
601                 useDate, this.minuteInterval);
602 
603         if (this.showSeconds)
604         {
605             Select tmp = getSecondSelector(selName + SECOND_SUFFIX, useDate,
606                     this.secondInterval);
607             if (onChangeSet)
608                 tmp.setOnChange(onChange);
609             secondSelect = tmp;
610         }
611         else
612         {
613             secondSelect = new Input(Input.hidden,
614                     selName + SECOND_SUFFIX,
615                     setSeconds);
616         }
617 
618         if (onChangeSet)
619         {
620             hourSelect.setOnChange(onChange);
621             minuteSelect.setOnChange(onChange);
622             ampmSelect.setOnChange(onChange);
623         }
624 
625         ElementContainer ec = new ElementContainer();
626         ec.addElement(new Comment(
627                 "== BEGIN org.apache.turbine.util.TimeSelector.ecsOutput() =="));
628         ec.addElement(hourSelect);
629         ec.addElement(":");
630         ec.addElement(minuteSelect);
631         if (this.showSeconds == true)
632             ec.addElement(":");
633         ec.addElement(secondSelect);
634         if (this.timeFormat == TimeSelector.TWELVE_HOUR)
635         {
636             ec.addElement(ampmSelect);
637         }
638         ec.addElement(new Comment(
639                 "== END org.apache.turbine.util.TimeSelector.ecsOutput() =="));
640         return (ec);
641     }
642 }