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
015package org.apache.tapestry.valid;
016
017import 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 */
025public 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}