jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/PrecisionDecimalDV.java
changeset 17538 d8d911c4e5d4
parent 12457 c348e06f0e82
equal deleted inserted replaced
17537:50528ec0ea37 17538:d8d911c4e5d4
    30  * @author Ankit Pasricha, IBM
    30  * @author Ankit Pasricha, IBM
    31  *
    31  *
    32  */
    32  */
    33 class PrecisionDecimalDV extends TypeValidator {
    33 class PrecisionDecimalDV extends TypeValidator {
    34 
    34 
    35     static class XPrecisionDecimal {
    35     static final class XPrecisionDecimal {
    36 
    36 
    37         // sign: 0 for absent; 1 for positive values; -1 for negative values (except in case of INF, -INF)
    37         // sign: 0 for absent; 1 for positive values; -1 for negative values (except in case of INF, -INF)
    38         int sign = 1;
    38         int sign = 1;
    39         // total digits. >= 1
    39         // total digits. >= 1
    40         int totalDigits = 0;
    40         int totalDigits = 0;
   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          */
   293             return ret == 0 ? EQUAL : (ret > 0 ? GREATER_THAN : LESS_THAN);
   371             return ret == 0 ? EQUAL : (ret > 0 ? GREATER_THAN : LESS_THAN);
   294         }
   372         }
   295 
   373 
   296         private String canonical;
   374         private String canonical;
   297 
   375 
       
   376         @Override
   298         public synchronized String toString() {
   377         public synchronized String toString() {
   299             if (canonical == null) {
   378             if (canonical == null) {
   300                 makeCanonical();
   379                 makeCanonical();
   301             }
   380             }
   302             return canonical;
   381             return canonical;
   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     }