KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > value > AtomicValue


1 package net.sf.saxon.value;
2
3 import net.sf.saxon.Err;
4 import net.sf.saxon.ConversionContext;
5 import net.sf.saxon.expr.ExpressionTool;
6 import net.sf.saxon.expr.StaticContext;
7 import net.sf.saxon.expr.StaticProperty;
8 import net.sf.saxon.expr.XPathContext;
9 import net.sf.saxon.om.*;
10 import net.sf.saxon.trans.StaticError;
11 import net.sf.saxon.trans.XPathException;
12 import net.sf.saxon.trans.DynamicError;
13 import net.sf.saxon.type.*;
14
15 import java.io.PrintStream JavaDoc;
16
17
18 /**
19  * The AtomicValue class corresponds to the concept of an atomic value in the
20  * XPath 2.0 data model. Atomic values belong to one of the 19 primitive types
21  * defined in XML Schema; or they are of type xdt:untypedAtomic; or they are
22  * "external objects", representing a Saxon extension to the XPath 2.0 type system.
23  * <p>
24  * The AtomicValue class contains some methods that are suitable for applications
25  * to use, and many others that are designed for internal use by Saxon itself.
26  * These have not been fully classified. At present, therefore, none of the methods on this
27  * class should be considered to be part of the public Saxon API.
28  * <p>
29  * @author Michael H. Kay
30  */

