001    // Copyright 2004, 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.valid;
016    
017    import java.util.HashMap;
018    import java.util.Locale;
019    import java.util.Map;
020    
021    import org.apache.tapestry.IMarkupWriter;
022    import org.apache.tapestry.IRequestCycle;
023    import org.apache.tapestry.form.IFormComponent;
024    
025    /**
026     * Simple validation of email strings, to enforce required, and minimum length (maximum length is
027     * enforced in the client browser, by setting a maximum input length on the text field).
028     * 
029     * @author Malcolm Edgar
030     * @since 2.3
031     */
032    
033    public class EmailValidator extends BaseValidator
034    {
035        private int _minimumLength;
036    
037        private String _minimumLengthMessage;
038    
039        private String _invalidEmailFormatMessage;
040    
041        private String _scriptPath = "/org/apache/tapestry/valid/EmailValidator.script";
042    
043        public EmailValidator()
044        {
045        }
046    
047        /**
048         * Initializes the EmailValidator with properties defined by the initializer.
049         * 
050         * @since 4.0
051         */
052    
053        public EmailValidator(String initializer)
054        {
055            super(initializer);
056        }
057    
058        public String toString(IFormComponent field, Object value)
059        {
060            if (value == null)
061                return null;
062    
063            return value.toString();
064        }
065    
066        public Object toObject(IFormComponent field, String input) throws ValidatorException
067        {
068            if (checkRequired(field, input))
069                return null;
070    
071            if (_minimumLength > 0 && input.length() < _minimumLength)
072                throw new ValidatorException(buildMinimumLengthMessage(field),
073                        ValidationConstraint.MINIMUM_WIDTH);
074    
075            if (!isValidEmail(input))
076                throw new ValidatorException(buildInvalidEmailFormatMessage(field),
077                        ValidationConstraint.EMAIL_FORMAT);
078    
079            return input;
080        }
081    
082        public int getMinimumLength()
083        {
084            return _minimumLength;
085        }
086    
087        public void setMinimumLength(int minimumLength)
088        {
089            _minimumLength = minimumLength;
090        }
091    
092        public void renderValidatorContribution(IFormComponent field, IMarkupWriter writer,
093                IRequestCycle cycle)
094        {
095            if (!isClientScriptingEnabled())
096                return;
097    
098            Map symbols = new HashMap();
099    
100            Locale locale = field.getPage().getLocale();
101            String displayName = field.getDisplayName();
102    
103            if (isRequired())
104                symbols.put("requiredMessage", buildRequiredMessage(field));
105    
106            if (_minimumLength > 0)
107                symbols.put("minimumLengthMessage", buildMinimumLengthMessage(field));
108    
109            String pattern = getPattern(getInvalidEmailFormatMessage(), "invalid-email-format", locale);
110    
111            symbols.put("emailFormatMessage", formatString(pattern, displayName));
112    
113            processValidatorScript(_scriptPath, cycle, field, symbols);
114        }
115    
116        public String getScriptPath()
117        {
118            return _scriptPath;
119        }
120    
121        /**
122         * Allows a developer to use the existing validation logic with a different client-side script.
123         * This is often sufficient to allow application-specific error presentation (perhaps by using
124         * DHTML to update the content of a <span> tag, or to use a more sophisticated pop-up
125         * window than <code>window.alert()</code>).
126         */
127    
128        public void setScriptPath(String scriptPath)
129        {
130            _scriptPath = scriptPath;
131        }
132    
133        /**
134         * Return true if the email format is valid.
135         * 
136         * @param email
137         *            the email string to validate
138         * @return true if the email format is valid
139         */
140    
141        protected boolean isValidEmail(String email)
142        {
143            int atIndex = email.indexOf('@');
144    
145            return !((atIndex <= 0) || (atIndex == email.length() - 1));
146        }
147    
148        /** @since 3.0 */
149    
150        public String getInvalidEmailFormatMessage()
151        {
152            return _invalidEmailFormatMessage;
153        }
154    
155        /** @since 3.0 */
156    
157        public String getMinimumLengthMessage()
158        {
159            return _minimumLengthMessage;
160        }
161    
162        /**
163         * Overrides the <code>invalid-email-format</code> bundle key. Parameter {0} is the display
164         * name of the field.
165         * 
166         * @since 3.0
167         */
168    
169        public void setInvalidEmailFormatMessage(String string)
170        {
171            _invalidEmailFormatMessage = string;
172        }
173    
174        /**
175         * Overrides the <code>field-too-short</code> bundle key. Parameter {0} is the minimum length.
176         * Parameter {1} is the display name of the field.
177         * 
178         * @since 3.0
179         */
180        public void setMinimumLengthMessage(String string)
181        {
182            _minimumLengthMessage = string;
183        }
184    
185        /** @since 3.0 */
186    
187        protected String buildMinimumLengthMessage(IFormComponent field)
188        {
189            String pattern = getPattern(_minimumLengthMessage, "field-too-short", field.getPage()
190                    .getLocale());
191    
192            return formatString(pattern, Integer.toString(_minimumLength), field.getDisplayName());
193        }
194    
195        /** @since 3.0 */
196    
197        protected String buildInvalidEmailFormatMessage(IFormComponent field)
198        {
199            String pattern = getPattern(_invalidEmailFormatMessage, "invalid-email-format", field
200                    .getPage().getLocale());
201    
202            return formatString(pattern, field.getDisplayName());
203        }
204    }