Source Code Cross Referenced for FloatValue.java in  » XML » saxonb » net » sf » saxon » value » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » XML » saxonb » net.sf.saxon.value 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package net.sf.saxon.value;
002:
003:        import net.sf.saxon.Err;
004:        import net.sf.saxon.functions.FormatNumber2;
005:        import net.sf.saxon.om.FastStringBuffer;
006:        import net.sf.saxon.expr.Token;
007:        import net.sf.saxon.expr.XPathContext;
008:        import net.sf.saxon.trans.DynamicError;
009:        import net.sf.saxon.trans.XPathException;
010:        import net.sf.saxon.type.*;
011:
012:        import java.math.BigDecimal;
013:        import java.util.regex.Matcher;
014:
015:        /**
016:         * A numeric (single precision floating point) value
017:         */
018:
019:        public final class FloatValue extends NumericValue {
020:            private float value;
021:
022:            /**
023:             * Constructor supplying a string
024:             */
025:
026:            public FloatValue(CharSequence val) throws DynamicError {
027:                try {
028:                    this .value = (float) Value.stringToNumber(val);
029:                } catch (NumberFormatException e) {
030:                    throw new DynamicError("Cannot convert string "
031:                            + Err.wrap(val, Err.VALUE) + " to a float");
032:                }
033:            }
034:
035:            /**
036:             * Constructor supplying a float
037:             * @param value the value of the float
038:             */
039:
040:            public FloatValue(float value) {
041:                this .value = value;
042:            }
043:
044:            /**
045:             * Get the value
046:             */
047:
048:            public float getValue() {
049:                return value;
050:            }
051:
052:            public double getDoubleValue() {
053:                return (double) value;
054:            }
055:
056:            /**
057:             * Get the hashCode. This must conform to the rules for other NumericValue hashcodes
058:             * @see NumericValue#hashCode
059:             */
060:
061:            public int hashCode() {
062:                if (value > Integer.MIN_VALUE && value < Integer.MAX_VALUE) {
063:                    return (int) value;
064:                } else {
065:                    return new Double(this .getDoubleValue()).hashCode();
066:                }
067:            }
068:
069:            /**
070:             * Test whether the value is the double/float value NaN
071:             */
072:
073:            public boolean isNaN() {
074:                return Float.isNaN(value);
075:            }
076:
077:            /**
078:             * Get the effective boolean value
079:             * @param context
080:             * @return true unless the value is zero or NaN
081:             */
082:            public boolean effectiveBooleanValue(XPathContext context) {
083:                return (value != 0.0 && !Float.isNaN(value));
084:            }
085:
086:            /**
087:             * Convert to target data type
088:             * @param requiredType an integer identifying the required atomic type
089:             * @param context
090:             * @return an AtomicValue, a value of the required type; or an ErrorValue
091:             */
092:
093:            public AtomicValue convertPrimitive(BuiltInAtomicType requiredType,
094:                    boolean validate, XPathContext context) {
095:                switch (requiredType.getPrimitiveType()) {
096:                case Type.BOOLEAN:
097:                    return BooleanValue
098:                            .get(value != 0.0 && !Float.isNaN(value));
099:                case Type.FLOAT:
100:                case Type.NUMBER:
101:                case Type.ANY_ATOMIC:
102:                case Type.ITEM:
103:                    return this ;
104:                case Type.INTEGER:
105:                    if (Float.isNaN(value)) {
106:                        ValidationException err = new ValidationException(
107:                                "Cannot convert float NaN to an integer");
108:                        err.setErrorCode("FORG0001");
109:                        //err.setXPathContext(context);
110:                        return new ValidationErrorValue(err);
111:                    }
112:                    if (Float.isInfinite(value)) {
113:                        ValidationException err = new ValidationException(
114:                                "Cannot convert float infinity to an integer");
115:                        err.setErrorCode("FORG0001");
116:                        //err.setXPathContext(context);
117:                        return new ValidationErrorValue(err);
118:                    }
119:                    if (value > Long.MAX_VALUE || value < Long.MIN_VALUE) {
120:                        return new BigIntegerValue(new BigDecimal(value)
121:                                .toBigInteger());
122:                    }
123:                    return new IntegerValue((long) value);
124:                case Type.DECIMAL:
125:                    try {
126:                        return new DecimalValue(value);
127:                    } catch (ValidationException e) {
128:                        return new ValidationErrorValue(e);
129:                    }
130:                case Type.DOUBLE:
131:                    return new DoubleValue((double) value);
132:                case Type.STRING:
133:                    return new StringValue(getStringValueCS());
134:                case Type.UNTYPED_ATOMIC:
135:                    return new UntypedAtomicValue(getStringValueCS());
136:                default:
137:                    ValidationException err = new ValidationException(
138:                            "Cannot convert float to "
139:                                    + requiredType.getDisplayName());
140:                    err.setErrorCode("XPTY0004");
141:                    err.setIsTypeError(true);
142:                    return new ValidationErrorValue(err);
143:                }
144:            }
145:
146:            /**
147:             * Get the value as a String
148:             * @return a String representation of the value
149:             */
150:
151:            public String getStringValue() {
152:                return getStringValueCS().toString();
153:            }
154:
155:            /**
156:             * Get the value as a String
157:             * @return a String representation of the value
158:             */
159:
160:            public CharSequence getStringValueCS() {
161:                return floatToString(value, Float.toString(value));
162:            }
163:
164:            /**
165:             * Regex indicating that a number may be worth rounding
166:             */
167:
168:            static java.util.regex.Pattern roundablePattern = java.util.regex.Pattern
169:                    .compile(".*99999.*|.*00000.*");
170:
171:            /**
172:             * Internal method used for conversion of a float to a string
173:             * @param value the actual value
174:             * @param javaString the result of converting the float to a string using the Java conventions.
175:             * This value is adjusted as necessary to cater for the differences between the Java and XPath rules.
176:             * @return the value converted to a string, according to the XPath casting rules.
177:             */
178:
179:            static CharSequence floatToString(float value, String javaString) {
180:                if (value == 0.0) {
181:                    if (javaString.charAt(0) == '-') {
182:                        return "-0";
183:                    } else {
184:                        return "0";
185:                    }
186:                }
187:                if (Float.isInfinite(value)) {
188:                    return (value > 0 ? "INF" : "-INF");
189:                }
190:                if (Float.isNaN(value)) {
191:                    return "NaN";
192:                }
193:                final float absval = Math.abs(value);
194:                String s = javaString;
195:                if (absval < (float) 1.0e-6 || absval >= (float) 1.0e+6) {
196:                    final int e = s.indexOf('E');
197:                    if (e < 0) {
198:                        // need to use scientific notation, but Java isn't using it
199:                        // (Java's cutoff is 1.0E7, while XPath's is 1.0E6)
200:                        // So we have for example -2000000.0 rather than -2.0e6
201:                        FastStringBuffer sb = new FastStringBuffer(32);
202:                        Matcher matcher = DoubleValue.nonExponentialPattern
203:                                .matcher(s);
204:                        if (matcher.matches()) {
205:                            sb.append(matcher.group(1));
206:                            sb.append('.');
207:                            sb.append(matcher.group(2));
208:                            final String fraction = matcher.group(4);
209:                            if ("0".equals(fraction)) {
210:                                sb.append("E"
211:                                        + (matcher.group(2).length() + matcher
212:                                                .group(3).length()));
213:                                return sb.toString();
214:                            } else {
215:                                sb.append(matcher.group(3));
216:                                sb.append(matcher.group(4));
217:                                sb.append("E"
218:                                        + (matcher.group(2).length() + matcher
219:                                                .group(3).length()));
220:                                return sb;
221:                            }
222:                        } else {
223:                            // fallback, this shouldn't happen
224:                            return s;
225:                        }
226:                    } else {
227:                        // test to see if rounding the last digit would change the result
228:                        // test case: string(xs:float("100000000000"))
229:                        if (roundablePattern.matcher(s).matches()) {
230:                            BigDecimal dec = FormatNumber2.adjustToDecimal(
231:                                    value, 1);
232:                            try {
233:                                return new DoubleValue(dec.toString())
234:                                        .getStringValue();
235:                            } catch (ValidationException err) {
236:                                throw new AssertionError(err);
237:                            }
238:                        }
239:                        return s;
240:                    }
241:                }
242:                int len = s.length();
243:                if (s.endsWith("E0")) {
244:                    s = s.substring(0, len - 2);
245:                }
246:                if (s.endsWith(".0")) {
247:                    return s.substring(0, len - 2);
248:                }
249:                int e = s.indexOf('E');
250:                if (e < 0) {
251:                    // For some reason, Double.toString() in Java can return strings such as "0.0040"
252:                    // so we remove any trailing zeros
253:                    while (s.charAt(len - 1) == '0' && s.charAt(len - 2) != '.') {
254:                        s = s.substring(0, --len);
255:                    }
256:                    return s;
257:                }
258:                int exp = Integer.parseInt(s.substring(e + 1));
259:                String sign;
260:                if (s.charAt(0) == '-') {
261:                    sign = "-";
262:                    s = s.substring(1);
263:                    --e;
264:                } else {
265:                    sign = "";
266:                }
267:                int nDigits = e - 2;
268:                if (exp >= nDigits) {
269:                    return sign + s.substring(0, 1) + s.substring(2, e)
270:                            + DoubleValue.zeros(exp - nDigits);
271:                } else if (exp > 0) {
272:                    return sign + s.substring(0, 1) + s.substring(2, 2 + exp)
273:                            + '.' + s.substring(2 + exp, e);
274:                } else {
275:                    while (s.charAt(e - 1) == '0')
276:                        e--;
277:                    return sign + "0." + DoubleValue.zeros(-1 - exp)
278:                            + s.substring(0, 1) + s.substring(2, e);
279:                }
280:            }
281:
282:            /**
283:             * Determine the data type of the expression
284:             * @return Type.DOUBLE
285:             * @param th
286:             */
287:
288:            public ItemType getItemType(TypeHierarchy th) {
289:                return Type.FLOAT_TYPE;
290:            }
291:
292:            /**
293:             * Negate the value
294:             */
295:
296:            public NumericValue negate() {
297:                return new FloatValue(-value);
298:            }
299:
300:            /**
301:             * Implement the XPath floor() function
302:             */
303:
304:            public NumericValue floor() {
305:                return new FloatValue((float) Math.floor(value));
306:            }
307:
308:            /**
309:             * Implement the XPath ceiling() function
310:             */
311:
312:            public NumericValue ceiling() {
313:                return new FloatValue((float) Math.ceil(value));
314:            }
315:
316:            /**
317:             * Implement the XPath round() function
318:             */
319:
320:            public NumericValue round() {
321:                if (Float.isNaN(value))
322:                    return this ;
323:                if (Float.isInfinite(value))
324:                    return this ;
325:                if (value == 0.0)
326:                    return this ; // handles the negative zero case
327:                if (value > -0.5 && value < 0.0)
328:                    return new DoubleValue(-0.0);
329:                if (value > Integer.MIN_VALUE && value < Integer.MAX_VALUE) {
330:                    return new FloatValue((float) Math.round(value));
331:                }
332:
333:                // if the float is larger than the maximum int, then
334:                // it can't have any significant digits after the decimal
335:                // point, so return it unchanged
336:
337:                return this ;
338:            }
339:
340:            /**
341:             * Implement the XPath round-to-half-even() function
342:             */
343:
344:            public NumericValue roundToHalfEven(int scale) {
345:                try {
346:                    return (FloatValue) new DoubleValue((double) value)
347:                            .roundToHalfEven(scale).convert(Type.FLOAT, null);
348:                } catch (XPathException err) {
349:                    throw new AssertionError(err);
350:                }
351:            }
352:
353:            /**
354:             * Determine whether the value is negative, zero, or positive
355:             * @return -1 if negative, 0 if zero (including negative zero), +1 if positive, NaN if NaN
356:             */
357:
358:            public double signum() {
359:                if (Float.isNaN(value)) {
360:                    return value;
361:                }
362:                if (value > 0)
363:                    return 1;
364:                if (value == 0)
365:                    return 0;
366:                return -1;
367:            }
368:
369:            /**
370:             * Determine whether the value is a whole number, that is, whether it compares
371:             * equal to some integer
372:             */
373:
374:            public boolean isWholeNumber() {
375:                return value == Math.floor(value) && !Float.isInfinite(value);
376:            }
377:
378:            /**
379:             * Evaluate a binary arithmetic operator.
380:             */
381:
382:            public NumericValue arithmetic(int operator, NumericValue other,
383:                    XPathContext context) throws XPathException {
384:                if (other instanceof  FloatValue) {
385:                    switch (operator) {
386:                    case Token.PLUS:
387:                        return new FloatValue(value
388:                                + ((FloatValue) other).value);
389:                    case Token.MINUS:
390:                        return new FloatValue(value
391:                                - ((FloatValue) other).value);
392:                    case Token.MULT:
393:                        return new FloatValue(value
394:                                * ((FloatValue) other).value);
395:                    case Token.DIV:
396:                        return new FloatValue(value
397:                                / ((FloatValue) other).value);
398:                    case Token.IDIV:
399:                        if (((FloatValue) other).value == 0.0) {
400:                            DynamicError e = new DynamicError(
401:                                    "Integer division by zero");
402:                            e.setErrorCode("FOAR0001");
403:                            e.setXPathContext(context);
404:                            throw e;
405:                        }
406:                        return (NumericValue) (new FloatValue(value
407:                                / ((FloatValue) other).value).convert(
408:                                Type.INTEGER, context));
409:                    case Token.MOD:
410:                        return new FloatValue(value
411:                                % ((FloatValue) other).value);
412:                    default:
413:                        throw new UnsupportedOperationException(
414:                                "Unknown operator");
415:                    }
416:                } else if (other instanceof  DoubleValue) {
417:                    return ((DoubleValue) convert(Type.DOUBLE, context))
418:                            .arithmetic(operator, other, context);
419:                } else {
420:                    return arithmetic(operator, (FloatValue) other.convert(
421:                            Type.FLOAT, context), context);
422:                }
423:            }
424:
425:            public int compareTo(Object other) {
426:                if (other instanceof  AtomicValue
427:                        && !((AtomicValue) other).hasBuiltInType()) {
428:                    return compareTo(((AtomicValue) other).getPrimitiveValue());
429:                }
430:                if (!(other instanceof  NumericValue)) {
431:                    throw new ClassCastException(
432:                            "Numeric values are not comparable to "
433:                                    + other.getClass());
434:                }
435:                if (other instanceof  FloatValue) {
436:                    float otherFloat = ((FloatValue) other).value;
437:                    if (value == otherFloat)
438:                        return 0;
439:                    if (value < otherFloat)
440:                        return -1;
441:                    return +1;
442:                }
443:                if (other instanceof  DoubleValue) {
444:                    return super .compareTo(other);
445:                }
446:                try {
447:                    return compareTo(((NumericValue) other).convert(Type.FLOAT,
448:                            null));
449:                } catch (XPathException err) {
450:                    throw new ClassCastException(
451:                            "Operand of comparison cannot be promoted to xs:float");
452:                }
453:            }
454:
455:            /**
456:             * Compare two values for equality. This supports identity constraints in XML Schema,
457:             * which allow list-valued elements and attributes to participate in key and uniqueness constraints.
458:             * This method returns false if any error occurs during the comparison, or if any of the items
459:             * in either sequence is a node rather than an atomic value. The default implementation of
460:             * schemaEquals() is the same as equals(), but subclasses can override this.
461:             */
462:
463:            public boolean schemaEquals(Value obj) {
464:                if (obj instanceof  AtomicValue) {
465:                    obj = ((AtomicValue) obj).getPrimitiveValue();
466:                }
467:                if (obj instanceof  FloatValue) {
468:                    return value == ((FloatValue) obj).value;
469:                } else {
470:                    return false;
471:                }
472:            }
473:
474:            /**
475:             * Convert to Java object (for passing to external functions)
476:             */
477:
478:            public Object convertToJava(Class target, XPathContext context)
479:                    throws XPathException {
480:                if (target == Object.class) {
481:                    return new Double(value);
482:                } else if (target.isAssignableFrom(DoubleValue.class)) {
483:                    return this ;
484:                } else if (target == boolean.class || target == Boolean.class) {
485:                    return Boolean.valueOf(value != 0.0 && !Float.isNaN(value));
486:                } else if (target == String.class
487:                        || target == CharSequence.class) {
488:                    return getStringValue();
489:                } else if (target == double.class || target == Double.class) {
490:                    return new Double((double) value);
491:                } else if (target == float.class || target == Float.class) {
492:                    return new Float(value);
493:                } else if (target == long.class || target == Long.class) {
494:                    return new Long((long) value);
495:                } else if (target == int.class || target == Integer.class) {
496:                    return new Integer((int) value);
497:                } else if (target == short.class || target == Short.class) {
498:                    return new Short((short) value);
499:                } else if (target == byte.class || target == Byte.class) {
500:                    return new Byte((byte) value);
501:                } else if (target == char.class || target == Character.class) {
502:                    return new Character((char) value);
503:                } else {
504:                    Object o = super .convertToJava(target, context);
505:                    if (o == null) {
506:                        DynamicError err = new DynamicError(
507:                                "Conversion of float to " + target.getName()
508:                                        + " is not supported");
509:                        err.setXPathContext(context);
510:                        err.setErrorCode("SAXON:0000");
511:                    }
512:                    return o;
513:                }
514:            }
515:
516:        }
517:
518:        //
519:        // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
520:        // you may not use this file except in compliance with the License. You may obtain a copy of the
521:        // License at http://www.mozilla.org/MPL/
522:        //
523:        // Software distributed under the License is distributed on an "AS IS" basis,
524:        // WITHOUT WARRANTY OF ANY KIND, either express or implied.
525:        // See the License for the specific language governing rights and limitations under the License.
526:        //
527:        // The Original Code is: all this file.
528:        //
529:        // The Initial Developer of the Original Code is Michael H. Kay.
530:        //
531:        // Contributor(s): none.
532:        //
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.