KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.value;
2 import net.sf.saxon.expr.ExpressionTool;
3 import net.sf.saxon.expr.StaticProperty;
4 import net.sf.saxon.expr.XPathContext;
5 import net.sf.saxon.expr.Token;
6 import net.sf.saxon.om.*;
7 import net.sf.saxon.pattern.*;
8 import net.sf.saxon.trans.XPathException;
9 import net.sf.saxon.type.ItemType;
10 import net.sf.saxon.type.Type;
11 import net.sf.saxon.style.StandardNames;
12
13 import java.io.PrintStream JavaDoc;
14
15 /**
16 * A value that is a sequence containing zero or one nodes
17 */

18
19 public class SingletonNode extends Value {
20
21     protected NodeInfo node = null;
22
23
24     /**
25      * Create a node-set containing zero or one nodes
26      * @param node The node to be contained in the node-set, or null if the node-set
27      * is to be empty
28     */

29
30     public SingletonNode(NodeInfo node) {
31         this.node = node;
32     }
33
34     /**
35      * An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
36      * This method indicates which of these methods is prefered.
37      */

38
39     public int getImplementationMethod() {
40         return EVALUATE_METHOD;
41     }
42
43     /**
44       * Process the instruction, without returning any tail calls
45       * @param context The dynamic context, giving access to the current node,
46       * the current variables, etc.
47       */

48
49     public void process(XPathContext context) throws XPathException {
50         if (node != null) {
51             context.getReceiver().append(node, 0, NodeInfo.ALL_NAMESPACES);
52         }
53     }
54
55
56     /**
57      * Determine the data type of the items in the expression. This method determines the most
58      * precise type that it can, because it is called when testing that the node conforms to a required
59      * type.
60      * @return the most precise possible type of the node.
61     */

62
63     public ItemType getItemType() {
64         switch (node.getNodeKind()) {
65             case Type.DOCUMENT:
66                 // Need to know whether the document is well-formed and if so what the element type is
67
AxisIterator iter = node.iterateAxis(Axis.CHILD);
68                 ItemType elementType = null;
69                 while (true) {
70                     NodeInfo n = (NodeInfo)iter.next();
71                     if (n==null) {
72                         break;
73                     }
74                     int kind = n.getNodeKind();
75                     if (kind==Type.TEXT) {
76                         elementType = null;
77                         break;
78                     } else if (kind==Type.ELEMENT) {
79                         if (elementType != null) {
80                             elementType = null;
81                             break;
82                         }
83                         elementType = new SingletonNode(n).getItemType();
84                     }
85                 }
86                 if (elementType == null) {
87                     return NodeKindTest.DOCUMENT;
88                 } else {
89                     return new DocumentNodeTest((NodeTest)elementType);
90                 }
91
92             case Type.ELEMENT:
93                 int eltype = node.getTypeAnnotation();
94                 if (eltype == -1 || eltype == StandardNames.XDT_UNTYPED || eltype == StandardNames.XS_ANY_TYPE) {
95                     return new NameTest(Type.ELEMENT, node.getFingerprint(), node.getNamePool());
96                 } else {
97                     return new CombinedNodeTest(
98                             new NameTest(Type.ELEMENT, node.getFingerprint(), node.getNamePool()),
99                             Token.INTERSECT,
100                             new ContentTypeTest(Type.ELEMENT, node.getConfiguration().getSchemaType(eltype),
101                                     node.getConfiguration()));
102                 }
103
104             case Type.ATTRIBUTE:
105                 int attype = node.getTypeAnnotation();
106                 if (attype == -1 || attype == StandardNames.XDT_UNTYPED_ATOMIC) {
107                     return new NameTest(Type.ATTRIBUTE, node.getFingerprint(), node.getNamePool());
108                 } else {
109                     return new CombinedNodeTest(
110                             new NameTest(Type.ATTRIBUTE, node.getFingerprint(), node.getNamePool()),
111                             Token.INTERSECT,
112                             new ContentTypeTest(Type.ATTRIBUTE, node.getConfiguration().getSchemaType(attype),
113                                     node.getConfiguration()));
114                 }
115
116             case Type.TEXT:
117                 return NodeKindTest.TEXT;
118
119             case Type.COMMENT:
120                 return NodeKindTest.COMMENT;
121
122             case Type.PROCESSING_INSTRUCTION:
123                  return NodeKindTest.PROCESSING_INSTRUCTION;
124
125             case Type.NAMESPACE:
126                 return NodeKindTest.NAMESPACE;
127
128             default:
129                 throw new IllegalArgumentException JavaDoc("Unknown node kind " + node.getNodeKind());
130         }
131     }
132
133     /**
134     * Determine the static cardinality
135     */

136
137     public int getCardinality() {
138         if (node==null) {
139             return StaticProperty.EMPTY;
140         } else {
141             return StaticProperty.EXACTLY_ONE;
142         }
143     }
144
145     /**
146      * Get the length of the sequence
147      */

148
149     public int getLength() throws XPathException {
150         return (node==null ? 0 : 1);
151     }
152
153     /**
154      * Get the n'th item in the sequence (starting from 0). This is defined for all
155      * SequenceValues, but its real benefits come for a SequenceValue stored extensionally
156      * (or for a MemoClosure, once all the values have been read)
157      */

158
159     public Item itemAt(int n) throws XPathException {
160         if (n==0 && node!=null) {
161             return node;
162         } else {
163             return null;
164         }
165
166     }
167
168     /**
169     * Get the node that forms the node-set. Return null if there is none.
170     */

171
172     public NodeInfo getNode() {
173         return node;
174     }
175
176     /**
177     * Get the static properties of this expression (other than its type). The result is
178     * bit-signficant. These properties are used for optimizations. In general, if
179     * property bit is set, it is true, but if it is unset, the value is unknown.
180     */

181
182     public int getSpecialProperties() {
183         return StaticProperty.ORDERED_NODESET |
184                 StaticProperty.NON_CREATIVE;
185     }
186
187     /**
188     * Return an enumeration of this nodeset value.
189     */

190
191     public SequenceIterator iterate(XPathContext context) {
192         return SingletonIterator.makeIterator(node);
193     }
194
195     /**
196     * Evaluate as an item
197     */

198
199     public Item evaluateItem(XPathContext context) {
200         return node;
201     }
202
203     /**
204      * Get the effective boolean value
205      */

206
207     public boolean effectiveBooleanValue(XPathContext context) {
208         return (node != null);
209     }
210
211     /**
212      * Convert the value to a string, using the serialization rules.
213      * For atomic values this is the same as a cast; for sequence values
214      * it gives a space-separated list. For QNames and NOTATIONS, or lists
215      * containing them, it fails.
216      */

217
218     public String JavaDoc getStringValue() {
219         return (node==null ? "" : node.getStringValue());
220     }
221
222     /**
223       * Evaluate an expression as a String. This function must only be called in contexts
224       * where it is known that the expression will return a single string (or where an empty sequence
225       * is to be treated as a zero-length string). Implementations should not attempt to convert
226       * the result to a string, other than converting () to "". This method is used mainly to
227       * evaluate expressions produced by compiling an attribute value template.
228       *
229       * @exception XPathException if any dynamic error occurs evaluating the
230       * expression
231       * @param context The context in which the expression is to be evaluated
232       * @return the value of the expression, evaluated in the current context.
233       * The expression must return a string or (); if the value of the
234       * expression is (), this method returns "".
235       */

236
237      public String JavaDoc evaluateAsString(XPathContext context) throws XPathException {
238          if (node==null) return "";
239          return node.getStringValue();
240      }
241
242
243     /**
244     * Diagnostic display
245     */

246
247     public void display(int depth, NamePool pool, PrintStream JavaDoc out) {
248         if (node==null) {
249             out.println(ExpressionTool.indent(depth) + "Empty node-set");
250         } else {
251             out.println(ExpressionTool.indent(depth) + "Node " + Navigator.getPath(node));
252         }
253     }
254
255     /**
256     * Convert to Java object (for passing to external functions)
257     */

258
259     public Object JavaDoc convertToJava(Class JavaDoc target, XPathContext context) throws XPathException {
260         if (node == null) {
261             return null;
262         }
263         if (target.isAssignableFrom(node.getClass())) {
264             return node;
265         }
266         if (target == String JavaDoc.class) {
267             return node.getStringValue();
268         }
269         return super.convertToJava(target, context);
270     }
271
272 }
273
274 //
275
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
276
// you may not use this file except in compliance with the License. You may obtain a copy of the
277
// License at http://www.mozilla.org/MPL/
278
//
279
// Software distributed under the License is distributed on an "AS IS" basis,
280
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
281
// See the License for the specific language governing rights and limitations under the License.
282
//
283
// The Original Code is: all this file.
284
//
285
// The Initial Developer of the Original Code is Michael H. Kay.
286
//
287
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
288
//
289
// Contributor(s): none.
290
//
291

292
Popular Tags