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    }