    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *     http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017    package org.apache.commons.jxpath.ri;
    018
    019    import org.apache.commons.jxpath.Pointer;
    020    import org.apache.commons.jxpath.ri.model.NodePointer;
    021    import org.apache.commons.jxpath.ri.model.VariablePointer;
    022
    023    /**
    024     * Type conversions, XPath style.
    025     *
    026     * @author Dmitri Plotnikov
    027     * @version $Revision: 652845 $ $Date: 2008-05-02 12:46:46 -0500 (Fri, 02 May 2008) $
    028     */
    029    public class InfoSetUtil {
    030
    031        private static final Double ZERO = new Double(0);
    032        private static final Double ONE = new Double(1);
    033        private static final Double NOT_A_NUMBER = new Double(Double.NaN);
    034
    035        /**
    036         * Converts the supplied object to String.
    037         * @param object to convert
    038         * @return String value
    039         */
    040        public static String stringValue(Object object) {
    041            if (object instanceof String) {
    042                return (String) object;
    043            }
    044            if (object instanceof Number) {
    045                double d = ((Number) object).doubleValue();
    046                long l = ((Number) object).longValue();
    047                return d == l ? String.valueOf(l) : String.valueOf(d);
    048            }
    049            if (object instanceof Boolean) {
    050                return ((Boolean) object).booleanValue() ? "true" : "false";
    051            }
    052            if (object == null) {
    053                return "";
    054            }
    055            if (object instanceof NodePointer) {
    056                return stringValue(((NodePointer) object).getValue());
    057            }
    058            if (object instanceof EvalContext) {
    059                EvalContext ctx = (EvalContext) object;
    060                Pointer ptr = ctx.getSingleNodePointer();
    061                return ptr == null ? "" : stringValue(ptr);
    062            }
    063            return String.valueOf(object);
    064        }
    065
    066        /**
    067         * Converts the supplied object to Number.
    068         * @param object to convert
    069         * @return Number result
    070         */
    071        public static Number number(Object object) {
    072            if (object instanceof Number) {
    073                return (Number) object;
    074            }
    075            if (object instanceof Boolean) {
    076                return ((Boolean) object).booleanValue() ? ONE : ZERO;
    077            }
    078            if (object instanceof String) {
    079                try {
    080                    return new Double((String) object);
    081                }
    082                catch (NumberFormatException ex) {
    083                    return NOT_A_NUMBER;
    084                }
    085            }
    086            if (object instanceof EvalContext) {
    087                EvalContext ctx = (EvalContext) object;
    088                Pointer ptr = ctx.getSingleNodePointer();
    089                return ptr == null ? NOT_A_NUMBER : number(ptr);
    090            }
    091            if (object instanceof NodePointer) {
    092                return number(((NodePointer) object).getValue());
    093            }
    094            return number(stringValue(object));
    095        }
    096
    097        /**
    098         * Converts the supplied object to double.
    099         * @param object to convert
    100         * @return double
    101         */
    102        public static double doubleValue(Object object) {
    103            if (object instanceof Number) {
    104                return ((Number) object).doubleValue();
    105            }
    106            if (object instanceof Boolean) {
    107                return ((Boolean) object).booleanValue() ? 0.0 : 1.0;
    108            }
    109            if (object instanceof String) {
    110                if (object.equals("")) {
    111                    return 0.0;
    112                }
    113                try {
    114                    return Double.parseDouble((String) object);
    115                }
    116                catch (NumberFormatException ex) {
    117                    return Double.NaN;
    118                }
    119            }
    120            if (object instanceof NodePointer) {
    121                return doubleValue(((NodePointer) object).getValue());
    122            }
    123            if (object instanceof EvalContext) {
    124                EvalContext ctx = (EvalContext) object;
    125                Pointer ptr = ctx.getSingleNodePointer();
    126                return ptr == null ? Double.NaN : doubleValue(ptr);
    127            }
    128            return doubleValue(stringValue(object));
    129        }
    130
    131        /**
    132         * Converts the supplied object to boolean.
    133         * @param object to convert
    134         * @return boolean
    135         */
    136        public static boolean booleanValue(Object object) {
    137            if (object instanceof Number) {
    138                double value = ((Number) object).doubleValue();
    139                final int negZero = -0;
    140                return value != 0 && value != negZero && !Double.isNaN(value);
    141            }
    142            if (object instanceof Boolean) {
    143                return ((Boolean) object).booleanValue();
    144            }
    145            if (object instanceof EvalContext) {
    146                EvalContext ctx = (EvalContext) object;
    147                Pointer ptr = ctx.getSingleNodePointer();
    148                return ptr == null ? false : booleanValue(ptr);
    149            }
    150            if (object instanceof String) {
    151                return ((String) object).length() != 0;
    152            }
    153            if (object instanceof NodePointer) {
    154                NodePointer pointer = (NodePointer) object;
    155                if (pointer instanceof VariablePointer) {
    156                    return booleanValue(pointer.getNode());
    157                }
    158                pointer = pointer.getValuePointer();
    159                return pointer.isActual();
    160            }
    161            return object != null;
    162        }
    163    }