001: package net.sf.saxon.functions;
002:
003: import net.sf.saxon.expr.Expression;
004: import net.sf.saxon.expr.StaticContext;
005: import net.sf.saxon.expr.TailExpression;
006: import net.sf.saxon.expr.XPathContext;
007: import net.sf.saxon.om.Item;
008: import net.sf.saxon.om.SequenceIterator;
009: import net.sf.saxon.trans.XPathException;
010: import net.sf.saxon.type.ItemType;
011: import net.sf.saxon.type.TypeHierarchy;
012: import net.sf.saxon.value.AtomicValue;
013: import net.sf.saxon.value.IntegerValue;
014: import net.sf.saxon.value.NumericValue;
015:
016: /**
017: * The XPath 2.0 remove() function
018: */
019:
020: public class Remove extends SystemFunction {
021:
022: /**
023: * Simplify. Recognize remove(seq, 1) as a TailExpression.
024: */
025:
026: public Expression simplify(StaticContext env) throws XPathException {
027: Expression exp = super .simplify(env);
028: if (exp instanceof Remove) {
029: return ((Remove) exp).simplifyAsTailExpression();
030: } else {
031: return exp;
032: }
033: }
034:
035: /**
036: * Simplify. Recognize remove(seq, 1) as a TailExpression. This
037: * is worth doing because tail expressions used in a recursive call
038: * are handled specially.
039: */
040:
041: private Expression simplifyAsTailExpression() {
042: if (argument[1] instanceof IntegerValue
043: && ((IntegerValue) argument[1]).longValue() == 1) {
044: return new TailExpression(argument[0], 2);
045: } else {
046: return this ;
047: }
048: }
049:
050: /**
051: * Determine the data type of the items in the sequence
052: * @return the type of the input sequence
053: * @param th
054: */
055:
056: public ItemType getItemType(TypeHierarchy th) {
057: return argument[0].getItemType(th);
058: }
059:
060: /**
061: * Evaluate the function to return an iteration of selected nodes.
062: */
063:
064: public SequenceIterator iterate(XPathContext context)
065: throws XPathException {
066: SequenceIterator seq = argument[0].iterate(context);
067: AtomicValue n0 = (AtomicValue) argument[1]
068: .evaluateItem(context);
069: NumericValue n = (NumericValue) n0.getPrimitiveValue();
070: int pos = (int) n.longValue();
071: if (pos < 1) {
072: return seq;
073: }
074: return new RemoveIterator(seq, pos);
075: }
076:
077: private class RemoveIterator implements SequenceIterator {
078:
079: SequenceIterator base;
080: int removePosition;
081: int position = 0;
082: Item current = null;
083:
084: public RemoveIterator(SequenceIterator base, int removePosition) {
085: this .base = base;
086: this .removePosition = removePosition;
087: }
088:
089: public Item next() throws XPathException {
090: current = base.next();
091: if (current != null && base.position() == removePosition) {
092: current = base.next();
093: }
094: if (current == null) {
095: position = -1;
096: } else {
097: position++;
098: }
099: return current;
100: }
101:
102: public Item current() {
103: return current;
104: }
105:
106: public int position() {
107: return position;
108: }
109:
110: public SequenceIterator getAnother() throws XPathException {
111: return new RemoveIterator(base.getAnother(), removePosition);
112: }
113:
114: /**
115: * Get properties of this iterator, as a bit-significant integer.
116: *
117: * @return the properties of this iterator. This will be some combination of
118: * properties such as {@link GROUNDED}, {@link LAST_POSITION_FINDER},
119: * and {@link LOOKAHEAD}. It is always
120: * acceptable to return the value zero, indicating that there are no known special properties.
121: * It is acceptable for the properties of the iterator to change depending on its state.
122: */
123:
124: public int getProperties() {
125: return 0;
126: }
127: }
128:
129: }
130:
131: //
132: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
133: // you may not use this file except in compliance with the License. You may obtain a copy of the
134: // License at http://www.mozilla.org/MPL/
135: //
136: // Software distributed under the License is distributed on an "AS IS" basis,
137: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
138: // See the License for the specific language governing rights and limitations under the License.
139: //
140: // The Original Code is: all this file.
141: //
142: // The Initial Developer of the Original Code is Michael H. Kay.
143: //
144: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
145: //
146: // Contributor(s): none.
147: //
|