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