286N/A/*
286N/A * reserved comment block
286N/A * DO NOT REMOVE OR ALTER!
286N/A */
286N/A/*
286N/A * Copyright 2001-2005 The Apache Software Foundation.
286N/A *
286N/A * Licensed under the Apache License, Version 2.0 (the "License");
286N/A * you may not use this file except in compliance with the License.
286N/A * You may obtain a copy of the License at
286N/A *
286N/A * http://www.apache.org/licenses/LICENSE-2.0
286N/A *
286N/A * Unless required by applicable law or agreed to in writing, software
286N/A * distributed under the License is distributed on an "AS IS" BASIS,
286N/A * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
286N/A * See the License for the specific language governing permissions and
286N/A * limitations under the License.
286N/A */
286N/A
286N/Apackage com.sun.org.apache.xerces.internal.impl.dv.xs;
286N/A
286N/Aimport com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
286N/Aimport com.sun.org.apache.xerces.internal.impl.dv.ValidationContext;
286N/Aimport com.sun.org.apache.xerces.internal.xs.datatypes.XSFloat;
286N/A
286N/A/**
286N/A * Represent the schema type "float"
286N/A *
286N/A * @xerces.internal
286N/A *
286N/A * @author Neeraj Bajaj, Sun Microsystems, inc.
286N/A * @author Sandy Gao, IBM
286N/A *
286N/A * @version $Id: FloatDV.java,v 1.7 2010-11-01 04:39:47 joehw Exp $
286N/A */
286N/Apublic class FloatDV extends TypeValidator {
286N/A
286N/A public short getAllowedFacets(){
286N/A return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE );
286N/A }//getAllowedFacets()
286N/A
286N/A //convert a String to Float form, we have to take care of cases specified in spec like INF, -INF and NaN
286N/A public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException {
286N/A try{
286N/A return new XFloat(content);
286N/A } catch (NumberFormatException ex){
286N/A throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "float"});
286N/A }
286N/A }//getActualValue()
286N/A
286N/A // Can't call Float#compareTo method, because it's introduced in jdk 1.2
286N/A public int compare(Object value1, Object value2){
286N/A return ((XFloat)value1).compareTo((XFloat)value2);
286N/A }//compare()
286N/A
286N/A //distinguishes between identity and equality for float datatype
286N/A //0.0 is equal but not identical to -0.0
286N/A public boolean isIdentical (Object value1, Object value2) {
286N/A if (value2 instanceof XFloat) {
286N/A return ((XFloat)value1).isIdentical((XFloat)value2);
286N/A }
286N/A return false;
286N/A }//isIdentical()
286N/A
286N/A private static final class XFloat implements XSFloat {
286N/A
286N/A private final float value;
286N/A public XFloat(String s) throws NumberFormatException {
286N/A if (DoubleDV.isPossibleFP(s)) {
286N/A value = Float.parseFloat(s);
286N/A }
286N/A else if ( s.equals("INF") ) {
286N/A value = Float.POSITIVE_INFINITY;
286N/A }
286N/A else if ( s.equals("-INF") ) {
286N/A value = Float.NEGATIVE_INFINITY;
286N/A }
286N/A else if ( s.equals("NaN") ) {
286N/A value = Float.NaN;
286N/A }
286N/A else {
286N/A throw new NumberFormatException(s);
286N/A }
286N/A }
286N/A
286N/A public boolean equals(Object val) {
286N/A if (val == this)
286N/A return true;
286N/A
286N/A if (!(val instanceof XFloat))
286N/A return false;
286N/A XFloat oval = (XFloat)val;
286N/A
286N/A // NOTE: we don't distinguish 0.0 from -0.0
286N/A if (value == oval.value)
286N/A return true;
286N/A
286N/A if (value != value && oval.value != oval.value)
286N/A return true;
286N/A
286N/A return false;
286N/A }
286N/A
286N/A public int hashCode() {
286N/A // This check is necessary because floatToIntBits(+0) != floatToIntBits(-0)
286N/A return (value == 0f) ? 0 : Float.floatToIntBits(value);
286N/A }
286N/A
286N/A // NOTE: 0.0 is equal but not identical to -0.0
286N/A public boolean isIdentical (XFloat val) {
286N/A if (val == this) {
286N/A return true;
286N/A }
286N/A
286N/A if (value == val.value) {
286N/A return (value != 0.0f ||
286N/A (Float.floatToIntBits(value) == Float.floatToIntBits(val.value)));
286N/A }
286N/A
286N/A if (value != value && val.value != val.value)
286N/A return true;
286N/A
286N/A return false;
286N/A }
286N/A
286N/A private int compareTo(XFloat val) {
286N/A float oval = val.value;
286N/A
286N/A // this < other
286N/A if (value < oval)
286N/A return -1;
286N/A // this > other
286N/A if (value > oval)
286N/A return 1;
286N/A // this == other
286N/A // NOTE: we don't distinguish 0.0 from -0.0
286N/A if (value == oval)
286N/A return 0;
286N/A
286N/A // one of the 2 values or both is/are NaN(s)
286N/A
286N/A if (value != value) {
286N/A // this = NaN = other
286N/A if (oval != oval)
286N/A return 0;
286N/A // this is NaN <> other
286N/A return INDETERMINATE;
286N/A }
286N/A
286N/A // other is NaN <> this
286N/A return INDETERMINATE;
286N/A }
286N/A
286N/A private String canonical;
286N/A public synchronized String toString() {
286N/A if (canonical == null) {
286N/A if (value == Float.POSITIVE_INFINITY)
286N/A canonical = "INF";
286N/A else if (value == Float.NEGATIVE_INFINITY)
286N/A canonical = "-INF";
286N/A else if (value != value)
286N/A canonical = "NaN";
286N/A // NOTE: we don't distinguish 0.0 from -0.0
286N/A else if (value == 0)
286N/A canonical = "0.0E1";
286N/A else {
286N/A // REVISIT: use the java algorithm for now, because we
286N/A // don't know what to output for 1.1f (which is no
286N/A // actually 1.1)
286N/A canonical = Float.toString(value);
286N/A // if it contains 'E', then it should be a valid schema
286N/A // canonical representation
286N/A if (canonical.indexOf('E') == -1) {
286N/A int len = canonical.length();
286N/A // at most 3 longer: E, -, 9
286N/A char[] chars = new char[len+3];
286N/A canonical.getChars(0, len, chars, 0);
286N/A // expected decimal point position
286N/A int edp = chars[0] == '-' ? 2 : 1;
286N/A // for non-zero integer part
286N/A if (value >= 1 || value <= -1) {
286N/A // decimal point position
286N/A int dp = canonical.indexOf('.');
286N/A // move the digits: ddd.d --> d.ddd
286N/A for (int i = dp; i > edp; i--) {
286N/A chars[i] = chars[i-1];
286N/A }
286N/A chars[edp] = '.';
286N/A // trim trailing zeros: d00.0 --> d.000 --> d.
286N/A while (chars[len-1] == '0')
286N/A len--;
286N/A // add the last zero if necessary: d. --> d.0
286N/A if (chars[len-1] == '.')
286N/A len++;
286N/A // append E: d.dd --> d.ddE
286N/A chars[len++] = 'E';
286N/A // how far we shifted the decimal point
286N/A int shift = dp - edp;
286N/A // append the exponent --> d.ddEd
286N/A // the exponent is at most 7
286N/A chars[len++] = (char)(shift + '0');
286N/A }
286N/A else {
286N/A // non-zero digit point
286N/A int nzp = edp + 1;
286N/A // skip zeros: 0.003
286N/A while (chars[nzp] == '0')
286N/A nzp++;
286N/A // put the first non-zero digit to the left of '.'
286N/A chars[edp-1] = chars[nzp];
286N/A chars[edp] = '.';
286N/A // move other digits (non-zero) to the right of '.'
286N/A for (int i = nzp+1, j = edp+1; i < len; i++, j++)
286N/A chars[j] = chars[i];
286N/A // adjust the length
286N/A len -= nzp - edp;
286N/A // append 0 if nessary: 0.03 --> 3. --> 3.0
286N/A if (len == edp + 1)
286N/A chars[len++] = '0';
286N/A // append E-: d.dd --> d.ddE-
286N/A chars[len++] = 'E';
286N/A chars[len++] = '-';
286N/A // how far we shifted the decimal point
286N/A int shift = nzp - edp;
286N/A // append the exponent --> d.ddEd
286N/A // the exponent is at most 3
286N/A chars[len++] = (char)(shift + '0');
286N/A }
286N/A canonical = new String(chars, 0, len);
286N/A }
286N/A }
286N/A }
286N/A return canonical;
286N/A }
286N/A
286N/A public float getValue() {
286N/A return value;
286N/A }
286N/A }
286N/A} // class FloatDV