001: package net.sf.saxon.expr;
002:
003: import net.sf.saxon.om.Item;
004: import net.sf.saxon.om.LookaheadIterator;
005: import net.sf.saxon.om.NodeInfo;
006: import net.sf.saxon.om.SequenceIterator;
007: import net.sf.saxon.sort.NodeOrderComparer;
008: import net.sf.saxon.trans.XPathException;
009:
010: /**
011: * An enumeration representing a nodeset that is a union of two other NodeSets.
012: */
013:
014: public class UnionEnumeration implements SequenceIterator,
015: LookaheadIterator {
016:
017: private SequenceIterator e1;
018: private SequenceIterator e2;
019: private NodeInfo nextNode1 = null;
020: private NodeInfo nextNode2 = null;
021: private NodeOrderComparer comparer;
022: private NodeInfo current = null;
023: private int position = 0;
024:
025: /**
026: * Create the iterator. The two input iterators must return nodes in document
027: * order for this to work.
028: */
029:
030: public UnionEnumeration(SequenceIterator p1, SequenceIterator p2,
031: NodeOrderComparer comparer) throws XPathException {
032: this .e1 = p1;
033: this .e2 = p2;
034: this .comparer = comparer;
035:
036: nextNode1 = next(e1);
037: nextNode2 = next(e2);
038: }
039:
040: /**
041: * Get the next item from one of the input sequences,
042: * checking that it is a node.
043: */
044:
045: private NodeInfo next(SequenceIterator iter) throws XPathException {
046: return (NodeInfo) iter.next();
047: // we rely on the type-checking mechanism to prevent a ClassCastException here
048: }
049:
050: public boolean hasNext() {
051: return nextNode1 != null || nextNode2 != null;
052: }
053:
054: public Item next() throws XPathException {
055:
056: // main merge loop: take a value from whichever set has the lower value
057:
058: position++;
059: if (nextNode1 != null && nextNode2 != null) {
060: int c = comparer.compare(nextNode1, nextNode2);
061: if (c < 0) {
062: current = nextNode1;
063: nextNode1 = next(e1);
064: return current;
065:
066: } else if (c > 0) {
067: current = nextNode2;
068: nextNode2 = next(e2);
069: return current;
070:
071: } else {
072: current = nextNode2;
073: nextNode2 = next(e2);
074: nextNode1 = next(e1);
075: return current;
076: }
077: }
078:
079: // collect the remaining nodes from whichever set has a residue
080:
081: if (nextNode1 != null) {
082: current = nextNode1;
083: nextNode1 = next(e1);
084: return current;
085: }
086: if (nextNode2 != null) {
087: current = nextNode2;
088: nextNode2 = next(e2);
089: return current;
090: }
091: current = null;
092: position = -1;
093: return null;
094: }
095:
096: public Item current() {
097: return current;
098: }
099:
100: public int position() {
101: return position;
102: }
103:
104: public SequenceIterator getAnother() throws XPathException {
105: return new UnionEnumeration(e1.getAnother(), e2.getAnother(),
106: comparer);
107: }
108:
109: /**
110: * Get properties of this iterator, as a bit-significant integer.
111: *
112: * @return the properties of this iterator. This will be some combination of
113: * properties such as {@link GROUNDED}, {@link LAST_POSITION_FINDER},
114: * and {@link LOOKAHEAD}. It is always
115: * acceptable to return the value zero, indicating that there are no known special properties.
116: * It is acceptable for the properties of the iterator to change depending on its state.
117: */
118:
119: public int getProperties() {
120: return LOOKAHEAD;
121: }
122:
123: }
124:
125: //
126: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
127: // you may not use this file except in compliance with the License. You may obtain a copy of the
128: // License at http://www.mozilla.org/MPL/
129: //
130: // Software distributed under the License is distributed on an "AS IS" basis,
131: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
132: // See the License for the specific language governing rights and limitations under the License.
133: //
134: // The Original Code is: all this file.
135: //
136: // The Initial Developer of the Original Code is Michael H. Kay.
137: //
138: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
139: //
140: // Contributor(s): none.
141: //
|