001: package net.sf.saxon.value;
002:
003: import net.sf.saxon.Err;
004: import net.sf.saxon.expr.XPathContext;
005: import net.sf.saxon.trans.DynamicError;
006: import net.sf.saxon.trans.XPathException;
007: import net.sf.saxon.type.*;
008:
009: /**
010: * A boolean XPath value
011: */
012:
013: public final class BooleanValue extends AtomicValue implements
014: Comparable {
015: private boolean value;
016:
017: /**
018: * The boolean value TRUE
019: */
020: public static final BooleanValue TRUE = new BooleanValue(true);
021: /**
022: * The boolean value FALSE
023: */
024: public static final BooleanValue FALSE = new BooleanValue(false);
025:
026: /**
027: * Private Constructor: create a boolean value. Only two instances of this class are
028: * ever created, one to represent true and one to represent false.
029: * @param value the initial value, true or false
030: */
031:
032: private BooleanValue(boolean value) {
033: this .value = value;
034: }
035:
036: /**
037: * Factory method: get a BooleanValue
038: *
039: * @param value true or false, to determine which boolean value is
040: * required
041: * @return the BooleanValue requested
042: */
043:
044: public static BooleanValue get(boolean value) {
045: return (value ? TRUE : FALSE);
046: }
047:
048: /**
049: * Convert a string to a boolean value, using the XML Schema rules (including
050: * whitespace trimming)
051: * @param s the input string
052: * @return the relevant BooleanValue if validation succeeds; or an ErrorValue if not.
053: */
054:
055: public static AtomicValue fromString(CharSequence s) {
056: s = trimWhitespace(s).toString();
057: if (s.equals("true") || s.equals("1")) {
058: return TRUE;
059: } else if (s.equals("false") || s.equals("0")) {
060: return FALSE;
061: } else {
062: ValidationException err = new ValidationException(
063: "The string " + Err.wrap(s, Err.VALUE)
064: + " cannot be cast to a boolean");
065: err.setErrorCode("FORG0001");
066: return new ValidationErrorValue(err);
067: }
068: }
069:
070: /**
071: * Get the value
072: * @return true or false, the actual boolean value of this BooleanValue
073: */
074:
075: public boolean getBooleanValue() {
076: return value;
077: }
078:
079: /**
080: * Get the effective boolean value of this expression
081: *
082: * @param context dynamic evaluation context, not used in this
083: * implementation
084: * @return the boolean value
085: */
086: public boolean effectiveBooleanValue(XPathContext context) {
087: return value;
088: }
089:
090: /**
091: * Convert to target data type
092: * @param requiredType an integer identifying the required atomic type
093: * @param context
094: * @return an AtomicValue, a value of the required type
095: */
096:
097: public AtomicValue convertPrimitive(BuiltInAtomicType requiredType,
098: boolean validate, XPathContext context) {
099: switch (requiredType.getPrimitiveType()) {
100: case Type.BOOLEAN:
101: case Type.ANY_ATOMIC:
102: case Type.ITEM:
103: return this ;
104: case Type.NUMBER:
105: case Type.INTEGER:
106: return new IntegerValue(value ? 1 : 0);
107: case Type.DECIMAL:
108: case Type.FLOAT:
109: case Type.DOUBLE:
110: return new IntegerValue(value ? 1 : 0).convertPrimitive(
111: requiredType, validate, context);
112: case Type.STRING:
113: return new StringValue(getStringValueCS());
114: case Type.UNTYPED_ATOMIC:
115: return new UntypedAtomicValue(getStringValueCS());
116: default:
117: ValidationException err = new ValidationException(
118: "Cannot convert boolean to "
119: + requiredType.getDisplayName());
120: err.setErrorCode("XPTY0004");
121: err.setIsTypeError(true);
122: return new ValidationErrorValue(err);
123: }
124: }
125:
126: /**
127: * Convert to string
128: * @return "true" or "false"
129: */
130:
131: public String getStringValue() {
132: return (value ? "true" : "false");
133: }
134:
135: /**
136: * Determine the data type of the expression
137: * @return Type.BOOLEAN,
138: * @param th
139: */
140:
141: public ItemType getItemType(TypeHierarchy th) {
142: return Type.BOOLEAN_TYPE;
143: }
144:
145: /**
146: * Convert to Java object (for passing to external functions)
147: *
148: * @param target the Java class to which conversion is required
149: * @exception XPathException if conversion is not possible or fails
150: * @return An object of the specified Java class
151: */
152:
153: public Object convertToJava(Class target, XPathContext context)
154: throws XPathException {
155: if (target == Object.class) {
156: return Boolean.valueOf(value);
157: } else if (target.isAssignableFrom(BooleanValue.class)) {
158: return this ;
159: } else if (target == boolean.class) {
160: return Boolean.valueOf(value);
161: } else if (target == Boolean.class) {
162: return Boolean.valueOf(value);
163: } else if (target == String.class
164: || target == CharSequence.class) {
165: return getStringValue();
166: } else if (target == double.class) {
167: return new Double((double) (value ? 1 : 0));
168: } else if (target == Double.class) {
169: return new Double((double) (value ? 1 : 0));
170: } else if (target == float.class) {
171: return new Float((float) (value ? 1 : 0));
172: } else if (target == Float.class) {
173: return new Float((float) (value ? 1 : 0));
174: } else if (target == long.class) {
175: return new Long((long) (value ? 1 : 0));
176: } else if (target == Long.class) {
177: return new Long((long) (value ? 1 : 0));
178: } else if (target == int.class) {
179: return new Integer(value ? 1 : 0);
180: } else if (target == Integer.class) {
181: return new Integer(value ? 1 : 0);
182: } else if (target == short.class) {
183: return new Short((short) (value ? 1 : 0));
184: } else if (target == Short.class) {
185: return new Short((short) (value ? 1 : 0));
186: } else if (target == byte.class) {
187: return new Byte((byte) (value ? 1 : 0));
188: } else if (target == Byte.class) {
189: return new Byte((byte) (value ? 1 : 0));
190: } else if (target == char.class) {
191: return new Character(value ? '1' : '0');
192: } else if (target == Character.class) {
193: return new Character(value ? '1' : '0');
194: } else {
195: Object o = super .convertToJava(target, context);
196: if (o == null) {
197: DynamicError err = new DynamicError(
198: "Conversion of boolean to " + target.getName()
199: + " is not supported");
200: err.setXPathContext(context);
201: err.setErrorCode("SAXON:0000");
202: throw err;
203: }
204: return o;
205: }
206: }
207:
208: /**
209: * Compare the value to another boolean value
210: *
211: * @throws ClassCastException if the other value is not a BooleanValue
212: * (the parameter is declared as Object to satisfy the Comparable
213: * interface)
214: * @param other The other boolean value
215: * @return -1 if this one is the lower, 0 if they are equal, +1 if this
216: * one is the higher. False is considered to be less than true.
217: */
218:
219: public int compareTo(Object other) {
220: if (!(other instanceof BooleanValue)) {
221: throw new ClassCastException(
222: "Boolean values are not comparable to "
223: + other.getClass());
224: }
225: if (this .value == ((BooleanValue) other).value)
226: return 0;
227: if (this .value)
228: return +1;
229: return -1;
230: }
231:
232: /**
233: * Determine whether two boolean values are equal
234: *
235: * @param other the value to be compared to this value
236: * @return true if the other value is a boolean value and is equal to this
237: * value
238: */
239: public boolean equals(Object other) {
240: if (!(other instanceof BooleanValue)) {
241: throw new ClassCastException(
242: "Boolean values are not comparable to "
243: + other.getClass());
244: }
245: return (this .value == ((BooleanValue) other).value);
246: }
247:
248: /**
249: * Get a hash code for comparing two BooleanValues
250: *
251: * @return the hash code
252: */
253: public int hashCode() {
254: return (value ? 0 : 1);
255: }
256:
257: /**
258: * Diagnostic display of this value as a string
259: * @return a string representation of this value: "true()" or "false()"
260: */
261: public String toString() {
262: return getStringValue() + "()";
263: }
264: }
265:
266: //
267: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
268: // you may not use this file except in compliance with the License. You may obtain a copy of the
269: // License at http://www.mozilla.org/MPL/
270: //
271: // Software distributed under the License is distributed on an "AS IS" basis,
272: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
273: // See the License for the specific language governing rights and limitations under the License.
274: //
275: // The Original Code is: all this file.
276: //
277: // The Initial Developer of the Original Code is Michael H. Kay.
278: //
279: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
280: //
281: // Contributor(s): none.
282: //
|