001: package net.sf.saxon.expr;
002:
003: import net.sf.saxon.om.ArrayIterator;
004: import net.sf.saxon.om.Item;
005: import net.sf.saxon.om.NamePool;
006: import net.sf.saxon.om.SequenceIterator;
007: import net.sf.saxon.trans.XPathException;
008: import net.sf.saxon.type.ItemType;
009: import net.sf.saxon.type.TypeHierarchy;
010:
011: import java.io.PrintStream;
012: import java.util.Iterator;
013:
014: /**
015: * A TailExpression represents a FilterExpression of the form EXPR[position() > n]
016: * Here n is usually 2, but we allow other values
017: */
018: public class TailExpression extends ComputedExpression {
019:
020: Expression base;
021: int start; // 1-based offset of first item from base expression
022:
023: // to be included
024:
025: /**
026: * Construct a TailExpression, representing a filter expression of the form
027: * $base[position() >= $start]
028: * @param base the expression to be filtered
029: * @param start the position (1-based) of the first item to be included
030: */
031:
032: public TailExpression(Expression base, int start) {
033: this .base = base;
034: this .start = start;
035: adoptChildExpression(base);
036: }
037:
038: public Expression typeCheck(StaticContext env,
039: ItemType contextItemType) throws XPathException {
040: base = base.typeCheck(env, contextItemType);
041: return this ;
042: }
043:
044: public Expression optimize(Optimizer opt, StaticContext env,
045: ItemType contextItemType) throws XPathException {
046: base = base.optimize(opt, env, contextItemType);
047: return this ;
048: }
049:
050: public Expression promote(PromotionOffer offer)
051: throws XPathException {
052: Expression exp = offer.accept(this );
053: if (exp != null) {
054: return exp;
055: } else {
056: if (offer.action != PromotionOffer.UNORDERED) {
057: base = doPromotion(base, offer);
058: }
059: return this ;
060: }
061: }
062:
063: public int computeSpecialProperties() {
064: return base.getSpecialProperties();
065: }
066:
067: public ItemType getItemType(TypeHierarchy th) {
068: return base.getItemType(th);
069: }
070:
071: public int computeCardinality() {
072: return base.getCardinality() | StaticProperty.ALLOWS_ZERO;
073: }
074:
075: public Iterator iterateSubExpressions() {
076: return new MonoIterator(base);
077: }
078:
079: public Expression getBaseExpression() {
080: return base;
081: }
082:
083: public int getStart() {
084: return start;
085: }
086:
087: public boolean equals(Object other) {
088: return other instanceof TailExpression
089: && base.equals(((TailExpression) other).base)
090: && start == ((TailExpression) other).start;
091: }
092:
093: public int hashCode() {
094: return base.hashCode();
095: }
096:
097: public SequenceIterator iterate(XPathContext context)
098: throws XPathException {
099: SequenceIterator baseIter = base.iterate(context);
100: if (baseIter instanceof ArrayIterator) {
101: return ((ArrayIterator) baseIter).makeSliceIterator(start,
102: Integer.MAX_VALUE);
103: } else {
104: return new TailIterator(baseIter, start);
105: }
106: }
107:
108: public void display(int level, NamePool pool, PrintStream out) {
109: out.println(ExpressionTool.indent(level) + "tail " + start);
110: base.display(level + 1, pool, out);
111: }
112:
113: public static class TailIterator implements SequenceIterator {
114:
115: private SequenceIterator base;
116: private int start;
117:
118: public TailIterator(SequenceIterator base, int start)
119: throws XPathException {
120: this .base = base;
121: this .start = start;
122:
123: // discard the first n-1 items from the underlying iterator
124: for (int i = 0; i < start - 1; i++) {
125: base.next();
126: }
127: }
128:
129: public Item next() throws XPathException {
130: return base.next();
131: }
132:
133: public Item current() {
134: return base.current();
135: }
136:
137: public int position() {
138: return base.position() - start + 1;
139: }
140:
141: public SequenceIterator getAnother() throws XPathException {
142: return new TailIterator(base.getAnother(), start);
143: }
144:
145: /**
146: * Get properties of this iterator, as a bit-significant integer.
147: *
148: * @return the properties of this iterator. This will be some combination of
149: * properties such as {@link GROUNDED}, {@link LAST_POSITION_FINDER},
150: * and {@link LOOKAHEAD}. It is always
151: * acceptable to return the value zero, indicating that there are no known special properties.
152: * It is acceptable for the properties of the iterator to change depending on its state.
153: */
154:
155: public int getProperties() {
156: return 0;
157: }
158: }
159: }
160:
161: //
162: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
163: // you may not use this file except in compliance with the License. You may obtain a copy of the
164: // License at http://www.mozilla.org/MPL/
165: //
166: // Software distributed under the License is distributed on an "AS IS" basis,
167: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
168: // See the License for the specific language governing rights and limitations under the License.
169: //
170: // The Original Code is: all this file.
171: //
172: // The Initial Developer of the Original Code is Michael H. Kay.
173: //
174: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
175: //
176: // Contributor(s): none.
177: //
|