KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.value;
2 import net.sf.saxon.expr.*;
3 import net.sf.saxon.om.*;
4 import net.sf.saxon.pattern.NodeKindTest;
5 import net.sf.saxon.trans.XPathException;
6 import net.sf.saxon.type.AnyItemType;
7 import net.sf.saxon.type.ItemType;
8 import net.sf.saxon.type.Type;
9
10 import java.util.List JavaDoc;
11
12
13 /**
14  * A sequence value implemented extensionally. That is, this class represents a sequence
15  * by allocating memory to each item in the sequence.
16  */

17
18 public final class SequenceExtent extends Value {
19     private Item[] value;
20     private int start = 0; // zero-based offset of the start
21
private int end; // the 0-based index of the first item that is NOT included
22
private ItemType itemType = null; // memoized
23

24 // private static int instances = 0;
25

26     /**
27      * Construct an sequence from an array of items. Note, the array of items is used as is,
28      * which means the caller must not subsequently change its contents.
29      *
30      * @param items the array of items to be included in the sequence
31      */

32
33     public SequenceExtent(Item[] items) {
34         this.value = items;
35         end = items.length;
36     }
37
38     /**
39      * Construct a SequenceExtent from part of an array of items
40      * @param value The array
41      * @param start zero-based offset of the first item in the array
42      * that is to be included in the new SequenceExtent
43      * @param length The number of items in the new SequenceExtent
44      */

45
46     public SequenceExtent(Item[] value, int start, int length) {
47         this.value = value;
48         this.start = start;
49         this.end = this.start + length;
50     }
51
52
53     /**
54      * Construct a SequenceExtent as a view of another SequenceExtent
55      * @param ext The existing SequenceExtent
56      * @param start zero-based offset of the first item in the existing SequenceExtent
57      * that is to be included in the new SequenceExtent
58      * @param length The number of items in the new SequenceExtent
59      */

60
61     public SequenceExtent(SequenceExtent ext, int start, int length) {
62         this.value = ext.value;
63         this.start = ext.start + start;
64         this.end = this.start + length;
65     }
66
67     /**
68      * Construct a SequenceExtent from a List. The members of the list must all
69      * be Items
70      *
71      * @param list the list of items to be included in the sequence
72      */

73
74     public SequenceExtent(List JavaDoc list) {
75         value = new Item[list.size()];
76         for (int i=0; i<list.size(); i++) {
77             value[i] = (Item)list.get(i);
78         }
79         end = list.size();
80     }
81
82     /**
83      * Construct a sequence containing all the items in a SequenceIterator.
84      *
85      * @exception net.sf.saxon.trans.XPathException if reading the items using the
86      * SequenceIterator raises an error
87      * @param iter The supplied sequence of items. This must be positioned at
88      * the start, so that hasNext() returns true if there are any nodes in
89      * the node-set, and next() returns the first node.
90      */

91
92     public SequenceExtent(SequenceIterator iter) throws XPathException {
93         int size = 20;
94                 // Although the iterator may be able to
95
// say how many nodes it contains, it may be an expensive operation,
96
// so we behave as if we don't know.
97
value = new Item[size];
98         int i = 0;
99         while (true) {
100             Item it = iter.next();
101             if (it == null) {
102                 break;
103             }
104             if (i>=size) {
105                 size *= 2;
106                 Item newarray[] = new Item[size];
107                 System.arraycopy(value, 0, newarray, 0, i);
108                 value = newarray;
109             }
110             value[i++] = it;
111         }
112         end = i;
113     }
114
115     /**
116      * Factory method to make a Value holding the contents of any SequenceIterator
117      */

118
119     public static Value makeSequenceExtent(SequenceIterator iter) throws XPathException {
120         if ((iter.getProperties() & SequenceIterator.GROUNDED) != 0) {
121             return ((GroundedIterator)iter).materialize();
122         }
123         //iter = new MappingIterator(iter, new UserFunctionCall.Flattener(), null);
124
return new SequenceExtent(iter);
125     }
126
127     /**
128      * An implementation of Expression must provide at least one of the methods evaluateItem(), iterate(), or process().
129      * This method indicates which of these methods is prefered.
130      */

131
132     public int getImplementationMethod() {
133         return ITERATE_METHOD;
134     }
135
136     /**
137      * Simplify this SequenceExtent
138      */

139
140     public Value simplify() {
141         int n = getLength();
142         if (n == 0) {
143             return EmptySequence.getInstance();
144         } else if (n == 1) {
145             return Value.asValue(itemAt(0));
146         } else {
147             return this;
148         }
149     }
150
151     /**
152      * Reduce a value to its simplest form. If the value is a closure or some other form of deferred value
153      * such as a FunctionCallPackage, then it is reduced to a SequenceExtent. If it is a SequenceExtent containing
154      * a single item, then it is reduced to that item. One consequence that is exploited by class FilterExpression
155      * is that if the value is a singleton numeric value, then the result will be an instance of NumericValue
156      */

157
158     public Value reduce() {
159         return simplify();
160     }
161
162     /**
163      * Get the number of items in the sequence
164      *
165      * @return the number of items in the sequence
166      */

167
168     public int getLength() {
169         return end - start;
170     }
171
172     /**
173      * Determine the cardinality
174      *
175      * @return the cardinality of the sequence, using the constants defined in
176      * net.sf.saxon.value.Cardinality
177      * @see net.sf.saxon.value.Cardinality
178      */

179
180     public int getCardinality() {
181         switch (end - start) {
182             case 0:
183                 return StaticProperty.EMPTY;
184             case 1:
185                 return StaticProperty.EXACTLY_ONE;
186             default:
187                 return StaticProperty.ALLOWS_ONE_OR_MORE;
188         }
189     }
190
191     /**
192      * Get the (lowest common) item type
193      *
194      * @return integer identifying an item type to which all the items in this
195      * sequence conform
196      */

197
198     public ItemType getItemType() {
199         if (itemType != null) {
200             // only calculate it the first time
201
return itemType;
202         }
203         if (end==start) {
204             itemType = AnyItemType.getInstance();
205         } else {
206             itemType = computeItemType(value[start]);
207             for (int i=start+1; i<end; i++) {
208                 if (itemType == AnyItemType.getInstance()) {
209                     // make a quick exit
210
return itemType;
211                 }
212                 itemType = Type.getCommonSuperType(itemType, computeItemType(value[i]));
213             }
214         }
215         return itemType;
216     }
217
218     private static ItemType computeItemType(Item item) {
219         if (item instanceof AtomicValue) {
220             return ((AtomicValue)item).getItemType();
221         } else {
222             return NodeKindTest.makeNodeKindTest(((NodeInfo)item).getNodeKind());
223             // ignore the type annotation for now
224
}
225     }
226
227
228     /**
229      * Get the n'th item in the sequence (starting with 0 as the first item)
230      *
231      * @param n the position of the required item
232      * @return the n'th item in the sequence
233      */

234
235     public Item itemAt(int n) {
236         if (n<0 || n>=getLength()) {
237             return null;
238         } else {
239             return value[start+n];
240         }
241     }
242
243     /**
244      * Swap two items (needed to support sorting)
245      *
246      * @param a the position of the first item to be swapped
247      * @param b the position of the second item to be swapped
248      */

249
250     public void swap(int a, int b) {
251         Item temp = value[start+a];
252         value[start+a] = value[start+b];
253         value[start+b] = temp;
254     }
255
256     /**
257      * Return an iterator over this sequence.
258      *
259      * @param context dynamic evaluation context; not used in this
260      * implementation of the method
261      * @return the required SequenceIterator, positioned at the start of the
262      * sequence
263      */

264
265     public SequenceIterator iterate(XPathContext context) {
266         return new ArrayIterator(value, start, end);
267     }
268
269     /**
270      * Return an enumeration of this sequence in reverse order (used for reverse axes)
271      *
272      * @return an AxisIterator that processes the items in reverse order
273      */

274
275     public AxisIterator reverseIterate() {
276         return new ReverseArrayIterator(value, start, end);
277     }
278
279     /**
280      * Get the effective boolean value
281      */

282
283     public boolean effectiveBooleanValue(XPathContext context) throws XPathException {
284         int len = getLength();
285         if (len == 0) {
286             return false;
287         } else if (value[0] instanceof NodeInfo) {
288             return true;
289         } else if (len > 1) {
290             // this is a type error - reuse the error messages
291
return ExpressionTool.effectiveBooleanValue(iterate(context));
292         } else {
293             return ((AtomicValue)value[0]).effectiveBooleanValue(context);
294         }
295     }
296
297
298 }
299
300 //
301
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
302
// you may not use this file except in compliance with the License. You may obtain a copy of the
303
// License at http://www.mozilla.org/MPL/
304
//
305
// Software distributed under the License is distributed on an "AS IS" basis,
306
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
307
// See the License for the specific language governing rights and limitations under the License.
308
//
309
// The Original Code is: all this file.
310
//
311
// The Initial Developer of the Original Code is Michael H. Kay.
312
//
313
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
314
//
315
// Contributor(s): none.
316
//
317

318
Popular Tags