KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > dv > xs > DoubleDV


1 /*
2  * Copyright 2001-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.impl.dv.xs;
18
19 import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
20 import org.apache.xerces.impl.dv.ValidationContext;
21 import org.apache.xerces.xs.datatypes.XSDouble;
22
23 /**
24  * Represent the schema type "double"
25  *
26  * @xerces.internal
27  *
28  * @author Neeraj Bajaj, Sun Microsystems, inc.
29  * @author Sandy Gao, IBM
30  *
31  * @version $Id: DoubleDV.java,v 1.12 2005/07/14 04:20:14 mrglavas Exp $
32  */

33 public class DoubleDV extends TypeValidator {
34
35     public short getAllowedFacets(){
36         return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE );
37     }//getAllowedFacets()
38

39     //convert a String to Double form, we have to take care of cases specified in spec like INF, -INF and NaN
40
public Object JavaDoc getActualValue(String JavaDoc content, ValidationContext context) throws InvalidDatatypeValueException {
41         try{
42             return new XDouble(content);
43         } catch (NumberFormatException JavaDoc ex){
44             throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object JavaDoc[]{content, "double"});
45         }
46     }//getActualValue()
47

48     // Can't call Double#compareTo method, because it's introduced in jdk 1.2
49
public int compare(Object JavaDoc value1, Object JavaDoc value2) {
50         return ((XDouble)value1).compareTo((XDouble)value2);
51     }//compare()
52

53     //distinguishes between identity and equality for double datatype
54
//0.0 is equal but not identical to -0.0
55
public boolean isIdentical (Object JavaDoc value1, Object JavaDoc value2) {
56         if (value2 instanceof XDouble) {
57             return ((XDouble)value1).isIdentical((XDouble)value2);
58         }
59         return false;
60     }//isIdentical()
61

62     /**
63      * Returns true if it's possible that the given
64      * string represents a valid floating point value
65      * (excluding NaN, INF and -INF).
66      */

