jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/PrecisionDecimalDV.java

Print this page




  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package com.sun.org.apache.xerces.internal.impl.dv.xs;
  21 
  22 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  23 import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext;
  24 
  25 /**
  26  * Validator for <precisionDecimal> datatype (W3C Schema 1.1)
  27  *
  28  * @xerces.experimental
  29  *
  30  * @author Ankit Pasricha, IBM
  31  *
  32  */
  33 class PrecisionDecimalDV extends TypeValidator {
  34 
  35     static class XPrecisionDecimal {
  36 
  37         // sign: 0 for absent; 1 for positive values; -1 for negative values (except in case of INF, -INF)
  38         int sign = 1;
  39         // total digits. >= 1
  40         int totalDigits = 0;
  41         // integer digits when sign != 0
  42         int intDigits = 0;
  43         // fraction digits when sign != 0
  44         int fracDigits = 0;
  45         //precision
  46         //int precision = 0;
  47         // the string representing the integer part
  48         String ivalue = "";
  49         // the string representing the fraction part
  50         String fvalue = "";
  51 
  52         int pvalue = 0;
  53 
  54 
  55         XPrecisionDecimal(String content) throws NumberFormatException {


 127                 if (!TypeValidator.isDigit(content.charAt(fracPos)))
 128                     throw new NumberFormatException();
 129             }
 130 
 131             intDigits = intEnd - actualIntStart;
 132             fracDigits = fracEnd - fracStart;
 133 
 134             if (intDigits > 0) {
 135                 ivalue = content.substring(actualIntStart, intEnd);
 136             }
 137 
 138             if (fracDigits > 0) {
 139                 fvalue = content.substring(fracStart, fracEnd);
 140                 if(fracEnd < len) {
 141                     pvalue = Integer.parseInt(content.substring(fracEnd + 1, len));
 142                 }
 143             }
 144             totalDigits = intDigits + fracDigits;
 145         }
 146 































































 147 

 148         public boolean equals(Object val) {
 149             if (val == this)
 150                 return true;
 151 
 152             if (!(val instanceof XPrecisionDecimal))
 153                 return false;
 154             XPrecisionDecimal oval = (XPrecisionDecimal)val;
 155 
 156             return this.compareTo(oval) == EQUAL;
 157         }
 158 














 159         /**
 160          * @return
 161          */
 162         private int compareFractionalPart(XPrecisionDecimal oval) {
 163             if(fvalue.equals(oval.fvalue))
 164                 return EQUAL;
 165 
 166             StringBuffer temp1 = new StringBuffer(fvalue);
 167             StringBuffer temp2 = new StringBuffer(oval.fvalue);
 168 
 169             truncateTrailingZeros(temp1, temp2);
 170             return temp1.toString().compareTo(temp2.toString());
 171         }
 172 
 173         private void truncateTrailingZeros(StringBuffer fValue, StringBuffer otherFValue) {
 174             for(int i = fValue.length() - 1;i >= 0; i--)
 175                 if(fValue.charAt(i) == '0')
 176                     fValue.deleteCharAt(i);
 177                 else
 178                     break;


 278          * @return
 279          */
 280         private int compareDecimal(String iValue, String fValue, String otherIValue, String otherFValue) {
 281             int ret = iValue.compareTo(otherIValue);
 282             if (ret != 0)
 283                 return ret > 0 ? GREATER_THAN : LESS_THAN;
 284 
 285             if(fValue.equals(otherFValue))
 286                 return EQUAL;
 287 
 288             StringBuffer temp1=new StringBuffer(fValue);
 289             StringBuffer temp2=new StringBuffer(otherFValue);
 290 
 291             truncateTrailingZeros(temp1, temp2);
 292             ret = temp1.toString().compareTo(temp2.toString());
 293             return ret == 0 ? EQUAL : (ret > 0 ? GREATER_THAN : LESS_THAN);
 294         }
 295 
 296         private String canonical;
 297 

 298         public synchronized String toString() {
 299             if (canonical == null) {
 300                 makeCanonical();
 301             }
 302             return canonical;
 303         }
 304 
 305         private void makeCanonical() {
 306             // REVISIT: to be determined by working group
 307             canonical = "TBD by Working Group";
 308         }
 309 
 310         /**
 311          * @param decimal
 312          * @return
 313          */
 314         public boolean isIdentical(XPrecisionDecimal decimal) {
 315             if(ivalue.equals(decimal.ivalue) && (ivalue.equals("INF") || ivalue.equals("-INF") || ivalue.equals("NaN")))
 316                 return true;
 317 
 318             if(sign == decimal.sign && intDigits == decimal.intDigits && fracDigits == decimal.fracDigits && pvalue == decimal.pvalue
 319                     && ivalue.equals(decimal.ivalue) && fvalue.equals(decimal.fvalue))
 320                 return true;
 321             return false;
 322         }
 323 
 324     }
 325     /* (non-Javadoc)
 326      * @see com.sun.org.apache.xerces.internal.impl.dv.xs.TypeValidator#getAllowedFacets()
 327      */

 328     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);
 330     }
 331 
 332     /* (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)
 334      */

 335     public Object getActualValue(String content, ValidationContext context)
 336     throws InvalidDatatypeValueException {
 337         try {
 338             return new XPrecisionDecimal(content);
 339         } catch (NumberFormatException nfe) {
 340             throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "precisionDecimal"});
 341         }
 342     }
 343 

 344     public int compare(Object value1, Object value2) {
 345         return ((XPrecisionDecimal)value1).compareTo((XPrecisionDecimal)value2);
 346     }
 347 

 348     public int getFractionDigits(Object value) {
 349         return ((XPrecisionDecimal)value).fracDigits;
 350     }
 351 

 352     public int getTotalDigits(Object value) {
 353         return ((XPrecisionDecimal)value).totalDigits;
 354     }
 355 

 356     public boolean isIdentical(Object value1, Object value2) {
 357         if(!(value2 instanceof XPrecisionDecimal) || !(value1 instanceof XPrecisionDecimal))
 358             return false;
 359         return ((XPrecisionDecimal)value1).isIdentical((XPrecisionDecimal)value2);
 360     }
 361 }


  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package com.sun.org.apache.xerces.internal.impl.dv.xs;
  21 
  22 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  23 import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext;
  24 
  25 /**
  26  * Validator for <precisionDecimal> datatype (W3C Schema 1.1)
  27  *
  28  * @xerces.experimental
  29  *
  30  * @author Ankit Pasricha, IBM
  31  *
  32  */
  33 class PrecisionDecimalDV extends TypeValidator {
  34 
  35     static final class XPrecisionDecimal {
  36 
  37         // sign: 0 for absent; 1 for positive values; -1 for negative values (except in case of INF, -INF)
  38         int sign = 1;
  39         // total digits. >= 1
  40         int totalDigits = 0;
  41         // integer digits when sign != 0
  42         int intDigits = 0;
  43         // fraction digits when sign != 0
  44         int fracDigits = 0;
  45         //precision
  46         //int precision = 0;
  47         // the string representing the integer part
  48         String ivalue = "";
  49         // the string representing the fraction part
  50         String fvalue = "";
  51 
  52         int pvalue = 0;
  53 
  54 
  55         XPrecisionDecimal(String content) throws NumberFormatException {


 127                 if (!TypeValidator.isDigit(content.charAt(fracPos)))
 128                     throw new NumberFormatException();
 129             }
 130 
 131             intDigits = intEnd - actualIntStart;
 132             fracDigits = fracEnd - fracStart;
 133 
 134             if (intDigits > 0) {
 135                 ivalue = content.substring(actualIntStart, intEnd);
 136             }
 137 
 138             if (fracDigits > 0) {
 139                 fvalue = content.substring(fracStart, fracEnd);
 140                 if(fracEnd < len) {
 141                     pvalue = Integer.parseInt(content.substring(fracEnd + 1, len));
 142                 }
 143             }
 144             totalDigits = intDigits + fracDigits;
 145         }
 146 
 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
 212         public boolean equals(Object val) {
 213             if (val == this)
 214                 return true;
 215 
 216             if (!(val instanceof XPrecisionDecimal))
 217                 return false;
 218             XPrecisionDecimal oval = (XPrecisionDecimal)val;
 219 
 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();
 235         }
 236 
 237         /**
 238          * @return
 239          */
 240         private int compareFractionalPart(XPrecisionDecimal oval) {
 241             if(fvalue.equals(oval.fvalue))
 242                 return EQUAL;
 243 
 244             StringBuffer temp1 = new StringBuffer(fvalue);
 245             StringBuffer temp2 = new StringBuffer(oval.fvalue);
 246 
 247             truncateTrailingZeros(temp1, temp2);
 248             return temp1.toString().compareTo(temp2.toString());
 249         }
 250 
 251         private void truncateTrailingZeros(StringBuffer fValue, StringBuffer otherFValue) {
 252             for(int i = fValue.length() - 1;i >= 0; i--)
 253                 if(fValue.charAt(i) == '0')
 254                     fValue.deleteCharAt(i);
 255                 else
 256                     break;


 356          * @return
 357          */
 358         private int compareDecimal(String iValue, String fValue, String otherIValue, String otherFValue) {
 359             int ret = iValue.compareTo(otherIValue);
 360             if (ret != 0)
 361                 return ret > 0 ? GREATER_THAN : LESS_THAN;
 362 
 363             if(fValue.equals(otherFValue))
 364                 return EQUAL;
 365 
 366             StringBuffer temp1=new StringBuffer(fValue);
 367             StringBuffer temp2=new StringBuffer(otherFValue);
 368 
 369             truncateTrailingZeros(temp1, temp2);
 370             ret = temp1.toString().compareTo(temp2.toString());
 371             return ret == 0 ? EQUAL : (ret > 0 ? GREATER_THAN : LESS_THAN);
 372         }
 373 
 374         private String canonical;
 375 
 376         @Override
 377         public synchronized String toString() {
 378             if (canonical == null) {
 379                 makeCanonical();
 380             }
 381             return canonical;
 382         }
 383 
 384         private void makeCanonical() {
 385             // REVISIT: to be determined by working group
 386             canonical = "TBD by Working Group";
 387         }
 388 
 389         /**
 390          * @param decimal
 391          * @return
 392          */
 393         public boolean isIdentical(XPrecisionDecimal decimal) {
 394             if(ivalue.equals(decimal.ivalue) && (ivalue.equals("INF") || ivalue.equals("-INF") || ivalue.equals("NaN")))
 395                 return true;
 396 
 397             if(sign == decimal.sign && intDigits == decimal.intDigits && fracDigits == decimal.fracDigits && pvalue == decimal.pvalue
 398                     && ivalue.equals(decimal.ivalue) && fvalue.equals(decimal.fvalue))
 399                 return true;
 400             return false;
 401         }
 402 
 403     }
 404     /* (non-Javadoc)
 405      * @see com.sun.org.apache.xerces.internal.impl.dv.xs.TypeValidator#getAllowedFacets()
 406      */
 407     @Override
 408     public short getAllowedFacets() {
 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);
 410     }
 411 
 412     /* (non-Javadoc)
 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)
 414      */
 415     @Override
 416     public Object getActualValue(String content, ValidationContext context)
 417     throws InvalidDatatypeValueException {
 418         try {
 419             return new XPrecisionDecimal(content);
 420         } catch (NumberFormatException nfe) {
 421             throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "precisionDecimal"});
 422         }
 423     }
 424 
 425     @Override
 426     public int compare(Object value1, Object value2) {
 427         return ((XPrecisionDecimal)value1).compareTo((XPrecisionDecimal)value2);
 428     }
 429 
 430     @Override
 431     public int getFractionDigits(Object value) {
 432         return ((XPrecisionDecimal)value).fracDigits;
 433     }
 434 
 435     @Override
 436     public int getTotalDigits(Object value) {
 437         return ((XPrecisionDecimal)value).totalDigits;
 438     }
 439 
 440     @Override
 441     public boolean isIdentical(Object value1, Object value2) {
 442         if(!(value2 instanceof XPrecisionDecimal) || !(value1 instanceof XPrecisionDecimal))
 443             return false;
 444         return ((XPrecisionDecimal)value1).isIdentical((XPrecisionDecimal)value2);
 445     }
 446 }