001    // Copyright 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.form.translator;
016    
017    import org.apache.hivemind.util.PropertyUtils;
018    import org.apache.tapestry.IMarkupWriter;
019    import org.apache.tapestry.IRequestCycle;
020    import org.apache.tapestry.form.FormComponentContributorContext;
021    import org.apache.tapestry.form.IFormComponent;
022    import org.apache.tapestry.json.JSONLiteral;
023    import org.apache.tapestry.json.JSONObject;
024    import org.apache.tapestry.valid.ValidationConstants;
025    import org.apache.tapestry.valid.ValidationConstraint;
026    import org.apache.tapestry.valid.ValidationStrings;
027    
028    import java.text.DateFormatSymbols;
029    import java.text.Format;
030    import java.text.SimpleDateFormat;
031    import java.util.Locale;
032    
033    /**
034     * A {@link java.text.SimpleDateFormat}-based {@link Translator} implementation.
035     * 
036     * @author Paul Ferraro
037     * @since 4.0
038     */
039    public class DateTranslator extends FormatTranslator
040    {
041        private boolean _lenient=true;
042    
043        protected SimpleDateFormat _rfc339Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
044        
045        public DateTranslator()
046        {
047        }
048        
049        // Needed until HIVEMIND-134 fix is available
050        public DateTranslator(String initializer)
051        {
052            PropertyUtils.configureProperties(this, initializer);
053        }
054        
055        /**
056         * @see org.apache.tapestry.form.translator.FormatTranslator#defaultPattern()
057         */
058        protected String defaultPattern()
059        {
060            return "MM/dd/yyyy";
061        }
062        
063        /**
064         * @see org.apache.tapestry.form.translator.FormatTranslator#getFormat(java.util.Locale)
065         */
066        protected Format getFormat(Locale locale)
067        {
068            return getDateFormat(locale);
069        }
070    
071        /**
072         * Get the RFC339 equivalent for the given object.
073         *
074         * @param input The object to be formatted.
075         * 
076         * @return A string value compliant with rfc339 internet time.
077         */
078        public String formatRfc3339(Object input)
079        {
080            return _rfc339Format.format(input);
081        }
082    
083        public SimpleDateFormat getDateFormat(Locale locale)
084        {
085            SimpleDateFormat ret = new SimpleDateFormat(getPattern(), new DateFormatSymbols(locale));
086            ret.setLenient(_lenient);
087            
088            return ret;
089        }
090        
091        /**
092         * @see org.apache.tapestry.form.translator.FormatTranslator#getMessageKey()
093         */
094        protected String getMessageKey()
095        {
096            return ValidationStrings.INVALID_DATE;
097        }
098        
099        /**
100         * @see org.apache.tapestry.form.translator.AbstractTranslator#getMessageParameters(java.util.Locale,
101         *      java.lang.String)
102         */
103        protected Object[] getMessageParameters(Locale locale, String label)
104        {
105            String pattern = getDateFormat(locale).toLocalizedPattern().toUpperCase(locale);
106            
107            return new Object[] { label, pattern };
108        }
109        
110        /**
111         * 
112         * {@inheritDoc}
113         */
114        public void renderContribution(IMarkupWriter writer, IRequestCycle cycle,
115                FormComponentContributorContext context, IFormComponent field)
116        {
117            super.renderContribution(writer, cycle, context, field);
118            
119            String message = buildMessage(context, field, getMessageKey());
120            
121            JSONObject profile = context.getProfile();
122            if (!profile.has(ValidationConstants.CONSTRAINTS)) {
123                profile.put(ValidationConstants.CONSTRAINTS, new JSONObject());
124            }
125            
126            JSONObject cons = profile.getJSONObject(ValidationConstants.CONSTRAINTS);
127            
128            context.addInitializationScript(field, "dojo.require(\"tapestry.form.datetime\");");
129            
130            accumulateProperty(cons, field.getClientId(), 
131                    new JSONLiteral("[tapestry.form.datetime.isValidDate,{"
132                            + "datePattern:" 
133                            + JSONObject.quote(getPattern())
134                            + (isLenient() ? "" : ",strict:true")
135                            + "}]"));
136            
137            accumulateProfileProperty(field, profile, ValidationConstants.CONSTRAINTS, message);
138        }
139        
140        /**
141         * @see org.apache.tapestry.form.translator.FormatTranslator#getConstraint()
142         */
143        protected ValidationConstraint getConstraint()
144        {
145            return ValidationConstraint.DATE_FORMAT;
146        }
147        
148        public void setLenient(boolean value)
149        {
150            _lenient = value;
151        }
152        
153        public boolean isLenient()
154        {
155            return _lenient;
156        }
157    }