67     static boolean isPossibleFP(String JavaDoc val) {
68         final int length = val.length();
69         for (int i = 0; i < length; ++i) {
70             char c = val.charAt(i);
71             if (!(c >= '0' && c <= '9' || c == '.' ||
72                 c == '-' || c == '+' || c == 'E' || c == 'e')) {
73                 return false;
74             }
75         }
76         return true;
77     }
78
79     private static final class XDouble implements XSDouble {
80         private double value;
81         public XDouble(String JavaDoc s) throws NumberFormatException JavaDoc {
82             if (isPossibleFP(s)) {
83                 value = Double.parseDouble(s);
84             }
85             else if ( s.equals("INF") ) {
86                 value = Double.POSITIVE_INFINITY;
87             }
88             else if ( s.equals("-INF") ) {
89                 value = Double.NEGATIVE_INFINITY;
90             }
91             else if ( s.equals("NaN" ) ) {
92                 value = Double.NaN;
93             }
94             else {
95                 throw new NumberFormatException JavaDoc(s);
96             }
97         }
98
99         public boolean equals(Object JavaDoc val) {
100             if (val == this)
101                 return true;
102     
103             if (!(val instanceof XDouble))
104                 return false;
105             XDouble oval = (XDouble)val;
106
107             // NOTE: we don't distinguish 0.0 from -0.0
108
if (value == oval.value)
109                 return true;
110             
111             if (value != value && oval.value != oval.value)
112                 return true;
113
114             return false;
115         }
116         
117         // NOTE: 0.0 is equal but not identical to -0.0
118
public boolean isIdentical (XDouble val) {
119             if (val == this) {
120                 return true;
121             }
122             
123             if (value == val.value) {
124                 return (value != 0.0d ||
125                     (Double.doubleToLongBits(value) == Double.doubleToLongBits(val.value)));
126             }
127             
128             if (value != value && val.value != val.value)
129                 return true;
130
131             return false;
132         }
133
134         private int compareTo(XDouble val) {
135             double oval = val.value;
136
137             // this < other
138
if (value < oval)
139                 return -1;
140             // this > other
141
if (value > oval)
142                 return 1;
143             // this == other
144
// NOTE: we don't distinguish 0.0 from -0.0
145
if (value == oval)
146                 return 0;
147
148             // one of the 2 values or both is/are NaN(s)
149

150             if (value != value) {
151                 // this = NaN = other
152
if (oval != oval)
153                     return 0;
154                 // this is NaN <> other
155
return INDETERMINATE;
156             }
157
158             // other is NaN <> this
159
return INDETERMINATE;
160         }
161
162         private String JavaDoc canonical;
163         public synchronized String JavaDoc toString() {
164             if (canonical == null) {
165                 if (value == Double.POSITIVE_INFINITY)
166                     canonical = "INF";
167                 else if (value == Double.NEGATIVE_INFINITY)
168                     canonical = "-INF";
169                 else if (value != value)
170                     canonical = "NaN";
171                 // NOTE: we don't distinguish 0.0 from -0.0
172
else if (value == 0)
173                     canonical = "0.0E1";
174                 else {
175                     // REVISIT: use the java algorithm for now, because we
176
// don't know what to output for 1.1d (which is no
177
// actually 1.1)
178
canonical = Double.toString(value);
179                     // if it contains 'E', then it should be a valid schema
180
// canonical representation
181
if (canonical.indexOf('E') == -1) {
182                         int len = canonical.length();
183                         // at most 3 longer: E, -, 9
184
char[] chars = new char[len+3];
185                         canonical.getChars(0, len, chars, 0);
186                         // expected decimal point position
187
int edp = chars[0] == '-' ? 2 : 1;
188                         // for non-zero integer part
189
if (value >= 1 || value <= -1) {
190                             // decimal point position
191
int dp = canonical.indexOf('.');
192                             // move the digits: ddd.d --> d.ddd
193
for (int i = dp; i > edp; i--) {
194                                 chars[i] = chars[i-1];
195                             }
196                             chars[edp] = '.';
197                             // trim trailing zeros: d00.0 --> d.000 --> d.
198
while (chars[len-1] == '0')
199                                 len--;
200                             // add the last zero if necessary: d. --> d.0
201
if (chars[len-1] == '.')
202                                 len++;
203                             // append E: d.dd --> d.ddE
204
chars[len++] = 'E';
205                             // how far we shifted the decimal point
206
int shift = dp - edp;
207                             // append the exponent --> d.ddEd
208
// the exponent is at most 7
209
chars[len++] = (char)(shift + '0');
210                         }
211                         else {
212                             // non-zero digit point
213
int nzp = edp + 1;
214                             // skip zeros: 0.003
215
while (chars[nzp] == '0')
216                                 nzp++;
217                             // put the first non-zero digit to the left of '.'
218
chars[edp-1] = chars[nzp];
219                             chars[edp] = '.';
220                             // move other digits (non-zero) to the right of '.'
221
for (int i = nzp+1, j = edp+1; i < len; i++, j++)
222                                 chars[j] = chars[i];
223                             // adjust the length
224
len -= nzp - edp;
225                             // append 0 if nessary: 0.03 --> 3. --> 3.0
226
if (len == edp + 1)
227                                 chars[len++] = '0';
228                             // append E-: d.dd --> d.ddE-
229
chars[len++] = 'E';
230                             chars[len++] = '-';
231                             // how far we shifted the decimal point
232
int shift = nzp - edp;
233                             // append the exponent --> d.ddEd
234
// the exponent is at most 3
235
chars[len++] = (char)(shift + '0');
236                         }
237                         canonical = new String JavaDoc(chars, 0, len);
238                     }
239                 }
240             }
241             return canonical;
242         }
243         public double getValue() {
244             return value;
245         }
246     }
247 } // class DoubleDV
248
Popular Tags