KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > impl > dv > xs > DecimalDV


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001, 2002 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) 2001, 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 com.sun.org.apache.xerces.internal.impl.dv.xs;
59
60 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
61 import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext;
62
63 /**
64  * Represent the schema type "decimal"
65  *
66  * @author Neeraj Bajaj, Sun Microsystems, inc.
67  * @author Sandy Gao, IBM
68  *
69  * @version $Id: DecimalDV.java,v 1.9 2003/05/08 20:11:55 elena Exp $
70  */

71 public class DecimalDV extends TypeValidator {
72
73     public final short getAllowedFacets(){
74         return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE | XSSimpleTypeDecl.FACET_TOTALDIGITS | XSSimpleTypeDecl.FACET_FRACTIONDIGITS);
75     }
76
77     public Object JavaDoc getActualValue(String JavaDoc content, ValidationContext context) throws InvalidDatatypeValueException {
78         try {
79             return new XDecimal(content);
80         } catch (NumberFormatException JavaDoc nfe) {
81             throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object JavaDoc[]{content, "decimal"});
82         }
83     }
84
85     public final int compare(Object JavaDoc value1, Object JavaDoc value2){
86         return ((XDecimal)value1).compareTo((XDecimal)value2);
87     }
88
89     public final int getTotalDigits(Object JavaDoc value){
90         return ((XDecimal)value).totalDigits;
91     }
92
93     public final int getFractionDigits(Object JavaDoc value){
94         return ((XDecimal)value).fracDigits;
95     }
96     
97     // Avoid using the heavy-weight java.math.BigDecimal
98
static class XDecimal {
99         // sign: 0 for vlaue 0; 1 for positive values; -1 for negative values
100
int sign = 1;
101         // total digits. >= 1
102
int totalDigits = 0;
103         // integer digits when sign != 0
104
int intDigits = 0;
105         // fraction digits when sign != 0
106
int fracDigits = 0;
107         // the string representing the integer part
108
String JavaDoc ivalue = "";
109         // the string representing the fraction part
110
String JavaDoc fvalue = "";
111         // whether the canonical form contains decimal point
112
boolean integer = false;
113         
114         XDecimal(String JavaDoc content) throws NumberFormatException JavaDoc {
115             initD(content);
116         }
117         XDecimal(String JavaDoc content, boolean integer) throws NumberFormatException JavaDoc {
118             if (integer)
119                 initI(content);
120             else
121                 initD(content);
122         }
123         void initD(String JavaDoc content) throws NumberFormatException JavaDoc {
124             int len = content.length();
125             if (len == 0)
126                 throw new NumberFormatException JavaDoc();
127     
128             // these 4 variables are used to indicate where the integre/fraction
129
// parts start/end.
130
int intStart = 0, intEnd = 0, fracStart = 0, fracEnd = 0;
131             
132             // Deal with leading sign symbol if present
133
if (content.charAt(0) == '+') {
134                 // skip '+', so intStart should be 1
135
intStart = 1;
136             }
137             else if (content.charAt(0) == '-') {
138                 // keep '-', so intStart is stil 0
139
intStart = 1;
140                 sign = -1;
141             }
142     
143             // skip leading zeroes in integer part
144
int actualIntStart = intStart;
145             while (actualIntStart < len && content.charAt(actualIntStart) == '0') {
146                 actualIntStart++;
147             }
148     
149             // Find the ending position of the integer part
150
for (intEnd = actualIntStart;
151                  intEnd < len && TypeValidator.isDigit(content.charAt(intEnd));
152                  intEnd++);
153     
154             // Not reached the end yet
155
if (intEnd < len) {
156                 // the remaining part is not ".DDD", error
157
if (content.charAt(intEnd) != '.')
158                     throw new NumberFormatException JavaDoc();
159     
160                 // fraction part starts after '.', and ends at the end of the input
161
fracStart = intEnd + 1;
162                 fracEnd = len;
163             }
164     
165             // no integer part, no fraction part, error.
166
if (intStart == intEnd && fracStart == fracEnd)
167                 throw new NumberFormatException JavaDoc();
168     
169             // ignore trailing zeroes in fraction part
170
while (fracEnd > fracStart && content.charAt(fracEnd-1) == '0') {
171                 fracEnd--;
172             }
173     
174             // check whether there is non-digit characters in the fraction part
175
for (int fracPos = fracStart; fracPos < fracEnd; fracPos++) {
176                 if (!TypeValidator.isDigit(content.charAt(fracPos)))
177                     throw new NumberFormatException JavaDoc();
178             }
179     
180             intDigits = intEnd - actualIntStart;
181             fracDigits = fracEnd - fracStart;
182             totalDigits = intDigits + fracDigits;
183     
184             if (intDigits > 0) {
185                 ivalue = content.substring(actualIntStart, intEnd);
186                 if (fracDigits > 0)
187                     fvalue = content.substring(fracStart, fracEnd);
188             }
189             else {
190                 if (fracDigits > 0) {
191                     fvalue = content.substring(fracStart, fracEnd);
192                 }
193                 else {
194                     // ".00", treat it as "0"
195
sign = 0;
196                 }
197             }
198         }
199         void initI(String JavaDoc content) throws NumberFormatException JavaDoc {
200             int len = content.length();
201             if (len == 0)
202                 throw new NumberFormatException JavaDoc();
203     
204             // these 2 variables are used to indicate where the integre start/end.
205
int intStart = 0, intEnd = 0;
206     
207             // Deal with leading sign symbol if present
208
if (content.charAt(0) == '+') {
209                 // skip '+', so intStart should be 1
210
intStart = 1;
211             }
212             else if (content.charAt(0) == '-') {
213                 // keep '-', so intStart is stil 0
214
intStart = 1;
215                 sign = -1;
216             }
217     
218             // skip leading zeroes in integer part
219
int actualIntStart = intStart;
220             while (actualIntStart < len && content.charAt(actualIntStart) == '0') {
221                 actualIntStart++;
222             }
223     
224             // Find the ending position of the integer part
225
for (intEnd = actualIntStart;
226                  intEnd < len && TypeValidator.isDigit(content.charAt(intEnd));
227                  intEnd++);
228     
229             // Not reached the end yet, error
230
if (intEnd < len)
231                 throw new NumberFormatException JavaDoc();
232     
233             // no integer part, error.
234
if (intStart == intEnd)
235                 throw new NumberFormatException JavaDoc();
236     
237             intDigits = intEnd - actualIntStart;
238             fracDigits = 0;
239             totalDigits = intDigits;
240     
241             if (intDigits > 0) {
242                 ivalue = content.substring(actualIntStart, intEnd);
243             }
244             else {
245                 // "00", treat it as "0"
246
sign = 0;
247             }
248             
249             integer = true;
250         }
251         public boolean equals(Object JavaDoc val) {
252             if (val == this)
253                 return true;
254     
255             if (!(val instanceof XDecimal))
256                 return false;
257             XDecimal oval = (XDecimal)val;
258             
259             if (sign != oval.sign)
260                return false;
261             if (sign == 0)
262                 return true;
263             
264             return intDigits == oval.intDigits && fracDigits == oval.fracDigits &&
265                    ivalue.equals(oval.ivalue) && fvalue.equals(oval.fvalue);
266         }
267         public int compareTo(XDecimal val) {
268             if (sign != val.sign)
269                 return sign > val.sign ? 1 : -1;
270             if (sign == 0)
271                 return 0;
272             return sign * intComp(val);
273         }
274         private int intComp(XDecimal val) {
275             if (intDigits != val.intDigits)
276                 return intDigits > val.intDigits ? 1 : -1;
277             int ret = ivalue.compareTo(val.ivalue);
278             if (ret != 0)
279                 return ret > 0 ? 1 : -1;;
280             ret = fvalue.compareTo(val.fvalue);
281             return ret == 0 ? 0 : (ret > 0 ? 1 : -1);
282         }
283         private String JavaDoc canonical;
284         public synchronized String JavaDoc toString() {
285             if (canonical == null) {
286                 makeCanonical();
287             }
288             return canonical;
289         }
290         
291         private void makeCanonical() {
292             if (sign == 0) {
293                 if (integer)
294                     canonical = "0";
295                 else
296                     canonical = "0.0";
297                 return;
298             }
299             if (integer && sign > 0) {
300                 canonical = ivalue;
301                 return;
302             }
303             // for -0.1, total digits is 1, so we need 3 extra spots
304
StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(totalDigits+3);
305             if (sign == -1)
306                 buffer.append('-');
307             if (intDigits != 0)
308                 buffer.append(ivalue);
309             else
310                 buffer.append('0');
311             if (!integer) {
312                 buffer.append('.');
313                 if (fracDigits != 0) {
314                     buffer.append(fvalue);
315                 }
316                 else {
317                     buffer.append('0');
318                 }
319             }
320             canonical = buffer.toString();
321         }
322     }
323 } // class DecimalDV
324

325
Popular Tags