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.valid;
016    
017    import org.apache.tapestry.form.IFormComponent;
018    
019    /**
020     * Base class for a number of implementations of {@link org.apache.tapestry.valid.IValidator},
021     * meant to replace the awkward {@link org.apache.tapestry.valid.NumberValidator}.
022     * 
023     * @author Howard M. Lewis Ship
024     */
025    public abstract class AbstractNumericValidator extends BaseValidator
026    {
027        private boolean _zeroIsNull;
028    
029        public AbstractNumericValidator()
030        {
031            super();
032        }
033    
034        public AbstractNumericValidator(String initializer)
035        {
036            super(initializer);
037        }
038    
039        public AbstractNumericValidator(boolean required)
040        {
041            super(required);
042        }
043    
044        /**
045         * If true, then when rendering, a zero is treated as a non-value, and null is returned. If
046         * false, the default, then zero is rendered as zero.
047         */
048    
049        public boolean getZeroIsNull()
050        {
051            return _zeroIsNull;
052        }
053    
054        public void setZeroIsNull(boolean zeroIsNull)
055        {
056            _zeroIsNull = zeroIsNull;
057        }
058    
059        private String _scriptPath = 
060            getDefaultScriptPath();
061    
062        
063        private String _invalidNumericFormatMessage;
064    
065        private String _invalidIntegerFormatMessage;
066    
067        private String _numberTooSmallMessage;
068    
069        private String _numberTooLargeMessage;
070    
071        private String _numberRangeMessage;
072    
073        /**
074         * @since 2.2
075         */
076        public String getScriptPath()
077        {
078            return _scriptPath;
079        }
080    
081        /**
082         * Allows a developer to use the existing validation logic with a different client-side script.
083         * This is often sufficient to allow application-specific error presentation (perhaps by using
084         * DHTML to update the content of a <span> tag, or to use a more sophisticated pop-up
085         * window than <code>window.alert()</code>).
086         * 
087         * @since 2.2
088         */
089        public void setScriptPath(String scriptPath)
090        {
091            _scriptPath = scriptPath;
092        }
093    
094        /** @since 3.0 */
095        public String getInvalidNumericFormatMessage()
096        {
097            return _invalidNumericFormatMessage;
098        }
099    
100        /** @since 3.0 */
101        public String getInvalidIntegerFormatMessage()
102        {
103            return _invalidIntegerFormatMessage;
104        }
105    
106        /** @since 3.0 */
107        public String getNumberRangeMessage()
108        {
109            return _numberRangeMessage;
110        }
111    
112        /** @since 3.0 */
113        public String getNumberTooLargeMessage()
114        {
115            return _numberTooLargeMessage;
116        }
117    
118        /** @since 3.0 */
119        public String getNumberTooSmallMessage()
120        {
121            return _numberTooSmallMessage;
122        }
123    
124        /**
125         * Overrides the <code>invalid-numeric-format</code> bundle key. Parameter {0} is the display
126         * name of the field.
127         * 
128         * @since 3.0
129         */
130        public void setInvalidNumericFormatMessage(String string)
131        {
132            _invalidNumericFormatMessage = string;
133        }
134    
135        /**
136         * Overrides the <code>invalid-int-format</code> bundle key. Parameter {0} is the display name
137         * of the field.
138         * 
139         * @since 3.0
140         */
141        public void setInvalidIntegerFormatMessage(String string)
142        {
143            _invalidIntegerFormatMessage = string;
144        }
145    
146        /**
147         * Overrides the <code>number-range</code> bundle key. Parameter [0} is the display name of
148         * the field. Parameter {1} is the minimum value. Parameter {2} is the maximum value.
149         * 
150         * @since 3.0
151         */
152        public void setNumberRangeMessage(String string)
153        {
154            _numberRangeMessage = string;
155        }
156    
157        /**
158         * Overrides the <code>number-too-large</code> bundle key. Parameter {0} is the display name
159         * of the field. Parameter {1} is the maximum allowed value.
160         * 
161         * @since 3.0
162         */
163        public void setNumberTooLargeMessage(String string)
164        {
165            _numberTooLargeMessage = string;
166        }
167    
168        /**
169         * Overrides the <code>number-too-small</code> bundle key. Parameter {0} is the display name
170         * of the field. Parameter {1} is the minimum allowed value.
171         * 
172         * @since 3.0
173         */
174        public void setNumberTooSmallMessage(String string)
175        {
176            _numberTooSmallMessage = string;
177        }
178    
179        /** @since 3.0 */
180        protected String buildInvalidNumericFormatMessage(IFormComponent field)
181        {
182            String pattern = getPattern(
183                    getInvalidNumericFormatMessage(),
184                    "invalid-numeric-format",
185                    field.getPage().getLocale());
186    
187            return formatString(pattern, field.getDisplayName());
188        }
189    
190        protected String buildNumberTooSmallMessage(IFormComponent field, Number minimum)
191        {
192            String pattern = getPattern(getNumberTooSmallMessage(), "number-too-small", field.getPage()
193                    .getLocale());
194    
195            return formatString(pattern, field.getDisplayName(), minimum);
196        }
197    
198        /** @since 3.0 */
199        protected String buildInvalidIntegerFormatMessage(IFormComponent field)
200        {
201            String pattern = getPattern(getInvalidIntegerFormatMessage(), "invalid-int-format", field
202                    .getPage().getLocale());
203        
204            return formatString(pattern, field.getDisplayName());
205        }
206    
207        /**
208         * @since 3.0
209         */
210        protected String buildNumberTooLargeMessage(IFormComponent field, Number maximum)
211        {
212            String pattern = getPattern(getNumberTooLargeMessage(), "number-too-large", field.getPage()
213                    .getLocale());
214        
215            return formatString(pattern, field.getDisplayName(), maximum);
216        }
217    
218        protected String buildNumberRangeMessage(IFormComponent field, Number mininum, Number maximum)
219        {
220            String pattern = getPattern(getNumberRangeMessage(), "number-range", field.getPage()
221                    .getLocale());
222        
223            return formatString(pattern, new Object[]
224            { field.getDisplayName(), mininum, maximum });
225        }
226    
227        protected String buildRangeMessage(IFormComponent field, Number minimum, Number maximum)
228        {
229            if (minimum != null && maximum != null)
230                return buildNumberRangeMessage(field, minimum, maximum);
231        
232            if (maximum != null)
233                return buildNumberTooLargeMessage(field, maximum);
234        
235            return buildNumberTooSmallMessage(field, minimum);
236        }
237        
238        protected abstract String getDefaultScriptPath();
239    }