    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
    018package org.apache.commons.jxpath.ri;
    019
    020import org.apache.commons.jxpath.Pointer;
    021import org.apache.commons.jxpath.ri.model.NodePointer;
    022import org.apache.commons.jxpath.ri.model.VariablePointer;
    023
    024/**
    025 * Type conversions, XPath style.
    026 */
    027public class InfoSetUtil {
    028
    029    private static final Double ZERO = Double.valueOf(0);
    030    private static final Double ONE = Double.valueOf(1);
    031    private static final Double NOT_A_NUMBER = Double.valueOf(Double.NaN);
    032
    033    /**
    034     * Converts the supplied object to boolean.
    035     *
    036     * @param object to convert
    037     * @return boolean
    038     */
    039    public static boolean booleanValue(final Object object) {
    040        if (object instanceof Number) {
    041            final double value = ((Number) object).doubleValue();
    042            final int negZero = -0;
    043            return value != 0 && value != negZero && !Double.isNaN(value);
    044        }
    045        if (object instanceof Boolean) {
    046            return ((Boolean) object).booleanValue();
    047        }
    048        if (object instanceof EvalContext) {
    049            final EvalContext ctx = (EvalContext) object;
    050            final Pointer ptr = ctx.getSingleNodePointer();
    051            return ptr != null && booleanValue(ptr);
    052        }
    053        if (object instanceof String) {
    054            return ((String) object).length() != 0;
    055        }
    056        if (object instanceof NodePointer) {
    057            NodePointer pointer = (NodePointer) object;
    058            if (pointer instanceof VariablePointer) {
    059                return booleanValue(pointer.getNode());
    060            }
    061            pointer = pointer.getValuePointer();
    062            return pointer.isActual();
    063        }
    064        return object != null;
    065    }
    066
    067    /**
    068     * Converts the supplied object to double.
    069     *
    070     * @param object to convert
    071     * @return double
    072     */
    073    public static double doubleValue(final Object object) {
    074        if (object instanceof Number) {
    075            return ((Number) object).doubleValue();
    076        }
    077        if (object instanceof Boolean) {
    078            return ((Boolean) object).booleanValue() ? 0.0 : 1.0;
    079        }
    080        if (object instanceof String) {
    081            if (object.equals("")) {
    082                return 0.0;
    083            }
    084            try {
    085                return Double.parseDouble((String) object);
    086            } catch (final NumberFormatException ex) {
    087                return Double.NaN;
    088            }
    089        }
    090        if (object instanceof NodePointer) {
    091            return doubleValue(((NodePointer) object).getValue());
    092        }
    093        if (object instanceof EvalContext) {
    094            final EvalContext ctx = (EvalContext) object;
    095            final Pointer ptr = ctx.getSingleNodePointer();
    096            return ptr == null ? Double.NaN : doubleValue(ptr);
    097        }
    098        return doubleValue(stringValue(object));
    099    }
    100
    101    /**
    102     * Converts the supplied object to Number.
    103     *
    104     * @param object to convert
    105     * @return Number result
    106     */
    107    public static Number number(final Object object) {
    108        if (object instanceof Number) {
    109            return (Number) object;
    110        }
    111        if (object instanceof Boolean) {
    112            return ((Boolean) object).booleanValue() ? ONE : ZERO;
    113        }
    114        if (object instanceof String) {
    115            try {
    116                return Double.valueOf((String) object);
    117            } catch (final NumberFormatException ex) {
    118                return NOT_A_NUMBER;
    119            }
    120        }
    121        if (object instanceof EvalContext) {
    122            final EvalContext ctx = (EvalContext) object;
    123            final Pointer ptr = ctx.getSingleNodePointer();
    124            return ptr == null ? NOT_A_NUMBER : number(ptr);
    125        }
    126        if (object instanceof NodePointer) {
    127            return number(((NodePointer) object).getValue());
    128        }
    129        return number(stringValue(object));
    130    }
    131
    132    /**
    133     * Converts the supplied object to String.
    134     *
    135     * @param object to convert
    136     * @return String value
    137     */
    138    public static String stringValue(final Object object) {
    139        if (object instanceof String) {
    140            return (String) object;
    141        }
    142        if (object instanceof Number) {
    143            final double d = ((Number) object).doubleValue();
    144            final long l = ((Number) object).longValue();
    145            return d == l ? String.valueOf(l) : String.valueOf(d);
    146        }
    147        if (object instanceof Boolean) {
    148            return ((Boolean) object).booleanValue() ? "true" : "false";
    149        }
    150        if (object == null) {
    151            return "";
    152        }
    153        if (object instanceof NodePointer) {
    154            return stringValue(((NodePointer) object).getValue());
    155        }
    156        if (object instanceof EvalContext) {
    157            final EvalContext ctx = (EvalContext) object;
    158            final Pointer ptr = ctx.getSingleNodePointer();
    159            return ptr == null ? "" : stringValue(ptr);
    160        }
    161        return String.valueOf(object);
    162    }
    163
    164    /**
    165     * Constructs a new instance.
    166     *
    167     * @deprecated Will be private in the next major version.
    168     */
    169    @Deprecated
    170    public InfoSetUtil() {
    171        // empty
    172    }
    173}