/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: XNumber.java 469368 2006-10-31 04:41:36Z minchau $
 */
package org.apache.xpath.objects;

import org.apache.xpath.ExpressionOwner;
import org.apache.xpath.XPathContext;
import org.apache.xpath.XPathVisitor;

This class represents an XPath number, and is capable of converting the number to other types, such as a string.
@xsl.usagegeneral
/** * This class represents an XPath number, and is capable of * converting the number to other types, such as a string. * @xsl.usage general */
public class XNumber extends XObject { static final long serialVersionUID = -2720400709619020193L;
Value of the XNumber object. @serial
/** Value of the XNumber object. * @serial */
double m_val;
Construct a XNodeSet object.
Params:
  • d – Value of the object
/** * Construct a XNodeSet object. * * @param d Value of the object */
public XNumber(double d) { super(); m_val = d; }
Construct a XNodeSet object.
Params:
  • num – Value of the object
/** * Construct a XNodeSet object. * * @param num Value of the object */
public XNumber(Number num) { super(); m_val = num.doubleValue(); setObject(num); }
Tell that this is a CLASS_NUMBER.
Returns:node type CLASS_NUMBER
/** * Tell that this is a CLASS_NUMBER. * * @return node type CLASS_NUMBER */
public int getType() { return CLASS_NUMBER; }
Given a request type, return the equivalent string. For diagnostic purposes.
Returns:type string "#NUMBER"
/** * Given a request type, return the equivalent string. * For diagnostic purposes. * * @return type string "#NUMBER" */
public String getTypeString() { return "#NUMBER"; }
Cast result object to a number.
Returns:the value of the XNumber object
/** * Cast result object to a number. * * @return the value of the XNumber object */
public double num() { return m_val; }
Evaluate expression to a number.
Throws:
Returns:0.0
/** * Evaluate expression to a number. * * @return 0.0 * * @throws javax.xml.transform.TransformerException */
public double num(XPathContext xctxt) throws javax.xml.transform.TransformerException { return m_val; }
Cast result object to a boolean.
Returns:false if the value is NaN or equal to 0.0
/** * Cast result object to a boolean. * * @return false if the value is NaN or equal to 0.0 */
public boolean bool() { return (Double.isNaN(m_val) || (m_val == 0.0)) ? false : true; } // /** // * Cast result object to a string. // * // * @return "NaN" if the number is NaN, Infinity or -Infinity if // * the number is infinite or the string value of the number. // */ // private static final int PRECISION = 16; // public String str() // { // // if (Double.isNaN(m_val)) // { // return "NaN"; // } // else if (Double.isInfinite(m_val)) // { // if (m_val > 0) // return "Infinity"; // else // return "-Infinity"; // } // // long longVal = (long)m_val; // if ((double)longVal == m_val) // return Long.toString(longVal); // // // String s = Double.toString(m_val); // int len = s.length(); // // if (s.charAt(len - 2) == '.' && s.charAt(len - 1) == '0') // { // return s.substring(0, len - 2); // } // // int exp = 0; // int e = s.indexOf('E'); // if (e != -1) // { // exp = Integer.parseInt(s.substring(e + 1)); // s = s.substring(0,e); // len = e; // } // // // Calculate Significant Digits: // // look from start of string for first digit // // look from end for last digit // // significant digits = end - start + (0 or 1 depending on decimal location) // // int decimalPos = -1; // int start = (s.charAt(0) == '-') ? 1 : 0; // findStart: for( ; start < len; start++ ) // { // switch (s.charAt(start)) // { // case '0': // break; // case '.': // decimalPos = start; // break; // default: // break findStart; // } // } // int end = s.length() - 1; // findEnd: for( ; end > start; end-- ) // { // switch (s.charAt(end)) // { // case '0': // break; // case '.': // decimalPos = end; // break; // default: // break findEnd; // } // } // // int sigDig = end - start; // // // clarify decimal location if it has not yet been found // if (decimalPos == -1) // decimalPos = s.indexOf('.'); // // // if decimal is not between start and end, add one to sigDig // if (decimalPos < start || decimalPos > end) // ++sigDig; // // // reduce significant digits to PRECISION if necessary // if (sigDig > PRECISION) // { // // re-scale BigDecimal in order to get significant digits = PRECISION // BigDecimal num = new BigDecimal(s); // int newScale = num.scale() - (sigDig - PRECISION); // if (newScale < 0) // newScale = 0; // s = num.setScale(newScale, BigDecimal.ROUND_HALF_UP).toString(); // // // remove trailing '0's; keep track of decimalPos // int truncatePoint = s.length(); // while (s.charAt(--truncatePoint) == '0') // ; // // if (s.charAt(truncatePoint) == '.') // { // decimalPos = truncatePoint; // } // else // { // decimalPos = s.indexOf('.'); // truncatePoint += 1; // } // // s = s.substring(0, truncatePoint); // len = s.length(); // } // // // Account for exponent by adding zeros as needed // // and moving the decimal place // // if (exp == 0) // return s; // // start = 0; // String sign; // if (s.charAt(0) == '-') // { // sign = "-"; // start++; // } // else // sign = ""; // // String wholePart = s.substring(start, decimalPos); // String decimalPart = s.substring(decimalPos + 1); // // // get the number of digits right of the decimal // int decimalLen = decimalPart.length(); // // if (exp >= decimalLen) // return sign + wholePart + decimalPart + zeros(exp - decimalLen); // // if (exp > 0) // return sign + wholePart + decimalPart.substring(0, exp) + "." // + decimalPart.substring(exp); // // return sign + "0." + zeros(-1 - exp) + wholePart + decimalPart; // }
Cast result object to a string.
Returns:"NaN" if the number is NaN, Infinity or -Infinity if the number is infinite or the string value of the number.
/** * Cast result object to a string. * * @return "NaN" if the number is NaN, Infinity or -Infinity if * the number is infinite or the string value of the number. */
public String str() { if (Double.isNaN(m_val)) { return "NaN"; } else if (Double.isInfinite(m_val)) { if (m_val > 0) return "Infinity"; else return "-Infinity"; } double num = m_val; String s = Double.toString(num); int len = s.length(); if (s.charAt(len - 2) == '.' && s.charAt(len - 1) == '0') { s = s.substring(0, len - 2); if (s.equals("-0")) return "0"; return s; } int e = s.indexOf('E'); if (e < 0) { if (s.charAt(len - 1) == '0') return s.substring(0, len - 1); else return s; } int exp = Integer.parseInt(s.substring(e + 1)); String sign; if (s.charAt(0) == '-') { sign = "-"; s = s.substring(1); --e; } else sign = ""; int nDigits = e - 2; if (exp >= nDigits) return sign + s.substring(0, 1) + s.substring(2, e) + zeros(exp - nDigits); // Eliminate trailing 0's - bugzilla 14241 while (s.charAt(e-1) == '0') e--; if (exp > 0) return sign + s.substring(0, 1) + s.substring(2, 2 + exp) + "." + s.substring(2 + exp, e); return sign + "0." + zeros(-1 - exp) + s.substring(0, 1) + s.substring(2, e); }
Return a string of '0' of the given length
Params:
  • n – Length of the string to be returned
Returns:a string of '0' with the given length
/** * Return a string of '0' of the given length * * * @param n Length of the string to be returned * * @return a string of '0' with the given length */
static private String zeros(int n) { if (n < 1) return ""; char[] buf = new char[n]; for (int i = 0; i < n; i++) { buf[i] = '0'; } return new String(buf); }
Return a java object that's closest to the representation that should be handed to an extension.
Returns:The value of this XNumber as a Double object
/** * Return a java object that's closest to the representation * that should be handed to an extension. * * @return The value of this XNumber as a Double object */
public Object object() { if(null == m_obj) setObject(new Double(m_val)); return m_obj; }
Tell if two objects are functionally equal.
Params:
  • obj2 – Object to compare this to
Throws:
Returns:true if the two objects are equal
/** * Tell if two objects are functionally equal. * * @param obj2 Object to compare this to * * @return true if the two objects are equal * * @throws javax.xml.transform.TransformerException */
public boolean equals(XObject obj2) { // In order to handle the 'all' semantics of // nodeset comparisons, we always call the // nodeset function. int t = obj2.getType(); try { if (t == XObject.CLASS_NODESET) return obj2.equals(this); else if(t == XObject.CLASS_BOOLEAN) return obj2.bool() == bool(); else return m_val == obj2.num(); } catch(javax.xml.transform.TransformerException te) { throw new org.apache.xml.utils.WrappedRuntimeException(te); } }
Tell if this expression returns a stable number that will not change during iterations within the expression. This is used to determine if a proximity position predicate can indicate that no more searching has to occur.
Returns:true if the expression represents a stable number.
/** * Tell if this expression returns a stable number that will not change during * iterations within the expression. This is used to determine if a proximity * position predicate can indicate that no more searching has to occur. * * * @return true if the expression represents a stable number. */
public boolean isStableNumber() { return true; }
See Also:
  • callVisitors.callVisitors(ExpressionOwner, XPathVisitor)
/** * @see org.apache.xpath.XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor) */
public void callVisitors(ExpressionOwner owner, XPathVisitor visitor) { visitor.visitNumberLiteral(owner, this); } }