1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 package org.jaxen.function;
50
51 import java.util.List;
52
53 import org.jaxen.Context;
54 import org.jaxen.Function;
55 import org.jaxen.FunctionCallException;
56 import org.jaxen.Navigator;
57
58 /***
59 * <p>
60 * <b>4.3</b> <code><i>boolean</i> boolean(<i>object</i>)</code>
61 * </p>
62 *
63 * <blockquote
64 * src="http://www.w3.org/TR/xpath#section-Boolean-Functions">
65 * <p>
66 * The <b><a href="http://www.w3.org/TR/xpath#function-boolean" target="_top">boolean</a></b>
67 * function converts its argument to a boolean as follows:
68 * </p>
69 *
70 * <ul>
71 *
72 * <li>
73 * <p>
74 * a number is true if and only if it is neither positive or negative
75 * zero nor NaN
76 * </p>
77 * </li>
78 *
79 * <li>
80 * <p>
81 * a node-set is true if and only if it is non-empty
82 * </p>
83 * </li>
84 *
85 * <li>
86 * <p>
87 * a string is true if and only if its length is non-zero
88 * </p>
89 * </li>
90 *
91 * <li>
92 *
93 * <p>
94 * an object of a type other than the four basic types is converted to a
95 * boolean in a way that is dependent on that type
96 * </p></li></ul>
97 * </blockquote>
98 *
99 * @author bob mcwhirter (bob @ werken.com)
100 * @see <a href="http://www.w3.org/TR/xpath#function-boolean">Section 4.3 of the XPath Specification</a>
101 */
102 public class BooleanFunction implements Function
103 {
104
105
106 /***
107 * Create a new <code>BooleanFunction</code> object.
108 */
109 public BooleanFunction() {}
110
111 /*** Convert the argument to a <code>Boolean</code>
112 *
113 * @param context the context at the point in the
114 * expression when the function is called
115 * @param args a list with exactly one item which will be converted to a
116 * <code>Boolean</code>
117 *
118 * @return the result of evaluating the function;
119 * <code>Boolean.TRUE</code> or <code>Boolean.FALSE</code>
120 *
121 * @throws FunctionCallException if <code>args</code> has more or less than one item
122 */
123 public Object call(Context context,
124 List args) throws FunctionCallException
125 {
126 if ( args.size() == 1 )
127 {
128 return evaluate( args.get(0), context.getNavigator() );
129 }
130
131 throw new FunctionCallException("boolean() requires one argument");
132 }
133
134 /***
135 * <p>Convert the argument <code>obj</code> to a <code>Boolean</code>
136 * according to the following rules:</p>
137 *
138 * <ul>
139 * <li>Lists are false if they're empty; true if they're not.</li>
140 * <li>Booleans are false if they're false; true if they're true.</li>
141 * <li>Strings are false if they're empty; true if they're not.</li>
142 * <li>Numbers are false if they're 0 or NaN; true if they're not.</li>
143 * <li>All other objects are true.</li>
144 * </ul>
145 *
146 * @param obj the object to convert to a boolean
147 * @param nav ignored
148 *
149 * @return <code>Boolean.TRUE</code> or <code>Boolean.FALSE</code>
150 */
151 public static Boolean evaluate(Object obj, Navigator nav)
152 {
153 if ( obj instanceof List )
154 {
155 List list = (List) obj;
156
157
158 if (list.size() == 0)
159 {
160 return Boolean.FALSE;
161 }
162
163
164 obj = list.get(0);
165 }
166
167
168
169
170
171 if ( obj instanceof Boolean )
172 {
173 return (Boolean) obj;
174 }
175
176 else if ( obj instanceof Number )
177 {
178 double d = ((Number) obj).doubleValue();
179 if ( d == 0 || Double.isNaN(d) )
180 {
181 return Boolean.FALSE;
182 }
183 return Boolean.TRUE;
184 }
185
186 else if ( obj instanceof String )
187 {
188 return ( ((String)obj).length() > 0
189 ? Boolean.TRUE
190 : Boolean.FALSE );
191 }
192 else
193 {
194
195
196 return ( obj != null ) ? Boolean.TRUE : Boolean.FALSE;
197 }
198
199 }
200 }