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;
016    
017    import java.util.Iterator;
018    
019    import org.apache.hivemind.service.ThreadLocale;
020    import org.apache.tapestry.IMarkupWriter;
021    import org.apache.tapestry.IRequestCycle;
022    import org.apache.tapestry.coerce.ValueConverter;
023    import org.apache.tapestry.form.validator.Validator;
024    import org.apache.tapestry.valid.ValidatorException;
025    
026    /**
027     * Default {@link ValidatableFieldSupport} implementation. This implementation generates calls to a
028     * static javascript function during render if client-side validation is enabled.
029     * 
030     * @author Paul Ferraro
031     * @since 4.0
032     */
033    public class ValidatableFieldSupportImpl implements ValidatableFieldSupport
034    {
035        private ValueConverter _converter;
036    
037        private ThreadLocale _threadLocale;
038    
039        public void setValueConverter(ValueConverter converter)
040        {
041            _converter = converter;
042        }
043    
044        public void setThreadLocale(ThreadLocale threadLocale)
045        {
046            _threadLocale = threadLocale;
047        }
048    
049        protected Iterator getValidatorsIterator(ValidatableField component)
050        {
051            return (Iterator) _converter.coerceValue(component.getValidators(), Iterator.class);
052        }
053    
054        /**
055         * @see org.apache.tapestry.form.ValidatableFieldSupport#renderContributions(ValidatableField, IMarkupWriter, IRequestCycle)
056         */
057        public void renderContributions(ValidatableField component, IMarkupWriter writer,
058                IRequestCycle cycle)
059        {
060            ValidatableFieldExtension extension = null;
061            if (ValidatableFieldExtension.class.isInstance(component))
062                extension = (ValidatableFieldExtension)component;
063            
064            if (component.getForm().isClientValidationEnabled())
065            {
066                FormComponentContributorContext context = new FormComponentContributorContextImpl(
067                        _threadLocale.getLocale(), cycle, component);
068    
069                Iterator validators = getValidatorsIterator(component);
070    
071                while (validators.hasNext())
072                {
073                    Validator validator = (Validator) validators.next();
074                    
075                    if (extension != null && extension.overrideValidator(validator, cycle))
076                        extension.overrideContributions(validator, context, writer, cycle);
077                    else
078                        validator.renderContribution(writer, cycle, context, component);
079                }
080            }
081        }
082    
083        /**
084         * @see org.apache.tapestry.form.ValidatableFieldSupport#validate(org.apache.tapestry.form.ValidatableField, org.apache.tapestry.IMarkupWriter, org.apache.tapestry.IRequestCycle, java.lang.Object)
085         */
086        public void validate(ValidatableField component, IMarkupWriter writer, IRequestCycle cycle, Object object) throws ValidatorException
087        {
088            boolean isNonNull = (object != null);
089    
090            Iterator validators = getValidatorsIterator(component);
091    
092            ValidationMessages messages = new ValidationMessagesImpl(component, _threadLocale.getLocale());
093    
094            while (validators.hasNext())
095            {
096                Validator validator = (Validator) validators.next();
097    
098                if (isNonNull || validator.getAcceptsNull())
099                    validator.validate(component, messages, object);
100            }
101        }
102    
103        public boolean isRequired(ValidatableField field)
104        {
105            Iterator i = getValidatorsIterator(field);
106    
107            while (i.hasNext())
108            {
109                Validator validator = (Validator) i.next();
110    
111                if (validator.isRequired())
112                    return true;
113            }
114    
115            return false;
116        }
117    }