142 } |
142 } |
143 } |
143 } |
144 totalDigits = intDigits + fracDigits; |
144 totalDigits = intDigits + fracDigits; |
145 } |
145 } |
146 |
146 |
147 |
147 // Construct a canonical String representation of this number |
|
148 // for the purpose of deriving a hashCode value compliant with |
|
149 // equals. |
|
150 // The toString representation will be: |
|
151 // NaN for NaN, INF for +infinity, -INF for -infinity, 0 for zero, |
|
152 // and [1-9].[0-9]*[1-9]?(E[1-9][0-9]*)? for other numbers. |
|
153 private static String canonicalToStringForHashCode(String ivalue, String fvalue, int sign, int pvalue) { |
|
154 if ("NaN".equals(ivalue)) { |
|
155 return "NaN"; |
|
156 } |
|
157 if ("INF".equals(ivalue)) { |
|
158 return sign < 0 ? "-INF" : "INF"; |
|
159 } |
|
160 final StringBuilder builder = new StringBuilder(); |
|
161 final int ilen = ivalue.length(); |
|
162 final int flen0 = fvalue.length(); |
|
163 int lastNonZero; |
|
164 for (lastNonZero = flen0; lastNonZero > 0 ; lastNonZero--) { |
|
165 if (fvalue.charAt(lastNonZero -1 ) != '0') break; |
|
166 } |
|
167 final int flen = lastNonZero; |
|
168 int iStart; |
|
169 int exponent = pvalue; |
|
170 for (iStart = 0; iStart < ilen; iStart++) { |
|
171 if (ivalue.charAt(iStart) != '0') break; |
|
172 } |
|
173 int fStart = 0; |
|
174 if (iStart < ivalue.length()) { |
|
175 builder.append(sign == -1 ? "-" : ""); |
|
176 builder.append(ivalue.charAt(iStart)); |
|
177 iStart++; |
|
178 } else { |
|
179 if (flen > 0) { |
|
180 for (fStart = 0; fStart < flen; fStart++) { |
|
181 if (fvalue.charAt(fStart) != '0') break; |
|
182 } |
|
183 if (fStart < flen) { |
|
184 builder.append(sign == -1 ? "-" : ""); |
|
185 builder.append(fvalue.charAt(fStart)); |
|
186 exponent -= ++fStart; |
|
187 } else { |
|
188 return "0"; |
|
189 } |
|
190 } else { |
|
191 return "0"; |
|
192 } |
|
193 } |
|
194 |
|
195 if (iStart < ilen || fStart < flen) { |
|
196 builder.append('.'); |
|
197 } |
|
198 while (iStart < ilen) { |
|
199 builder.append(ivalue.charAt(iStart++)); |
|
200 exponent++; |
|
201 } |
|
202 while (fStart < flen) { |
|
203 builder.append(fvalue.charAt(fStart++)); |
|
204 } |
|
205 if (exponent != 0) { |
|
206 builder.append("E").append(exponent); |
|
207 } |
|
208 return builder.toString(); |
|
209 } |
|
210 |
|
211 @Override |
148 public boolean equals(Object val) { |
212 public boolean equals(Object val) { |
149 if (val == this) |
213 if (val == this) |
150 return true; |
214 return true; |
151 |
215 |
152 if (!(val instanceof XPrecisionDecimal)) |
216 if (!(val instanceof XPrecisionDecimal)) |
153 return false; |
217 return false; |
154 XPrecisionDecimal oval = (XPrecisionDecimal)val; |
218 XPrecisionDecimal oval = (XPrecisionDecimal)val; |
155 |
219 |
156 return this.compareTo(oval) == EQUAL; |
220 return this.compareTo(oval) == EQUAL; |
|
221 } |
|
222 |
|
223 @Override |
|
224 public int hashCode() { |
|
225 // There's nothing else we can use easily, because equals could |
|
226 // return true for widely different representation of the |
|
227 // same number - and we don't have any canonical representation. |
|
228 // The problem here is that we must ensure that if two numbers |
|
229 // are equals then their hash code must also be equals. |
|
230 // hashCode for 1.01E1 should be the same as hashCode for 0.101E2 |
|
231 // So we call cannonicalToStringForHashCode - which implements an |
|
232 // algorithm that invents a normalized string representation |
|
233 // for this number, and we return a hash for that. |
|
234 return canonicalToStringForHashCode(ivalue, fvalue, sign, pvalue).hashCode(); |
157 } |
235 } |
158 |
236 |
159 /** |
237 /** |
160 * @return |
238 * @return |
161 */ |
239 */ |
323 |
402 |
324 } |
403 } |
325 /* (non-Javadoc) |
404 /* (non-Javadoc) |
326 * @see com.sun.org.apache.xerces.internal.impl.dv.xs.TypeValidator#getAllowedFacets() |
405 * @see com.sun.org.apache.xerces.internal.impl.dv.xs.TypeValidator#getAllowedFacets() |
327 */ |
406 */ |
|
407 @Override |
328 public short getAllowedFacets() { |
408 public short getAllowedFacets() { |
329 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); |
409 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); |
330 } |
410 } |
331 |
411 |
332 /* (non-Javadoc) |
412 /* (non-Javadoc) |
333 * @see com.sun.org.apache.xerces.internal.impl.dv.xs.TypeValidator#getActualValue(java.lang.String, com.sun.org.apache.xerces.internal.impl.dv.ValidationContext) |
413 * @see com.sun.org.apache.xerces.internal.impl.dv.xs.TypeValidator#getActualValue(java.lang.String, com.sun.org.apache.xerces.internal.impl.dv.ValidationContext) |
334 */ |
414 */ |
|
415 @Override |
335 public Object getActualValue(String content, ValidationContext context) |
416 public Object getActualValue(String content, ValidationContext context) |
336 throws InvalidDatatypeValueException { |
417 throws InvalidDatatypeValueException { |
337 try { |
418 try { |
338 return new XPrecisionDecimal(content); |
419 return new XPrecisionDecimal(content); |
339 } catch (NumberFormatException nfe) { |
420 } catch (NumberFormatException nfe) { |
340 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "precisionDecimal"}); |
421 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "precisionDecimal"}); |
341 } |
422 } |
342 } |
423 } |
343 |
424 |
|
425 @Override |
344 public int compare(Object value1, Object value2) { |
426 public int compare(Object value1, Object value2) { |
345 return ((XPrecisionDecimal)value1).compareTo((XPrecisionDecimal)value2); |
427 return ((XPrecisionDecimal)value1).compareTo((XPrecisionDecimal)value2); |
346 } |
428 } |
347 |
429 |
|
430 @Override |
348 public int getFractionDigits(Object value) { |
431 public int getFractionDigits(Object value) { |
349 return ((XPrecisionDecimal)value).fracDigits; |
432 return ((XPrecisionDecimal)value).fracDigits; |
350 } |
433 } |
351 |
434 |
|
435 @Override |
352 public int getTotalDigits(Object value) { |
436 public int getTotalDigits(Object value) { |
353 return ((XPrecisionDecimal)value).totalDigits; |
437 return ((XPrecisionDecimal)value).totalDigits; |
354 } |
438 } |
355 |
439 |
|
440 @Override |
356 public boolean isIdentical(Object value1, Object value2) { |
441 public boolean isIdentical(Object value1, Object value2) { |
357 if(!(value2 instanceof XPrecisionDecimal) || !(value1 instanceof XPrecisionDecimal)) |
442 if(!(value2 instanceof XPrecisionDecimal) || !(value1 instanceof XPrecisionDecimal)) |
358 return false; |
443 return false; |
359 return ((XPrecisionDecimal)value1).isIdentical((XPrecisionDecimal)value2); |
444 return ((XPrecisionDecimal)value1).isIdentical((XPrecisionDecimal)value2); |
360 } |
445 } |