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