001    /*
002     * Apache License
003     * Version 2.0, January 2004
004     * http://www.apache.org/licenses/
005     *
006     * Copyright 2009 by chenillekit.org
007     *
008     * Licensed under the Apache License, Version 2.0 (the "License");
009     * you may not use this file except in compliance with the License.
010     * You may obtain a copy of the License at
011     *
012     * http://www.apache.org/licenses/LICENSE-2.0
013     */
014    
015    package org.chenillekit.tapestry.core.components;
016    
017    import java.util.Calendar;
018    import java.util.Date;
019    import java.util.List;
020    import java.util.Locale;
021    
022    import org.apache.tapestry5.Binding;
023    import org.apache.tapestry5.BindingConstants;
024    import org.apache.tapestry5.ComponentResources;
025    import org.apache.tapestry5.FieldValidationSupport;
026    import org.apache.tapestry5.FieldValidator;
027    import org.apache.tapestry5.MarkupWriter;
028    import org.apache.tapestry5.ValidationException;
029    import org.apache.tapestry5.ValidationTracker;
030    import org.apache.tapestry5.annotations.Environmental;
031    import org.apache.tapestry5.annotations.Parameter;
032    import org.apache.tapestry5.annotations.Persist;
033    import org.apache.tapestry5.annotations.Property;
034    import org.apache.tapestry5.corelib.base.AbstractField;
035    import org.apache.tapestry5.ioc.annotations.Inject;
036    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
037    import org.apache.tapestry5.services.ComponentDefaultProvider;
038    import org.apache.tapestry5.services.Request;
039    
040    /**
041     * @author <a href="mailto:shomburg@depot120.dpd.de">S.Homburg</a>
042     * @version $Id: DateSelector.java 471 2009-05-09 09:28:38Z homburgs $
043     */
044    public class DateSelector extends AbstractField
045    {
046            @Parameter(required = true, defaultPrefix = BindingConstants.PROP)
047            private Date value;
048    
049            @Parameter(defaultPrefix = BindingConstants.PROP, value = "1970")
050            private int firstYear;
051    
052            @Parameter(defaultPrefix = BindingConstants.PROP, value = "2030")
053            private int lastYear;
054    
055            @Parameter(defaultPrefix = BindingConstants.PROP, value = "false")
056            private boolean longMonth;
057    
058            /**
059             * The object that will perform input validation (which occurs after translation). The validate binding prefix is
060             * generally used to provide this object in a declarative fashion.
061             */
062            @Parameter(defaultPrefix = BindingConstants.VALIDATE)
063            @SuppressWarnings("unchecked")
064            private FieldValidator<Object> validate;
065    
066            @Property
067            @Persist
068            private int dayValue;
069    
070            @Property
071            @Persist
072            private int monthValue;
073    
074            @Property
075            @Persist
076            private int yearValue;
077    
078            @Inject
079            private Locale locale;
080    
081            @Inject
082            private ComponentDefaultProvider defaultProvider;
083    
084            @Inject
085            private Request request;
086    
087            @Inject
088            private ComponentResources resources;
089    
090            @Environmental
091            private ValidationTracker tracker;
092    
093            @Inject
094            private FieldValidationSupport fieldValidationSupport;
095    
096            private List<Integer> days = CollectionFactory.newList();
097            private List<Integer> months = CollectionFactory.newList();
098            private List<Integer> years = CollectionFactory.newList();
099    
100            private Calendar calendar = Calendar.getInstance(locale);
101    
102            /**
103             * Computes a default value for the "validate" parameter using {@link org.apache.tapestry5.services.FieldValidatorDefaultSource}.
104             */
105            final Binding defaultValidate()
106            {
107                    return defaultProvider.defaultValidatorBinding("value", resources);
108            }
109    
110            /**
111             * Tapestry render phase method.
112             * Initialize temporary instance variables here.
113             */
114            void setupRender()
115            {
116                    if (value == null)
117                            value = new Date();
118    
119                    calendar.setTime(value);
120                    dayValue = calendar.get(Calendar.DAY_OF_MONTH);
121                    monthValue = calendar.get(Calendar.MONTH);
122                    yearValue = calendar.get(Calendar.YEAR);
123            }
124    
125            /**
126             * Tapestry render phase method.
127             * Start a tag here, end it in afterRender
128             */
129            void beginRender(MarkupWriter writer)
130            {
131                    writer.element("span",
132                                               "class", "ck-dateselector",
133                                               "id", getClientId());
134    
135                    writer.element("select",
136                                               "class", "day",
137                                               "id", getClientId() + "_day",
138                                               "name", getControlName() + "_day");
139    
140                    for (int day = 1; day < 32; day++)
141                    {
142                            org.apache.tapestry5.dom.Element element = writer.element("option",
143                                                                                                                                              "value", day);
144    
145                            if (dayValue == day)
146                                    element.attribute("selected", "selected");
147    
148                            writer.write(String.format("%02d", day));
149                            writer.end();
150                    }
151                    writer.end();
152    
153                    writer.element("select",
154                                               "class", "month",
155                                               "id", getClientId() + "_month",
156                                               "name", getControlName() + "_month");
157    
158                    for (int month = 0; month < 12; month++)
159                    {
160                            org.apache.tapestry5.dom.Element element = writer.element("option",
161                                                                                                                                              "value", month);
162    
163                            if (monthValue == month)
164                                    element.attribute("selected", "selected");
165    
166                            writer.write(String.format("%02d", month + 1));
167    
168                            writer.end();
169                    }
170                    writer.end();
171    
172                    writer.element("select",
173                                               "class", "year",
174                                               "id", getClientId() + "_year",
175                                               "name", getControlName() + "_year");
176    
177                    for (int year = firstYear; year <= lastYear; year++)
178                    {
179                            org.apache.tapestry5.dom.Element element = writer.element("option",
180                                                                                                                                              "value", year);
181    
182                            if (yearValue == year)
183                                    element.attribute("selected", "selected");
184    
185                            writer.write(String.format("%d", year));
186                            writer.end();
187                    }
188                    writer.end();
189            }
190    
191            /**
192             * Tapestry render phase method. End a tag here.
193             */
194            void afterRender(MarkupWriter writer)
195            {
196                    writer.end();
197            }
198    
199    
200            public List<Integer> getDaySelectModel()
201            {
202                    return days;
203            }
204    
205            public List<Integer> getMonthSelectModel()
206            {
207                    return months;
208            }
209    
210            public List<Integer> getYearSelectModel()
211            {
212                    return years;
213            }
214    
215            /**
216             * Method implemented by subclasses to actually do the work of processing the submission of the form. The element's
217             * elementName property will already have been set. This method is only invoked if the field is <strong>not {@link
218             * #isDisabled() disabled}</strong>.
219             *
220             * @param elementName the name of the element (used to find the correct parameter in the request)
221             */
222            protected void processSubmission(String elementName)
223            {
224                    String rawDayValue = request.getParameter(elementName + "_day");
225                    String rawMonthValue = request.getParameter(elementName + "_month");
226                    String rawYearValue = request.getParameter(elementName + "_year");
227    
228                    try
229                    {
230                            calendar.set(Integer.parseInt(rawYearValue), Integer.parseInt(rawMonthValue), Integer.parseInt(rawDayValue));
231                            calendar.setLenient(false);
232                            Date translated = calendar.getTime();
233                            fieldValidationSupport.validate(translated, resources, validate);
234                            value = translated;
235                    }
236                    catch (ValidationException ex)
237                    {
238                            tracker.recordError(this, ex.getMessage());
239                    }
240                    catch (IllegalArgumentException ex)
241                    {
242                            tracker.recordError(this, ex.getMessage());
243                    }
244            }
245    }