View Javadoc

    1   /*
    2    * $Header: /home/projects/jaxen/scm/jaxen/src/java/main/org/jaxen/function/BooleanFunction.java,v 1.16 2005/06/28 13:44:45 elharo Exp $
    3    * $Revision: 1.16 $
    4    * $Date: 2005/06/28 13:44:45 $
    5    *
    6    * ====================================================================
    7    *
    8    * Copyright (C) 2000-2002 bob mcwhirter & James Strachan.
    9    * All rights reserved.
    10   *
    11   * Redistribution and use in source and binary forms, with or without
    12   * modification, are permitted provided that the following conditions
    13   * are met:
    14   *
    15   * 1. Redistributions of source code must retain the above copyright
    16   *    notice, this list of conditions, and the following disclaimer.
    17   *
    18   * 2. Redistributions in binary form must reproduce the above copyright
    19   *    notice, this list of conditions, and the disclaimer that follows
    20   *    these conditions in the documentation and/or other materials
    21   *    provided with the distribution.
    22   *
    23   * 3. The name "Jaxen" must not be used to endorse or promote products
    24   *    derived from this software without prior written permission.  For
    25   *    written permission, please contact license@jaxen.org.
    26   *
    27   * 4. Products derived from this software may not be called "Jaxen", nor
    28   *    may "Jaxen" appear in their name, without prior written permission
    29   *    from the Jaxen Project Management (pm@jaxen.org).
    30   *
    31   * In addition, we request (but do not require) that you include in the
    32   * end-user documentation provided with the redistribution and/or in the
    33   * software itself an acknowledgement equivalent to the following:
    34   *     "This product includes software developed by the
    35   *      Jaxen Project <http://www.jaxen.org/>."
    36   * Alternatively, the acknowledgment may be graphical using the logos
    37   * available at http://www.jaxen.org/
    38   *
    39   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
    40   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    41   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    42   * DISCLAIMED.  IN NO EVENT SHALL THE Jaxen AUTHORS OR THE PROJECT
    43   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    44   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    45   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
    46   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    47   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    48   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    49   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    50   * SUCH DAMAGE.
    51   *
    52   * ====================================================================
    53   * This software consists of voluntary contributions made by many
    54   * individuals on behalf of the Jaxen Project and was originally
    55   * created by bob mcwhirter <bob@werken.com> and
    56   * James Strachan <jstrachan@apache.org>.  For more information on the
    57   * Jaxen Project, please see <http://www.jaxen.org/>.
    58   *
    59   * $Id: BooleanFunction.java,v 1.16 2005/06/28 13:44:45 elharo Exp $
    60   */
    61
    62
    63  package org.jaxen.function;
    64
    65  import java.util.List;
    66
    67  import org.jaxen.Context;
    68  import org.jaxen.Function;
    69  import org.jaxen.FunctionCallException;
    70  import org.jaxen.Navigator;
    71
    72  /***
    73   * <p>
    74   * <b>4.3</b> <code><i>boolean</i> boolean(<i>object</i>)</code>
    75   * </p>
    76   *
    77   * <blockquote
    78   * src="http://www.w3.org/TR/xpath#section-Boolean-Functions">
    79   * <p>
    80   * The <b><a href="http://www.w3.org/TR/xpath#function-boolean" target="_top">boolean</a></b>
    81   * function converts its argument to a boolean as follows:
    82   * </p>
    83   *
    84   * <ul>
    85   *
    86   * <li>
    87   * <p>
    88   * a number is true if and only if it is neither positive or negative
    89   * zero nor NaN
    90   * </p>
    91   * </li>
    92   *
    93   * <li>
    94   * <p>
    95   * a node-set is true if and only if it is non-empty
    96   * </p>
    97   * </li>
    98   *
    99   * <li>
    100  * <p>
    101  * a string is true if and only if its length is non-zero
    102  * </p>
    103  * </li>
    104  *
    105  * <li>
    106  *
    107  * <p>
    108  * an object of a type other than the four basic types is converted to a
    109  * boolean in a way that is dependent on that type
    110  * </p></li></ul>
    111  * </blockquote>
    112  *
    113  * @author bob mcwhirter (bob @ werken.com)
    114  * @see <a href="http://www.w3.org/TR/xpath#function-boolean">Section 4.3 of the XPath Specification</a>
    115  */
    116 public class BooleanFunction implements Function
    117 {
    118
    119
    120     /***
    121      * Create a new <code>BooleanFunction</code> object.
    122      */
    123     public BooleanFunction() {}
    124
    125     /*** Convert the argument to a <code>Boolean</code>
    126      *
    127      * @param context the context at the point in the
    128      *         expression when the function is called
    129      * @param args a list with exactly one item which will be converted to a
    130      *     <code>Boolean</code>
    131      *
    132      * @return the result of evaluating the function;
    133      *     <code>Boolean.TRUE</code> or <code>Boolean.FALSE</code>
    134      *
    135      * @throws FunctionCallException if <code>args</code> has more or less than one item
    136      */
    137     public Object call(Context context,
    138                        List args) throws FunctionCallException
    139     {
    140         if ( args.size() == 1 )
    141         {
    142             return evaluate( args.get(0), context.getNavigator() );
    143         }
    144
    145         throw new FunctionCallException("boolean() requires one argument");
    146     }
    147
    148     /***
    149      * <p>Convert the argument <code>obj</code> to a <code>Boolean</code>
    150      * according to the following rules:</p>
    151      *
    152      * <ul>
    153      * <li>Lists are false if they're empty; true if they're not.</li>
    154      * <li>Booleans are false if they're false; true if they're true.</li>
    155      * <li>Strings are false if they're empty; true if they're not.</li>
    156      * <li>Numbers are false if they're 0 or NaN; true if they're not.</li>
    157      * <li>All other objects are true.</li>
    158      * </ul>
    159      *
    160      * @param obj the object to convert to a boolean
    161      * @param nav ignored
    162      *
    163      * @return <code>Boolean.TRUE</code> or <code>Boolean.FALSE</code>
    164      */
    165     public static Boolean evaluate(Object obj, Navigator nav)
    166     {
    167         if ( obj instanceof List )
    168         {
    169             List list = (List) obj;
    170
    171             // if it's an empty list, then we have a null node-set -> false
    172             if (list.size() == 0)
    173             {
    174                 return Boolean.FALSE;
    175             }
    176
    177             // otherwise, unwrap the list and check the primitive
    178             obj = list.get(0);
    179         }
    180
    181         // now check for primitive types
    182         // otherwise a non-empty node-set is true
    183
    184         // if it's a Boolean, let it decide
    185         if ( obj instanceof Boolean )
    186         {
    187             return (Boolean) obj;
    188         }
    189         // if it's a Number, != 0 -> true
    190         else if ( obj instanceof Number )
    191         {
    192             double d = ((Number) obj).doubleValue();
    193             if ( d == 0 || Double.isNaN(d) )
    194             {
    195                 return Boolean.FALSE;
    196             }
    197             return Boolean.TRUE;
    198         }
    199         // if it's a String, "" -> false
    200         else if ( obj instanceof String )
    201         {
    202             return ( ((String)obj).length() > 0
    203                      ? Boolean.TRUE
    204                      : Boolean.FALSE );
    205         }
    206         else
    207         {
    208             // assume it's a node so that this node-set is non-empty
    209             // and so it's true
    210             return ( obj != null ) ? Boolean.TRUE : Boolean.FALSE;
    211         }
    212
    213     }
    214 }