001: package net.sf.saxon.functions;
002:
003: import net.sf.saxon.expr.XPathContext;
004: import net.sf.saxon.om.Item;
005: import net.sf.saxon.om.SequenceIterator;
006: import net.sf.saxon.sort.AtomicComparer;
007: import net.sf.saxon.trans.XPathException;
008: import net.sf.saxon.type.TypeHierarchy;
009: import net.sf.saxon.type.Type;
010: import net.sf.saxon.value.AtomicValue;
011: import net.sf.saxon.value.IntegerValue;
012:
013: /**
014: * The XPath 2.0 index-of() function
015: */
016:
017: public class IndexOf extends CollatingFunction {
018:
019: /**
020: * Evaluate the function to return an iteration of selected nodes.
021: */
022:
023: public SequenceIterator iterate(XPathContext context)
024: throws XPathException {
025: AtomicComparer comparer = getAtomicComparer(2, context);
026: SequenceIterator seq = argument[0].iterate(context);
027: AtomicValue val = (AtomicValue) argument[1]
028: .evaluateItem(context);
029: final TypeHierarchy th = context.getConfiguration()
030: .getNamePool().getTypeHierarchy();
031: return new IndexIterator(seq, val, th, comparer);
032: }
033:
034: private class IndexIterator implements SequenceIterator {
035:
036: SequenceIterator base;
037: AtomicValue value;
038: AtomicComparer comparer;
039: int index = 0;
040: int position = 0;
041: Item current = null;
042: int primitiveTypeRequired;
043: TypeHierarchy typeHierarchy;
044:
045: public IndexIterator(SequenceIterator base, AtomicValue value,
046: TypeHierarchy th, AtomicComparer comparer) {
047: this .base = base;
048: this .value = value;
049: this .comparer = comparer;
050: this .typeHierarchy = th;
051: primitiveTypeRequired = value.getPrimitiveValue()
052: .getItemType(th).getPrimitiveType();
053: }
054:
055: public Item next() throws XPathException {
056: while (true) {
057: AtomicValue i = (AtomicValue) base.next();
058: if (i == null)
059: break;
060: index++;
061: if (Type.isComparable(primitiveTypeRequired, i
062: .getPrimitiveValue().getItemType(typeHierarchy)
063: .getPrimitiveType())) {
064: try {
065: if (comparer.comparesEqual(i, value)) {
066: current = new IntegerValue(index);
067: position++;
068: return current;
069: }
070: } catch (ClassCastException err) {
071: // non-comparable values are treated as not equal
072: // Exception shouldn't happen but we catch it anyway
073: }
074: }
075: }
076: current = null;
077: position = -1;
078: return null;
079: }
080:
081: public Item current() {
082: return current;
083: }
084:
085: public int position() {
086: return position;
087: }
088:
089: public SequenceIterator getAnother() throws XPathException {
090: return new IndexIterator(base.getAnother(), value,
091: typeHierarchy, comparer);
092: }
093:
094: /**
095: * Get properties of this iterator, as a bit-significant integer.
096: *
097: * @return the properties of this iterator. This will be some combination of
098: * properties such as {@link GROUNDED}, {@link LAST_POSITION_FINDER},
099: * and {@link LOOKAHEAD}. It is always
100: * acceptable to return the value zero, indicating that there are no known special properties.
101: * It is acceptable for the properties of the iterator to change depending on its state.
102: */
103:
104: public int getProperties() {
105: return 0;
106: }
107: }
108:
109: }
110:
111: //
112: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
113: // you may not use this file except in compliance with the License. You may obtain a copy of the
114: // License at http://www.mozilla.org/MPL/
115: //
116: // Software distributed under the License is distributed on an "AS IS" basis,
117: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
118: // See the License for the specific language governing rights and limitations under the License.
119: //
120: // The Original Code is: all this file.
121: //
122: // The Initial Developer of the Original Code is Michael H. Kay.
123: //
124: // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
125: //
126: // Contributor(s): none.
127: //
|