KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > validators > datatype > DecimalDatatypeValidator


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.enhydra.apache.xerces.validators.datatype;
59
60 import java.math.BigDecimal JavaDoc;
61 import java.util.Hashtable JavaDoc;
62 import java.util.Vector JavaDoc;
63
64 import org.enhydra.apache.xerces.validators.schema.SchemaSymbols;
65
66 /**
67  *
68  * DecimalDatatypeValidator validates that content satisfies the W3C XML Datatype for decimal
69  *
70  * @author Elena Litani
71  * @author Ted Leung
72  * @author Jeffrey Rodriguez
73  * @author Mark Swinkles - List Validation refactoring
74  * @version $Id: DecimalDatatypeValidator.java,v 1.2 2005/01/26 08:28:44 jkjome Exp $
75  */

76
77 public class DecimalDatatypeValidator extends AbstractNumericValidator {
78
79     protected int fTotalDigits;
80     protected int fFractionDigits;
81
82     public DecimalDatatypeValidator () throws InvalidDatatypeFacetException {
83         this( null, null, false ); // Native, No Facets defined, Restriction
84
}
85
86     public DecimalDatatypeValidator ( DatatypeValidator base, Hashtable JavaDoc facets,
87                                       boolean derivedByList ) throws InvalidDatatypeFacetException {
88         super (base, facets, derivedByList);
89     }
90
91     public int compare( String JavaDoc value1, String JavaDoc value2) {
92         try {
93             BigDecimal JavaDoc d1 = new BigDecimal JavaDoc(stripPlusIfPresent(value1));
94             BigDecimal JavaDoc d2 = new BigDecimal JavaDoc(stripPlusIfPresent(value2));
95             return d1.compareTo(d2);
96         }
97         catch ( NumberFormatException JavaDoc e ) {
98             //REVISIT: should we throw exception??
99
return -1;
100         }
101         catch ( Exception JavaDoc e){
102             return -1;
103         }
104     }
105
106     protected void inheritAdditionalFacets() {
107
108         // inherit totalDigits
109
if ( (( ((DecimalDatatypeValidator)fBaseValidator).fFacetsDefined & DatatypeValidator.FACET_TOTALDIGITS) != 0) &&
110              !((fFacetsDefined & DatatypeValidator.FACET_TOTALDIGITS) != 0) ) {
111             fFacetsDefined |= FACET_TOTALDIGITS;
112             fTotalDigits = ((DecimalDatatypeValidator)fBaseValidator).fTotalDigits;
113         }
114         // inherit fractionDigits
115
if ( (( ((DecimalDatatypeValidator)fBaseValidator).fFacetsDefined & DatatypeValidator.FACET_FRACTIONDIGITS) != 0)
116              && !((fFacetsDefined & DatatypeValidator.FACET_FRACTIONDIGITS) != 0) ) {
117             fFacetsDefined |= FACET_FRACTIONDIGITS;
118             fFractionDigits = ((DecimalDatatypeValidator)fBaseValidator).fFractionDigits;
119         }
120     }
121
122     protected void checkFacetConstraints() throws InvalidDatatypeFacetException{
123         // check 4.3.12.c1 must: fractionDigits <= totalDigits
124
if ( ((fFacetsDefined & DatatypeValidator.FACET_FRACTIONDIGITS) != 0) &&
125              ((fFacetsDefined & DatatypeValidator.FACET_TOTALDIGITS) != 0) ) {
126             if ( fFractionDigits > fTotalDigits )
127                 throw new InvalidDatatypeFacetException( "fractionDigits value ='" + this.fFractionDigits + "'must be <= totalDigits value ='" +
128                                                          this.fTotalDigits + "'. " );
129         }
130     }
131
132     protected void checkBaseFacetConstraints() throws InvalidDatatypeFacetException{
133
134         // check 4.3.11.c1 error: totalDigits > base.totalDigits
135
if ( ((fFacetsDefined & DatatypeValidator.FACET_TOTALDIGITS) != 0) ) {
136             if ( (( ((DecimalDatatypeValidator)fBaseValidator).fFacetsDefined & DatatypeValidator.FACET_TOTALDIGITS) != 0)){
137                 if ((((DecimalDatatypeValidator)fBaseValidator).fFlags & DatatypeValidator.FACET_TOTALDIGITS) != 0 &&
138                      fTotalDigits != ((DecimalDatatypeValidator)fBaseValidator).fTotalDigits){
139                     throw new InvalidDatatypeFacetException("totalDigits value = '" + fTotalDigits +
140                                                             "' must be equal to base.totalDigits value = '" +
141                                                             ((DecimalDatatypeValidator)fBaseValidator).fTotalDigits +
142                                                             "' with attribute {fixed} = true" );
143                 }
144                 if (fTotalDigits > ((DecimalDatatypeValidator)fBaseValidator).fTotalDigits ){
145                     throw new InvalidDatatypeFacetException( "totalDigits value ='" + fTotalDigits + "' must be <= base.totalDigits value ='" +
146                                                          ((DecimalDatatypeValidator)fBaseValidator).fTotalDigits + "'." );
147                 }
148             }
149         }
150         // check fixed value for fractionDigits
151
if ( ((fFacetsDefined & DatatypeValidator.FACET_FRACTIONDIGITS) != 0) ) {
152             if ( (( ((DecimalDatatypeValidator)fBaseValidator).fFacetsDefined & DatatypeValidator.FACET_FRACTIONDIGITS) != 0)){
153                 if ((((DecimalDatatypeValidator)fBaseValidator).fFlags & DatatypeValidator.FACET_FRACTIONDIGITS) != 0 &&
154                      fFractionDigits != ((DecimalDatatypeValidator)fBaseValidator).fFractionDigits){
155                     throw new InvalidDatatypeFacetException("fractionDigits value = '" + fFractionDigits +
156                                                             "' must be equal to base.fractionDigits value = '" +
157                                                             ((DecimalDatatypeValidator)fBaseValidator).fFractionDigits +
158                                                             "' with attribute {fixed} = true" );
159                 }
160             }
161         }
162     }
163
164     protected void assignAdditionalFacets(String JavaDoc key, Hashtable JavaDoc facets ) throws InvalidDatatypeFacetException{
165
166         String JavaDoc value = null;
167         try {
168             if ( key.equals(SchemaSymbols.ELT_TOTALDIGITS) ) {
169                 value = ((String JavaDoc) facets.get(key ));
170                 fFacetsDefined |= DatatypeValidator.FACET_TOTALDIGITS;
171                 fTotalDigits = Integer.parseInt(value );
172                 // check 4.3.11.c0 must: totalDigits > 0
173
if ( fTotalDigits <= 0 )
174                     throw new InvalidDatatypeFacetException("totalDigits value '"+fTotalDigits+"' must be a positiveInteger.");
175             }
176             else if ( key.equals(SchemaSymbols.ELT_FRACTIONDIGITS) ) {
177                 value = ((String JavaDoc) facets.get(key ));
178                 fFacetsDefined |= DatatypeValidator.FACET_FRACTIONDIGITS;
179                 fFractionDigits = Integer.parseInt( value );
180                 // check 4.3.12.c0 must: fractionDigits > 0
181
if ( fFractionDigits < 0 )
182                     throw new InvalidDatatypeFacetException("fractionDigits value '"+fFractionDigits+"' must be a positiveInteger.");
183             }
184             else {
185                 throw new InvalidDatatypeFacetException( getErrorString( DatatypeMessageProvider.ILLEGAL_DECIMAL_FACET,
186                                                                          DatatypeMessageProvider.MSG_NONE, new Object JavaDoc [] { value, key}));
187             }
188         }
189         catch ( Exception JavaDoc ex ) {
190             throw new InvalidDatatypeFacetException( getErrorString( DatatypeMessageProvider.ILLEGAL_FACET_VALUE,
191                                                                      DatatypeMessageProvider.MSG_NONE, new Object JavaDoc [] { value, key}));
192         }
193     }
194
195     protected int compareValues (Object JavaDoc value1, Object JavaDoc value2) {
196         return((BigDecimal JavaDoc)value1).compareTo((BigDecimal JavaDoc)value2);
197     }
198
199     protected void setMaxInclusive (String JavaDoc value) {
200         fMaxInclusive = new BigDecimal JavaDoc(stripPlusIfPresent(value));
201     }
202     protected void setMinInclusive (String JavaDoc value) {
203         fMinInclusive = new BigDecimal JavaDoc(stripPlusIfPresent(value));
204
205     }
206     protected void setMaxExclusive (String JavaDoc value) {
207         fMaxExclusive = new BigDecimal JavaDoc(stripPlusIfPresent(value));
208
209     }
210     protected void setMinExclusive (String JavaDoc value) {
211         fMinExclusive = new BigDecimal JavaDoc(stripPlusIfPresent(value));
212
213     }
214     protected void setEnumeration (Vector JavaDoc enumeration) throws InvalidDatatypeValueException{
215         if ( enumeration != null ) {
216             fEnumeration = new BigDecimal JavaDoc[enumeration.size()];
217             Object JavaDoc baseEnum=null;
218             try {
219
220                 for ( int i = 0; i < enumeration.size(); i++ ) {
221                     fEnumeration[i] = new BigDecimal JavaDoc( stripPlusIfPresent(((String JavaDoc) enumeration.elementAt(i))));;
222                     ((DecimalDatatypeValidator)fBaseValidator).validate((String JavaDoc)enumeration.elementAt(i), null);
223                 }
224             }
225             catch ( Exception JavaDoc e ) {
226                 throw new InvalidDatatypeValueException(e.getMessage());
227             }
228         }
229     }
230
231
232     protected String JavaDoc getMaxInclusive (boolean isBase) {
233         return(isBase)?(((DecimalDatatypeValidator)fBaseValidator).fMaxInclusive.toString())
234         :((BigDecimal JavaDoc)fMaxInclusive).toString();
235     }
236     protected String JavaDoc getMinInclusive (boolean isBase) {
237         return(isBase)?(((DecimalDatatypeValidator)fBaseValidator).fMinInclusive.toString())
238         :((BigDecimal JavaDoc)fMinInclusive).toString();
239     }
240     protected String JavaDoc getMaxExclusive (boolean isBase) {
241         return(isBase)?(((DecimalDatatypeValidator)fBaseValidator).fMaxExclusive.toString())
242         :((BigDecimal JavaDoc)fMaxExclusive).toString();
243     }
244     protected String JavaDoc getMinExclusive (boolean isBase) {
245         return(isBase)?(((DecimalDatatypeValidator)fBaseValidator).fMinExclusive.toString())
246         :((BigDecimal JavaDoc)fMinExclusive).toString();
247     }
248
249
250
251     protected void checkContent(String JavaDoc content, Object JavaDoc state, Vector JavaDoc enumeration, boolean asBase)
252     throws InvalidDatatypeValueException {
253         // validate against parent type if any
254
if ( this.fBaseValidator != null ) {
255             // validate content as a base type
256
((DecimalDatatypeValidator)fBaseValidator).checkContent(content, state, enumeration, true);
257         }
258
259         // we check pattern first
260
if ( (fFacetsDefined & DatatypeValidator.FACET_PATTERN ) != 0 ) {
261             if ( fRegex == null || fRegex.matches( content) == false )
262                 throw new InvalidDatatypeValueException("Value'"+content+
263                                                         "' does not match regular expression facet " + fRegex.getPattern() );
264         }
265
266         // if this is a base validator, we only need to check pattern facet
267
// all other facet were inherited by the derived type
268
if ( asBase )
269             return;
270
271         BigDecimal JavaDoc d = null; // Is content a Decimal
272
try {
273             d = new BigDecimal JavaDoc( stripPlusIfPresent( content));
274         }
275         catch ( Exception JavaDoc nfe ) {
276             throw new InvalidDatatypeValueException( getErrorString(DatatypeMessageProvider.NOT_DECIMAL,
277                                                                     DatatypeMessageProvider.MSG_NONE,
278                                                                     new Object JavaDoc[] { "'" + content +"'"}));
279         }
280
281         if ( enumeration != null ) { //the call was made from List or Union
282
int size= enumeration.size();
283             BigDecimal JavaDoc[] enumDecimal = new BigDecimal JavaDoc[size];
284             int i = 0;
285             try {
286                 for ( ; i < size; i++ )
287                     enumDecimal[i] = new BigDecimal JavaDoc( stripPlusIfPresent(((String JavaDoc) enumeration.elementAt(i))));
288             }
289             catch ( NumberFormatException JavaDoc nfe ) {
290                 throw new InvalidDatatypeValueException( getErrorString(DatatypeMessageProvider.INVALID_ENUM_VALUE,
291                                                                         DatatypeMessageProvider.MSG_NONE,
292                                                                         new Object JavaDoc [] { enumeration.elementAt(i)}));
293             }
294             enumCheck(d, enumDecimal);
295         }
296
297         if ( (fFacetsDefined & DatatypeValidator.FACET_FRACTIONDIGITS)!=0 ) {
298             if ( d.scale() > fFractionDigits )
299                 throw new InvalidDatatypeValueException(
300                                                        getErrorString(DatatypeMessageProvider.FRACTION_EXCEEDED,
301                                                                       DatatypeMessageProvider.MSG_NONE,
302                                                                       new Object JavaDoc[] { "'" + content + "'" + " with fractionDigits = '"+ d.scale() +"'"
303                                                                           , "'" + fFractionDigits + "'"}));
304         }
305         if ( (fFacetsDefined & DatatypeValidator.FACET_TOTALDIGITS)!=0 ) {
306             int totalDigits = d.movePointRight(d.scale()).toString().length() -
307                               ((d.signum() < 0) ? 1 : 0); // account for minus sign
308
if ( totalDigits > fTotalDigits )
309                 throw new InvalidDatatypeValueException(
310                                                        getErrorString(DatatypeMessageProvider.TOTALDIGITS_EXCEEDED,
311                                                                       DatatypeMessageProvider.MSG_NONE,
312                                                                       new Object JavaDoc[] { "'" + content + "'" + " with totalDigits = '"+ totalDigits +"'"
313                                                                           , "'" + fTotalDigits + "'"} ));
314         }
315         boundsCheck(d);
316         if ( fEnumeration != null )
317             enumCheck(d, (BigDecimal JavaDoc[]) fEnumeration);
318
319         return;
320
321     }
322
323     /**
324      * This class deals with a bug in BigDecimal class
325      * present up to version 1.1.2. 1.1.3 knows how
326      * to deal with the + sign.
327      *
328      * This method strips the first '+' if it found
329      * alone such as.
330      * +33434.344
331      *
332      * If we find +- then nothing happens we just
333      * return the string passed
334      *
335      * @param value
336      * @return
337      */

338     static private String JavaDoc stripPlusIfPresent( String JavaDoc value ) {
339         String JavaDoc strippedPlus = value;
340
341         if ( value.length() >= 2 && value.charAt(0) == '+' && value.charAt(1) != '-' ) {
342             strippedPlus = value.substring(1);
343         }
344         return strippedPlus;
345     }
346
347     private void enumCheck(BigDecimal JavaDoc v, BigDecimal JavaDoc[] enumer) throws InvalidDatatypeValueException {
348         for ( int i = 0; i < enumer.length; i++ ) {
349             if ( v.equals(enumer[i] ) ) {
350                 return;
351             }
352         }
353         throw new InvalidDatatypeValueException(
354                                                getErrorString(DatatypeMessageProvider.NOT_ENUM_VALUE,
355                                                               DatatypeMessageProvider.MSG_NONE,
356                                                               new Object JavaDoc [] { v}));
357     }
358
359 }
360
Popular Tags