KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > expr > NodeSetIntent


1 package com.icl.saxon.expr;
2 import com.icl.saxon.Context;
3 import com.icl.saxon.Controller;
4 import com.icl.saxon.om.NodeInfo;
5 import com.icl.saxon.om.NodeEnumeration;
6
7 /**
8 * A node-set value implemented intensionally. It is a wrapper round an Expression which
9 * can be evaluated independently of context, that is it has been reduced so there are
10 * no remaining context-dependencies.
11 */

12
13 public class NodeSetIntent extends NodeSetValue {
14     private NodeSetExpression expression;
15     private NodeSetExtent extent = null;
16     private Controller controller;
17     private boolean sorted = false;
18     private int useCount = 0;
19
20     /**
21     * Construct a node-set containing all the nodes in a NodeEnumeration
22     */

23
24     public NodeSetIntent(NodeSetExpression exp, Controller controller) throws XPathException {
25         if (exp.getDependencies()!=0) {
26             exp.display(10);
27             throw new UnsupportedOperationException JavaDoc("Cannot create intensional node-set with context dependencies: " + exp.getClass() + ":" + exp.getDependencies());
28         }
29         expression = exp;
30         this.controller = controller;
31     }
32     
33     /**
34     * Make a Context to use when enumerating the underlying expression
35     */

36     
37     private Context makeContext() {
38         Context c = new Context(controller);
39         c.setStaticContext(expression.getStaticContext());
40         return c;
41     }
42
43     /**
44     * Get the encapsulated NodeSetExpression
45     */

46
47     public NodeSetExpression getNodeSetExpression() {
48         return expression;
49     }
50
51     /**
52     * Set a flag to indicate whether the nodes are sorted. Used when the creator of the
53     * node-set knows that they are already in document order.
54     * @param isSorted true if the caller wishes to assert that the nodes will be delivered
55     * in document order and do not need to be further sorted
56     */

57
58     public void setSorted(boolean isSorted) {
59         sorted = isSorted;
60     }
61
62     /**
63     * Test whether the value is known to be sorted
64     * @return true if the value is known to be sorted in document order, false if it is not
65     * known whether it is sorted.
66     */

67
68     public boolean isSorted() throws XPathException {
69         return (sorted || expression.enumerate(makeContext(), false).isSorted());
70     }
71
72     /**
73     * Determine, in the case of an expression whose data type is Value.NODESET,
74     * whether all the nodes in the node-set are guaranteed to come from the same
75     * document as the context node. Used for optimization.
76     */

77     
78     public boolean isContextDocumentNodeSet() {
79         return expression.isContextDocumentNodeSet();
80     }
81     
82     /**
83     * Convert to string value
84     * @return the value of the first node in the node-set if there
85     * is one, otherwise an empty string
86     */

87
88     public String JavaDoc asString() throws XPathException {
89         NodeInfo first = getFirst();
90         return (first==null ? "" : first.getStringValue());
91     }
92
93     /**
94     * Evaluate as a boolean.
95     * @return true if the node set is not empty
96     */

97
98     public boolean asBoolean() throws XPathException {
99         return enumerate().hasMoreElements();
100     }
101     
102     /**
103     * Count the nodes in the node-set. Note this will sort the node set if necessary, to
104     * make sure there are no duplicates.
105     */

106
107     public int getCount() throws XPathException {
108         if (extent == null) {
109             NodeEnumeration enumeration = expression.enumerate(makeContext(), false);
110             if (enumeration instanceof LastPositionFinder && enumeration.isSorted()) {
111                 return ((LastPositionFinder)enumeration).getLastPosition();
112             }
113             extent = new NodeSetExtent(enumeration, controller);
114         }
115         return extent.getCount();
116     }
117
118     private void fix() throws XPathException {
119         if (extent == null) {
120             NodeEnumeration enumeration = expression.enumerate(makeContext(), false);
121             extent = new NodeSetExtent(enumeration, controller);
122         }
123     }
124
125     /**
126     * Sort the nodes into document order.
127     * This does nothing if the nodes are already known to be sorted; to force a sort,
128     * call setSorted(false)
129     * @return the same NodeSetValue, after sorting.
130     */

131
132     public NodeSetValue sort() throws XPathException {
133         if (sorted) return this;
134         fix();
135         return extent.sort();
136     }
137
138     /**
139     * Get the first node in the nodeset (in document order)
140     * @return the first node
141     */

142
143     public NodeInfo getFirst() throws XPathException {
144         if (extent!=null) return extent.getFirst();
145
146         NodeEnumeration enumeration = expression.enumerate(makeContext(), false);
147         if (sorted || enumeration.isSorted()) {
148             sorted = true;
149             if (enumeration.hasMoreElements()) {
150                 return enumeration.nextElement();
151             } else {
152                 return null;
153             }
154         } else {
155             NodeInfo first = null;
156             while (enumeration.hasMoreElements()) {
157                 NodeInfo node = enumeration.nextElement();
158                 if (first==null || controller.compare(node, first) < 0) {
159                     first = node;
160                 }
161             }
162             return first;
163         }
164     }
165
166     /**
167     * Return the first node in the nodeset (in document order)
168     * @param context The context for the evaluation: not used
169     * @return the NodeInfo of the first node in document order, or null if the node-set
170     * is empty.
171     */

172
173     public NodeInfo selectFirst(Context context) throws XPathException {
174         return getFirst();
175     }
176
177     /**
178     * Return an enumeration of this nodeset value.
179     */

180
181     public NodeEnumeration enumerate() throws XPathException {
182         if (extent!=null) {
183             return extent.enumerate();
184         } else {
185             // arbitrarily, we decide that the third time the expression is used,
186
// we will allocate it some memory for faster access on future occasions.
187
useCount++;
188             if (useCount < 3) {
189                 return expression.enumerate(makeContext(), false);
190             } else {
191                 fix();
192                 return extent.enumerate();
193             }
194         }
195     }
196
197 }
198
199 //
200
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
201
// you may not use this file except in compliance with the License. You may obtain a copy of the
202
// License at http://www.mozilla.org/MPL/
203
//
204
// Software distributed under the License is distributed on an "AS IS" basis,
205
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
206
// See the License for the specific language governing rights and limitations under the License.
207
//
208
// The Original Code is: all this file.
209
//
210
// The Initial Developer of the Original Code is
211
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
212
//
213
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
214
//
215
// Contributor(s): none.
216
//
217

218
Popular Tags