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 GroupStartingIterator iterates over a sequence of groups defined by
017: * xsl:for-each-group group-starting-with="x". The groups are returned in
018: * order of first appearance.
019: */
020:
021: public class GroupStartingIterator implements GroupIterator {
022:
023: private SequenceIterator population;
024: private Pattern startPattern;
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 GroupStartingIterator(SequenceIterator population,
033: Pattern startPattern, XPathContext context)
034: throws XPathException {
035: this .population = population;
036: this .startPattern = startPattern;
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(10);
046: currentMembers.add(current);
047: while (true) {
048: NodeInfo nextCandidate = (NodeInfo) population.next();
049: if (nextCandidate == null) {
050: break;
051: }
052: if (startPattern.matches(nextCandidate, runningContext)) {
053: next = nextCandidate;
054: return;
055: } else {
056: currentMembers.add(nextCandidate);
057: }
058: }
059: next = null;
060: }
061:
062: public AtomicValue getCurrentGroupingKey() {
063: return null;
064: }
065:
066: public SequenceIterator iterateCurrentGroup() {
067: return new ListIterator(currentMembers);
068: }
069:
070: public Item next() throws XPathException {
071: if (next != null) {
072: current = next;
073: position++;
074: advance();
075: return current;
076: } else {
077: current = null;
078: position = -1;
079: return null;
080: }
081: }
082:
083: public Item current() {
084: return current;
085: }
086:
087: public int position() {
088: return position;
089: }
090:
091: public SequenceIterator getAnother() throws XPathException {
092: return new GroupStartingIterator(population.getAnother(),
093: startPattern, baseContext);
094: }
095:
096: /**
097: * Get properties of this iterator, as a bit-significant integer.
098: *
099: * @return the properties of this iterator. This will be some combination of
100: * properties such as {@link GROUNDED}, {@link LAST_POSITION_FINDER},
101: * and {@link LOOKAHEAD}. It is always
102: * acceptable to return the value zero, indicating that there are no known special properties.
103: * It is acceptable for the properties of the iterator to change depending on its state.
104: */
105:
106: public int getProperties() {
107: return 0;
108: }
109:
110: }
111:
112: //
113: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
114: // you may not use this file except in compliance with the License. You may obtain a copy of the
115: // License at http://www.mozilla.org/MPL/
116: //
117: // Software distributed under the License is distributed on an "AS IS" basis,
118: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
119: // See the License for the specific language governing rights and limitations under the License.
120: //
121: // The Original Code is: all this file.
122: //
123: // The Initial Developer of the Original Code is Michael H. Kay
124: //
125: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
126: //
127: // Contributor(s): none
128: //
|