001: package net.sf.saxon.value;
002:
003: import net.sf.saxon.expr.XPathContext;
004: import net.sf.saxon.trans.DynamicError;
005: import net.sf.saxon.trans.XPathException;
006: import net.sf.saxon.type.*;
007:
008: /**
009: * An XPath value that encapsulates a Java object. Such a value can only be obtained by
010: * calling an extension function that returns it.
011: */
012:
013: public class ObjectValue extends AtomicValue {
014: private Object value;
015:
016: /**
017: * Default constructor for use in subclasses
018: */
019:
020: public ObjectValue() {
021: }
022:
023: /**
024: * Constructor
025: * @param object the object to be encapsulated
026: */
027:
028: public ObjectValue(Object object) {
029: this .value = object;
030: }
031:
032: /**
033: * Set the value in this object value
034: */
035:
036: public void setValue(Object value) {
037: this .value = value;
038: }
039:
040: /**
041: * Convert to target data type
042: */
043:
044: public AtomicValue convertPrimitive(BuiltInAtomicType requiredType,
045: boolean validate, XPathContext context) {
046: switch (requiredType.getPrimitiveType()) {
047: case Type.ANY_ATOMIC:
048: case Type.OBJECT:
049: case Type.ITEM:
050: return this ;
051: case Type.BOOLEAN:
052: return BooleanValue.get((value == null ? false : value
053: .toString().length() > 0));
054: case Type.STRING:
055: return new StringValue(getStringValue());
056: case Type.UNTYPED_ATOMIC:
057: return new UntypedAtomicValue(getStringValue());
058: default:
059: return new StringValue(getStringValue()).convertPrimitive(
060: requiredType, validate, context);
061: }
062: }
063:
064: /**
065: * Get the value as a String
066: * @return a String representation of the value
067: */
068:
069: public String getStringValue() {
070: return (value == null ? "" : value.toString());
071: }
072:
073: /**
074: * Determine the data type of the expression
075: * @return Type.OBJECT
076: * @param th
077: */
078:
079: public ItemType getItemType(TypeHierarchy th) {
080: return new ExternalObjectType(value.getClass());
081: }
082:
083: /**
084: * Get the encapsulated object
085: */
086:
087: public Object getObject() {
088: return value;
089: }
090:
091: /**
092: * Determine if two ObjectValues are equal
093: * @throws ClassCastException if they are not comparable
094: */
095:
096: public boolean equals(Object other) {
097: return this .value.equals(((ObjectValue) other).value);
098: }
099:
100: public int hashCode() {
101: return value.hashCode();
102: }
103:
104: /**
105: * Convert to Java object (for passing to external functions)
106: */
107:
108: public Object convertToJava(Class target, XPathContext context)
109: throws XPathException {
110:
111: if (value == null)
112: return null;
113:
114: if (target.isAssignableFrom(value.getClass())) {
115: return value;
116: } else if (target == Value.class || target == ObjectValue.class) {
117: return this ;
118: } else if (target == boolean.class || target == Boolean.class) {
119: BooleanValue bval = (BooleanValue) convert(Type.BOOLEAN,
120: context);
121: return Boolean.valueOf(bval.getBooleanValue());
122: } else if (target == String.class
123: || target == CharSequence.class) {
124: return getStringValue();
125: } else if (target == double.class || target == Double.class) {
126: DoubleValue bval = (DoubleValue) convert(Type.DOUBLE,
127: context);
128: return new Double(bval.getDoubleValue());
129: } else if (target == float.class || target == Float.class) {
130: DoubleValue bval = (DoubleValue) convert(Type.FLOAT,
131: context);
132: return new Float(bval.getDoubleValue());
133: } else if (target == long.class || target == Long.class) {
134: IntegerValue bval = (IntegerValue) convert(Type.INTEGER,
135: context);
136: return new Long(bval.longValue());
137: } else if (target == int.class || target == Integer.class) {
138: IntegerValue bval = (IntegerValue) convert(Type.INTEGER,
139: context);
140: return new Integer((int) bval.longValue());
141: } else if (target == short.class || target == Short.class) {
142: IntegerValue bval = (IntegerValue) convert(Type.INTEGER,
143: context);
144: return new Short((short) bval.longValue());
145: } else if (target == byte.class || target == Byte.class) {
146: IntegerValue bval = (IntegerValue) convert(Type.INTEGER,
147: context);
148: return new Byte((byte) bval.longValue());
149: } else if (target == char.class || target == Character.class) {
150: String s = getStringValue();
151: if (s.length() == 1) {
152: return new Character(s.charAt(0));
153: } else {
154: throw new DynamicError(
155: "Cannot convert string to Java char unless length is 1");
156: }
157: } else {
158: throw new DynamicError("Conversion of external object to "
159: + target.getName() + " is not supported");
160: }
161: }
162:
163: }
164:
165: //
166: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
167: // you may not use this file except in compliance with the License. You may obtain a copy of the
168: // License at http://www.mozilla.org/MPL/
169: //
170: // Software distributed under the License is distributed on an "AS IS" basis,
171: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
172: // See the License for the specific language governing rights and limitations under the License.
173: //
174: // The Original Code is: all this file.
175: //
176: // The Initial Developer of the Original Code is Michael H. Kay.
177: //
178: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
179: //
180: // Contributor(s): none.
181: //
|