001: package net.sf.saxon.functions;
002:
003: import net.sf.saxon.expr.Expression;
004: import net.sf.saxon.expr.MappingFunction;
005: import net.sf.saxon.expr.StaticContext;
006: import net.sf.saxon.expr.XPathContext;
007: import net.sf.saxon.om.Item;
008: import net.sf.saxon.trans.XPathException;
009: import net.sf.saxon.type.Type;
010: import net.sf.saxon.value.*;
011:
012: /**
013: * Implements the XPath number() function. This can also be used as a mapping function
014: * in a MappingIterator to map a sequence of values to numbers.
015: */
016:
017: public class NumberFn extends SystemFunction implements MappingFunction {
018:
019: /**
020: * Simplify and validate.
021: * This is a pure function so it can be simplified in advance if the arguments are known
022: */
023:
024: public Expression simplify(StaticContext env) throws XPathException {
025: useContextItemAsDefault();
026: return simplifyArguments(env);
027: }
028:
029: /**
030: * Evaluate in a general context
031: */
032:
033: public Item evaluateItem(XPathContext context)
034: throws XPathException {
035: Item arg0 = argument[0].evaluateItem(context);
036: if (arg0 == null) {
037: return DoubleValue.NaN;
038: }
039: if (arg0 instanceof BooleanValue
040: || arg0 instanceof NumericValue) {
041: return ((AtomicValue) arg0).convert(Type.DOUBLE, context);
042: }
043: CharSequence s = arg0.getStringValueCS();
044: try {
045: return new DoubleValue(Value.stringToNumber(s));
046: } catch (NumberFormatException e) {
047: return DoubleValue.NaN;
048: }
049: }
050:
051: /**
052: * Static method to perform the same conversion as the number() function. This is different from the
053: * convert(Type.DOUBLE) in that it produces NaN rather than an error for non-numeric operands.
054: */
055:
056: public static DoubleValue convert(AtomicValue value) {
057: try {
058: if (value == null) {
059: return DoubleValue.NaN;
060: }
061: if (value instanceof BooleanValue
062: || value instanceof NumericValue) {
063: return (DoubleValue) value.convert(Type.DOUBLE, null);
064: }
065: CharSequence s = value.getStringValueCS();
066: return new DoubleValue(Value.stringToNumber(s));
067: } catch (NumberFormatException e) {
068: return DoubleValue.NaN;
069: } catch (XPathException e) {
070: return DoubleValue.NaN;
071: }
072: }
073:
074: /**
075: * Mapping function for use when converting a sequence of atomic values to doubles
076: * using the rules of the number() function
077: */
078:
079: public Object map(Item item, XPathContext context)
080: throws XPathException {
081: return convert((AtomicValue) item);
082: }
083: }
084:
085: //
086: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
087: // you may not use this file except in compliance with the License. You may obtain a copy of the
088: // License at http://www.mozilla.org/MPL/
089: //
090: // Software distributed under the License is distributed on an "AS IS" basis,
091: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
092: // See the License for the specific language governing rights and limitations under the License.
093: //
094: // The Original Code is: all this file.
095: //
096: // The Initial Developer of the Original Code is Michael H. Kay.
097: //
098: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
099: //
100: // Contributor(s): none.
101: //
|