KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > sort > GroupAdjacentIterator


1 package net.sf.saxon.sort;
2
3 import net.sf.saxon.expr.Expression;
4 import net.sf.saxon.expr.XPathContext;
5 import net.sf.saxon.om.Item;
6 import net.sf.saxon.om.ListIterator;
7 import net.sf.saxon.om.LookaheadIterator;
8 import net.sf.saxon.om.SequenceIterator;
9 import net.sf.saxon.trans.DynamicError;
10 import net.sf.saxon.trans.XPathException;
11 import net.sf.saxon.value.AtomicValue;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Comparator JavaDoc;
15 import java.util.List JavaDoc;
16
17 /**
18  * A GroupAdjacentIterator iterates over a sequence of groups defined by
19  * xsl:for-each-group group-adjacent="x". The groups are returned in
20  * order of first appearance.
21  */

22
23 public class GroupAdjacentIterator implements GroupIterator, LookaheadIterator {
24
25     private SequenceIterator population;
26     private Expression keyExpression;
27     private Comparator JavaDoc collator;
28     private AtomicSortComparer comparer;
29     private AtomicSortComparer.ComparisonKey currentComparisonKey;
30     private XPathContext baseContext;
31     private XPathContext runningContext;
32     private AtomicValue currentKey = null;
33     private List JavaDoc currentMembers;
34     private AtomicValue nextKey = null;
35     private Item next;
36     private Item current = null;
37     private int position = 0;
38
39     public GroupAdjacentIterator(SequenceIterator population, Expression keyExpression,
40                                  XPathContext baseContext, Comparator JavaDoc collator)
41     throws XPathException {
42         this.population = population;
43         this.keyExpression = keyExpression;
44         this.baseContext = baseContext;
45         this.runningContext = baseContext.newMinorContext();
46         //runningContext.setOrigin(baseContext);
47
runningContext.setCurrentIterator(population);
48         this.collator = collator;
49         this.comparer = new AtomicSortComparer(collator, baseContext);
50         next = population.next();
51         if (next != null) {
52             nextKey = (AtomicValue)keyExpression.evaluateItem(runningContext);
53         }
54     }
55
56     private void advance() throws XPathException {
57         currentMembers = new ArrayList JavaDoc(20);
58         currentMembers.add(current);
59         while (true) {
60             Item nextCandidate = population.next();
61             if (nextCandidate == null) {
62                 break;
63             }
64             AtomicValue candidateKey =
65                     (AtomicValue)keyExpression.evaluateItem(runningContext);
66             try {
67                 if (currentComparisonKey.equals(comparer.getComparisonKey(candidateKey))) {
68                     currentMembers.add(nextCandidate);
69                 } else {
70                     next = nextCandidate;
71                     nextKey = candidateKey;
72                     return;
73                 }
74             } catch (ClassCastException JavaDoc e) {
75                 DynamicError err = new DynamicError("Grouping key values are of non-comparable types (" +
76                         currentKey.getItemType() +
77                         " and " +
78                         candidateKey.getItemType() + ')');
79                 err.setIsTypeError(true);
80                 err.setXPathContext(runningContext);
81                 throw err;
82             }
83         }
84         next = null;
85         nextKey = null;
86     }
87
88     public AtomicValue getCurrentGroupingKey() {
89         return currentKey;
90     }
91
92     public SequenceIterator iterateCurrentGroup() {
93         return new ListIterator(currentMembers);
94     }
95
96     public boolean hasNext() {
97         return next != null;
98     }
99
100     public Item next() throws XPathException {
101         if (next == null) {
102             current = null;
103             position = -1;
104             return null;
105         }
106         current = next;
107         currentKey = nextKey;
108         currentComparisonKey = comparer.getComparisonKey(currentKey);
109         position++;
110         advance();
111         return current;
112     }
113
114     public Item current() {
115         return current;
116     }
117
118     public int position() {
119         return position;
120     }
121
122     public SequenceIterator getAnother() throws XPathException {
123         return new GroupAdjacentIterator(population.getAnother(), keyExpression, baseContext, collator);
124     }
125
126     /**
127      * Get properties of this iterator, as a bit-significant integer.
128      *
129      * @return the properties of this iterator. This will be some combination of
130      * properties such as {@link GROUNDED}, {@link LAST_POSITION_FINDER},
131      * and {@link LOOKAHEAD}. It is always
132      * acceptable to return the value zero, indicating that there are no known special properties.
133      * It is acceptable for the properties of the iterator to change depending on its state.
134      */

135
136     public int getProperties() {
137         return LOOKAHEAD;
138     }
139
140
141 }
142
143
144 //
145
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
146
// you may not use this file except in compliance with the License. You may obtain a copy of the
147
// License at http://www.mozilla.org/MPL/
148
//
149
// Software distributed under the License is distributed on an "AS IS" basis,
150
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
151
// See the License for the specific language governing rights and limitations under the License.
152
//
153
// The Original Code is: all this file.
154
//
155
// The Initial Developer of the Original Code is Michael H. Kay
156
//
157
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
158
//
159
// Contributor(s): none
160
//
Popular Tags