31
32 public abstract class AtomicValue extends Value implements Item {
33
34     /**
35      * Test whether the type of this atomic value is a built-in type.
36      * Default implementation returns true.
37      */

38
39     public boolean hasBuiltInType() {
40         return true;
41     }
42
43     /**
44      * An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
45      * This method indicates which of these methods is prefered.
46      */

47
48     public int getImplementationMethod() {
49         return EVALUATE_METHOD;
50     }
51
52     /**
53      * Process the instruction, without returning any tail calls
54      *
55      * @param context The dynamic context, giving access to the current node,
56      * the current variables, etc.
57      */

58
59     public void process(XPathContext context) throws XPathException {
60         Item item = evaluateItem(context);
61         if (item != null) {
62             context.getReceiver().append(item, 0, NodeInfo.ALL_NAMESPACES);
63         }
64     }
65
66     /**
67      * Determine the static cardinality
68      *
69      * @return code identifying the cardinality
70      * @see net.sf.saxon.value.Cardinality
71      */

72
73     public final int getCardinality() {
74         return StaticProperty.EXACTLY_ONE;
75     }
76
77     /**
78      * Convert the value to a given type. The result of the conversion will be an
79      * atomic value of the required type. This method works only where the target
80      * type is a built-in type.
81      *
82      * @param requiredType type code of the required atomic type
83      * @param conversion
84      * @return the result of the conversion, if conversion was possible. This
85      * will always be an instance of the class corresponding to the type
86      * of value requested
87      * @throws XPathException if conversion is not allowed for this
88      * required type, or if the particular value cannot be converted
89      */

90
91     public final AtomicValue convert(int requiredType, ConversionContext conversion) throws XPathException {
92         SchemaType schemaType = BuiltInSchemaFactory.getSchemaType(requiredType);
93         if (schemaType instanceof BuiltInAtomicType) {
94             AtomicValue val = convertPrimitive((BuiltInAtomicType)schemaType, true, conversion);
95             if (val instanceof ValidationErrorValue) {
96                 throw ((ValidationErrorValue)val).getException();
97             }
98             return val;
99         } else {
100             throw new IllegalArgumentException JavaDoc(
101                     "This method can only be used for conversion to a built-in atomic type");
102         }
103     };
104
105     /**
106      * Convert a value to another primitive data type, with control over how validation is
107      * handled.
108      *
109      * @param requiredType type code of the required atomic type
110      * @param validate true if validation is required. If set to false, the caller guarantees that
111      * the value is valid for the target data type, and that further validation is therefore not required.
112      * Note that a validation failure may be reported even if validation was not requested.
113      * @param conversion The conversion context to be used. This is required at present only when converting to
114      * a date or time: it provides the implicit timezone.
115      * @return the result of the conversion, if successful. If unsuccessful, the value returned
116      * will be an ErrorValue. The caller must check for this condition. No exception is thrown, instead
117      * the exception will be encapsulated within the ErrorValue.
118      */

119     public abstract AtomicValue convertPrimitive(BuiltInAtomicType requiredType, boolean validate, ConversionContext conversion);
120
121     /**
122      * Convert the value to a given type. The result of the conversion will be
123      * an atomic value of the required type. This method works where the target
124      * type is a built-in atomic type and also where it is a user-defined atomic
125      * type.
126      *
127      * @param targetType the type to which the value is to be converted
128      * @param context the evaluation context
129      * @param validate true if validation is required, false if the caller already knows that the
130      * value is valid
131      * @return the value after conversion if successful; or a {@link ValidationErrorValue} if conversion failed. The
132      * caller must check for this condition. Validation may fail even if validation was not requested.
133      */

134
135     public AtomicValue convert(AtomicType targetType, ConversionContext context, boolean validate) {
136         if (targetType instanceof BuiltInAtomicType) {
137             return convertPrimitive((BuiltInAtomicType)targetType, validate, context);
138         } else {
139             CharSequence JavaDoc lexicalValue = getStringValueCS();
140             AtomicValue v = convertPrimitive(
141                     (BuiltInAtomicType)targetType.getPrimitiveItemType(),
142                     validate,
143                     context);
144             if (v instanceof ValidationErrorValue) {
145                 // conversion has failed
146
return v;
147             }
148             return targetType.makeDerivedValue(v, lexicalValue, validate);
149         }
150     }
151
152     /**
153      * Get the length of the sequence
154      *
155      * @return always 1 for an atomic value
156      */

157
158     public final int getLength() {
159         return 1;
160     }
161
162     /**
163      * Evaluate the value (this simply returns the value unchanged)
164      *
165      * @param context the evaluation context (not used in this implementation)
166      * @return the value, unchanged
167      * @throws XPathException
168      */

169
170     public Item evaluateItem(XPathContext context) throws XPathException {
171         return this;
172     }
173
174     /**
175      * Iterate over the (single) item in the sequence
176      *
177      * @param context the evaluation context (not used in this implementation)
178      * @return a SequenceIterator that iterates over the single item in this
179      * value
180      */

181
182     public final SequenceIterator iterate(XPathContext context) {
183         return SingletonIterator.makeIterator(this);
184     }
185
186     /**
187      * Evaluate as a string
188      */

189
190     public final String JavaDoc evaluateAsString(XPathContext context) {
191         return getStringValue();
192     }
193
194     /**
195      * Convert the value to a string, using the serialization rules.
196      * For atomic values this is the same as a cast; for sequence values
197      * it gives a space-separated list. This method is refined for AtomicValues
198      * so that it never throws an Exception.
199      */

200
201     public abstract String JavaDoc getStringValue();
202
203     /**
204      * Get the value of the item as a CharSequence. This is in some cases more efficient than
205      * the version of the method that returns a String.
206      */

207
208     public CharSequence JavaDoc getStringValueCS() {
209         return getStringValue();
210     }
211
212     /**
213      * Get the typed value of this item
214      *
215      * @return the typed value of the expression (which is this value)
216      */

217
218     public final SequenceIterator getTypedValue() {
219         return SingletonIterator.makeIterator(this);
220     }
221
222     /**
223      * Get the primitive value (the value in the value space). This returns an
224      * AtomicValue of a class that would be used to represent the primitive value.
225      * In effect this means that for built-in types, it returns the value itself,
226      * but for user-defined type, it returns the primitive value minus the type
227      * annotation. Note that getItemType() when applied to the result of this
228      * function does not not necessarily return a primitive type: for example, this
229      * function may return a value of type xdt:dayTimeDuration, which is not a
230      * primitive type as defined by {@link net.sf.saxon.type.Type#isPrimitiveType(int)}
231      */

232
233     public AtomicValue getPrimitiveValue() {
234         // overridden where necessary
235
return this;
236     }
237
238     /**
239      * Get the effective boolean value of the value
240      *
241      * @param context the evaluation context (not used in this implementation)
242      * @return true, unless the value is boolean false, numeric zero, or
243      * zero-length string
244      */

245     public boolean effectiveBooleanValue(XPathContext context) throws XPathException {
246         DynamicError err = new DynamicError("Effective boolean value is not defined for an atomic value of type " +
247                 (context == null ?
248                 "other than boolean, number, or string" :
249                 getItemType().toString(context.getController().getNamePool())));
250         err.setIsTypeError(true);
251         err.setXPathContext(context);
252         throw err;
253         // unless otherwise specified in a subclass
254
}
255
256     /**
257      * Method to extract components of a value. Implemented by some subclasses,
258      * but defined at this level for convenience
259      */

260
261     public AtomicValue getComponent(int component) throws XPathException {
262         throw new UnsupportedOperationException JavaDoc("Data type does not support component extraction");
263     }
264
265     /**
266      * Check statically that the results of the expression are capable of constructing the content
267      * of a given schema type.
268      *
269      * @param parentType The schema type
270      * @param env the static context
271      * @param whole true if this atomic value accounts for the entire content of the containing node
272      * @throws net.sf.saxon.trans.XPathException
273      * if the expression doesn't match the required content type
274      */

275
276     public void checkPermittedContents(SchemaType parentType, StaticContext env, boolean whole) throws XPathException {
277         if (whole) {
278             SimpleType stype = null;
279             if (parentType instanceof SimpleType) {
280                 stype = (SimpleType)parentType;
281             } else if (parentType instanceof ComplexType && ((ComplexType)parentType).isSimpleContent()) {
282                 stype = ((ComplexType)parentType).getSimpleContentType();
283             }
284             if (stype != null && !stype.isNamespaceSensitive()) {
285                 // Can't validate namespace-sensitive content statically
286
XPathException err = stype.validateContent(getStringValueCS(), null, env.getConfiguration());
287                 if (err != null) {
288                     throw err;
289                 }
290                 return;
291             }
292         }
293         if (parentType instanceof ComplexType &&
294                 !((ComplexType)parentType).isSimpleContent() &&
295                 !((ComplexType)parentType).isMixedContent() &&
296                 !Whitespace.isWhite(getStringValueCS())) {
297             StaticError err = new StaticError("Complex type " + parentType.getDescription() +
298                     " does not allow text content " +
299                     Err.wrap(getStringValueCS()));
300             err.setIsTypeError(true);
301             throw err;
302         }
303     }
304
305     /**
306      * Get string value. In general toString() for an atomic value displays the value as it would be
307      * written in XPath: that is, as a literal if available, or as a call on a constructor function
308      * otherwise.
309      */

310
311     public String JavaDoc toString() {
312         return getItemType().toString() + " (\"" + getStringValueCS() + "\")";
313     }
314
315     /**
316      * Compare two values for equality. This supports identity constraints in XML Schema,
317      * which allow list-valued elements and attributes to participate in key and uniqueness constraints.
318      * This method returns false if any error occurs during the comparison, or if any of the items
319      * in either sequence is a node rather than an atomic value. The default implementation of
320      * schemaEquals() is the same as equals(), but subclasses can override this.
321      */

322
323     public boolean schemaEquals(Value obj) {
324         return equals(obj);
325     }
326
327     /**
328      * Diagnostic print of expression structure
329      *
330      * @param level the indentation level of the output
331      * @param out
332      */

333
334     public final void display(int level, NamePool pool, PrintStream JavaDoc out) {
335         out.println(ExpressionTool.indent(level) + toString());
336     }
337
338 }
339
340 //
341
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
342
// you may not use this file except in compliance with the License. You may obtain a copy of the
343
// License at http://www.mozilla.org/MPL/
344
//
345
// Software distributed under the License is distributed on an "AS IS" basis,
346
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
347
// See the License for the specific language governing rights and limitations under the License.
348
//
349
// The Original Code is: all this file.
350
//
351
// The Initial Developer of the Original Code is Michael H. Kay.
352
//
353
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
354
//
355
// Contributor(s): none.
356
//
357

358
Popular Tags