1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2001-2005 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 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 21 package com.sun.org.apache.xerces.internal.impl.dv.xs; 22 23 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException; 24 import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext; 25 import com.sun.org.apache.xerces.internal.xs.datatypes.XSFloat; 26 27 /** 28 * Represent the schema type "float" 29 * 30 * @xerces.internal 31 * 32 * @author Neeraj Bajaj, Sun Microsystems, inc. 33 * @author Sandy Gao, IBM 34 * 35 */ 36 public class FloatDV extends TypeValidator { 37 38 public short getAllowedFacets(){ 39 return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE ); 40 }//getAllowedFacets() 41 42 //convert a String to Float form, we have to take care of cases specified in spec like INF, -INF and NaN 43 public Object getActualValue(String content, ValidationContext context) throws InvalidDatatypeValueException { 44 try{ 45 return new XFloat(content); 46 } catch (NumberFormatException ex){ 47 throw new InvalidDatatypeValueException("cvc-datatype-valid.1.2.1", new Object[]{content, "float"}); 48 } 49 }//getActualValue() 50 51 // Can't call Float#compareTo method, because it's introduced in jdk 1.2 52 public int compare(Object value1, Object value2){ 53 return ((XFloat)value1).compareTo((XFloat)value2); 54 }//compare() 55 56 //distinguishes between identity and equality for float datatype 57 //0.0 is equal but not identical to -0.0 58 public boolean isIdentical (Object value1, Object value2) { 59 if (value2 instanceof XFloat) { 60 return ((XFloat)value1).isIdentical((XFloat)value2); 61 } 62 return false; 63 }//isIdentical() 64 65 private static final class XFloat implements XSFloat { 66 67 private final float value; 68 public XFloat(String s) throws NumberFormatException { 69 if (DoubleDV.isPossibleFP(s)) { 70 value = Float.parseFloat(s); 71 } 72 else if ( s.equals("INF") ) { 73 value = Float.POSITIVE_INFINITY; 74 } 75 else if ( s.equals("-INF") ) { 76 value = Float.NEGATIVE_INFINITY; 77 } 78 else if ( s.equals("NaN") ) { 79 value = Float.NaN; 80 } 81 else { 82 throw new NumberFormatException(s); 83 } 84 } 85 86 public boolean equals(Object val) { 87 if (val == this) 88 return true; 89 90 if (!(val instanceof XFloat)) 91 return false; 92 XFloat oval = (XFloat)val; 93 94 // NOTE: we don't distinguish 0.0 from -0.0 95 if (value == oval.value) 96 return true; 97 98 if (value != value && oval.value != oval.value) 99 return true; 100 101 return false; 102 } 103 104 public int hashCode() { 105 // This check is necessary because floatToIntBits(+0) != floatToIntBits(-0) 106 return (value == 0f) ? 0 : Float.floatToIntBits(value); 107 } 108 109 // NOTE: 0.0 is equal but not identical to -0.0 110 public boolean isIdentical (XFloat val) { 111 if (val == this) { 112 return true; 113 } 114 115 if (value == val.value) { 116 return (value != 0.0f || 117 (Float.floatToIntBits(value) == Float.floatToIntBits(val.value))); 118 } 119 120 if (value != value && val.value != val.value) 121 return true; 122 123 return false; 124 } 125 126 private int compareTo(XFloat val) { 127 float oval = val.value; 128 129 // this < other 130 if (value < oval) 131 return -1; 132 // this > other 133 if (value > oval) 134 return 1; 135 // this == other 136 // NOTE: we don't distinguish 0.0 from -0.0 137 if (value == oval) 138 return 0; 139 140 // one of the 2 values or both is/are NaN(s) 141 142 if (value != value) { 143 // this = NaN = other 144 if (oval != oval) 145 return 0; 146 // this is NaN <> other 147 return INDETERMINATE; 148 } 149 150 // other is NaN <> this 151 return INDETERMINATE; 152 } 153 154 private String canonical; 155 public synchronized String toString() { 156 if (canonical == null) { 157 if (value == Float.POSITIVE_INFINITY) 158 canonical = "INF"; 159 else if (value == Float.NEGATIVE_INFINITY) 160 canonical = "-INF"; 161 else if (value != value) 162 canonical = "NaN"; 163 // NOTE: we don't distinguish 0.0 from -0.0 164 else if (value == 0) 165 canonical = "0.0E1"; 166 else { 167 // REVISIT: use the java algorithm for now, because we 168 // don't know what to output for 1.1f (which is no 169 // actually 1.1) 170 canonical = Float.toString(value); 171 // if it contains 'E', then it should be a valid schema 172 // canonical representation 173 if (canonical.indexOf('E') == -1) { 174 int len = canonical.length(); 175 // at most 3 longer: E, -, 9 176 char[] chars = new char[len+3]; 177 canonical.getChars(0, len, chars, 0); 178 // expected decimal point position 179 int edp = chars[0] == '-' ? 2 : 1; 180 // for non-zero integer part 181 if (value >= 1 || value <= -1) { 182 // decimal point position 183 int dp = canonical.indexOf('.'); 184 // move the digits: ddd.d --> d.ddd 185 for (int i = dp; i > edp; i--) { 186 chars[i] = chars[i-1]; 187 } 188 chars[edp] = '.'; 189 // trim trailing zeros: d00.0 --> d.000 --> d. 190 while (chars[len-1] == '0') 191 len--; 192 // add the last zero if necessary: d. --> d.0 193 if (chars[len-1] == '.') 194 len++; 195 // append E: d.dd --> d.ddE 196 chars[len++] = 'E'; 197 // how far we shifted the decimal point 198 int shift = dp - edp; 199 // append the exponent --> d.ddEd 200 // the exponent is at most 7 201 chars[len++] = (char)(shift + '0'); 202 } 203 else { 204 // non-zero digit point 205 int nzp = edp + 1; 206 // skip zeros: 0.003 207 while (chars[nzp] == '0') 208 nzp++; 209 // put the first non-zero digit to the left of '.' 210 chars[edp-1] = chars[nzp]; 211 chars[edp] = '.'; 212 // move other digits (non-zero) to the right of '.' 213 for (int i = nzp+1, j = edp+1; i < len; i++, j++) 214 chars[j] = chars[i]; 215 // adjust the length 216 len -= nzp - edp; 217 // append 0 if nessary: 0.03 --> 3. --> 3.0 218 if (len == edp + 1) 219 chars[len++] = '0'; 220 // append E-: d.dd --> d.ddE- 221 chars[len++] = 'E'; 222 chars[len++] = '-'; 223 // how far we shifted the decimal point 224 int shift = nzp - edp; 225 // append the exponent --> d.ddEd 226 // the exponent is at most 3 227 chars[len++] = (char)(shift + '0'); 228 } 229 canonical = new String(chars, 0, len); 230 } 231 } 232 } 233 return canonical; 234 } 235 236 public float getValue() { 237 return value; 238 } 239 } 240 } // class FloatDV