001: package net.sf.saxon.sort;
002:
003: import net.sf.saxon.expr.XPathContext;
004: import net.sf.saxon.om.Item;
005: import net.sf.saxon.om.ListIterator;
006: import net.sf.saxon.om.NodeInfo;
007: import net.sf.saxon.om.SequenceIterator;
008: import net.sf.saxon.pattern.Pattern;
009: import net.sf.saxon.trans.XPathException;
010: import net.sf.saxon.value.AtomicValue;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: /**
016: * A GroupEndingIterator iterates over a sequence of groups defined by
017: * xsl:for-each-group group-ending-with="x". The groups are returned in
018: * order of first appearance.
019: */
020:
021: public class GroupEndingIterator implements GroupIterator {
022:
023: private SequenceIterator population;
024: private Pattern endPattern;
025: private XPathContext baseContext;
026: private XPathContext runningContext;
027: private List currentMembers;
028: private Item next;
029: private Item current = null;
030: private int position = 0;
031:
032: public GroupEndingIterator(SequenceIterator population,
033: Pattern endPattern, XPathContext context)
034: throws XPathException {
035: this .population = population;
036: this .endPattern = endPattern;
037: baseContext = context;
038: runningContext = context.newMinorContext();
039: runningContext.setCurrentIterator(population);
040: // the first item in the population always starts a new group
041: next = population.next();
042: }
043:
044: private void advance() throws XPathException {
045: currentMembers = new ArrayList(20);
046: currentMembers.add(current);
047:
048: next = current;
049: while (next != null) {
050: if (endPattern.matches((NodeInfo) next, runningContext)) {
051: next = population.next();
052: if (next != null) {
053: break;
054: }
055: } else {
056: next = population.next();
057: if (next != null) {
058: currentMembers.add(next);
059: }
060: }
061: }
062: }
063:
064: public AtomicValue getCurrentGroupingKey() {
065: return null;
066: }
067:
068: public SequenceIterator iterateCurrentGroup() {
069: return new ListIterator(currentMembers);
070: }
071:
072: public Item next() throws XPathException {
073: if (next != null) {
074: current = next;
075: position++;
076: advance();
077: return current;
078: } else {
079: current = null;
080: position = -1;
081: return null;
082: }
083: }
084:
085: public Item current() {
086: return current;
087: }
088:
089: public int position() {
090: return position;
091: }
092:
093: public SequenceIterator getAnother() throws XPathException {
094: return new GroupEndingIterator(population.getAnother(),
095: endPattern, baseContext);
096: }
097:
098: /**
099: * Get properties of this iterator, as a bit-significant integer.
100: *
101: * @return the properties of this iterator. This will be some combination of
102: * properties such as {@link GROUNDED}, {@link LAST_POSITION_FINDER},
103: * and {@link LOOKAHEAD}. It is always
104: * acceptable to return the value zero, indicating that there are no known special properties.
105: * It is acceptable for the properties of the iterator to change depending on its state.
106: */
107:
108: public int getProperties() {
109: return 0;
110: }
111:
112: }
113:
114: //
115: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
116: // you may not use this file except in compliance with the License. You may obtain a copy of the
117: // License at http://www.mozilla.org/MPL/
118: //
119: // Software distributed under the License is distributed on an "AS IS" basis,
120: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
121: // See the License for the specific language governing rights and limitations under the License.
122: //
123: // The Original Code is: all this file.
124: //
125: // The Initial Developer of the Original Code is Michael H. Kay
126: //
127: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
128: //
129: // Contributor(s): none
130: //
|