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 }
|